]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/netpfil/pf/fragmentation_pass.sh
zfs: merge openzfs/zfs@95f71c019
[FreeBSD/FreeBSD.git] / tests / sys / netpfil / pf / fragmentation_pass.sh
1 #
2 # SPDX-License-Identifier: BSD-2-Clause
3 #
4 # Copyright (c) 2017 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 "too_many_fragments" "cleanup"
32
33 too_many_fragments_head()
34 {
35         atf_set descr 'IPv4 fragment limitation test'
36         atf_set require.user root
37 }
38
39 too_many_fragments_body()
40 {
41         pft_init
42
43         epair=$(vnet_mkepair)
44         vnet_mkjail alcatraz ${epair}a
45
46         ifconfig ${epair}b inet 192.0.2.1/24 up
47         jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up
48
49         ifconfig ${epair}b mtu 200
50         jexec alcatraz ifconfig ${epair}a mtu 200
51
52         jexec alcatraz pfctl -e
53         pft_set_rules alcatraz \
54                 "set reassemble yes" \
55                 "pass keep state"
56
57         # So we know pf is limiting things
58         jexec alcatraz sysctl net.inet.ip.maxfragsperpacket=1024
59
60         # Sanity check
61         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
62
63         # We can ping with < 64 fragments
64         atf_check -s exit:0 -o ignore ping -c 1 -s 800 192.0.2.2
65
66         # Too many fragments should fail
67         atf_check -s exit:2 -o ignore ping -c 1 -s 20000 192.0.2.2
68 }
69
70 too_many_fragments_cleanup()
71 {
72         pft_cleanup
73 }
74
75 atf_test_case "v6" "cleanup"
76 v6_head()
77 {
78         atf_set descr 'IPv6 fragmentation test'
79         atf_set require.user root
80         atf_set require.progs scapy
81 }
82
83 v6_body()
84 {
85         pft_init
86
87         epair_send=$(vnet_mkepair)
88         epair_link=$(vnet_mkepair)
89
90         vnet_mkjail alcatraz ${epair_send}b ${epair_link}a
91         vnet_mkjail singsing ${epair_link}b
92
93         ifconfig ${epair_send}a inet6 2001:db8:42::1/64 no_dad up
94
95         jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 no_dad up
96         jexec alcatraz ifconfig ${epair_link}a inet6 2001:db8:43::2/64 no_dad up
97         jexec alcatraz sysctl net.inet6.ip6.forwarding=1
98
99         jexec singsing ifconfig ${epair_link}b inet6 2001:db8:43::3/64 no_dad up
100         jexec singsing route add -6 2001:db8:42::/64 2001:db8:43::2
101         route add -6 2001:db8:43::/64 2001:db8:42::2
102
103         jexec alcatraz ifconfig ${epair_send}b inet6 -ifdisabled
104         jexec alcatraz ifconfig ${epair_link}a inet6 -ifdisabled
105         jexec singsing ifconfig ${epair_link}b inet6 -ifdisabled
106         ifconfig ${epair_send}a inet6 -ifdisabled
107
108         ifconfig ${epair_send}a
109         jexec alcatraz ifconfig ${epair_send}b
110         lladdr=$(jexec alcatraz ifconfig ${epair_send}b | awk '/ scopeid / { print($2); }' | cut -f 1 -d %)
111
112         jexec alcatraz pfctl -e
113         pft_set_rules alcatraz \
114                 "set reassemble yes" \
115                 "pass keep state" \
116                 "block in" \
117                 "pass in inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
118                 "pass in inet6 proto icmp6 icmp6-type { echoreq, echorep }" \
119                 "set skip on lo"
120
121         # Host test
122         atf_check -s exit:0 -o ignore \
123                 ping -6 -c 1 2001:db8:42::2
124
125         atf_check -s exit:0 -o ignore \
126                 ping -6 -c 1 -s 4500 2001:db8:42::2
127
128         atf_check -s exit:0 -o ignore\
129                 ping -6 -c 1 -b 70000 -s 65000 2001:db8:42::2
130
131         # Force an NDP lookup
132         ping -6 -c 1 ${lladdr}%${epair_send}a
133
134         atf_check -s exit:0 -o ignore\
135                 ping -6 -c 1 -b 70000 -s 65000 ${lladdr}%${epair_send}a
136
137         # Forwarding test
138         atf_check -s exit:0 -o ignore \
139                 ping -6 -c 1 2001:db8:43::3
140
141         atf_check -s exit:0 -o ignore \
142                 ping -6 -c 1 -s 4500 2001:db8:43::3
143
144         atf_check -s exit:0 -o ignore\
145                 ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3
146
147         $(atf_get_srcdir)/CVE-2019-5597.py \
148                 ${epair_send}a \
149                 2001:db8:42::1 \
150                 2001:db8:43::3
151 }
152
153 v6_cleanup()
154 {
155         pft_cleanup
156 }
157
158 atf_test_case "mtu_diff" "cleanup"
159 mtu_diff_head()
160 {
161         atf_set descr 'Test reassembly across different MTUs, PR #255432'
162         atf_set require.user root
163 }
164
165 mtu_diff_body()
166 {
167         pft_init
168
169         epair_small=$(vnet_mkepair)
170         epair_large=$(vnet_mkepair)
171
172         vnet_mkjail first ${epair_small}b ${epair_large}a
173         vnet_mkjail second ${epair_large}b
174
175         ifconfig ${epair_small}a 192.0.2.1/25 up
176         jexec first ifconfig ${epair_small}b 192.0.2.2/25 up
177
178         jexec first sysctl net.inet.ip.forwarding=1
179         jexec first ifconfig ${epair_large}a 192.0.2.130/25 up
180         jexec first ifconfig ${epair_large}a mtu 9000
181         jexec second ifconfig ${epair_large}b 192.0.2.131/25 up
182         jexec second ifconfig ${epair_large}b mtu 9000
183         jexec second route add default 192.0.2.130
184
185         route add 192.0.2.128/25 192.0.2.2
186
187         jexec first pfctl -e
188         pft_set_rules first \
189                 "set reassemble yes" \
190                 "pass keep state"
191
192         # Sanity checks
193         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
194         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.130
195         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.131
196
197         # Large packet that'll get reassembled and sent out in one on the large
198         # epair
199         atf_check -s exit:0 -o ignore ping -c 1 -s 8000 192.0.2.131
200 }
201
202 mtu_diff_cleanup()
203 {
204         pft_cleanup
205 }
206
207 frag_common()
208 {
209         name=$1
210
211         pft_init
212
213         epair=$(vnet_mkepair)
214         vnet_mkjail alcatraz ${epair}a
215
216         ifconfig ${epair}b inet 192.0.2.1/24 up
217         jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up
218
219         jexec alcatraz pfctl -e
220         pft_set_rules alcatraz \
221                 "set reassemble yes" \
222                 "pass keep state"
223
224         # Sanity check
225         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
226
227         atf_check -s exit:0 -o ignore $(atf_get_srcdir)/frag-${1}.py \
228                 --to 192.0.2.2 \
229                 --fromaddr 192.0.2.1 \
230                 --sendif ${epair}b \
231                 --recvif ${epair}b
232 }
233
234 atf_test_case "overreplace" "cleanup"
235 overreplace_head()
236 {
237         atf_set descr 'ping fragment that overlaps fragment at index boundary and replace it'
238         atf_set require.user root
239         atf_set require.progs scapy
240 }
241
242 overreplace_body()
243 {
244         frag_common overreplace
245 }
246
247 overreplace_cleanup()
248 {
249         pft_cleanup
250 }
251
252 atf_test_case "overindex" "cleanup"
253 overindex_head()
254 {
255         atf_set descr 'ping fragment that overlaps the first fragment at index boundary'
256         atf_set require.user root
257         atf_set require.progs scapy
258 }
259
260 overindex_body()
261 {
262         frag_common overindex
263 }
264
265 overindex_cleanup()
266 {
267         pft_cleanup
268 }
269
270 atf_test_case "overlimit" "cleanup"
271 overlimit_head()
272 {
273         atf_set descr 'ping fragment at index boundary that cannot be requeued'
274         atf_set require.user root
275         atf_set require.progs scapy
276 }
277
278 overlimit_body()
279 {
280         frag_common overlimit
281 }
282
283 overlimit_cleanup()
284 {
285         pft_cleanup
286 }
287
288 atf_test_case "reassemble" "cleanup"
289 reassemble_head()
290 {
291         atf_set descr 'Test reassembly'
292         atf_set require.user root
293 }
294
295 reassemble_body()
296 {
297         pft_init
298
299         epair=$(vnet_mkepair)
300         vnet_mkjail alcatraz ${epair}a
301
302         ifconfig ${epair}b inet 192.0.2.1/24 up
303         jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up
304
305         # Sanity check
306         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
307
308         jexec alcatraz pfctl -e
309         pft_set_rules alcatraz \
310                 "pass out" \
311                 "block in" \
312                 "pass in inet proto icmp all icmp-type echoreq"
313
314         # Single fragment passes
315         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
316
317         # But a fragmented ping does not
318         atf_check -s exit:2 -o ignore ping -c 1 -s 2000 192.0.2.2
319
320         pft_set_rules alcatraz \
321                 "set reassemble yes" \
322                 "pass out" \
323                 "block in" \
324                 "pass in inet proto icmp all icmp-type echoreq"
325
326         # Both single packet & fragmented pass when we scrub
327         atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
328         atf_check -s exit:0 -o ignore ping -c 1 -s 2000 192.0.2.2
329 }
330
331 reassemble_cleanup()
332 {
333         pft_cleanup
334 }
335
336 atf_test_case "no_df" "cleanup"
337 no_df_head()
338 {
339         atf_set descr 'Test removing of DF flag'
340         atf_set require.user root
341 }
342
343 no_df_body()
344 {
345         setup_router_server_ipv4
346
347         ifconfig ${epair_tester}a mtu 9000
348         jexec router ifconfig ${epair_tester}b mtu 9000
349         jexec router ifconfig ${epair_server}a mtu 1500
350         jexec server ifconfig ${epair_server}b mtu 1500
351
352         # Sanity check.
353         ping_server_check_reply exit:0 --ping-type=icmp
354
355         pft_set_rules router \
356                 "set reassemble no" \
357                 "pass out" \
358                 "block in" \
359                 "pass in inet proto icmp all icmp-type echoreq"
360
361         # Ping with normal, fragmentable packets.
362         ping_server_check_reply exit:1 --ping-type=icmp --send-length=2000
363
364         pft_set_rules router \
365                 "set reassemble yes" \
366                 "pass out" \
367                 "block in" \
368                 "pass in inet proto icmp all icmp-type echoreq"
369
370         # Ping with normal, fragmentable packets.
371         ping_server_check_reply exit:0 --ping-type=icmp --send-length=2000
372
373         # Ping with non-fragmentable packets.
374         ping_server_check_reply exit:1 --ping-type=icmp --send-length=2000 --send-flags DF
375
376         pft_set_rules router \
377                 "set reassemble yes no-df" \
378                 "pass out" \
379                 "block in" \
380                 "pass in inet proto icmp all icmp-type echoreq"
381
382         # Ping with non-fragmentable packets again.
383         # This time pf will strip the DF flag.
384         ping_server_check_reply exit:0 --ping-type=icmp --send-length=2000 --send-flags DF
385 }
386 no_df_cleanup()
387 {
388         pft_cleanup
389 }
390
391 atf_test_case "no_df" "cleanup"
392 no_df_head()
393 {
394         atf_set descr 'Test removing of DF flag'
395         atf_set require.user root
396 }
397
398 no_df_body()
399 {
400         setup_router_server_ipv4
401
402         # Tester can send long packets which will get fragmented by the router.
403         # Replies from server will come in fragments which might get
404         # reassembled resulting in a long reply packet sent back to tester.
405         ifconfig ${epair_tester}a mtu 9000
406         jexec router ifconfig ${epair_tester}b mtu 9000
407         jexec router ifconfig ${epair_server}a mtu 1500
408         jexec server ifconfig ${epair_server}b mtu 1500
409
410         # Sanity check.
411         ping_server_check_reply exit:0 --ping-type=icmp
412
413         # Enable packet reassembly with clearing of the no-df flag.
414         pft_set_rules router \
415                 "scrub all fragment reassemble no-df" \
416                 "block" \
417                 "pass inet proto icmp all icmp-type echoreq"
418         # Ping with non-fragmentable packets.
419         # pf will strip the DF flag resulting in fragmentation and packets
420         # getting properly forwarded.
421         ping_server_check_reply exit:0 --ping-type=icmp --send-length=2000 --send-flags DF
422 }
423 no_df_cleanup()
424 {
425         pft_cleanup
426 }
427
428 atf_test_case "reassemble_slowpath" "cleanup"
429 reassemble_slowpath_head()
430 {
431         atf_set descr 'Test reassembly on the slow path'
432         atf_set require.user root
433 }
434
435 reassemble_slowpath_body()
436 {
437         if ! sysctl -q kern.features.ipsec >/dev/null ; then
438                 atf_skip "This test requires ipsec"
439         fi
440
441         setup_router_server_ipv4
442
443         # Now define an ipsec policy so we end up taking the slow path.
444         # We don't actually need the traffic to go through ipsec, we just don't
445         # want to go through ip_tryforward().
446         echo "flush;
447         spdflush;
448         spdadd 203.0.113.1/32 203.0.113.2/32 any -P out ipsec esp/transport//require;
449         add 203.0.113.1 203.0.113.2 esp 0x1001 -E aes-gcm-16 \"12345678901234567890\";" \
450             | jexec router setkey -c
451
452         # Sanity check.
453         ping_server_check_reply exit:0 --ping-type=icmp
454
455         # Enable packet reassembly with clearing of the no-df flag.
456         pft_set_rules router \
457                 "scrub in on ${epair_tester}b fragment no reassemble" \
458                 "scrub on ${epair_server}a fragment reassemble" \
459                 "pass"
460
461         # Ensure that the packet makes it through the slow path
462         atf_check -s exit:0 -o ignore \
463             ping -c 1 -s 2000 198.51.100.2
464 }
465
466 reassemble_slowpath_cleanup()
467 {
468         pft_cleanup
469 }
470
471 atf_init_test_cases()
472 {
473         atf_add_test_case "too_many_fragments"
474         atf_add_test_case "v6"
475         atf_add_test_case "mtu_diff"
476         atf_add_test_case "overreplace"
477         atf_add_test_case "overindex"
478         atf_add_test_case "overlimit"
479         atf_add_test_case "reassemble"
480         atf_add_test_case "no_df"
481         atf_add_test_case "reassemble_slowpath"
482 }