Skip to content

Commit de4ca48

Browse files
Routed network ACL: match protocol-number rules with ip protocol, not ip nexthdr (#14352)
Signed-off-by: Brad House <bhouse@nexthop.ai>
1 parent def2644 commit de4ca48

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

‎systemvm/debian/opt/cloud/bin/configure.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ def __process_routing_ip4(self, direction, rule_list):
450450
if protocol != "all":
451451
icmp_type = ""
452452
if protocol == "protocol":
453-
protocol = "ip nexthdr %d" % rule['protocol']
453+
protocol = "ip protocol %d" % rule['protocol']
454454
proto = protocol
455455
if proto == "icmp":
456456
proto = proto_str = "icmp"

‎systemvm/test/TestCsAclRouting.py‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
import unittest
19+
from configure import CsAcl
20+
21+
22+
class FakeConfig:
23+
24+
def __init__(self):
25+
self.fw = []
26+
self.ipv6_acl = []
27+
self.nft_ipv4_acl = []
28+
29+
def get_fw(self):
30+
return self.fw
31+
32+
def get_ipv6_acl(self):
33+
return self.ipv6_acl
34+
35+
def get_nft_ipv4_acl(self):
36+
return self.nft_ipv4_acl
37+
38+
def is_vpc(self):
39+
return True
40+
41+
def is_routed(self):
42+
return True
43+
44+
45+
class TestCsAclRouting(unittest.TestCase):
46+
47+
def test_protocol_number_rule(self):
48+
config = FakeConfig()
49+
obj = {"device": "eth3", "nic_ip": "10.1.1.1", "nic_netmask": "24", "nic_ip6_cidr": "fd00:1::/64",
50+
"ingress_rules": [{"type": "protocol", "protocol": 47, "cidr": "1.2.3.4/32,2001:db8::/64", "allowed": True}],
51+
"egress_rules": [{"type": "protocol", "protocol": 47, "cidr": "5.6.7.8/32", "allowed": False}]}
52+
acl = CsAcl.AclDevice(obj, config)
53+
acl.create()
54+
55+
# nexthdr is an IPv6 header field, nft rejects it in an ip rule
56+
ip4 = [r['rule'] for r in config.nft_ipv4_acl if r.get('chain') == "eth3_ingress_policy" and 'rule' in r]
57+
self.assertIn("ip saddr 1.2.3.4/32 ip protocol 47 accept", ip4)
58+
ip6 = [r['rule'] for r in config.ipv6_acl if r.get('chain') == "eth3_ingress_policy" and 'rule' in r]
59+
# the IPv4 match must not leak into the IPv6 rule
60+
self.assertTrue(any(r.startswith("ip6 saddr 2001:db8::/64 ") and r.endswith(" 47 accept") for r in ip6))
61+
self.assertFalse(any("ip protocol" in r for r in ip6))
62+
ip4 = [r['rule'] for r in config.nft_ipv4_acl if r.get('chain') == "eth3_egress_policy" and 'rule' in r]
63+
self.assertIn("ip daddr 5.6.7.8/32 ip protocol 47 drop", ip4)
64+
65+
66+
if __name__ == '__main__':
67+
unittest.main()

0 commit comments

Comments
 (0)