summaryrefslogtreecommitdiffstats
path: root/test/test_ipsec_default.py
diff options
context:
space:
mode:
authorZachary Leaf <zachary.leaf@arm.com>2021-10-26 10:05:58 -0500
committerFan Zhang <roy.fan.zhang@intel.com>2022-03-08 17:43:43 +0000
commit26fec718f2fa7913a484008fca7b1bc015c6efb5 (patch)
treed1ff50ea37c938f7caa4b88ca25885c13f83d4bb /test/test_ipsec_default.py
parent1031098b903e6eb4bca4d268350795e6827abdda (diff)
ipsec: input: drop by default for non-matching pkts
As per IPSec RFC4301 [1], any non-matching packets should be dropped by default. This is handled correctly in ipsec_output.c, however in ipsec_input.c non-matching packets are allowed to pass as per a matched BYPASS rule. For full details, see: https://lists.fd.io/g/vpp-dev/topic/ipsec_input_output_default/84943480 It appears the ipsec6_input_node only matches PROTECT policies. Until this is extended to handle BYPASS + DISCARD, we may wish to not drop by default here, since all IPv6 traffic not matching a PROTECT policy will be dropped. [1]: https://datatracker.ietf.org/doc/html/rfc4301 Type: fix Signed-off-by: Zachary Leaf <zachary.leaf@arm.com> Change-Id: Iddbfd008dbe082486d1928f6a10ffbd83d859a20
Diffstat (limited to 'test/test_ipsec_default.py')
-rw-r--r--test/test_ipsec_default.py156
1 files changed, 156 insertions, 0 deletions
diff --git a/test/test_ipsec_default.py b/test/test_ipsec_default.py
new file mode 100644
index 00000000000..71bbd759297
--- /dev/null
+++ b/test/test_ipsec_default.py
@@ -0,0 +1,156 @@
+import socket
+import unittest
+
+from util import ppp
+from framework import VppTestRunner
+from template_ipsec import IPSecIPv4Fwd
+
+"""
+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(IPSecIPv4Fwd):
+ """ 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("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(IPSecIPv4Fwd):
+ """ 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("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)