forked from horar/vpnc-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvpnc-script-ptrtd
executable file
·167 lines (138 loc) · 4.96 KB
/
vpnc-script-ptrtd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/bin/sh
#
# © 2009 David Woodhouse <[email protected]>
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
################
#
# This is a replacement for the standard vpnc-script for use with vpnc
# and openconnect. It sets up VPN routing which doesn't screw over the
# _normal_ routing of the box.
# It sets up a new network namespace for the VPN to use, and it runs
# pTRTd (http://www.litech.org/ptrtd/) in that namespace. Connections
# to the VPN are actually made as IPv6 connections, and pTRTd handles
# converting them to Legacy IP and forwarding them.
# The full range of Legacy IP addresses on the VPN is available to the
# host through a tiny corner of the IPv6 address space; for this purpose
# we use fec0:0:0:ffff:0:0:xxyy:zzww to represent the address xx.yy.zz.ww
# on the VPN.
# TODO: Either use totd (ftp://ftp.pasta.cs.uit.no/pub/Vermicelli/) or
# preferably extend dnsmasq to handle DNS for us. We want the following:
# - A queries for non-existent VPN hosts return NXDOMAIN (no munging)
# - A queries for _extant_ VPN hosts return NOERROR instead of the result.
# - AAAA queries return the A result, converted to the above IPv6 space.
# - PTR queries within the IPv6 space converted appropriately.
connect_parent()
{
# XXX: How do we work out what it _really_ is?
export PARENT_NETNS=$$
# XXX: Make sure it doesn't exist in this namespace already
export RETURNDEV=x$TUNDEV
./netunshare $0 $@ &
CHILDPID=$!
# XXX: If we do this too soon (before the unshare), we're just
# giving it to our _own_ netns. which achieves nothing.
# So give it away until we _can't_ give it away any more.
while /sbin/ip link set $TUNDEV netns $CHILDPID 2>/dev/null; do
sleep 0.1
done
# Wait for the ptrtd tundev to appear in this namespace
while ! ip link show $RETURNDEV >/dev/null 2>&1 ; do
sleep 1
done
/sbin/ip link set $RETURNDEV up
/sbin/ip addr add fe80::1 dev $RETURNDEV
/sbin/ip route add fec0:0:0:ffff::/64 dev $RETURNDEV
# XXX: Local hack -- my company's VPN server returns
# "foo.company.com" instead of just "company.com".
CISCO_DEF_DOMAIN=`echo $CISCO_DEF_DOMAIN | cut -f2- -d.`
# Work out the IPv6 address of the nameservers...
IPV6NS=
for NS in $INTERNAL_IP4_DNS; do
A=`echo $NS | cut -f1 -d.`
B=`echo $NS | cut -f2 -d.`
C=`echo $NS | cut -f3 -d.`
D=`echo $NS | cut -f4 -d.`
THISNS=`printf fec0:0:0:ffff:0:0:%02x%02x:%02x%02x $A $B $C $D`
IPV6NS="$THISNS $IPV6NS"
DNSMASQ_CMDLINE="-S /$CISCO_DEF_DOMAIN/$IPV6NS $DNSMASQ_CMDLINE"
done
echo IPv6 DNS: $IPV6NS
# XXX: Add totd-like capability to dnsmasq
dnsmasq $DNSMASQ_CMDLINE
}
connect()
{
if [ -z "$PARENT_NETNS" ]; then
connect_parent
exit 0
fi
# Wait for the tundev to appear in this namespace
while ! ip link show $TUNDEV >/dev/null 2>&1 ; do
sleep 0.1
done
# Set up Legacy IP in the new namespace
/sbin/ip link set lo up
/sbin/ip link set $TUNDEV up
/sbin/ip -4 addr add $INTERNAL_IP4_ADDRESS dev $TUNDEV
/sbin/ip -4 route add default dev $TUNDEV
if [ "$INTERNAL_IP4_MTU" != "" ]; then
/sbin/ip link set $TUNDEV mtu $INTERNAL_IP4_MTU
fi
# ifconfig
# route
# For debugging, really. Lets you ssh into the netns with
# ssh fec0:0:0:ffff:0:0:7f00:1
/usr/sbin/sshd -D &
SSHD_PID=$!
# Start ptrtd
ptrtd -i tun:$RETURNDEV -d >/dev/null 2>&1 &
PTRTD_PID=$!
# Wait for the ptrtd to make its device
while ! ip link show $TUNDEV >/dev/null 2>&1 ; do
sleep 0.1
done
# Now give the ptrtd device back to the parent
ip link set $RETURNDEV down
/sbin/ip link set $RETURNDEV netns $PARENT_NETNS
#Hm, this doesn't work because the tundev doesn't go away when it should
#while ip link show $TUNDEV 2> /dev/null ; do
# sleep 1
#done
# Wait for ptrtd to die (which it will when disconnect() kills its tun)
wait $PTRTD_PID
kill -TERM $SSHD_PID
# Wait a while to avoid tun BUG() if we quit and the netns goes away
# before vpnc/openconnect closes its tun fd.
sleep 1
}
disconnect()
{
RETURNDEV=x$TUNDEV
# This will kill ptrtd inside the netns, leaving the script to clean up
ip link del $RETURNDEV
# XXX: Undo the dnsmasq stuff.
killall dnsmasq
# XXX: properly.
}
case $reason in
connect)
connect
;;
disconnect)
disconnect
;;
esac