X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=ipif%2Fudptunnel;h=963245c49f01e326e097e98cf027a0b46993df86;hb=70b9d2e0dbecb8fe1e2045a1752465cd35885bb0;hp=e52ee73bad0cdb846a1fda77df601a0012c76393;hpb=0f4b558c78aae6fda9f52287e1b53483e9435903;p=userv-utils.git diff --git a/ipif/udptunnel b/ipif/udptunnel index e52ee73..963245c 100755 --- a/ipif/udptunnel +++ b/ipif/udptunnel @@ -1,78 +1,115 @@ #!/usr/bin/perl -# Simple tunnel for userv-ipif tunnels. +# Encrypting VPN tunnel for use with userv-ipif. +# +# This comment is reference documentation. See ipif/INSTALL for the +# installation instructions and setup tutorial. # # usage: -# udptunnel -# [ -l[] ... . +# To make a tunnel between two machines `alice' and `bob', +# on `alice', the active endpoint, run: +# +# udptunnel +# [ -l[] ... . # | -e [/...] -# | -m (`masquerade support': subcommand gets `Wait' instead of our addr/port) -# | -d (`dump keys': when no subcmd, spew keys rather than reading them; -# we always send keys to our subcmd if there is one) +# | -m (`masquerade support': bob gets `Wait' instead of our addr/port) +# | -d (`dump keys': when no peer, spew keys rather than reading them; +# we always send keys to our peer if there is one) # | -Dcrypto (debug crypto - use with care, prints keys, packets &c on screen!) # | -f # ... # ] -# , -# , -# ,,, -# , -# -# [ [ ...] ] +# , +# , +# ,,, +# ,[,] +# +# [ [ ...] ] +# +# This will run udptunnel-forwarder on alice, and use +# (usually an ssh invocation) to run udptunnel appropriately on bob. +# Key material will be generated by alice and fed to udptunnel on bob +# via 's stdin, and the physical address and port on bob +# will be (if so configured) returned via 's stdout. +# +# The tunnel will stay up until one of the subprocesses involved dies, +# or the keepalive timeout expires. If you want the tunnel to remain +# up permanently, you must arrange to invoke it repeatedly (eg, from +# inittab). See INSTALL. # -# proto may be slip or cslip +# may be slip or cslip # -# Any <..-addr> may also be hostname +# will be the MTU of the tunnel interfaces; it is best if this +# is enough smaller than the path MTU between the physical interfaces +# that the encapsulated packets will fit without fragmentation. # -# Local addr's and ports may also be: +# Any <..-addr> supplied to udptunnel may also be hostname; these will +# all be looked up on alice and IP addresses passed to bob. +# +# The `local' physical address and ports (ie, alice's own details), +# may have these special values: +# `Any' choose one ourselves and do not print it (the port chosen +# will be supplied to bob) # `Print' choose one ourselves and print both port and addr -# `Any' choose one ourselves and do not print it -# Remote addr's and ports may also be: -# `Wait' wait to receive a packet before assigning address -# `Command' run a subcommand and wait for it to tell us the values -# When any addr or port is `Command' then must be specified. +# (this is not usually useful specified directly; it's +# used by udptunnel when it invokes itself on bob via +# , to have its other self print the +# relevant value. # -# If is specified it should run udptunnel at the -# remote end; it will be invoked as -# [ <-e arguments passed along> ] -# , -# , -# ,,, -# , -# +# The `remote' physical address and port (ie, on alice, bob's details), +# may also have the special values: +# `Command' wait for to tell us the values (this is +# usually the right choice on alice for at least the +# port). must be specified (ie, this +# only makes sense on alice). +# `Wait' alice will wait to receive a packet from bob and use +# whatever address and port it came from # - -# If it was given Print for , this command's first -# stdout output should be the real -# , pair (and of course this -# udptunnel's output will be). It may then produce more stdout which, -# if any, will be forwarded to the local end's stdout as debugging info. +# These special values are case-sensitive. When alice runs udptunnel +# on bob they are automatically translated to appropriate other values +# in the arguments to bob's udptunnel. +# +# If is specified it should run udptunnel at the +# bob end; it will be invoked as +# [ ... ] +# [ <-e arguments passed along> ] +# , +# , +# ,,, +# ,[,] +# # -# After this, if any encryption was specified, the encryption -# parameters will be fed into its stdin. See the documentation in the -# mech-*.c files for details of the parameters. udptunnel will -# arrange to feed the keys fd of udptunnel-forwarder into the stdin of -# the remote command. +# If it was given Print for , udptunnel's first stdout +# output will be the real , pair. It +# may then produce more stdout which, if any, will be forwarded to the +# local end's stdout as debugging info. # -# is as follows: -# -# actual addr/port that addr/port -# `Command' `Print' -# `Wait' `Any' +# After this, if any encryption was specified, the encryption key +# material will be fed into its stdin. See the documentation in the +# mech-*.c files for details of the parameters. udptunnel on alice +# will arrange to feed the keys fd of udptunnel-forwarder into the +# stdin of the udptunnel on bob. # -# is as follows: -# -# (-m not specified) (-m specified) +# is as follows: +# +# actual addr/port that addr/port +# `Command' `Print' +# `Wait' `Any' +# +# is as follows: +# +# (-m not specified) (-m specified) # actual addr/port that addr/port `Wait' -# `Wait' the chosen address `Wait' # `Print' the chosen address `Wait' +# `Any' `Wait' for addr, `Wait' +# chosen port for port # -# udptunnel will userv ipif locally, as -# userv root ipif ,,, -# +# In each case udptunnel will run userv ipif locally, as +# userv root ipif ,,, +# # or, if -l was given, userv root ipif is replaced with the argument(s) # following -l option(s) until `.'. # -# udptunnel will also run udptunnel-forwarder with appropriate options +# udptunnel will also run udptunnel-forwarder with appropriate options. # # recommended encryption parameters are: # -e nonce (prepend 32 bit counter) @@ -80,7 +117,10 @@ # -e pkcs5/8 (pad as per PKCS#5 to 8-byte boundary) # -e blowfish-cbcmac/128 (prepend CBC MAC with random IV and 128 bit key) # -e blowfish-cbc/128 (encrypt with CBC, random IV and 128 bit key) -# where is perhaps 10 and perhaps 30. +# where is perhaps 10 and perhaps 30. If your +# clocks are not sufficiently well synchronised, you could replace +# `-e nonce -e timestamp/...' with just `-e sequence'. Do not just +# remove `-e timestamp/...'. # Copyright (C) 1999-2000 Ian Jackson # @@ -166,8 +206,6 @@ sub arg_value ($$) { return shift @ARGV; } -$|=1; - @lcmd= (); @encryption= (); $masq= 0; @@ -189,7 +227,7 @@ while ($ARGV[0] =~ m/^-/) { $encrarg= arg_value($_,'-e'); push @remoteopts, "-e$encrarg"; @thisencryption= split m#/#, $encrarg; - $thisencryption[0] =~ s/^/\!/; + $thisencryption[0] =~ s/^/\|/; push @encryption, @thisencryption; } elsif (s/^-m/-/) { $masq= 1; @@ -224,8 +262,16 @@ m/^([.0-9]+),([.0-9]+),(\d+),(slip|cslip)$/ ($lva,$rva,$mtu,$proto) = ($1,$2,$3,$4); $_= shift @ARGV; -m/^(\d+),(\d+)$/ or quit("keepalive,timeout missing or bad syntax"); -($keepalive,$timeout)= ($1,$2); +if (m/^(\d+),(\d+)$/) { + ($keepalive,$timeout,$reannounce)= ($1+0,$2+0,0); + $ka_to_ra= "$keepalive,$timeout"; +} elsif (m/^(\d+),(\d+),(\d+)$/) { + ($keepalive,$timeout,$reannounce)= ($1+0,$2+0,$3); + "$keepalive,$timeout", + $ka_to_ra= "$keepalive,$timeout,$reannounce"; +} else { + quit("keepalive,timeout missing or bad syntax"); +} $keepalive && ($timeout > $keepalive*2) or quit("timeout must be < 2*keepalive") if $timeout; @@ -264,15 +310,14 @@ if (@ARGV) { @rcmd= (@ARGV, @remoteopts, "$rad,$rpd", - $masq ? 'Wait,Wait' : $lapd, + $masq ? 'Wait,Wait' : $las eq 'Any' ? "Wait,$lpd" : $lapd, "$rva,$lva,$mtu,$proto", - "$keepalive,$timeout", + $ka_to_ra, $rexn, $lexn); debug("remote command @rcmd"); if ($rapcmd) { pipe(RAPREAD,RCMDREADSUB) or fail("pipe"); - select(RCMDREADSUB); $|=1; select(STDOUT); } pipe(RCMDWRITESUB,DUMPKEYS) or fail("pipe"); defined($c_rcmd= fork) or fail("fork for remote"); @@ -291,30 +336,33 @@ if (@ARGV) { if ($rapcmd) { close RCMDREADSUB if $rapcmd; - $!=0; $_= ; $e="$!"; + $_= ''; + while (!m/\n/) { + $!=0; + defined($nread= sysread(RAPREAD,$_,1,length)) + or fail("read from remote command"); + if (!$nread) { + close DUMPKEYS; + close RAPREAD; + waitpid $c_rcmd,0 or fail("wait for remote command"); + quit($? ? "remote command failed (code $?)" : + "no details received from remote"); + } + } + chomp; + m/^([.0-9]+)\,(\d+)$/ or quit("invalid details from remote end: \`$_'"); + ($rar,$rpr) = ($1,$2); + $ra= conv_host_addr($rar); + $rp= conv_port_number($rpr); defined($c_catremdebug= fork) or fail("fork for cat remote debug"); if (!$c_catremdebug) { open(STDIN,"<&RAPREAD") or fail("redirect remote debug"); - close RAPREAD; close DUMPKEYS; close L; exec "cat"; fail("execute cat"); } close RAPREAD; - - if (!length) { - close DUMPKEYS; - waitpid $c_rcmd,0 or fail("wait for remote command"); - quit($? ? "remote command failed (code $?)" : - $e ? "read error from remote command: $e" : - "no details received from remote"); - } - chomp; - m/^([.0-9]+)\,(\d+)$/ or quit("invalid details from remote end: \`$_'"); - ($rar,$rpr) = ($1,$2); - $ra= conv_host_addr($rar); - $rp= conv_port_number($rpr); } } elsif ($dump) { open DUMPKEYS, ">&STDOUT" or fail("reopen stdout for key material"); @@ -356,7 +404,7 @@ $xfwdopts.= 'w' if $dump; @fcmd= ($fcmd, $xfwdopts, fileno(L), fileno(DW), fileno(UR), fileno(DUMPKEYS), - $mtu, $keepalive, $timeout, + $mtu, $keepalive, $timeout, $reannounce, @rapf, @encryption); debug("forwarding command @fcmd.");