t_ipsec_natt.sh revision 1.1 1 1.1 ozaki # $NetBSD: t_ipsec_natt.sh,v 1.1 2017/10/30 15:59:23 ozaki-r Exp $
2 1.1 ozaki #
3 1.1 ozaki # Copyright (c) 2017 Internet Initiative Japan Inc.
4 1.1 ozaki # All rights reserved.
5 1.1 ozaki #
6 1.1 ozaki # Redistribution and use in source and binary forms, with or without
7 1.1 ozaki # modification, are permitted provided that the following conditions
8 1.1 ozaki # are met:
9 1.1 ozaki # 1. Redistributions of source code must retain the above copyright
10 1.1 ozaki # notice, this list of conditions and the following disclaimer.
11 1.1 ozaki # 2. Redistributions in binary form must reproduce the above copyright
12 1.1 ozaki # notice, this list of conditions and the following disclaimer in the
13 1.1 ozaki # documentation and/or other materials provided with the distribution.
14 1.1 ozaki #
15 1.1 ozaki # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 1.1 ozaki # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 1.1 ozaki # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 1.1 ozaki # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 1.1 ozaki # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 1.1 ozaki # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 1.1 ozaki # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 1.1 ozaki # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 1.1 ozaki # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 1.1 ozaki # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 ozaki # POSSIBILITY OF SUCH DAMAGE.
26 1.1 ozaki #
27 1.1 ozaki
28 1.1 ozaki SOCK_LOCAL=unix://ipsec_natt_local
29 1.1 ozaki SOCK_NAT=unix://ipsec_natt_nat
30 1.1 ozaki SOCK_REMOTE=unix://ipsec_natt_remote
31 1.1 ozaki BUS_LOCAL=./bus_ipsec_natt_local
32 1.1 ozaki BUS_NAT=./bus_ipsec_natt_nat
33 1.1 ozaki BUS_REMOTE=./bus_ipsec_natt_remote
34 1.1 ozaki
35 1.1 ozaki DEBUG=${DEBUG:-false}
36 1.1 ozaki HIJACKING_NPF="${HIJACKING},blanket=/dev/npf"
37 1.1 ozaki
38 1.1 ozaki setup_servers()
39 1.1 ozaki {
40 1.1 ozaki
41 1.1 ozaki rump_server_crypto_start $SOCK_LOCAL netipsec
42 1.1 ozaki rump_server_npf_start $SOCK_NAT
43 1.1 ozaki rump_server_crypto_start $SOCK_REMOTE netipsec
44 1.1 ozaki rump_server_add_iface $SOCK_LOCAL shmif0 $BUS_LOCAL
45 1.1 ozaki rump_server_add_iface $SOCK_NAT shmif0 $BUS_LOCAL
46 1.1 ozaki rump_server_add_iface $SOCK_NAT shmif1 $BUS_NAT
47 1.1 ozaki rump_server_add_iface $SOCK_REMOTE shmif0 $BUS_NAT
48 1.1 ozaki }
49 1.1 ozaki
50 1.1 ozaki setup_sp()
51 1.1 ozaki {
52 1.1 ozaki local proto=$1
53 1.1 ozaki local algo_args="$2"
54 1.1 ozaki local ip_local=$3
55 1.1 ozaki local ip_remote=$4
56 1.1 ozaki local ip_nat_remote=$5
57 1.1 ozaki local tmpfile=./tmp
58 1.1 ozaki
59 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
60 1.1 ozaki cat > $tmpfile <<-EOF
61 1.1 ozaki spdadd $ip_local $ip_remote any -P out ipsec $proto/transport//require;
62 1.1 ozaki spdadd $ip_remote $ip_local any -P in ipsec $proto/transport//require;
63 1.1 ozaki EOF
64 1.1 ozaki $DEBUG && cat $tmpfile
65 1.1 ozaki atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
66 1.1 ozaki #check_sp_entries $SOCK_LOCAL $ip_local $ip_remote
67 1.1 ozaki
68 1.1 ozaki export RUMP_SERVER=$SOCK_REMOTE
69 1.1 ozaki cat > $tmpfile <<-EOF
70 1.1 ozaki spdadd $ip_remote $ip_nat_remote any -P out ipsec $proto/transport//require;
71 1.1 ozaki spdadd $ip_local $ip_remote any -P in ipsec $proto/transport//require;
72 1.1 ozaki EOF
73 1.1 ozaki $DEBUG && cat $tmpfile
74 1.1 ozaki atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
75 1.1 ozaki #check_sp_entries $SOCK_REMOTE $ip_remote $ip_local
76 1.1 ozaki }
77 1.1 ozaki
78 1.1 ozaki add_sa()
79 1.1 ozaki {
80 1.1 ozaki local proto=$1
81 1.1 ozaki local algo_args="$2"
82 1.1 ozaki local ip_local=$3
83 1.1 ozaki local ip_remote=$4
84 1.1 ozaki local ip_nat_remote=$5
85 1.1 ozaki local spi=$6
86 1.1 ozaki local port=$7
87 1.1 ozaki local tmpfile=./tmp
88 1.1 ozaki
89 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
90 1.1 ozaki cat > $tmpfile <<-EOF
91 1.1 ozaki add $ip_local [4500] $ip_remote [4500] $proto $((spi)) $algo_args;
92 1.1 ozaki add $ip_remote [4500] $ip_local [4500] $proto $((spi + 1)) $algo_args;
93 1.1 ozaki EOF
94 1.1 ozaki $DEBUG && cat $tmpfile
95 1.1 ozaki atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
96 1.1 ozaki $DEBUG && $HIJACKING setkey -D
97 1.1 ozaki # XXX it can be expired if $lifetime is very short
98 1.1 ozaki #check_sa_entries $SOCK_LOCAL $ip_local $ip_remote
99 1.1 ozaki
100 1.1 ozaki export RUMP_SERVER=$SOCK_REMOTE
101 1.1 ozaki cat > $tmpfile <<-EOF
102 1.1 ozaki add $ip_local [$port] $ip_remote [4500] $proto $((spi)) $algo_args;
103 1.1 ozaki add $ip_remote [4500] $ip_nat_remote [$port] $proto $((spi + 1)) $algo_args;
104 1.1 ozaki EOF
105 1.1 ozaki $DEBUG && cat $tmpfile
106 1.1 ozaki atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
107 1.1 ozaki $DEBUG && $HIJACKING setkey -D
108 1.1 ozaki # XXX it can be expired if $lifetime is very short
109 1.1 ozaki #check_sa_entries $SOCK_PEER $ip_local $ip_remote
110 1.1 ozaki }
111 1.1 ozaki
112 1.1 ozaki prepare_file()
113 1.1 ozaki {
114 1.1 ozaki local file=$1
115 1.1 ozaki local data="0123456789"
116 1.1 ozaki
117 1.1 ozaki touch $file
118 1.1 ozaki for i in `seq 1 512`
119 1.1 ozaki do
120 1.1 ozaki echo $data >> $file
121 1.1 ozaki done
122 1.1 ozaki }
123 1.1 ozaki
124 1.1 ozaki build_npf_conf()
125 1.1 ozaki {
126 1.1 ozaki local outfile=$1
127 1.1 ozaki local localnet=$2
128 1.1 ozaki
129 1.1 ozaki cat > $outfile <<-EOF
130 1.1 ozaki set bpf.jit off
131 1.1 ozaki \$int_if = inet4(shmif0)
132 1.1 ozaki \$ext_if = inet4(shmif1)
133 1.1 ozaki \$localnet = { $localnet }
134 1.1 ozaki map \$ext_if dynamic \$localnet -> \$ext_if
135 1.1 ozaki group "external" on \$ext_if {
136 1.1 ozaki pass stateful out final all
137 1.1 ozaki }
138 1.1 ozaki group "internal" on \$int_if {
139 1.1 ozaki block in all
140 1.1 ozaki pass in final from \$localnet
141 1.1 ozaki pass out final all
142 1.1 ozaki }
143 1.1 ozaki group default {
144 1.1 ozaki pass final on lo0 all
145 1.1 ozaki block all
146 1.1 ozaki }
147 1.1 ozaki EOF
148 1.1 ozaki }
149 1.1 ozaki
150 1.1 ozaki PIDSFILE=./terminator.pids
151 1.1 ozaki start_natt_terminator()
152 1.1 ozaki {
153 1.1 ozaki local sock=$1
154 1.1 ozaki local ip=$2
155 1.1 ozaki local port=$3
156 1.1 ozaki local pidsfile=$4
157 1.1 ozaki local backup=$RUMP_SERVER
158 1.1 ozaki local pid=
159 1.1 ozaki local terminator="$(atf_get_srcdir)/natt_terminator"
160 1.1 ozaki
161 1.1 ozaki export RUMP_SERVER=$sock
162 1.1 ozaki
163 1.1 ozaki env LD_PRELOAD=/usr/lib/librumphijack.so \
164 1.1 ozaki $terminator $ip $port &
165 1.1 ozaki pid=$!
166 1.1 ozaki if [ ! -f $PIDSFILE ]; then
167 1.1 ozaki touch $PIDSFILE
168 1.1 ozaki fi
169 1.1 ozaki echo $pid >> $PIDSFILE
170 1.1 ozaki
171 1.1 ozaki $DEBUG && rump.netstat -a -f inet
172 1.1 ozaki
173 1.1 ozaki export RUMP_SERVER=$backup
174 1.1 ozaki
175 1.1 ozaki sleep 1
176 1.1 ozaki }
177 1.1 ozaki
178 1.1 ozaki stop_natt_terminators()
179 1.1 ozaki {
180 1.1 ozaki local pid=
181 1.1 ozaki
182 1.1 ozaki if [ ! -f $PIDSFILE ]; then
183 1.1 ozaki return
184 1.1 ozaki fi
185 1.1 ozaki
186 1.1 ozaki for pid in $(cat $PIDSFILE); do
187 1.1 ozaki kill -9 $pid
188 1.1 ozaki done
189 1.1 ozaki rm -f $PIDSFILE
190 1.1 ozaki }
191 1.1 ozaki
192 1.1 ozaki test_ipsec_natt_transport()
193 1.1 ozaki {
194 1.1 ozaki local algo=$1
195 1.1 ozaki local ip_local=10.0.1.2
196 1.1 ozaki local ip_nat_local=10.0.1.1
197 1.1 ozaki local ip_nat_remote=20.0.0.1
198 1.1 ozaki local ip_remote=20.0.0.2
199 1.1 ozaki local subnet_local=10.0.1.0
200 1.1 ozaki local outfile=./out
201 1.1 ozaki local npffile=./npf.conf
202 1.1 ozaki local file_send=./file.send
203 1.1 ozaki local file_recv=./file.recv
204 1.1 ozaki local algo_args="$(generate_algo_args esp-udp $algo)"
205 1.1 ozaki local pid= port=
206 1.1 ozaki
207 1.1 ozaki setup_servers
208 1.1 ozaki
209 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
210 1.1 ozaki atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
211 1.1 ozaki atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
212 1.1 ozaki atf_check -s exit:0 -o ignore \
213 1.1 ozaki rump.route -n add default $ip_nat_local
214 1.1 ozaki
215 1.1 ozaki export RUMP_SERVER=$SOCK_NAT
216 1.1 ozaki atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
217 1.1 ozaki atf_check -s exit:0 rump.ifconfig shmif0 $ip_nat_local/24
218 1.1 ozaki atf_check -s exit:0 rump.ifconfig shmif1 $ip_nat_remote/24
219 1.1 ozaki atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.forwarding=1
220 1.1 ozaki
221 1.1 ozaki export RUMP_SERVER=$SOCK_REMOTE
222 1.1 ozaki atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
223 1.1 ozaki atf_check -s exit:0 rump.ifconfig shmif0 $ip_remote/24
224 1.1 ozaki atf_check -s exit:0 -o ignore \
225 1.1 ozaki rump.route -n add -net $subnet_local $ip_nat_remote
226 1.1 ozaki
227 1.1 ozaki extract_new_packets $BUS_NAT > $outfile
228 1.1 ozaki
229 1.1 ozaki # There is no NAT/NAPT. ping should just work.
230 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
231 1.1 ozaki atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote
232 1.1 ozaki
233 1.1 ozaki extract_new_packets $BUS_NAT > $outfile
234 1.1 ozaki $DEBUG && cat $outfile
235 1.1 ozaki atf_check -s exit:0 \
236 1.1 ozaki -o match:"$ip_local > $ip_remote: ICMP echo request" \
237 1.1 ozaki cat $outfile
238 1.1 ozaki atf_check -s exit:0 \
239 1.1 ozaki -o match:"$ip_remote > $ip_local: ICMP echo reply" \
240 1.1 ozaki cat $outfile
241 1.1 ozaki
242 1.1 ozaki # Setup an NAPT with npf
243 1.1 ozaki build_npf_conf $npffile "$subnet_local/24"
244 1.1 ozaki
245 1.1 ozaki export RUMP_SERVER=$SOCK_NAT
246 1.1 ozaki atf_check -s exit:0 $HIJACKING_NPF npfctl reload $npffile
247 1.1 ozaki atf_check -s exit:0 $HIJACKING_NPF npfctl start
248 1.1 ozaki $DEBUG && ${HIJACKING},"blanket=/dev/npf" npfctl show
249 1.1 ozaki
250 1.1 ozaki # There is an NAPT. ping works but source IP/port are translated
251 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
252 1.1 ozaki atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote
253 1.1 ozaki
254 1.1 ozaki extract_new_packets $BUS_NAT > $outfile
255 1.1 ozaki $DEBUG && cat $outfile
256 1.1 ozaki atf_check -s exit:0 \
257 1.1 ozaki -o match:"$ip_nat_remote > $ip_remote: ICMP echo request" \
258 1.1 ozaki cat $outfile
259 1.1 ozaki atf_check -s exit:0 \
260 1.1 ozaki -o match:"$ip_remote > $ip_nat_remote: ICMP echo reply" \
261 1.1 ozaki cat $outfile
262 1.1 ozaki
263 1.1 ozaki # Try TCP communications just in case
264 1.1 ozaki start_nc_server $SOCK_REMOTE 4501 $file_recv ipv4
265 1.1 ozaki prepare_file $file_send
266 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
267 1.1 ozaki atf_check -s exit:0 $HIJACKING nc -w 3 $ip_remote 4501 < $file_send
268 1.1 ozaki atf_check -s exit:0 diff -q $file_send $file_recv
269 1.1 ozaki stop_nc_server
270 1.1 ozaki
271 1.1 ozaki extract_new_packets $BUS_NAT > $outfile
272 1.1 ozaki $DEBUG && cat $outfile
273 1.1 ozaki atf_check -s exit:0 \
274 1.1 ozaki -o match:"${ip_nat_remote}\.[0-9]+ > ${ip_remote}\.4501" \
275 1.1 ozaki cat $outfile
276 1.1 ozaki atf_check -s exit:0 \
277 1.1 ozaki -o match:"${ip_remote}\.4501 > ${ip_nat_remote}\.[0-9]+" \
278 1.1 ozaki cat $outfile
279 1.1 ozaki
280 1.1 ozaki # Launch a nc server as a terminator of NAT-T on outside the NAPT
281 1.1 ozaki start_natt_terminator $SOCK_REMOTE $ip_remote 4500
282 1.1 ozaki echo zzz > $file_send
283 1.1 ozaki
284 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
285 1.1 ozaki # Send a UDP packet to the remote server at port 4500 from the local
286 1.1 ozaki # host of port 4500. This makes a mapping on the NAPT between them
287 1.1 ozaki atf_check -s exit:0 $HIJACKING \
288 1.1 ozaki nc -u -w 3 -p 4500 $ip_remote 4500 < $file_send
289 1.1 ozaki # Launch a nc server as a terminator of NAT-T on inside the NAPT,
290 1.1 ozaki # taking over port 4500 of the local host.
291 1.1 ozaki start_natt_terminator $SOCK_LOCAL $ip_local 4500
292 1.1 ozaki
293 1.1 ozaki # We need to keep the servers for NAT-T
294 1.1 ozaki
295 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
296 1.1 ozaki $DEBUG && rump.netstat -na -f inet
297 1.1 ozaki export RUMP_SERVER=$SOCK_REMOTE
298 1.1 ozaki $DEBUG && rump.netstat -na -f inet
299 1.1 ozaki
300 1.1 ozaki # Get a translated port number from 4500 on the NAPT
301 1.1 ozaki export RUMP_SERVER=$SOCK_NAT
302 1.1 ozaki $DEBUG && $HIJACKING_NPF npfctl list
303 1.1 ozaki # 10.0.1.2:4500 20.0.0.2:4500 via shmif1:9696
304 1.1 ozaki port=$($HIJACKING_NPF npfctl list | awk -F 'shmif1:' '/4500/ {print $2;}')
305 1.1 ozaki $DEBUG && echo port=$port
306 1.1 ozaki if [ -z "$port" ]; then
307 1.1 ozaki atf_fail "Failed to get a traslated port on NAPT"
308 1.1 ozaki fi
309 1.1 ozaki
310 1.1 ozaki # Create ESP-UDP IPsec connections
311 1.1 ozaki setup_sp esp "$algo_args" $ip_local $ip_remote $ip_nat_remote
312 1.1 ozaki add_sa "esp-udp" "$algo_args" $ip_local $ip_remote $ip_nat_remote 10000 $port
313 1.1 ozaki
314 1.1 ozaki # ping should still work
315 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
316 1.1 ozaki atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote
317 1.1 ozaki
318 1.1 ozaki # Try TCP communications over the ESP-UDP connections
319 1.1 ozaki start_nc_server $SOCK_REMOTE 4501 $file_recv ipv4
320 1.1 ozaki prepare_file $file_send
321 1.1 ozaki export RUMP_SERVER=$SOCK_LOCAL
322 1.1 ozaki atf_check -s exit:0 -o ignore $HIJACKING nc -w 3 $ip_remote 4501 < $file_send
323 1.1 ozaki atf_check -s exit:0 diff -q $file_send $file_recv
324 1.1 ozaki stop_nc_server
325 1.1 ozaki
326 1.1 ozaki # Check both ports and UDP encapsulation
327 1.1 ozaki extract_new_packets $BUS_NAT > $outfile
328 1.1 ozaki $DEBUG && cat $outfile
329 1.1 ozaki atf_check -s exit:0 \
330 1.1 ozaki -o match:"${ip_nat_remote}\.$port > ${ip_remote}\.4500: UDP-encap" \
331 1.1 ozaki cat $outfile
332 1.1 ozaki atf_check -s exit:0 \
333 1.1 ozaki -o match:"${ip_remote}\.4500 > ${ip_nat_remote}\.$port: UDP-encap" \
334 1.1 ozaki cat $outfile
335 1.1 ozaki
336 1.1 ozaki # Kill the NAT-T terminator
337 1.1 ozaki stop_natt_terminators
338 1.1 ozaki }
339 1.1 ozaki
340 1.1 ozaki add_test_ipsec_natt_transport()
341 1.1 ozaki {
342 1.1 ozaki local algo=$1
343 1.1 ozaki local _algo=$(echo $algo | sed 's/-//g')
344 1.1 ozaki local name= desc=
345 1.1 ozaki
346 1.1 ozaki desc="Test IPsec NAT-T ($algo)"
347 1.1 ozaki name="ipsec_natt_transport_${_algo}"
348 1.1 ozaki
349 1.1 ozaki atf_test_case ${name} cleanup
350 1.1 ozaki eval "
351 1.1 ozaki ${name}_head() {
352 1.1 ozaki atf_set descr \"$desc\"
353 1.1 ozaki atf_set require.progs rump_server setkey nc
354 1.1 ozaki }
355 1.1 ozaki ${name}_body() {
356 1.1 ozaki test_ipsec_natt_transport $algo
357 1.1 ozaki rump_server_destroy_ifaces
358 1.1 ozaki }
359 1.1 ozaki ${name}_cleanup() {
360 1.1 ozaki stop_nc_server
361 1.1 ozaki stop_natt_terminators
362 1.1 ozaki \$DEBUG && dump
363 1.1 ozaki cleanup
364 1.1 ozaki }
365 1.1 ozaki "
366 1.1 ozaki atf_add_test_case ${name}
367 1.1 ozaki }
368 1.1 ozaki
369 1.1 ozaki atf_init_test_cases()
370 1.1 ozaki {
371 1.1 ozaki local algo=
372 1.1 ozaki
373 1.1 ozaki for algo in $ESP_ENCRYPTION_ALGORITHMS_MINIMUM; do
374 1.1 ozaki add_test_ipsec_natt_transport $algo
375 1.1 ozaki done
376 1.1 ozaki }
377