.PHONY: all clean realclean dist install
PACKAGE:=secnet
-VERSION:=0.1.7
+VERSION:=0.1.8
@SET_MAKE@
serpent.o md5.o version.o tun.o slip.o sha1.o ipaddr.o log.o \
process.o
-DISTFILES:=COPYING CREDITS INSTALL Makefile.in NOTES README TODO \
+DISTFILES:=COPYING CREDITS INSTALL Makefile.in NEWS NOTES README TODO \
conffile.c conffile.fl conffile.h conffile.y \
conffile_internal.h config.h.bot \
config.h.in config.h.top configure \
configure.in debian dh.c \
- example-sites-file example.conf make-secnet-sites.py \
+ example.conf make-secnet-sites.py \
install.sh ipaddr.c ipaddr.h ipaddr.py linux log.c md5.c md5.h \
modules.c netlink.c netlink.h process.c process.h \
random.c resolver.c rsa.c \
--- /dev/null
+* New in version 0.1.8
+
+Netlink devices now support a 'point-to-point' mode. In this mode the
+netlink device does not require an IP address; instead, the IP address
+of the other end of the tunnel is specified using the 'ptp-address'
+option. Precisely one site must be configured to use the netlink
+device.
+
+The tunnel code in site.c now initiates a key setup if the
+reverse-transform function fails (wrong key, bad MAC, too much skew,
+etc.) - this should make secnet more reliable on dodgy links, which
+are much more common than links with active attackers... (an attacker
+can now force a new key setup by replaying an old packet, but apart
+from minor denial of service on slow links or machines this won't
+achieve them much).
+
+The sequence number skew detection code in transform.c now only
+complains about 'reverse skew' - replays of packets that are too
+old. 'Forward skew' (gaps in the sequence numbers of received packets)
+is now tolerated silently, to cope with large amounts of packet loss.
by any remote site using this netlink device
local-address (string): IP address of host's tunnel interface
secnet-address (string): IP address of this netlink device
+ ptp-address (string): IP address of the other end of a point-to-point link
mtu (integer): MTU of host's tunnel interface
+Only one of secnet-address or ptp-address may be specified. If
+point-to-point mode is in use then precisely one tunnel must register
+with the netlink device.
+
Netlink will dump its current routing table to the system/log on
receipt of SIGUSR1.
route-path (string): optional, path to route command
plus generic netlink options, as for 'null-netlink'
+ I recommend you don't specify the 'interface' option unless you're
+ doing something that requires the interface name to be constant.
+
** rsa
Defines:
Defines:
sha1 (hash closure)
+
+** conffile
+
+Defines:
+ makelist (dictionary => list of definitions)
+ readfile (string => string)
+ map (closure,list => list)
+
+makelist: dictionary
+ returns a list consisting of the definitions in the dictionary. The keys
+ are discarded.
+
+readfile: string
+ reads the named file and returns its contents as a string
+
+map:
+ applies the closure specified as arg1 to each of the elements in the list.
+ Returns a list made up of the outputs of the closure.
dh.c: change format to binary from decimal string (without introducing
endianness problems)
+ipaddr.c: implement the useful functionality from ipaddr.py
+
netlink.c: investigate why 'default' routes don't appear to work
(reported by JDA).
-
-slip.c: restart userv-ipif to cope with soft routes? Restart it if it
-fails in use?
-
-tun.c: jdamery reports tun-old code works on Linux-2.2.
-Unresolved problem with ioctl(TUNSETIFF) sometimes returning EINVAL, seems
-to be related to early 2.4.x (x<=5) series kernels. 2.4.9 and above seem ok;
-2.4.[678] untested.
+Implement the 'allow_route' option properly.
random.c: test
site.c: the site_incoming() routing could be implemented much more
cleanly using a table. There's still quite a lot of redundancy in this
file. Abandon key exchanges when a bad packet is received. Modify
-protocol to include version fields, as described in the NOTES file.
+protocol to include version fields, as described in the NOTES
+file. Implement keepalive mode. Make policy about when to initiate key
+exchanges more configurable (how many NAKs / bad reverse-transforms
+does it take to prompt a key exchange?)
+
+slip.c: restart userv-ipif to cope with soft routes? Restart it if it
+fails in use?
+userv-ipif doesn't like the same bit of network to be specified
+twice. Use the new functionality in ipaddr.c once it's done to prevent
+this.
+
+tun.c: jdamery reports tun-old code works on Linux-2.2.
+Unresolved problem with ioctl(TUNSETIFF) sometimes returning EINVAL, seems
+to be related to early 2.4.x (x<=5) series kernels. 2.4.9 and above seem ok;
+2.4.[678] untested.
transform.c: separate the transforms into multiple parts, which can
then be combined in the configuration file. Will allow the user to
plug in different block ciphers, invent an authenticity-only mode,
etc.
-
-sha1.c: test
-
+++ /dev/null
-# This is an example /etc/secnet/sites file. It doesn't define any real
-# sites. The diffie-hellman modulus and generator are real and will work,
-# but if you're setting up your own VPN I suggest you choose your own.
-
-example-vpn {
-
-dh diffie-hellman("8db5f2c15ac96d9f3382d1ef4688fba14dc7908ae7dfd71a9cfe7f479a75d506dc53f159aeaf488bde073fe544bc91c099f101fcf60074f30c06e36263c03ca9e07931ce3fc235fe1171dc6d9316fb097bd4362891e2c36e234e7c16b038fd97b1f165c710e90537de66ee4f54001f5712b050d4e07de3fba07607b19b64f6c3","2");
-hash md5;
-
-key-lifetime 3600000; # One hour = 3600000 milliseconds
-
-some-site {
- # The 'name' here must match the 'local-name' defined in the
- # site's /etc/secnet/secnet.conf, because it's used in the
- # key-setup protocol.
- # The name of this dictionary doesn't have to - it's local
- # to the configuration system.
- name "some-site";
- address "foo.greenend.org.uk";
- port 5678;
- networks "192.168.x.x/24", "192.168.x.x/24";
- key rsa-public("35","131453873229748492184986747327990913828179255774895541667982108408897406369168730551214152673574619385573519088922707364993860644376262000057302119569116289693520981276177337391324943049983046703853106890057346878967444626093102422836819979338760420960495059950787838142162794317002315919126174831103379472833");
- };
-
-some-other-site {
- name "some-other-site";
- address "bar.greenend.org.uk";
- port 18436;
- networks "192.168.x.x/24", "192.168.x.x/24";
- key rsa-public("35","154107175724781677184264293617887954015562225725852111745852699493257053099810379926047345975839848434403852210573185384327420788855664167034282567346429150999373740871227795773749618022407366186555483566435251279808390618987056868368084933125373643004284007109877210578088697520329039753099981203724057693543");
- };
-
-a-third-site {
- name "different-for-a-change";
- address "baz.greenend.org.uk";
- port 3234;
- networks "foo";
- key-lifetime 1800000; # Can be set per-site as well, you see...
- setup-retries 10; # So can this
- setup-timeout 2000; # And this. (And 'wait-time' too.)
- key rsa-public("e","n");
- };
-
-};
# wait-time wait between unsuccessful key setup attempts, in ms
# renegotiate-time set up a new key if we see any traffic after this time
+setup-retries 10;
+setup-timeout 2000;
+
# Use the universal TUN/TAP driver to get packets to and from the kernel
# (use tun-old if you are not on Linux-2.4)
netlink tun {
# that it's non-blocking. XXX 'yes' isn't implemented yet.
random randomfile("/dev/urandom",no);
+# If you're using the make-secnet-sites.py script then your local-name
+# will be of the form "vpnname/location/site" eg. "sgo/greenend/sinister"
local-name "your-site-name";
local-key rsa-private("/etc/secnet/key");
packet to the kernel we check that the tunnel it came over could
reasonably have produced it. */
-/* XXX new feature: "point-to-point" mode. Instead of specifying a
- secnet-address in the configuration dictionary, the user specifies
- the address of the machine at the other end of the (one and only)
- tunnel. We bypass all IP packet processing code. This mode is
- useful for leafnodes like laptops, which don't require a secnet
- router address. */
-
#include "secnet.h"
#include "util.h"
#include "ipaddr.h"
/* Check source */
if (client) {
- /* Check that the packet source is in 'nets' and its destination is
- in st->networks */
+ /* Check that the packet source is appropriate for the tunnel
+ it came down */
if (!subnet_matches_list(client->networks,source)) {
string_t s,d;
s=ipaddr_to_string(source);
return;
}
} else {
+ /* Check that the packet originates in our configured local
+ network, and hasn't been forwarded from elsewhere or
+ generated with the wrong source address */
if (!subnet_matches_list(&st->networks,source)) {
string_t s,d;
s=ipaddr_to_string(source);
return;
}
}
+
+ /* If this is a point-to-point device we don't examine the packet at
+ all; we blindly send it down our one-and-only registered tunnel,
+ or to the host, depending on where it came from. */
+ if (st->ptp) {
+ if (client) {
+ st->deliver_to_host(st->dst,NULL,buf);
+ } else {
+ st->clients->deliver(st->clients->dst,NULL,buf);
+ }
+ BUF_ASSERT_FREE(buf);
+ return;
+ }
+
/* (st->secnet_address needs checking before matching destination
addresses) */
if (dest==st->secnet_address) {
Message(M_ERROR,"%s: site %s specifies networks that "
"intersect with the explicitly excluded remote networks\n",
st->name,client_name);
- return False;
+ return NULL;
+ }
+
+ if (st->clients && st->ptp) {
+ fatal("%s: only one site may use a point-to-point netlink device\n",
+ st->name);
+ return NULL;
}
c=safe_malloc(sizeof(*c),"netlink_regnets");
c->networks=nets;
c->deliver=deliver;
c->dst=dst;
- c->name=client_name; /* XXX copy it? */
+ c->name=client_name;
c->options=options;
c->link_quality=LINK_QUALITY_DOWN;
c->next=st->clients;
struct netlink_client *c;
uint32_t i,j;
+ if (!st->clients && st->ptp) {
+ /* Point-to-point netlink devices must have precisely one
+ client. If none has registered by now, complain. */
+ fatal("%s: point-to-point netlink devices must have precisely "
+ "one client. This one doesn't have any.\n",st->name);
+ }
+
/* All the networks serviced by the various tunnels should now
* have been registered. We build a routing table by sorting the
* routes into most-specific-first order. */
netlink_route_fn *set_route,
netlink_deliver_fn *to_host)
{
+ item_t *sa, *ptpa;
+
st->dst=dst;
st->cl.description=description;
st->cl.type=CL_NETLINK;
/* secnet-address does not have to be in local-networks;
however, it should be advertised in the 'sites' file for the
local site. */
- st->secnet_address=string_to_ipaddr(
- dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
+ sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
+ ptpa=dict_find_item(dict,"ptp-address", False, "netlink", loc);
+ if (sa && ptpa) {
+ cfgfatal(loc,st->name,"you may not specify secnet-address and "
+ "ptp-address in the same netlink device\n");
+ }
+ if (!(sa || ptpa)) {
+ cfgfatal(loc,st->name,"you must specify secnet-address or "
+ "ptp-address for this netlink device\n");
+ }
+ if (sa) {
+ st->secnet_address=string_to_ipaddr(sa,"netlink");
+ st->ptp=False;
+ } else {
+ st->secnet_address=string_to_ipaddr(ptpa,"netlink");
+ st->ptp=True;
+ }
st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
buffer_new(&st->icmp,ICMP_BUFSIZE);
st->n_routes=0;
uint32_t max_end_pad;
struct subnet_list networks;
struct subnet_list exclude_remote_networks;
- uint32_t secnet_address; /* our own address */
+ uint32_t secnet_address; /* our own address, or possibly the address of
+ the other end of a point-to-point link */
+ bool_t ptp;
uint32_t mtu;
struct netlink_client *clients;
netlink_deliver_fn *deliver_to_host; /* Provided by driver */
msg0,&transform_err)) {
/* There's a problem */
slog(st,LOG_SEC,"transform: %s",transform_err);
- return False;
+ return initiate_key_setup(st);
}
CHECK_AVAIL(msg0,4);
type=buf_unprepend_uint32(msg0);
is only allowed to increase. */
seqnum=buf_unprepend_uint32(buf);
skew=seqnum-ti->lastrecvseq;
- if (skew<10) {
+ if (skew<0x8fffffff) {
/* Ok */
ti->lastrecvseq=seqnum;
- } else if ((0-skew)<10) {
+ } else if ((0-skew)<ti->max_skew) {
/* Ok */
} else {
/* Too much skew */
#include <linux/if_tun.h>
#endif
-/* XXX where do we find if_tun on other platforms? */
+/* Where do we find if_tun on other platforms? */
/* Connection to the kernel through the universal TUN/TAP driver */
struct tun *st=sst;
BUF_ASSERT_USED(buf);
-
- /* No error checking, because we'd just throw the packet away anyway */
+ /* No error checking, because we'd just throw the packet away
+ anyway if it didn't work. */
write(st->fd,buf->start,buf->size);
BUF_FREE(buf);
}