chiark / gitweb /
Makefile.in: Use -MMD, not depend.sh
[secnet.git] / NOTES
diff --git a/NOTES b/NOTES
index 272e359c8a250559e21a44c3112013cc130fc56a..f5ebc652045e20818d83188fd6f919e8deb11b53 100644 (file)
--- a/NOTES
+++ b/NOTES
@@ -1,9 +1,10 @@
-#* Design of new, multi-subnet secnet protocol
+* Design of new, multi-subnet secnet protocol
 
-Like the first version, we're tunnelling IP packets inside UDP
-packets. To defeat various restrictions which may be imposed on us by
-network providers (like the prohibition of incoming TCP connections)
-we're sticking with UDP for everything this time, including key setup.
+Like the first (1995/6) version, we're tunnelling IP packets inside
+UDP packets. To defeat various restrictions which may be imposed on us
+by network providers (like the prohibition of incoming TCP
+connections) we're sticking with UDP for everything this time,
+including key setup. This means we have to handle retries, etc.
 
 Other new features include being able to deal with subnets hidden
 behind changing 'real' IP addresses, and the ability to choose
@@ -11,6 +12,8 @@ algorithms and keys per pair of communicating sites.
 
 ** Configuration and structure
 
+[The original plan]
+
 The network is made up from a number of 'sites'. These are collections
 of machines with private IP addresses. The new secnet code runs on
 machines which have interfaces on the private site network and some
@@ -21,61 +24,121 @@ convenient for every gateway machine to use the same name for each
 tunnel endpoint, but this is not vital. Individual tunnels are
 identified by their two endpoint names.
 
+[The new plan]
+
+It appears that people want to be able to use secnet on mobile
+machines like laptops as well as to interconnect sites. In particular,
+they want to be able to use their laptop in three situations:
+
+1) connected to their internal LAN by a cable; no tunnel involved
+2) connected via wireless, using a tunnel to protect traffic
+3) connected to some other network, using a tunnel to access the
+internal LAN.
+
+They want the laptop to keep the same IP address all the time.
+
+Case (1) is simple.
+
+Case (2) requires that the laptop run a copy of secnet, and have a
+tunnel configured between it and the main internal LAN default
+gateway. secnet must support the concept of a 'soft' tunnel where it
+adds a route and causes the gateway to do proxy-ARP when the tunnel is
+up, and removes the route again when the tunnel is down.
+
+The usual prohibition of packets coming in from one tunnel and going
+out another must be relaxed in this case (in particular, the
+destination address of packets from these 'mobile station' tunnels may
+be another tunnel as well as the host).
+
+(Quick sanity check: if chiark's secnet address was in
+192.168.73.0/24, would this work properly? Yes, because there will be
+an explicit route to it, and proxy ARP will be done for it. Do we want
+packets from the chiark tunnel to be able to go out along other
+routes? No. So, spotting a 'local' address in a remote site's list of
+networks isn't sufficient to switch on routing for a site. We need an
+explicit option. NB packets may be routed if the source OR the
+destination is marked as allowing routing [otherwise packets couldn't
+get back from eg. chiark to a laptop at greenend]).
 
-The configuration is held in memory as a data structure as follows:
+[the even newer plan]
 
-The root is a Dictionary. Dictionaries hold (key,value) pairs. Keys
-are atoms. Values are lists, dictionaries or closures. Lists can hold
-the following types: string, number.
+secnet sites are configured to grant access to particular IP address
+ranges to the holder of a particular public key.  The key can certify
+other keys, which will then be permitted to use a subrange of the IP
+address range of the certifying key.
 
-Closures cannot be constructed directly; they are added to the
-'default' dictionary before the configuration file is read. Invocation
-of a closure can return any type of value.
+This means that secnet won't know in advance (i.e. at configuration
+time) how many tunnels it might be required to support, so we have to
+be able to create them (and routes, and so on) on the fly.
 
+** VPN-level configuration
 
-Configuration file format: the file describes a dictionary.
+At a high level we just want to be able to indicate which groups of
+users can claim ownership of which ranges of IP addresses. Assuming
+these users (or their representatives) all have accounts on a single
+machine, we can automate the submission of keys and other information
+to make up a 'sites' file for the entire VPN.
 
-key value;
+The distributed 'sites' file should be in a more restricted format
+than the secnet configuration file, to prevent attackers who manage to
+distribute bogus sites files from taking over their victim's machines.
 
-value is item[,item...]
+The distributed 'sites' file is read one line at a time. Each line
+consists of a keyword followed by other information. It defines a
+number of VPNs; within each VPN it defines a number of locations;
+within each location it defines a number of sites. These VPNs,
+locations and sites are turned into a secnet.conf file fragment using
+a script.
 
-item can be "string", number, path (looks up in dictionary),
-{dictionary}, value(value), value{dictionary}.  If item is a list it
-is copied into the list - we can't have lists of lists.
+Some keywords are valid at any 'level' of the distributed 'sites'
+file, indicating defaults.
 
-A path is [/]key[\[index\]][/key[\[index\]]...], defining a lookup
-from the current dictionary (or parents) or the root. If a key refers
-to a list of more than one item then an index number (base 0) in
-square brackets can be used to specify the list item number.
+The keywords are:
 
-Items of the form value1(value2) invoke executable value1 with an
-argument of value2. The return value can be a string or dictionary,
-but not a list. (Invocation happens after the entire configuration
-file has been read.)
+vpn n: we are now declaring information to do with VPN 'n'. Must come first.
 
-Items of the form value{dict} invoke executable value with an argument
-of a single-element list, containing dict. It's just syntactic sugar
-for value({dict}).
+location n: we are now declaring information for location 'n'.
 
+site n: we are now declaring information for site 'n'.
+endsite: we're finished declaring information for the current site
 
-When a key is used (rather than defined) it is looked up in the
-current dictionary, and if it isn't found it is looked up in the
-(lexical) parent, until the root is reached. 
+restrict-nets a b c ...: restrict the allowable 'networks' for the current
+  level to those in this list.
+end-definitions: prevent definition of further vpns and locations, and
+  modification of defaults at VPN level
 
+dh x y: the current VPN uses the specified group; x=modulus, y=generator
 
+hash x: which hash function to use. Valid options are 'md5' and 'sha1'.
 
+admin n: administrator email address for current level
 
-What sorts of crypto-related things do we need to define?
+key-lifetime n
+setup-retries n
+setup-timeout n
+wait-time n
+renegotiate-time n
 
-sources of randomness
-block algorithms
-block cipher modes?
-hash functions
-padding functions
-public key signature algorithms
-public key crypto key stores
-key setup algorithms
+address a b: a=dnsname, b=port
+networks a b c ...
+pubkey x y z: x=keylen, y=encryption key, z=modulus
+mobile: declare this to be a 'mobile' site
 
+** Logging etc.
+
+There are several possible ways of running secnet:
+
+'reporting' only: --version, --help, etc. command line options and the
+--just-check-config mode.
+
+'normal' run: perform setup in the foreground, and then background.
+
+'failed' run: setup in the foreground, and terminate with an error
+before going to background.
+
+'reporting' modes should never output anything except to stdout/stderr.
+'normal' and 'failed' runs output to stdout/stderr before
+backgrounding, then thereafter output only to log destinations.
 
 ** Protocols
 
@@ -111,8 +174,9 @@ quite stable so the feature doesn't gain us much.
 
 Definitions:
 
-A is the originating gateway machine
-B is the destination gateway machine
+A is the originating gateway machine name
+B is the destination gateway machine name
+A+ and B+ are the names with optional additional data, see below
 PK_A is the public RSA key of A
 PK_B is the public RSA key of B
 PK_A^-1 is the private RSA key of A
@@ -130,16 +194,86 @@ i? is appropriate index for receiver
 Note that 'i' may be re-used from one session to the next, whereas 'n'
 is always fresh.
 
+The optional additional data after the sender's name consists of some
+initial subset of the following list of items:
+ * A 32-bit integer with a set of capability flags, representing the
+   abilities of the sender.
+ * In MSG3/MSG4: a 16-bit integer being the sender's MTU, or zero.
+   (In other messages: nothing.)  See below.
+ * More data which is yet to be defined and which must be ignored
+   by receivers.
+The optional additional data after the receiver's name is not
+currently used.  If any is seen, it must be ignored.
+
+Capability flag bits must be in one the following two categories:
+
+1. Early capability flags must be advertised in MSG1 or MSG2, as
+   applicable.  If MSG3 or MSG4 advertise any "early" capability bits,
+   MSG1 or MSG3 (as applicable) must have advertised them too.  Sadly,
+   advertising an early capability flag will produce MSG1s which are
+   not understood by versions of secnet which predate the capability
+   mechanism.
+
+2. Late capability flags are advertised in MSG2 or MSG3, as
+   applicable.  They may also appear in MSG1, but this is not
+   guaranteed.  MSG4 must advertise the same set as MSG2.
+
+No capability flags are currently defined.  Unknown capability flags
+should be treated as late ones.
+
+
+MTU handling
+
+In older versions of secnet, secnet was not capable of fragmentation
+or sending ICMP Frag Needed.  Administrators were expected to configure
+consistent MTUs across the network.
+
+It is still the case in the current version that the MTUs need to be
+configured reasonably coherently across the network: the allocated
+buffer sizes must be sufficient to cope with packets from all other
+peers.
+
+However, provided the buffers are sufficient, all packets will be
+processed properly: a secnet receiving a packet larger than the
+applicable MTU for its delivery will either fragment it, or reject it
+with ICMP Frag Needed.
+
+The MTU additional data field allows secnet to advertise an MTU to the
+peer.  This allows the sending end to handle overlarge packets, before
+they are transmitted across the underlying public network.  This can
+therefore be used to work around underlying network braindamage
+affecting large packets.
+
+If the MTU additional data field is zero or not present, then the peer
+should use locally-configured MTU information (normally, its local
+netlink MTU) instead.
+
+If it is nonzero, the peer may send packets up to the advertised size
+(and if that size is bigger than the peer's administratively
+configured size, the advertiser promises that its buffers can handle
+such a large packet).
+
+A secnet instance should not assume that just because it has
+advertised an mtu which is lower than usual for the vpn, the peer will
+honour it, unless the administrator knows that the peers are
+sufficiently modern to understand the mtu advertisement option.  So
+secnet will still accept packets which exceed the link MTU (whether
+negotiated or assumed).
+
+
 Messages:
 
-1) A->B: *,iA,msg1,A,B,nA
+1) A->B: *,iA,msg1,A+,B+,nA
 
-2) B->A: iA,iB,msg2,B,A,nB,nA
+i* must be encoded as 0.  (However, it is permitted for a site to use
+zero as its "index" for another site.)
+
+2) B->A: iA,iB,msg2,B+,A+,nB,nA
 
 (The order of B and A reverses in alternate messages so that the same
 code can be used to construct them...)
 
-3) A->B: {iB,iA,msg3,A,B,nA,nB,g^x mod m}_PK_A^-1
+3) A->B: {iB,iA,msg3,A+,B+,[chosen-transform],nA,nB,g^x mod m}_PK_A^-1
 
 If message 1 was a replay then A will not generate message 3, because
 it doesn't recognise nA.
@@ -147,7 +281,7 @@ it doesn't recognise nA.
 If message 2 was from an attacker then B will not generate message 4,
 because it doesn't recognise nB.
 
-4) B->A: {iA,iB,msg4,B,A,nB,nA,g^y mod m}_PK_B^-1
+4) B->A: {iA,iB,msg4,B+,A+,nB,nA,g^y mod m}_PK_B^-1
 
 At this point, A and B share a key, k. B must keep retransmitting
 message 4 until it receives a packet encrypted using key k.
@@ -172,23 +306,63 @@ retransmit or confirm reception. It is suggested that this message be
 sent when a key times out, or the tunnel is forcibly terminated for
 some reason.
 
-8) i?,i?,NAK/msg8
+**** Protocol sub-goal 3: send a packet
+
+8) i?,i?,msg0,(send-packet/msg9,packet)_k
+
+**** Other messages
+
+9) i?,i?,NAK (NAK is encoded as zero)
 
 If the link-layer can't work out what to do with a packet (session has
-gone away, etc.) it can transmit a NAK back to the sender.  The sender
-can then try to verify whether the session is alive by sending ping
-packets, and forget the key if it isn't. Potential denial-of-service
-if the attacker can stop the ping/pong packets getting through (the
-key will be forgotten and another key setup must take place), but if
-they can delete packets then we've lost anyway...
+gone away, etc.) it can transmit a NAK back to the sender.
 
-The attacker can of course forge NAKs since they aren't protected. But
-if they can only forge packets then they won't be able to stop the
-ping/pong working. Trust in NAKs can be rate-limited...
+This can alert the sender to the situation where the sender has a key
+but the receiver doesn't (eg because it has been restarted).  The
+sender, on receiving the NAK, will try to initiate a key exchange.
 
-Alternative idea: if you receive a packet you can't decode, because
-there's no key established, then initiate key setup...
+Forged (or overly delayed) NAKs can cause wasted resources due to
+spurious key exchange initiation, but there is a limit on this because
+of the key exchange retry timeout.
 
-**** Protocol sub-goal 3: send a packet
+10) i?,i?,msg8,A,B,nA,nB,msg?
+
+This is an obsolete form of NAK packet which is not sent by any even
+vaguely recent version of secnet.  (In fact, there is no evidence in
+the git history of it ever being sent.)
+
+This message number is reserved.
+
+11) *,*,PROD,A,B
+
+Sent in response to a NAK from B to A.  Requests that B initiates a
+key exchange with A, if B is willing and lacks a transport key for A.
+(If B doesn't have A's address configured, implicitly supplies A's
+public address.)
+
+This is necessary because if one end of a link (B) is restarted while
+a key exchange is in progress, the following bad state can persist:
+the non-restarted end (A) thinks that the key is still valid and keeps
+sending packets, but B either doesn't realise that a key exchange with
+A is necessary or (if A is a mobile site) doesn't know A's public IP
+address.
+
+Normally in these circumstances B would send NAKs to A, causing A to
+initiate a key exchange.  However if A and B were already in the
+middle of a key exchange then A will not want to try another one until
+the first one has timed out ("setup-time" x "setup-retries") and then
+the key exchange retry timeout ("wait-time") has elapsed.
+
+However if B's setup has timed out, B would be willing to participate
+in a key exchange initiated by A, if A could be induced to do so.
+This is the purpose of the PROD packet.
+
+We send no more PRODs than we would want to send data packets, to
+avoid a traffic amplification attack.  We also send them only in state
+WAIT, as in other states we wouldn't respond favourably.  And we only
+honour them if we don't already have a key.
 
-9) i?,i?,msg0,(send-packet/msg9,packet)_k
+With PROD, the period of broken communication due to a key exchange
+interrupted by a restart is limited to the key exchange total
+retransmission timeout, rather than also including the key exchange
+retry timeout.