diff options
author | Andrew Topp <andrewt@telekinetica.net> | 2024-08-04 17:52:57 +1000 |
---|---|---|
committer | Andrew Topp <andrewt@telekinetica.net> | 2024-08-04 17:52:57 +1000 |
commit | 60b0614296874c144665417130d4881461114db0 (patch) | |
tree | 404eb8bf72582b60cad69d9c23535b41a49094f6 /smoketest | |
parent | 15c77978f30bebe7c6d4f4e9a87c56e12e1382cd (diff) | |
download | vyos-1x-60b0614296874c144665417130d4881461114db0.tar.gz vyos-1x-60b0614296874c144665417130d4881461114db0.zip |
firewall: T4694: Adding GRE flags & fields matches to firewall rules
* Only matching flags and fields used by modern RFC2890 "extended GRE" -
this is backwards-compatible, but does not match all possible flags.
* There are no nftables helpers for the GRE key field, which is critical
to match individual tunnel sessions (more detail in the forum post)
* nft expression syntax is not flexible enough for multiple field
matches in a single rule and the key offset changes depending on flags.
* Thus, clumsy compromise in requiring an explicit match on the "checksum"
flag if a key is present, so we know where key will be. In most cases,
nobody uses the checksum, but assuming it to be off or automatically
adding a "not checksum" match unless told otherwise would be confusing
* The automatic "flags key" check when specifying a key doesn't have similar
validation, I added it first and it makes sense. I would still like
to find a workaround to the "checksum" offset problem.
* If we could add 2 rules from 1 config definition, we could match
both cases with appropriate offsets, but this would break existing
FW generation logic, logging, etc.
* Added a "test_gre_match" smoketest
Diffstat (limited to 'smoketest')
-rwxr-xr-x | smoketest/scripts/cli/test_firewall.py | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 551f8ce65..dfc816a42 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -1100,5 +1100,60 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): with self.assertRaises(ConfigSessionError): self.cli_commit() + def test_gre_match(self): + name = 'smoketest-gre' + + self.cli_set(['firewall', 'ipv4', 'name', name, 'default-action', 'return']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'protocol', 'gre']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'gre', 'flags', 'key']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'gre', 'flags', 'checksum', 'unset']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'gre', 'key', '1234']) + self.cli_set(['firewall', 'ipv4', 'name', name, 'rule', '1', 'log']) + + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '2', 'action', 'continue']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '2', 'protocol', 'gre']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '2', 'gre', 'inner-proto', '0x6558']) + self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '2', 'log']) + + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'protocol', 'gre']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'gre', 'flags', 'checksum']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'gre', 'key', '4321']) + + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '4', 'action', 'reject']) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '4', 'protocol', 'gre']) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '4', 'gre', 'version', 'pptp']) + + self.cli_commit() + + nftables_search_v4 = [ + ['gre protocol 0x6558', 'continue comment'], + ['gre flags & 5 == 4 @th,32,32 0x4d2', 'accept comment'], + ] + + nftables_search_v6 = [ + ['gre flags & 5 == 5 @th,64,32 0x10e1', 'drop comment'], + ['gre version 1', 'reject comment'], + ] + + self.verify_nftables(nftables_search_v4, 'ip vyos_filter') + self.verify_nftables(nftables_search_v6, 'ip6 vyos_filter') + + # GRE match will only work with protocol GRE + self.cli_delete(['firewall', 'ipv4', 'name', name, 'rule', '1', 'protocol', 'gre']) + + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_discard() + + # GREv1 (PPTP) does not include a key field, match not available + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '4', 'gre', 'flags', 'checksum', 'unset']) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '4', 'gre', 'key', '1234']) + + with self.assertRaises(ConfigSessionError): + self.cli_commit() + if __name__ == '__main__': unittest.main(verbosity=2) |