summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/firewall.xml.in2
-rw-r--r--interface-definitions/include/firewall/packet-length.xml.i18
-rw-r--r--python/vyos/firewall.py23
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py22
-rwxr-xr-xsrc/validators/packet-length29
5 files changed, 93 insertions, 1 deletions
diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in
index 9488ddcdc..cca3c0f7d 100644
--- a/interface-definitions/firewall.xml.in
+++ b/interface-definitions/firewall.xml.in
@@ -383,6 +383,7 @@
</children>
</node>
#include <include/firewall/common-rule.xml.i>
+ #include <include/firewall/packet-length.xml.i>
<node name="hop-limit">
<properties>
<help>Hop Limit</help>
@@ -571,6 +572,7 @@
</children>
</node>
#include <include/firewall/common-rule.xml.i>
+ #include <include/firewall/packet-length.xml.i>
<node name="icmp">
<properties>
<help>ICMP type and code information</help>
diff --git a/interface-definitions/include/firewall/packet-length.xml.i b/interface-definitions/include/firewall/packet-length.xml.i
new file mode 100644
index 000000000..866a76bbb
--- /dev/null
+++ b/interface-definitions/include/firewall/packet-length.xml.i
@@ -0,0 +1,18 @@
+<!-- include start from firewall/packet-length.xml.i -->
+<leafNode name="packet-length">
+ <properties>
+ <help>Payload size in bytes, including header and data</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Packet length value. Multiple values can be specified as a comma-separated list. Inverted match is also supported</description>
+ </valueHelp>
+ <valueHelp>
+ <format>&lt;start-end&gt;</format>
+ <description>Packet length range. Inverted match is also supported (e.g. 1001-1005 or !1001-1005)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="packet-length"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py
index 663c4394a..ea28aa91d 100644
--- a/python/vyos/firewall.py
+++ b/python/vyos/firewall.py
@@ -265,6 +265,29 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name):
if 'type' in rule_conf[icmp]:
output.append(icmp + ' type ' + rule_conf[icmp]['type'])
+
+ if 'packet_length' in rule_conf:
+ #proto = rule_conf['protocol']
+ length = rule_conf['packet_length'].split(',')
+
+ lengths = []
+ negated_lengths = []
+
+ for p in length:
+ if p[0] == '!':
+ negated_lengths.append(p[1:])
+ else:
+ lengths.append(p)
+
+ if lengths:
+ lengths_str = ','.join(lengths)
+ output.append(f'ip{def_suffix} length {{{lengths_str}}}')
+
+ if negated_lengths:
+ negated_lengths_str = ','.join(negated_lengths)
+ output.append(f'ip{def_suffix} length != {{{negated_lengths_str}}}')
+
+
if 'ipsec' in rule_conf:
if 'match_ipsec' in rule_conf['ipsec']:
output.append('meta ipsec == 1')
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index 684a07681..8b6c221e3 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -209,6 +209,13 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '5', 'tcp', 'flags', 'syn'])
self.cli_set(['firewall', 'name', 'smoketest', 'rule', '5', 'tcp', 'mss', mss_range])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '6', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '6', 'packet-length', '64,512,1024'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '7', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '7', 'packet-length', '0-30000'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '8', 'action', 'accept'])
+ self.cli_set(['firewall', 'name', 'smoketest', 'rule', '8', 'packet-length', '!60000-65535'])
+
self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest'])
self.cli_commit()
@@ -220,7 +227,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['tcp dport { 22 }', 'limit rate 5/minute', 'return'],
['log prefix "[smoketest-default-D]"','smoketest default-action', 'drop'],
['tcp dport { 22 }', 'add @RECENT_smoketest_4 { ip saddr limit rate over 10/minute burst 10 packets }', 'drop'],
- [f'tcp flags & syn == syn tcp option maxseg size {mss_range}']
+ [f'tcp flags & syn == syn tcp option maxseg size {mss_range}'],
+ ['ip length { 64, 512, 1024 }', 'return'],
+ ['ip length { 0-30000 }', 'return'],
+ ['ip length != { 60000-65535 }', 'return']
]
self.verify_nftables(nftables_search, 'ip filter')
@@ -239,6 +249,13 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'protocol', 'tcp_udp'])
self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'destination', 'port', '8888'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '3', 'action', 'accept'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '3', 'packet-length', '64,512,1024'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '4', 'action', 'accept'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '4', 'packet-length', '0-30000'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '5', 'action', 'accept'])
+ self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '5', 'packet-length', '!60000-65535'])
+
self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'ipv6-name', 'v6-smoketest'])
self.cli_commit()
@@ -247,6 +264,9 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['iifname "eth0"', 'jump NAME6_v6-smoketest'],
['saddr 2002::1', 'daddr 2002::1:1', 'log prefix "[v6-smoketest-1-A]" level crit', 'return'],
['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'reject'],
+ ['ip6 length { 64, 512, 1024 }', 'return'],
+ ['ip6 length { 0-30000 }', 'return'],
+ ['ip6 length != { 60000-65535 }', 'return'],
['smoketest default-action', 'log prefix "[v6-smoketest-default-D]"', 'drop']
]
diff --git a/src/validators/packet-length b/src/validators/packet-length
new file mode 100755
index 000000000..d96093849
--- /dev/null
+++ b/src/validators/packet-length
@@ -0,0 +1,29 @@
+#!/usr/bin/python3
+
+from sys import argv
+from sys import exit
+import re
+
+if __name__ == '__main__':
+ if len(argv)>1:
+ lengths = argv[1].split(",")
+
+ for length in lengths:
+ if length and length[0] == '!':
+ length = length[1:]
+ if re.match('^[0-9]{1,5}-[0-9]{1,5}$', length):
+ length_1, length_2 = length.split('-')
+ if int(length_1) not in range(0, 65536) or int(length_2) not in range(0, 65536):
+ print(f'Error: {length} is not a valid length range')
+ exit(1)
+ if int(length_1) > int(length_2):
+ print(f'Error: {length} is not a valid length range')
+ exit(1)
+ elif length.isnumeric():
+ if int(length) not in range(0, 65536):
+ print(f'Error: {length} is not a valid length value')
+ exit(1)
+ else:
+ exit(2)
+
+ exit(0) \ No newline at end of file