This file, INSTALL, is a -*- text -*- file tutorial on how to * install userv ipif and udptunnel, * configure them to create a VPN tunnel between two hosts or networks, or * use udptunnel-reconf to create a multi-site VPN. See README for details of other available documentation. BUILD AND INSTALLATION INSTRUCTIONS ----------------------------------- 1. Install userv, 1.0.1 or later. This is in Debian GNU/Linux. 2. Make sure your Linux kernel has SLIP and CSLIP compiled in. You will need to be using Linux 2.2 (with Unix98-style ptys). 3. udptunnel works best if your ssh can do ssh-protocol-level keepalives. Currently these are only supported by using a special patch, which can be found (for various OpenSSH versions) at ftp.chiark.greenend.org.uk:/users/ian/openssh+protocolkeepalives. Pre-compiled Debian packages are available there too. 4. Obtain a fresh copy of userv-utils, if you haven't already. cd to ipif, and run `make' and (as root) `make install'. After you have done this the software will still not do anything, and by default userv ipif will not allow anyone (except root) to create network interfaces. The software will probably only work on Linux - in particular, userv ipif's service program (service.c) uses Linux-specific ways of setting up SLIP interfaces. It might be possible in principle to create alternatives for other platforms. `slattach' problem: There is a problem with some versions of `slattach' on Linux. If you see a message from it about being unable to open /dev/2 or some such, then you need to upgrade or patch your `slattach'. In Debian GNU/Linux it's in the `netbase' package, and the fix is in Debian 2.1 in 3.16-3 and later; however the bug has regressed, and is known to be in Debian 2.2's 3.18-4 and earlier. The relevant Debian bug reports are #45515 (now closed) and #45944. A patch to correct 3.18-4 is provided here as `slattach.diff', and a fixed binary is available from me. UDPTUNNEL SETUP TUTORIAL ------------------------ 1. BACKGROUND INFORMATION Firstly, note that userv ipif and udptunnel are extremely flexible, as they aim to be `Lego brick' networking components. Many much more interesting configurations can be constructed than there is room to document here. If you want to do something strange, consult the README to locate the appropriate reference documentation. 1.1. About udptunnel udptunnel is point-to-point; you need a separate `invocation' for each pair of machines (or networks) you wish to connect. It is `one-shot': it will set up a tunnel and keep it going as long as it can, and then exit; if you want a permanent tunnel you must arrange to reinvoke udptunnel. It is asymmetric, in that one of the endpoints starts the tunnel, and the other sits and waits to be contacted. We'll call the active endpoint `alice' and the passive endpoint `bob'. Usually alice invokes udptunnel on bob via OpenSSH (`ssh'). udptunnel does not need root privilege to run. However, you do need to configure userv ipif to know that the user who will be running udptunnel is permitted to use the IP addresses and network ranges which will be used. So, though most of the configuration can be done as the normal users who will run udptunnel on each end, a small amount (editing /etc/userv/ipif-networks) needs to be done as root on each end - and the information configured as root needs to match up This tutorial will explain how to do these things. 1.2. About point-to-point tunnelling in general A tunnel is an _additional_ (in the case of udptunnel, encrypted) network link between a pair of machines. Packets are encapsulated at one end, sent over the real network between them, and decoded again at the other end. As with any network connection, it is possible to arrange for networks behind the endpoint machines to be able to communicate via the tunnel. Each endpoint machine will have at least two network interfaces: Firstly, the real `physical' interface through which the encapsulated packets will be really sent and received. Secondly, the `virtual' interface created by the tunnelling software, which represents its end of the (encrypted) tunnel link. The physical and virtual interfaces MUST have different addresses. Each endpoint machine may also have additional network interfaces; for example, it may be the router for a network which sits behind it, which an interface on that network, or it may be the endpoint for more than one tunnel. It is OK for several tunnels terminating at the same machine to use the same virtual address (provided that the tunnels are not `layered' on top of each other but are `in parallel'), and it is also OK to use as the virtual tunnel address a router's address on a private network which will be sent via the tunnel. 1.3. Diagram ____ ______________ ______________ ____ __( )__ |ALICE | | BOB| __( )__ ,' ` ' `. | _ | Tunnel | _ | ,' ` ' `. | alice | | |\\ ,- - - - - - - - - -. //| | | bob | `._private _.' | | || | | || | | `._private _.' | networks |==+--------'|| | Public | ||`--------+==| networks | | | | alice | Network | bob | | | `.~ ~.' | virtual +=============+ virtual | `.~ ~.' (__,'`.__) |______________|alice bob|______________| (__,'`.__) physical physical _ Key: HOSTNAME +===+ Actual Network |\\ Tunnel Descriptive Text ----- Data Flow | ||Endpoint host or network number - - - Encrypted Data Flow || 2. INFORMATION COLLECTION AND PRELIMINARY SETUP You will need to collect and/or decide upon various information, and make sure that your two endpoint systems can talk to each other over the public network. 2.1. Find out, or choose, private network numbers You need to make sure you know what all of the addresses in the above diagram are going to be. Usually you must choose the private and virtual addresses yourself: hosts on the private networks usually won't communicate with the global Internet other than through proxies or masquerading firewalls. You MUST choose from the reserved ranges in RFC1918, which are: 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 If you do not do so you'll end up reusing someone else's addresses, which can cause lots of hard-to-diagnose and embarrasing problems. You should CHOOSE RANDOMLY ! This makes sure that when you decide to connect your VPN to someone else's VPN, your network allocation numbers are unlikely to clash. If you both choose 192.168.0.0/24 you'll have to renumber (and will look like fools). To help with choosing random network numbers from RFC1918 space, the author maintains a web page at , which can pick network numbers for you. Additionally, there is a database there - people in Cambridge (in England) are encouraged to register their network address usage there. Please do not register in the database unless you're likely to want to connect your VPN to others already listed. 2.2. Find out, or choose, public network numbers These are usually specified by your ISP, either statically or dynamically assigned. If the active end (`alice physical') is dynamically assigned you can use the `Wait' option (see below) to avoid specifying it, but otherwise you will need to have some kind of script to find it each time you invoke udptunnel, or use a hostname which automatically tracks the source host using dynamic DNS. In some situations you may find yourself using a `public network' which is not actually the public Internet - for example, you may want to run one tunnel `through' another, or your `public network' is actually a `private', but not sufficiently secure, radio LAN. In this case you'll have to choose the addresses to use from RFC1918-space, as above. 2.3. Decide which user account(s) on alice and bob you will use These user accounts will see the plaintext for all network packets going over the tunnel and if compromised will be able steal or forge tunnel traffic. So, they should be reasonably secure. Let us assume that the account on alice is called Tbob, and the account on bob is called Talice. (NB that your system may not correctly handle usernames containing uppercase.) Each account should be in a group of its own, which will be used for the userv ipif access control. Arrange that Tbob@alice can ssh to Talice@bob without needing a passphrase or other user interaction. (Obviously, if you need to create accounts, edit groups, or change the sshd configuratioon, you may need to be root.) 2.4. Decide whether to use `udptunnel-reconf' There are two ways to set up a tunnel with udptunnel. Either you can simply give udptunnel the right command, by putting it in an appropriate script and arranging it to be called, or you can have a program `udptunnel-reconf' read some configuration files and do it for you. udptunnel-reconf is not as well documented, but its behaviour is somewhat more `cooked'. It is especially useful if you need to maintain many tunnels as part of an organised, multi-site, VPN. Using udptunnel directly is somewhat more flexible, and may be easier if you only want one tunnel. 3. SETUP INSTRUCTIONS - USING UDPTUNNEL-RECONF Edit or create the following files, as root: /etc/userv/vpn/sites /etc/userv/vpn/tunnels /etc/userv/vpn/global Run udptunnel-reconf, as root. This will create: /var/lib/userv/vpn/passive-sites /var/lib/userv/vpn/active-sites /var/lib/userv/vpn/command. It will also spit out to stdout two things: firstly, a list of suggested commands to put in your inittab, and secondly a suggested line to put in your /etc/userv/ipif-networks. Test that your setup is working, by running (one of) the /var/lib/userv/vpn/command. file(s) by hand - see section 5. If it works, you can put the relevant things in your inittab and say `init q'. To find out what all the configuration settings do, look at /usr/local/share/userv/udptunnel-vpn-defaults, which contains the default settings and shows where all the hooks are. Consult section 4 of this file to understand what the options to udptunnel do. 4. SETUP INSTRUCTIONS - INVOKING UDPTUNNEL DIRECTLY All of these steps can be done using the appropriate normal user accounts, unless otherwise indicated. 4.1. Configure the private network numbers in /etc/userv/ipif-networks (This step needs to be done as root.) On alice, in /etc/userv/ipif-networks, put ,=/32, , ,/32, , and for each of bob's private networks ,/, , You can leave out the /32 line if bob's virtual address is in one of bob's private networks. On bob, do the corresponding. In /etc/userv/ipif-networks, put ,=/32, , ,/32, , and for each of alice's private networks ,/, , Again, you can leave out if one of the virtual networks covers it. All the specifications in /etc/userv/ipif-networks must be numerical addresses - hostnames are not allowed. Also, the /32 indicating a specific host cannot be omitted. Note the use of `=' for each host's own virtual address, which indicates to userv ipif that it's OK for that gid to create a local interface with that address, but the address may not be assigned to a remote host or route. 4.2. Construct the udptunnel invocation (on alice) udptunnel has a long and complicated command line, rather than a configuration file. The best way to deal with this is to create a shell script which runs udptunnel with the right options. This script will live on alice in ~Tbob, and be run by Tbob. Let us call it `udptunnel-invoke-bob'. For the most basic setup, it should look something like this: #!/bin/sh set -e set -x udptunnel \ -e nonce -e timestamp/10/30 \ -e pkcs5/8 -e blowfish-cbcmac/128 -e blowfish-cbc/128 \ ,Any \ ,Command \ ,,1000,cslip \ 30,130,1800 \ \ ssh -o 'BatchMode yes' \ -v @ \ udptunnel You have to fill in the right values for things in angle brackets. (See also section 6. for a moderately complex example, below.) 4.4.1. Syntax of and These arguments to udptunnel are the network address ranges at each end which are to be connected via the tunnel. Let us consider just ; is just the same, but for bob's end. is a comma-separated list of networks specified as /. The network address must be numerical, and the prefix length must always be specified. If there are no private networks `behind' alice, ie the tunnel is just to connect alice to bob and things at bob's end, then specify `-' for . 4.4.2. IP masquerading (NAT) at alice's end If alice is behind a masquerading (NAT) firewall, you can still get it to work. You need to add an option `-m' before the other arguments. This will make udptunnel on alice tell udptunnel on bob to wait for alice's first encapsulated packet before deciding what alice's physcial address and port number are, as seen by bob. That way alice doesn't need to know what port number the NAT proxy will use. 4.4.3. Using fixed UDP port numbers (eg to make firewally happy) If alice is behind a firewall which will not allow incoming UDP to arbitrary ports, even when sent in reply to packets of alice's, you have to arrange for alice to use a fixed port number. Change ,Any \ to , \ udptunnel will need to be able to bind to the relevant port, so you must either (i) choose a port number over 1024, which risks other processes on alice accidentally using that port, (ii) run udptunnel as root on alice, or (iii) use authbind (authbind is a utility, included in Debian, which can allow non-root programs to bind to low ports in a controlled way). If bob is behind such a firewall too, you can replace ,Command \ with , \ 4.4.4. Clock skew and excessive delay The default configuration given above, which includes this -e nonce -e timestamp/10/30 \ will not work if there is more than 10s of clock skew between alice and bob's system clocks, or if the lag in either direction is more than 30s. It is best if your systems run with synchronised clocks (you can run NTP over the tunnel if necessary) and don't have such bad lag, of course. However, you can increase these parameters if you really want. To increase the tolerance to clock skew to some amount, make sure that both numbers are at least the amount of clock skew you're willing to tolerate. To increase the tolerance to delay it's only necessary to increase the second number. Warning: if you increase these numbers too much there is a risk that packets delayed or repeated by an attacker will be treated as genuine and cause communication or security problems. I would not recommend using a value more than 120 (2 minutes). If you really can't get reasonable clock synch at all, you can use sequence number replay detection instead of clock-based replay detection. Replace -e nonce -e timestamp/10/30 \ with -e sequence \ 4.4.5. Other things to tweak (it's usually safe to ignore this part) Do not mess with the `-e' parameters and arguments except as explained above, unless you are a cryptographer. 30,130,1800 are timeouts which control the `dead tunnel detection'. The first is the keepalive interval: when one end hasn't sent anything for that many seconds, it will send an empty keepalive packet. The second is the dead tunnel timeout: when one end hasn't received anything for that many seconds, it assumes the tunnel is dead and dies (the other end will then usually die shortly if it hasn't already). The third is the status reporting interval - at intervals of that many seconds each end will report (to udptunnel's stdout) that the tunnel is still open and give some statistics; these diagnostics also prevent the controlling ssh connection's entry in masquerading and firewall tables from timing out. 1000 (in ...,...,1000,cslip) is the MTU - the maximum size of packet which will be sent through the tunnel. It is best if this number is a certain amount smaller than the path MTU over the physical network, so that encapsulated packets do not get fragmented. (Each packet will be increased in size by 24 bytes + the size of a UDP and IP header + the effects of SLIP duplication of certain bytes.) 4.5. Testing your script After you've written your script, you should run it to see if it works. See section 5 for details. 4.6. Configure the tunnel to run automatically Now that the tunnel works if you invoke it by hand, it is time to arrange to run it automatically. If you want the tunnel to run over a dialup link only when the dialup link is up, then I'm afraid you'll have to arrange to start and kill it yourself, probably. I haven't set up such a configuration. More information about this for this document, if you manage to do it, would be good. So, I shall assume that you want the tunnel to be up all of the time (or at least, as much as possible). The best way to do this is to run it from `init', by setting it up in inittab. For example, you could put something like this in your inittab: t0:23:respawn:su Tbob -c ./udptunnel-invoke-bob 2>&1 | logger -p local2.info -t tunnel-bob (Note that if you have more than one tunnel the `id' field, at the start of the inittab line, must be different for each one.) This would use `su' to become bob and run the actual tunnelling software, and arrange for the diagnostic output to be sent to syslog with facility `local2' and priority `info', tagged with `tunnel-bob'. With an appropriate line in /etc/syslog.conf, such as local2.* /var/log/local2-all.log (remember that you have to use tabs in syslog.conf) this will produce, in /var/log/local2-all.log, all the diagnostics, including reassuring messages like this: Sep 18 00:27:48 alice tunnel-bob: udptunnel-forwarder: alice: tunnel still open: received 5262 packets, 5262 bytes Sep 18 00:28:44 alice tunnel-bob: udptunnel-forwarder: bob: tunnel still open: received 5280 packets, 5280 bytes 5. TESTING YOUR UDPTUNNEL INVOCATION SCRIPT 5.1. Invocation Log into alice as Tbob, and run ./udptunnel-invoke-bob. A great deal of diagnostic output will ensue. If all is well you will see two messages looking something like this udptunnel-forwarder: bob: tunnel open with peer 127.0.0.3:76543 udptunnel-forwarder: alice: tunnel open and the session will just sit there. This means it thinks it's working; go on to section 5.2. If it didn't say that, here are some debugging tips: * If it just sits there for a minute or two and then udptunnel times out, the physical packets aren't getting back and forth. Use tcpdump, check your firewall and routing (as below), and consult the sections above about NAT and firewalls. * If it bombed out, look for an error message in the diagnostics. There will be lots of `subprocess somethingorother exited with nonzero exit status 47', `no details received from remote' and the like, but these are probably not the ones you want to look at, because they're usually just consequences of some other failure. Permission denied. udptunnel - alice: fatal error: remote command failed (code ...) Tbob had trouble ssh'ing to Talice@bob. Check that the ssh configuration is set up, and test it separately. userv-ipif service: access denied for ...., .... udptunnel - alice: subprocess local command failed with code 2048 The arguments to udptunnel don't correspond to /etc/userv/ipif-networks on alice. Either the arguments to udptunnel or the ipif-networks file is wrong. (Or, if the message about `local command failed' mentions bob, look on bob.) udptunnel - alice: subprocess forwarder failed with code 14 The tunnel timed out - no packets were successfully received for 130 seconds. See 2.4.5 above for details of the timeout parameters. (NB, applies to `code 14' only.) usage errors from udptunnel or ssh, or sh: ...: unknown command Perhaps you dropped a \ from the udptunnel-invoke-bob script ? udptunnel not found, udptunnel-forwarder not found Check that the PATH includes /usr/local/bin. Noninteractive `ssh' invocations (ie, ones with a command specified) often have a different PATH. slattach cannot open /dev/2 (or similar messages) Your slattach is buggy. See under `slattach problem' in the build and installation instructions, above. slattach cannot change line discipline (or some other weird message) Check whether your kernel is compiled with SLIP and/or CSLIP support. * Other messages: udptunnel-forwarder: alice: bad packet: blowfish-cbcmac: verify failed This can be caused by actual packet corruption on the physical network (or even by an actual hostile attack), but when using fixed port numbers these messages are common after the tunnel has died and been restarted: they correspond to packets from the previous invocation (which is usung different keys) being rejected because their checksums don't match. In this case they should go away in a minute or two. 5.2. Testing, once the tunnel claims to be working In another session on alice, you should be able to ping bob's virtual interface. If this works, test pinging between hosts on the private networks behind alice and bob. If all is well, go onto step 4. If not, here are some troubleshooting hints: * Use numerical addresses when testing. This eliminates DNS problems from your test strategy. * Use `ifconfig' and `route -n' on alice and bob to check that the interfaces and routes all look right. The tunnel will show up as a `sl' for some . * Use `tcpdump -n -i ' to watch the traffic go across some interface, to try to figure out where the traffic is going. Look both for the private traffic before it goes into the tunnel, and the physical traffic, to try to find out where it disappears. The diagnostics will tell you which physical ports it's using, something like this: udptunnel - alice: debug: using remote Wait,Wait local 131.111.232.108,1422 udptunnel - bob: debug: using remote 131.111.232.108,1422 local 195.224.38.6,2413 * alice and bob can see each other but the private networks can't ? Make sure alice and bob both have IP forwarding enabled. * Check your firewalls, if you have them. It's most helpful if your firewall configuration arranges to log rejected packets - without that, they can be a complete pain to debug. 6. DNS, firewall, mail, etc. When you have IP level connectivity between your two networks, you must also arrange for: * An appropriate firewall on each tunnel endpoint (to stop attacks from one network to another) and also at all the borders of each network (to stop traffic that is going to, or looks like it came from, the private networks). * DNS configuration so that hosts on both sides of the tunnel can see each other's names, addresses and other information. * Mail, news and other application protocols may need to be configured to use the private tunnel connectivity, rather than treating the other private network's names as being `elsewhere' and using unencrypted connectivity via the global Internet. How to do these things is beyond the scope of this document. 7. Example This example is the tunnel between chiark and Relativity. I'll quote it and explain the details, below. See also the comment at the top of udptunnel. authbind udptunnel \ -m \ -e nonce -e timestamp/10/30 -e pkcs5/8 \ -e blowfish-cbcmac/128 -e blowfish-cbc/128 \ davenant-external,410 \ chiark-public,Command \ 172.31.80.6,172.31.80.9,1000,cslip \ 30,120,1800 \ - 172.18.45.0/24 \ ssh -o 'ForwardAgent no' -o 'ForwardX11 no' \ -o 'BatchMode yes' \ -i ~ian/.ssh/identity -l ian \ -v chiark.greenend.org.uk \ udptunnel Because at Relativity the tunnel endpoint has to not be our firewall, because the firewall is a 386SX/16 and so not powerful enough, Relativity practically has to be the active partner in any tunnels it is involved in. This also necessitates the use of the `-m' option and various other things. Exposition of the example udptunnel invocation: > authbind udptunnel \ `authbind' is used because at Relativity the tunnel endpoint address has to be on a fixed port because our tunnel endpoint is not on the firewall system (if it's not on a fixed port we can't write a good firewall rule to let it through). The port we are using is port 410, a low port to prevent other processes `stealing' it, so root privilege or authbind is needed. > -m \ -m tells this invocation of udptunnel that its endpoint address and port (for encapsulated packets) are going to be NATted before the far end sees them. The effect is that instead of supplying this information to the far end, the far end is told to `wait and see'. This should not usually be used in other circumstances. (For full details see the comment at the top of udptunnel.) > -e nonce -e timestamp/10/30 -e pkcs5/8 \ > -e blowfish-cbcmac/128 -e blowfish-cbc/128 \ This is the crypto configuration. > davenant-external,410 \ This is the local physical address and port. davenant is the tunnel endpoint, and davenant-external is its public address (we run two networks on the wire at Relativity, an internal one and a public one). > chiark-public,Command \ This is the physical remote address and port. `Command' means find out the remote physical address or port by having udptunnel at the far end print its address and port when they have been allocated. Another possibility here is to use a fixed remote port number. The DNS at GR is configured so that just `chiark' means chiark via the tunnel, so we have to use chiark-public which means its public IP address. > 172.31.80.6,172.31.80.9,1000,cslip \ 172.31.80.6 is davenant's virtual address. 172.31.80.9 is chiark's virtual address for the Relativity tunnel. > 30,130,1800 \ These are the timing parameters. > - 172.18.45.0/24 \ No remote virtual networks are reachable via chiark. 172.18.45.0/24 is the Relativity house ethernet, which is to be reachable via the tunnel from chiark. > ssh -o 'ForwardAgent no' -o 'ForwardX11 no' \ > -o 'BatchMode yes' \ > -i ~ian/.ssh/identity -l ian \ > -v chiark.greenend.org.uk \ > udptunnel This is the ssh invocation to run udptunnel at the far end. At Relativity we put the udptunnel invocation in a file and run it out of inittab, like this: t0:235:respawn:/usr/local/sbin/really -u ian /usr/local/sbin/udptunnel-invoke 2>&1 | logger -p local2.info -t tunnel-chiark 8. Copyright notice Copyright (C) 1999-2000,2003 Ian Jackson This file is part of ipif, part of userv-utils This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with userv-utils; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id$