]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/netpfil/pf/route_to.sh
Remove $FreeBSD$: one-line sh pattern
[FreeBSD/FreeBSD.git] / tests / sys / netpfil / pf / route_to.sh
1 #
2 # SPDX-License-Identifier: BSD-2-Clause
3 #
4 # Copyright (c) 2018 Kristof Provost <kp@FreeBSD.org>
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
26
27 . $(atf_get_srcdir)/utils.subr
28
29 common_dir=$(atf_get_srcdir)/../common
30
31 atf_test_case "v4" "cleanup"
32 v4_head()
33 {
34         atf_set descr 'Basic route-to test'
35         atf_set require.user root
36 }
37
38 v4_body()
39 {
40         pft_init
41
42         epair_send=$(vnet_mkepair)
43         ifconfig ${epair_send}a 192.0.2.1/24 up
44         epair_route=$(vnet_mkepair)
45         ifconfig ${epair_route}a 203.0.113.1/24 up
46
47         vnet_mkjail alcatraz ${epair_send}b ${epair_route}b
48         jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up
49         jexec alcatraz ifconfig ${epair_route}b 203.0.113.2/24 up
50         jexec alcatraz route add -net 198.51.100.0/24 192.0.2.1
51         jexec alcatraz pfctl -e
52
53         # Attempt to provoke PR 228782
54         pft_set_rules alcatraz "block all" "pass user 2" \
55                 "pass out route-to (${epair_route}b 203.0.113.1) from 192.0.2.2 to 198.51.100.1 no state"
56         jexec alcatraz nc -w 3 -s 192.0.2.2 198.51.100.1 22
57
58         # atf wants us to not return an error, but our netcat will fail
59         true
60 }
61
62 v4_cleanup()
63 {
64         pft_cleanup
65 }
66
67 atf_test_case "v6" "cleanup"
68 v6_head()
69 {
70         atf_set descr 'Basic route-to test (IPv6)'
71         atf_set require.user root
72 }
73
74 v6_body()
75 {
76         pft_init
77
78         epair_send=$(vnet_mkepair)
79         ifconfig ${epair_send}a inet6 2001:db8:42::1/64 up no_dad -ifdisabled
80         epair_route=$(vnet_mkepair)
81         ifconfig ${epair_route}a inet6 2001:db8:43::1/64 up no_dad -ifdisabled
82
83         vnet_mkjail alcatraz ${epair_send}b ${epair_route}b
84         jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 up no_dad
85         jexec alcatraz ifconfig ${epair_route}b inet6 2001:db8:43::2/64 up no_dad
86         jexec alcatraz route add -6 2001:db8:666::/64 2001:db8:42::2
87         jexec alcatraz pfctl -e
88
89         # Attempt to provoke PR 228782
90         pft_set_rules alcatraz "block all" "pass user 2" \
91                 "pass out route-to (${epair_route}b 2001:db8:43::1) from 2001:db8:42::2 to 2001:db8:666::1 no state"
92         jexec alcatraz nc -6 -w 3 -s 2001:db8:42::2 2001:db8:666::1 22
93
94         # atf wants us to not return an error, but our netcat will fail
95         true
96 }
97
98 v6_cleanup()
99 {
100         pft_cleanup
101 }
102
103 atf_test_case "multiwan" "cleanup"
104 multiwan_head()
105 {
106         atf_set descr 'Multi-WAN redirection / reply-to test'
107         atf_set require.user root
108 }
109
110 multiwan_body()
111 {
112         pft_init
113
114         epair_one=$(vnet_mkepair)
115         epair_two=$(vnet_mkepair)
116         epair_cl_one=$(vnet_mkepair)
117         epair_cl_two=$(vnet_mkepair)
118
119         vnet_mkjail srv ${epair_one}b ${epair_two}b
120         vnet_mkjail wan_one ${epair_one}a ${epair_cl_one}b
121         vnet_mkjail wan_two ${epair_two}a ${epair_cl_two}b
122         vnet_mkjail client ${epair_cl_one}a ${epair_cl_two}a
123
124         jexec client ifconfig ${epair_cl_one}a 203.0.113.1/25
125         jexec wan_one ifconfig ${epair_cl_one}b 203.0.113.2/25
126         jexec wan_one ifconfig ${epair_one}a 192.0.2.1/24 up
127         jexec wan_one sysctl net.inet.ip.forwarding=1
128         jexec srv ifconfig ${epair_one}b 192.0.2.2/24 up
129         jexec client route add 192.0.2.0/24 203.0.113.2
130
131         jexec client ifconfig ${epair_cl_two}a 203.0.113.128/25
132         jexec wan_two ifconfig ${epair_cl_two}b 203.0.113.129/25
133         jexec wan_two ifconfig ${epair_two}a 198.51.100.1/24 up
134         jexec wan_two sysctl net.inet.ip.forwarding=1
135         jexec srv ifconfig ${epair_two}b 198.51.100.2/24 up
136         jexec client route add 198.51.100.0/24 203.0.113.129
137
138         jexec srv ifconfig lo0 127.0.0.1/8 up
139         jexec srv route add default 192.0.2.1
140         jexec srv sysctl net.inet.ip.forwarding=1
141
142         # Run echo server in srv jail
143         jexec srv /usr/sbin/inetd -p multiwan.pid $(atf_get_srcdir)/echo_inetd.conf
144
145         jexec srv pfctl -e
146         pft_set_rules srv \
147                 "nat on ${epair_one}b inet from 127.0.0.0/8 to any -> (${epair_one}b)" \
148                 "nat on ${epair_two}b inet from 127.0.0.0/8 to any -> (${epair_two}b)" \
149                 "rdr on ${epair_one}b inet proto tcp from any to 192.0.2.2 port 7 -> 127.0.0.1 port 7" \
150                 "rdr on ${epair_two}b inet proto tcp from any to 198.51.100.2 port 7 -> 127.0.0.1 port 7" \
151                 "block in"      \
152                 "block out"     \
153                 "pass in quick on ${epair_one}b reply-to (${epair_one}b 192.0.2.1) inet proto tcp from any to 127.0.0.1 port 7" \
154                 "pass in quick on ${epair_two}b reply-to (${epair_two}b 198.51.100.1) inet proto tcp from any to 127.0.0.1 port 7"
155
156         # These will always succeed, because we don't change interface to route
157         # correctly here.
158         result=$(echo "one" | jexec wan_one nc -N -w 3 192.0.2.2 7)
159         if [ "${result}" != "one" ]; then
160                 atf_fail "Redirect on one failed"
161         fi
162         result=$(echo "two" | jexec wan_two nc -N -w 3 198.51.100.2 7)
163         if [ "${result}" != "two" ]; then
164                 atf_fail "Redirect on two failed"
165         fi
166
167         result=$(echo "one" | jexec client nc -N -w 3 192.0.2.2 7)
168         if [ "${result}" != "one" ]; then
169                 atf_fail "Redirect from client on one failed"
170         fi
171
172         # This should trigger the issue fixed in 829a69db855b48ff7e8242b95e193a0783c489d9
173         result=$(echo "two" | jexec client nc -N -w 3 198.51.100.2 7)
174         if [ "${result}" != "two" ]; then
175                 atf_fail "Redirect from client on two failed"
176         fi
177 }
178
179 multiwan_cleanup()
180 {
181         rm -f multiwan.pid
182         pft_cleanup
183 }
184
185 atf_test_case "multiwanlocal" "cleanup"
186 multiwanlocal_head()
187 {
188         atf_set descr 'Multi-WAN local origin source-based redirection / route-to test'
189         atf_set require.user root
190 }
191
192 multiwanlocal_body()
193 {
194         pft_init
195
196         epair_one=$(vnet_mkepair)
197         epair_two=$(vnet_mkepair)
198         epair_cl_one=$(vnet_mkepair)
199         epair_cl_two=$(vnet_mkepair)
200
201         vnet_mkjail srv1 ${epair_one}b
202         vnet_mkjail srv2 ${epair_two}b
203         vnet_mkjail wan_one ${epair_one}a ${epair_cl_one}b
204         vnet_mkjail wan_two ${epair_two}a ${epair_cl_two}b
205         vnet_mkjail client ${epair_cl_one}a ${epair_cl_two}a
206
207         jexec client ifconfig ${epair_cl_one}a 203.0.113.1/25
208         jexec wan_one ifconfig ${epair_cl_one}b 203.0.113.2/25
209         jexec wan_one ifconfig ${epair_one}a 192.0.2.1/24 up
210         jexec wan_one sysctl net.inet.ip.forwarding=1
211         jexec srv1 ifconfig ${epair_one}b 192.0.2.2/24 up
212
213         jexec client ifconfig ${epair_cl_two}a 203.0.113.128/25
214         jexec wan_two ifconfig ${epair_cl_two}b 203.0.113.129/25
215         jexec wan_two ifconfig ${epair_two}a 198.51.100.1/24 up
216         jexec wan_two sysctl net.inet.ip.forwarding=1
217         jexec srv2 ifconfig ${epair_two}b 198.51.100.2/24 up
218
219         jexec client route add default 203.0.113.2
220         jexec srv1 route add default 192.0.2.1
221         jexec srv2 route add default 198.51.100.1
222
223         # Run data source in srv1 and srv2
224         jexec srv1 sh -c 'dd if=/dev/zero bs=1024 count=100 | nc -l 7 -w 2 -N &'
225         jexec srv2 sh -c 'dd if=/dev/zero bs=1024 count=100 | nc -l 7 -w 2 -N &'
226
227         jexec client pfctl -e
228         pft_set_rules client \
229                 "block in"      \
230                 "block out"     \
231                 "pass out quick route-to (${epair_cl_two}a 203.0.113.129) inet proto tcp from 203.0.113.128 to any port 7" \
232                 "pass out on ${epair_cl_one}a inet proto tcp from any to any port 7" \
233                 "set skip on lo"
234
235         # This should work
236         result=$(jexec client nc -N -w 1 192.0.2.2 7 | wc -c)
237         if [ ${result} -ne 102400 ]; then
238                 jexec client pfctl -ss
239                 atf_fail "Redirect from client on one failed: ${result}"
240         fi
241
242         # This should trigger the issue
243         result=$(jexec client nc -N -w 1 -s 203.0.113.128 198.51.100.2 7 | wc -c)
244         jexec client pfctl -ss
245         if [ ${result} -ne 102400 ]; then
246                 atf_fail "Redirect from client on two failed: ${result}"
247         fi
248 }
249
250 multiwanlocal_cleanup()
251 {
252         pft_cleanup
253 }
254
255 atf_test_case "icmp_nat" "cleanup"
256 icmp_nat_head()
257 {
258         atf_set descr 'Test that ICMP packets are correct for route-to + NAT'
259         atf_set require.user root
260         atf_set require.progs scapy
261 }
262
263 icmp_nat_body()
264 {
265         pft_init
266
267         epair_one=$(vnet_mkepair)
268         epair_two=$(vnet_mkepair)
269         epair_three=$(vnet_mkepair)
270
271         vnet_mkjail gw ${epair_one}b ${epair_two}a ${epair_three}a
272         vnet_mkjail srv ${epair_two}b
273         vnet_mkjail srv2 ${epair_three}b
274
275         ifconfig ${epair_one}a 192.0.2.2/24 up
276         route add -net 198.51.100.0/24 192.0.2.1
277         jexec gw sysctl net.inet.ip.forwarding=1
278         jexec gw ifconfig ${epair_one}b 192.0.2.1/24 up
279         jexec gw ifconfig ${epair_two}a 198.51.100.1/24 up
280         jexec gw ifconfig ${epair_three}a 203.0.113.1/24 up mtu 500
281         jexec srv ifconfig ${epair_two}b 198.51.100.2/24 up
282         jexec srv route add default 198.51.100.1
283         jexec srv2 ifconfig ${epair_three}b 203.0.113.2/24 up mtu 500
284         jexec srv2 route add default 203.0.113.1
285
286         # Sanity check
287         atf_check -s exit:0 -o ignore ping -c 1 198.51.100.2
288
289         jexec gw pfctl -e
290         pft_set_rules gw \
291                 "nat on ${epair_two}a inet from 192.0.2.0/24 to any -> (${epair_two}a)" \
292                 "nat on ${epair_three}a inet from 192.0.2.0/24 to any -> (${epair_three}a)" \
293                 "pass out route-to (${epair_three}a 203.0.113.2) proto icmp icmp-type echoreq"
294
295         # Now ensure that we get an ICMP error with the correct IP addresses in it.
296         atf_check -s exit:0 ${common_dir}/pft_icmp_check.py \
297                 --to 198.51.100.2 \
298                 --fromaddr 192.0.2.2 \
299                 --recvif ${epair_one}a \
300                 --sendif ${epair_one}a
301
302         # ping reports the ICMP error, so check of that too.
303         atf_check -s exit:2 -o match:'frag needed and DF set' \
304                 ping -D -c 1 -s 1000 198.51.100.2
305 }
306
307 icmp_nat_cleanup()
308 {
309         pft_cleanup
310 }
311
312 atf_test_case "dummynet" "cleanup"
313 dummynet_head()
314 {
315         atf_set descr 'Test that dummynet applies to route-to packets'
316         atf_set require.user root
317 }
318
319 dummynet_body()
320 {
321         dummynet_init
322
323         epair_srv=$(vnet_mkepair)
324         epair_gw=$(vnet_mkepair)
325
326         vnet_mkjail srv ${epair_srv}a
327         jexec srv ifconfig ${epair_srv}a 192.0.2.1/24 up
328         jexec srv route add default 192.0.2.2
329
330         vnet_mkjail gw ${epair_srv}b ${epair_gw}a
331         jexec gw ifconfig ${epair_srv}b 192.0.2.2/24 up
332         jexec gw ifconfig ${epair_gw}a 198.51.100.1/24 up
333         jexec gw sysctl net.inet.ip.forwarding=1
334
335         ifconfig ${epair_gw}b 198.51.100.2/24 up
336         route add -net 192.0.2.0/24 198.51.100.1
337
338         # Sanity check
339         atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
340
341         jexec gw dnctl pipe 1 config delay 1200
342         pft_set_rules gw \
343                 "pass out route-to (${epair_srv}b 192.0.2.1) to 192.0.2.1 dnpipe 1"
344         jexec gw pfctl -e
345
346         # The ping request will pass, but take 1.2 seconds
347         # So this works:
348         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
349         # But this times out:
350         atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.1
351
352         # return path dummynet
353         pft_set_rules gw \
354                 "pass out route-to (${epair_srv}b 192.0.2.1) to 192.0.2.1 dnpipe (0, 1)"
355
356         # The ping request will pass, but take 1.2 seconds
357         # So this works:
358         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
359         # But this times out:
360         atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.1
361 }
362
363 dummynet_cleanup()
364 {
365         pft_cleanup
366 }
367
368 atf_init_test_cases()
369 {
370         atf_add_test_case "v4"
371         atf_add_test_case "v6"
372         atf_add_test_case "multiwan"
373         atf_add_test_case "multiwanlocal"
374         atf_add_test_case "icmp_nat"
375         atf_add_test_case "dummynet"
376 }