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$