mirror of
https://github.com/opnsense/src.git
synced 2026-02-04 03:00:53 -06:00
pf tests: add more fragmentation test cases
Add more test cases for pf fragment hole counter. Also look into
final fragment of echo reply and check total length of IP packet.
MFC after: 1 week
Obtained from: OpenBSD, bluhm <bluhm@openbsd.org>, 640736615b
Sponsored by: Rubicon Communications, LLC ("Netgate")
(cherry picked from commit db100bd93036855c7688dc088b811dc7b660f51d)
This commit is contained in:
parent
5be39bc21c
commit
b8ab1d06e8
@ -62,6 +62,8 @@ ${PACKAGE}FILES+= CVE-2019-5597.py \
|
||||
frag-overindex.py \
|
||||
frag-overlimit.py \
|
||||
frag-overreplace.py \
|
||||
frag-overhole.py \
|
||||
frag-adjhole.py \
|
||||
pfsync_defer.py \
|
||||
pft_ether.py \
|
||||
rdr-srcport.py \
|
||||
@ -73,6 +75,8 @@ ${PACKAGE}FILESMODE_fragcommon.py= 0555
|
||||
${PACKAGE}FILESMODE_frag-overindex.py= 0555
|
||||
${PACKAGE}FILESMODE_frag-overlimit.py= 0555
|
||||
${PACKAGE}FILESMODE_frag-overreplace.py= 0555
|
||||
${PACKAGE}FILESMODE_frag-overhole.py= 0555
|
||||
${PACKAGE}FILESMODE_frag-adjhole.py= 0555
|
||||
${PACKAGE}FILESMODE_pfsync_defer.py= 0555
|
||||
${PACKAGE}FILESMODE_pft_ether.py= 0555
|
||||
|
||||
|
||||
58
tests/sys/netpfil/pf/frag-adjhole.py
Normal file
58
tests/sys/netpfil/pf/frag-adjhole.py
Normal file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2025 Alexander Bluhm <bluhm@openbsd.org>
|
||||
|
||||
from fragcommon import *
|
||||
|
||||
# |--------|
|
||||
# |--------|
|
||||
# |-------|
|
||||
# |----|
|
||||
|
||||
def send(src, dst, send_if, recv_if):
|
||||
pid = os.getpid()
|
||||
eid = pid & 0xffff
|
||||
payload = b"ABCDEFGHIJKLMNOP" * 2
|
||||
packet = sp.IP(src=src, dst=dst)/ \
|
||||
sp.ICMP(type='echo-request', id=eid) / payload
|
||||
frag = []
|
||||
fid = pid & 0xffff
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
flags='MF') / bytes(packet)[20:36])
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=2, flags='MF') / bytes(packet)[36:52])
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=1, flags='MF') / bytes(packet)[28:44])
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=4) / bytes(packet)[52:60])
|
||||
eth=[]
|
||||
for f in frag:
|
||||
eth.append(sp.Ether()/f)
|
||||
if os.fork() == 0:
|
||||
time.sleep(1)
|
||||
sp.sendp(eth, iface=send_if)
|
||||
os._exit(0)
|
||||
|
||||
ans = sp.sniff(iface=recv_if, timeout=3, filter=
|
||||
"ip and src " + dst + " and dst " + src + " and icmp")
|
||||
for a in ans:
|
||||
if a and a.type == sp.ETH_P_IP and \
|
||||
a.payload.proto == 1 and \
|
||||
a.payload.frag == 0 and a.payload.flags == 0 and \
|
||||
sp.icmptypes[a.payload.payload.type] == 'echo-reply':
|
||||
id = a.payload.payload.id
|
||||
print("id=%#x" % (id))
|
||||
if id != eid:
|
||||
print("WRONG ECHO REPLY ID")
|
||||
exit(2)
|
||||
data = a.payload.payload.payload.load
|
||||
print("payload=%s" % (data))
|
||||
if data == payload:
|
||||
exit(0)
|
||||
print("PAYLOAD!=%s" % (payload))
|
||||
exit(1)
|
||||
print("NO ECHO REPLY")
|
||||
exit(2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(send)
|
||||
83
tests/sys/netpfil/pf/frag-overhole.py
Normal file
83
tests/sys/netpfil/pf/frag-overhole.py
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2025 Alexander Bluhm <bluhm@openbsd.org>
|
||||
|
||||
from fragcommon import *
|
||||
|
||||
# index boundary 4096 |
|
||||
# |--------------|
|
||||
# ....
|
||||
# |--------------|
|
||||
# |----------|
|
||||
# |XXXX----------|
|
||||
# |XXXX----|
|
||||
# |---|
|
||||
|
||||
# this should trigger "frag tail overlap %d" and "frag head overlap %d"
|
||||
def send(src, dst, send_if, recv_if):
|
||||
pid = os.getpid()
|
||||
eid = pid & 0xffff
|
||||
payload = b"ABCDEFGHIJKLMNOP"
|
||||
dummy = b"01234567"
|
||||
fragsize = 1024
|
||||
boundary = 4096
|
||||
fragnum = int(boundary / fragsize)
|
||||
packet = sp.IP(src=src, dst=dst)/ \
|
||||
sp.ICMP(type='echo-request', id=eid)/ \
|
||||
((int((boundary + fragsize) / len(payload)) + 1) * payload)
|
||||
packet_length = len(packet)
|
||||
frag = []
|
||||
fid = pid & 0xffff
|
||||
for i in range(fragnum-1):
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=(i * fragsize)>>3, flags='MF')/
|
||||
bytes(packet)[20 + i * fragsize:20 + (i + 1) * fragsize])
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=(boundary - fragsize) >> 3, flags='MF')/
|
||||
bytes(packet)[20 + boundary - fragsize:20 + boundary - len(dummy)])
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=(boundary - len(dummy)) >> 3, flags='MF')/
|
||||
(dummy+bytes(packet)[20 + boundary:20 + boundary + fragsize]))
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=(boundary - 8 - len(dummy)) >> 3, flags='MF')/
|
||||
(dummy+bytes(packet)[20 + boundary - 8:20 + boundary]))
|
||||
frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid,
|
||||
frag=(boundary + fragsize) >> 3)/bytes(packet)[20 + boundary + fragsize:])
|
||||
eth=[]
|
||||
for f in frag:
|
||||
eth.append(sp.Ether() / f)
|
||||
|
||||
if os.fork() == 0:
|
||||
time.sleep(1)
|
||||
for e in eth:
|
||||
sp.sendp(e, iface=send_if)
|
||||
time.sleep(0.001)
|
||||
os._exit(0)
|
||||
|
||||
ans = sp.sniff(iface=recv_if, timeout=3, filter=
|
||||
"ip and src " + dst + " and dst " + src + " and icmp")
|
||||
for a in ans:
|
||||
if a and a.type == sp.ETH_P_IP and \
|
||||
a.payload.proto == 1 and \
|
||||
a.payload.frag == 0 and \
|
||||
sp.icmptypes[a.payload.payload.type] == 'echo-reply':
|
||||
id = a.payload.payload.id
|
||||
print("id=%#x" % (id))
|
||||
if id != eid:
|
||||
print("WRONG ECHO REPLY ID")
|
||||
exit(2)
|
||||
if a and a.type == sp.ETH_P_IP and \
|
||||
a.payload.proto == 1 and \
|
||||
a.payload.frag > 0 and \
|
||||
a.payload.flags == '':
|
||||
length = (a.payload.frag << 3) + a.payload.len
|
||||
print("len=%d" % (length))
|
||||
if length != packet_length:
|
||||
print("WRONG ECHO REPLY LENGTH")
|
||||
exit(1)
|
||||
exit(0)
|
||||
print("NO ECHO REPLY")
|
||||
exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(send)
|
||||
@ -285,6 +285,42 @@ overlimit_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "overhole" "cleanup"
|
||||
overhole_head()
|
||||
{
|
||||
atf_set descr 'ping fragment at index boundary which modifies pf hole counter'
|
||||
atf_set require.user root
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
overhole_body()
|
||||
{
|
||||
frag_common overhole
|
||||
}
|
||||
|
||||
overhole_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "adjhole" "cleanup"
|
||||
adjhole_head()
|
||||
{
|
||||
atf_set descr 'overlapping ping fragments which modifies pf hole counter'
|
||||
atf_set require.user root
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
adjhole_body()
|
||||
{
|
||||
frag_common adjhole
|
||||
}
|
||||
|
||||
adjhole_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "reassemble" "cleanup"
|
||||
reassemble_head()
|
||||
{
|
||||
@ -476,6 +512,8 @@ atf_init_test_cases()
|
||||
atf_add_test_case "overreplace"
|
||||
atf_add_test_case "overindex"
|
||||
atf_add_test_case "overlimit"
|
||||
atf_add_test_case "overhole"
|
||||
atf_add_test_case "adjhole"
|
||||
atf_add_test_case "reassemble"
|
||||
atf_add_test_case "no_df"
|
||||
atf_add_test_case "reassemble_slowpath"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user