mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-07 00:50:50 +00:00
pf tests: test pflow NAT state information
pflow(4) now also exports NAT session creation/destruction information. Test that this works as expected. While here improve the parsing of ipfix (i.e. pflowproto 10) a bit, and check more information for the existing state information exports. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D43117
This commit is contained in:
parent
2be6f75707
commit
c4d97a9487
|
@ -124,7 +124,7 @@ state_defaults_body()
|
|||
ping -c 1 192.0.2.1
|
||||
|
||||
# We default to version 5
|
||||
atf_check -o match:"^v=5.*" \
|
||||
atf_check -o match:".*v=5.*" \
|
||||
$(atf_get_srcdir)/pft_read_ipfix.py --recvif ${epair}a --port 2055
|
||||
|
||||
# Switch to version 10
|
||||
|
@ -132,7 +132,7 @@ state_defaults_body()
|
|||
|
||||
ping -c 1 192.0.2.1
|
||||
|
||||
atf_check -o match:"^v=10.*" \
|
||||
atf_check -o match:".*v=10.*" \
|
||||
$(atf_get_srcdir)/pft_read_ipfix.py --recvif ${epair}a --port 2055
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ v6_body()
|
|||
|
||||
ping -6 -c 1 2001:db8::1
|
||||
|
||||
atf_check -o match:"^v=10.*" \
|
||||
atf_check -o match:".*v=10,IPv6,proto=58,src=2001:db8::2,dst=2001:db8::1.*" \
|
||||
$(atf_get_srcdir)/pft_read_ipfix.py --recvif ${epair}a --port 2055
|
||||
}
|
||||
|
||||
|
@ -183,9 +183,61 @@ v6_cleanup()
|
|||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "nat" "cleanup"
|
||||
nat_head()
|
||||
{
|
||||
atf_set descr 'Test pflow export for NAT44'
|
||||
atf_set require.user root
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
nat_body()
|
||||
{
|
||||
pflow_init
|
||||
|
||||
epair=$(vnet_mkepair)
|
||||
epair_srv=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail srv ${epair_srv}a
|
||||
vnet_mkjail rtr ${epair_srv}b ${epair}a
|
||||
|
||||
ifconfig ${epair}b 192.0.2.2/24 up
|
||||
|
||||
jexec srv ifconfig ${epair_srv}a 198.51.100.2/24 up
|
||||
jexec srv route add default 198.51.100.1
|
||||
|
||||
jexec rtr ifconfig ${epair_srv}b 198.51.100.1/24 up
|
||||
jexec rtr ifconfig ${epair}a 192.0.2.1/24 up
|
||||
jexec rtr sysctl net.inet.ip.forwarding=1
|
||||
|
||||
route add -net 198.51.100.0/24 192.0.2.1
|
||||
|
||||
jexec rtr pfctl -e
|
||||
pft_set_rules rtr \
|
||||
"set state-defaults pflow" \
|
||||
"nat pass on ${epair_srv}b inet from 192.0.2.0/24 to any -> (${epair_srv}b)" \
|
||||
"pass"
|
||||
|
||||
pflow=$(jexec rtr pflowctl -c)
|
||||
jexec rtr pflowctl -s ${pflow} dst 192.0.2.2:2055 proto 10
|
||||
|
||||
# Sanity check
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -c 1 198.51.100.2
|
||||
|
||||
atf_check -o match:".*v=10,NAT=4,proto=1,src=192.0.2.2-198.51.100.1.*" \
|
||||
$(atf_get_srcdir)/pft_read_ipfix.py --recvif ${epair}b --port 2055
|
||||
}
|
||||
|
||||
nat_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "basic"
|
||||
atf_add_test_case "state_defaults"
|
||||
atf_add_test_case "v6"
|
||||
atf_add_test_case "nat"
|
||||
}
|
||||
|
|
|
@ -31,6 +31,34 @@
|
|||
logging.getLogger("scapy").setLevel(logging.CRITICAL)
|
||||
import scapy.all as sp
|
||||
|
||||
def parse_ipfix(p):
|
||||
if not sp.NetflowDataflowsetV9 in p:
|
||||
# A template?
|
||||
return
|
||||
|
||||
c = p
|
||||
while sp.NetflowDataflowsetV9 in c:
|
||||
datafl = c[sp.NetflowDataflowsetV9]
|
||||
if datafl.templateID == 258:
|
||||
# NAT
|
||||
for r in datafl.records:
|
||||
print("v=10,NAT=%d,proto=%s,src=%s-%s,dst=%s-%s" %
|
||||
(int.from_bytes(r.natEvent, "big"), r.PROTOCOL,
|
||||
r.IPV4_SRC_ADDR, r.postNATSourceIPv4Address,
|
||||
r.IPV4_DST_ADDR, r.postNATDestinationIPv4Address))
|
||||
elif datafl.templateID == 257:
|
||||
# IPv6
|
||||
for r in datafl.records:
|
||||
print("v=10,IPv6,proto=%s,src=%s,dst=%s" %
|
||||
(r.PROTOCOL, r.IPV6_SRC_ADDR, r.IPV6_DST_ADDR))
|
||||
elif datafl.templateID == 256:
|
||||
# IPv4
|
||||
for r in datafl.records:
|
||||
print("v=10,proto=%s,src=%s,dst=%s" %
|
||||
(r.PROTOCOL, r.IPV4_SRC_ADDR, r.IPV4_DST_ADDR))
|
||||
|
||||
c = datafl.payload
|
||||
|
||||
def receive(recvif, recvport):
|
||||
pkts = sp.sniff(iface=recvif, timeout=65)
|
||||
|
||||
|
@ -38,6 +66,8 @@ def receive(recvif, recvport):
|
|||
print("No data")
|
||||
return
|
||||
|
||||
pkts = sp.ipfix_defragment(pkts)
|
||||
|
||||
for pkt in pkts:
|
||||
udp = pkt.getlayer(sp.UDP)
|
||||
if not udp:
|
||||
|
@ -46,18 +76,19 @@ def receive(recvif, recvport):
|
|||
if udp.dport != recvport:
|
||||
continue
|
||||
|
||||
hdr = pkt.getlayer(sp.NetflowHeader)
|
||||
if not sp.NetflowHeader in pkt:
|
||||
continue
|
||||
|
||||
hdr = pkt.getlayer(sp.NetflowHeader)
|
||||
if hdr.version == 5:
|
||||
v5hdr = pkt.getlayer(sp.NetflowHeaderV5)
|
||||
out=""
|
||||
for i in range(1, v5hdr.count + 1):
|
||||
r = pkt.getlayer(sp.NetflowRecordV5, nb=i)
|
||||
out = "%s,proto=%d,src=%s,dst=%s,srcport=%d,dstport=%d" % (out, r.prot, r.src, r.dst, r.srcport, r.dstport)
|
||||
print("v=%d,count=%d%s" % (hdr.version, v5hdr.count, out))
|
||||
print("v=%d,proto=%d,src=%s,dst=%s,srcport=%d,dstport=%d" %
|
||||
(hdr.version, r.prot, r.src, r.dst, r.srcport, r.dstport))
|
||||
elif hdr.version == 10:
|
||||
print("v=10")
|
||||
return
|
||||
parse_ipfix(pkt)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser("pft_read_ipfix.py",
|
||||
|
|
Loading…
Reference in a new issue