pf tests: Test unicast reverse path forwarding check
Ensure that pf's urpf-failed keyword works as expected. PR: 253479 MFC after: 1 week Reviewed by: melifaro@ Differential Revision: https://reviews.freebsd.org/D28694
This commit is contained in:
parent
9f6cf1426f
commit
6b52139eb8
@ -115,6 +115,35 @@ def check_ping6_request(args, packet):
|
||||
|
||||
return True
|
||||
|
||||
def check_ping_reply(args, packet):
|
||||
return check_ping4_reply(args, packet)
|
||||
|
||||
def check_ping4_reply(args, packet):
|
||||
"""
|
||||
Check that this is a reply to the ping request we sent
|
||||
"""
|
||||
dst_ip = args.to[0]
|
||||
|
||||
ip = packet.getlayer(sp.IP)
|
||||
if not ip:
|
||||
return False
|
||||
if ip.src != dst_ip:
|
||||
return False
|
||||
|
||||
icmp = packet.getlayer(sp.ICMP)
|
||||
if not icmp:
|
||||
return False
|
||||
if sp.icmptypes[icmp.type] != 'echo-reply':
|
||||
return False
|
||||
|
||||
raw = packet.getlayer(sp.Raw)
|
||||
if not raw:
|
||||
return False
|
||||
if raw.load != PAYLOAD_MAGIC:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def ping(send_if, dst_ip, args):
|
||||
ether = sp.Ether()
|
||||
ip = sp.IP(dst=dst_ip)
|
||||
@ -124,6 +153,9 @@ def ping(send_if, dst_ip, args):
|
||||
if args.send_tos:
|
||||
ip.tos = int(args.send_tos[0])
|
||||
|
||||
if args.fromaddr:
|
||||
ip.src = args.fromaddr[0]
|
||||
|
||||
req = ether / ip / icmp / raw
|
||||
sp.sendp(req, iface=send_if, verbose=False)
|
||||
|
||||
@ -132,6 +164,9 @@ def ping6(send_if, dst_ip, args):
|
||||
ip6 = sp.IPv6(dst=dst_ip)
|
||||
icmp = sp.ICMPv6EchoRequest(data=sp.raw(PAYLOAD_MAGIC))
|
||||
|
||||
if args.fromaddr:
|
||||
ip.src = args.fromaddr[0]
|
||||
|
||||
req = ether / ip6 / icmp
|
||||
sp.sendp(req, iface=send_if, verbose=False)
|
||||
|
||||
@ -189,6 +224,8 @@ def main():
|
||||
required=True,
|
||||
help='The interface through which the packet(s) will be sent')
|
||||
parser.add_argument('--recvif', nargs=1,
|
||||
help='The interface on which to expect the ICMP echo request')
|
||||
parser.add_argument('--replyif', nargs=1,
|
||||
help='The interface on which to expect the ICMP echo response')
|
||||
parser.add_argument('--checkdup', nargs=1,
|
||||
help='The interface on which to expect the duplicated ICMP packets')
|
||||
@ -197,6 +234,8 @@ def main():
|
||||
parser.add_argument('--to', nargs=1,
|
||||
required=True,
|
||||
help='The destination IP address for the ICMP echo request')
|
||||
parser.add_argument('--fromaddr', nargs=1,
|
||||
help='The source IP address for the ICMP echo request')
|
||||
|
||||
# TCP options
|
||||
parser.add_argument('--tcpsyn', action='store_true',
|
||||
@ -225,6 +264,11 @@ def main():
|
||||
|
||||
sniffer = Sniffer(args, checkfn)
|
||||
|
||||
replysniffer = None
|
||||
if not args.replyif is None:
|
||||
checkfn=check_ping_reply
|
||||
replysniffer = Sniffer(args, checkfn, recvif=args.replyif[0])
|
||||
|
||||
dupsniffer = None
|
||||
if args.checkdup is not None:
|
||||
dupsniffer = Sniffer(args, check_dup, recvif=args.checkdup[0])
|
||||
@ -250,5 +294,13 @@ def main():
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
if replysniffer:
|
||||
replysniffer.join()
|
||||
|
||||
if replysniffer.foundCorrectPacket:
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
. $(atf_get_srcdir)/utils.subr
|
||||
|
||||
common_dir=$(atf_get_srcdir)/../common
|
||||
|
||||
atf_test_case "v4" "cleanup"
|
||||
v4_head()
|
||||
{
|
||||
@ -189,10 +191,75 @@ nested_inline_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "urpf" "cleanup"
|
||||
urpf_head()
|
||||
{
|
||||
atf_set descr "Test unicast reverse path forwarding check"
|
||||
atf_set require.user root
|
||||
atf_set require.progs scapy
|
||||
}
|
||||
|
||||
urpf_body()
|
||||
{
|
||||
pft_init
|
||||
|
||||
epair_one=$(vnet_mkepair)
|
||||
epair_two=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail alcatraz ${epair_one}b ${epair_two}b
|
||||
|
||||
ifconfig ${epair_one}a 192.0.2.2/24 up
|
||||
ifconfig ${epair_two}a 198.51.100.2/24 up
|
||||
|
||||
jexec alcatraz ifconfig ${epair_one}b 192.0.2.1/24 up
|
||||
jexec alcatraz ifconfig ${epair_two}b 198.51.100.1/24 up
|
||||
jexec alcatraz sysctl net.inet.ip.forwarding=1
|
||||
|
||||
# Sanity checks
|
||||
atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
|
||||
atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1
|
||||
atf_check -s exit:0 ${common_dir}/pft_ping.py \
|
||||
--sendif ${epair_one}a \
|
||||
--to 192.0.2.1 \
|
||||
--fromaddr 198.51.100.2 \
|
||||
--replyif ${epair_two}a
|
||||
atf_check -s exit:0 ${common_dir}/pft_ping.py \
|
||||
--sendif ${epair_two}a \
|
||||
--to 198.51.100.1 \
|
||||
--fromaddr 192.0.2.2 \
|
||||
--replyif ${epair_one}a
|
||||
|
||||
pft_set_rules alcatraz \
|
||||
"block quick from urpf-failed"
|
||||
jexec alcatraz pfctl -e
|
||||
|
||||
# Correct source still works
|
||||
atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
|
||||
atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.1
|
||||
|
||||
# Unexpected source interface is blocked
|
||||
atf_check -s exit:1 ${common_dir}/pft_ping.py \
|
||||
--sendif ${epair_one}a \
|
||||
--to 192.0.2.1 \
|
||||
--fromaddr 198.51.100.2 \
|
||||
--replyif ${epair_two}a
|
||||
atf_check -s exit:1 ${common_dir}/pft_ping.py \
|
||||
--sendif ${epair_two}a \
|
||||
--to 198.51.100.1 \
|
||||
--fromaddr 192.0.2.2 \
|
||||
--replyif ${epair_one}a
|
||||
}
|
||||
|
||||
urpf_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "v4"
|
||||
atf_add_test_case "v6"
|
||||
atf_add_test_case "noalias"
|
||||
atf_add_test_case "nested_inline"
|
||||
atf_add_test_case "urpf"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user