diff options
Diffstat (limited to 'test/test_ipsec_default.py')
-rw-r--r-- | test/test_ipsec_default.py | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/test/test_ipsec_default.py b/test/test_ipsec_default.py new file mode 100644 index 00000000000..2fefb771c48 --- /dev/null +++ b/test/test_ipsec_default.py @@ -0,0 +1,199 @@ +import socket +import unittest + +from util import ppp +from asfframework import VppTestRunner +from template_ipsec import IpsecDefaultTemplate + +""" +When an IPSec SPD is configured on an interface, any inbound packets +not matching inbound policies, or outbound packets not matching outbound +policies, must be dropped by default as per RFC4301. + +This test uses simple IPv4 forwarding on interfaces with IPSec enabled +to check if packets with no matching rules are dropped by default. + +The basic setup is a single SPD bound to two interfaces, pg0 and pg1. + + ┌────┐ ┌────┐ + │SPD1│ │SPD1│ + ├────┤ ─────> ├────┤ + │PG0 │ │PG1 │ + └────┘ └────┘ + +First, both inbound and outbound BYPASS policies are configured allowing +traffic to pass from pg0 -> pg1. + +Packets are captured and verified at pg1. + +Then either the inbound or outbound policies are removed and we verify +packets are dropped as expected. + +""" + + +class IPSecInboundDefaultDrop(IpsecDefaultTemplate): + """IPSec: inbound packets drop by default with no matching rule""" + + def test_ipsec_inbound_default_drop(self): + # configure two interfaces and bind the same SPD to both + self.create_interfaces(2) + self.spd_create_and_intf_add(1, self.pg_interfaces) + pkt_count = 5 + + # catch-all inbound BYPASS policy, all interfaces + inbound_policy = self.spd_add_rem_policy( + 1, + None, + None, + socket.IPPROTO_UDP, + is_out=0, + priority=10, + policy_type="bypass", + all_ips=True, + ) + + # outbound BYPASS policy allowing traffic from pg0->pg1 + outbound_policy = self.spd_add_rem_policy( + 1, + self.pg0, + self.pg1, + socket.IPPROTO_UDP, + is_out=1, + priority=10, + policy_type="bypass", + ) + + # create a packet stream pg0->pg1 + add to pg0 + packets0 = self.create_stream(self.pg0, self.pg1, pkt_count) + self.pg0.add_stream(packets0) + + # with inbound BYPASS rule at pg0, we expect to see forwarded + # packets on pg1 + self.pg_interfaces[1].enable_capture() + self.pg_start() + cap1 = self.pg1.get_capture() + for packet in cap1: + try: + self.logger.debug(ppp("SPD - Got packet:", packet)) + except Exception: + self.logger.error(ppp("Unexpected or invalid packet:", packet)) + raise + self.logger.debug("SPD: Num packets: %s", len(cap1.res)) + # verify captures on pg1 + self.verify_capture(self.pg0, self.pg1, cap1) + # verify policies matched correct number of times + self.verify_policy_match(pkt_count, inbound_policy) + self.verify_policy_match(pkt_count, outbound_policy) + + # remove inbound catch-all BYPASS rule, traffic should now be dropped + self.spd_add_rem_policy( # inbound, all interfaces + 1, + None, + None, + socket.IPPROTO_UDP, + is_out=0, + priority=10, + policy_type="bypass", + all_ips=True, + remove=True, + ) + + # create another packet stream pg0->pg1 + add to pg0 + packets1 = self.create_stream(self.pg0, self.pg1, pkt_count) + self.pg0.add_stream(packets1) + self.pg_interfaces[1].enable_capture() + self.pg_start() + # confirm traffic has now been dropped + self.pg1.assert_nothing_captured( + remark="inbound pkts with no matching" "rules NOT dropped by default" + ) + # both policies should not have matched any further packets + # since we've dropped at input stage + self.verify_policy_match(pkt_count, outbound_policy) + self.verify_policy_match(pkt_count, inbound_policy) + + +class IPSecOutboundDefaultDrop(IpsecDefaultTemplate): + """IPSec: outbound packets drop by default with no matching rule""" + + def test_ipsec_inbound_default_drop(self): + # configure two interfaces and bind the same SPD to both + self.create_interfaces(2) + self.spd_create_and_intf_add(1, self.pg_interfaces) + pkt_count = 5 + + # catch-all inbound BYPASS policy, all interfaces + inbound_policy = self.spd_add_rem_policy( + 1, + None, + None, + socket.IPPROTO_UDP, + is_out=0, + priority=10, + policy_type="bypass", + all_ips=True, + ) + + # outbound BYPASS policy allowing traffic from pg0->pg1 + outbound_policy = self.spd_add_rem_policy( + 1, + self.pg0, + self.pg1, + socket.IPPROTO_UDP, + is_out=1, + priority=10, + policy_type="bypass", + ) + + # create a packet stream pg0->pg1 + add to pg0 + packets0 = self.create_stream(self.pg0, self.pg1, pkt_count) + self.pg0.add_stream(packets0) + + # with outbound BYPASS rule allowing pg0->pg1, we expect to see + # forwarded packets on pg1 + self.pg_interfaces[1].enable_capture() + self.pg_start() + cap1 = self.pg1.get_capture() + for packet in cap1: + try: + self.logger.debug(ppp("SPD - Got packet:", packet)) + except Exception: + self.logger.error(ppp("Unexpected or invalid packet:", packet)) + raise + self.logger.debug("SPD: Num packets: %s", len(cap1.res)) + # verify captures on pg1 + self.verify_capture(self.pg0, self.pg1, cap1) + # verify policies matched correct number of times + self.verify_policy_match(pkt_count, inbound_policy) + self.verify_policy_match(pkt_count, outbound_policy) + + # remove outbound rule + self.spd_add_rem_policy( + 1, + self.pg0, + self.pg1, + socket.IPPROTO_UDP, + is_out=1, + priority=10, + policy_type="bypass", + remove=True, + ) + + # create another packet stream pg0->pg1 + add to pg0 + packets1 = self.create_stream(self.pg0, self.pg1, pkt_count) + self.pg0.add_stream(packets1) + self.pg_interfaces[1].enable_capture() + self.pg_start() + # confirm traffic was dropped and not forwarded + self.pg1.assert_nothing_captured( + remark="outbound pkts with no matching rules NOT dropped " "by default" + ) + # inbound rule should have matched twice the # of pkts now + self.verify_policy_match(pkt_count * 2, inbound_policy) + # as dropped at outbound, outbound policy is the same + self.verify_policy_match(pkt_count, outbound_policy) + + +if __name__ == "__main__": + unittest.main(testRunner=VppTestRunner) |