mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04: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")
This commit is contained in:
parent
8b2feafb53
commit
db100bd930
4 changed files with 183 additions and 0 deletions
|
|
@ -71,6 +71,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 \
|
||||
pft_read_ipfix.py \
|
||||
|
|
@ -83,6 +85,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
|
||||
${PACKAGE}FILESMODE_pft_read_ipfix.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)
|
||||
|
|
@ -354,6 +354,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()
|
||||
{
|
||||
|
|
@ -618,6 +654,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…
Reference in a new issue