summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/configd-include.json1
-rw-r--r--interface-definitions/firewall-options.xml.in50
-rw-r--r--interface-definitions/include/interface/adjust-mss.xml.i23
-rw-r--r--interface-definitions/include/interface/ipv4-options.xml.i1
-rw-r--r--interface-definitions/include/interface/ipv6-options.xml.i1
-rw-r--r--interface-definitions/interfaces-pppoe.xml.in2
-rwxr-xr-xpython/vyos/ifconfig/interface.py66
-rw-r--r--python/vyos/ifconfig/pppoe.py4
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py22
-rwxr-xr-xsrc/conf_mode/firewall_options.py150
-rwxr-xr-xsrc/migration-scripts/firewall/5-to-663
11 files changed, 177 insertions, 206 deletions
diff --git a/data/configd-include.json b/data/configd-include.json
index 2d7ea149b..6893aaa86 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -6,7 +6,6 @@
"dhcpv6_relay.py",
"dns_forwarding.py",
"dynamic_dns.py",
-"firewall_options.py",
"host_name.py",
"https.py",
"igmp_proxy.py",
diff --git a/interface-definitions/firewall-options.xml.in b/interface-definitions/firewall-options.xml.in
deleted file mode 100644
index 8d9225a9a..000000000
--- a/interface-definitions/firewall-options.xml.in
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<interfaceDefinition>
- <node name="firewall">
- <children>
- <node name="options">
- <properties>
- <help>Firewall options/Packet manipulation</help>
- <priority>990</priority>
- </properties>
- <children>
- <tagNode name="interface" owner="${vyos_conf_scripts_dir}/firewall_options.py">
- <properties>
- <help>Interface clamping options</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
- </completionHelp>
- </properties>
- <children>
- #include <include/generic-disable-node.xml.i>
- <leafNode name="adjust-mss">
- <properties>
- <help>Adjust MSS for IPv4 transit packets</help>
- <valueHelp>
- <format>500-1460</format>
- <description>TCP Maximum segment size in bytes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 500-1460"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="adjust-mss6">
- <properties>
- <help>Adjust MSS for IPv6 transit packets</help>
- <valueHelp>
- <format>1280-1492</format>
- <description>TCP Maximum segment size in bytes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1280-1492"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- </children>
- </node>
- </children>
- </node>
-</interfaceDefinition>
diff --git a/interface-definitions/include/interface/adjust-mss.xml.i b/interface-definitions/include/interface/adjust-mss.xml.i
new file mode 100644
index 000000000..57019f02c
--- /dev/null
+++ b/interface-definitions/include/interface/adjust-mss.xml.i
@@ -0,0 +1,23 @@
+<!-- include start from interface/adjust-mss.xml.i -->
+<!-- https://datatracker.ietf.org/doc/html/rfc6691 -->
+<leafNode name="adjust-mss">
+ <properties>
+ <help>Adjust TCP MSS value</help>
+ <completionHelp>
+ <list>clamp-mss-to-pmtu</list>
+ </completionHelp>
+ <valueHelp>
+ <format>clamp-mss-to-pmtu</format>
+ <description>Automatically sets the MSS to the proper value</description>
+ </valueHelp>
+ <valueHelp>
+ <format>u32:500-65535</format>
+ <description>TCP Maximum segment size in bytes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 500-65535"/>
+ <regex>^(clamp-mss-to-pmtu)$</regex>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface/ipv4-options.xml.i b/interface-definitions/include/interface/ipv4-options.xml.i
index 10884b6eb..bca1229c6 100644
--- a/interface-definitions/include/interface/ipv4-options.xml.i
+++ b/interface-definitions/include/interface/ipv4-options.xml.i
@@ -4,6 +4,7 @@
<help>IPv4 routing parameters</help>
</properties>
<children>
+ #include <include/interface/adjust-mss.xml.i>
#include <include/interface/arp-cache-timeout.xml.i>
#include <include/interface/disable-arp-filter.xml.i>
#include <include/interface/disable-forwarding.xml.i>
diff --git a/interface-definitions/include/interface/ipv6-options.xml.i b/interface-definitions/include/interface/ipv6-options.xml.i
index e57c242b0..2d2d1d3b2 100644
--- a/interface-definitions/include/interface/ipv6-options.xml.i
+++ b/interface-definitions/include/interface/ipv6-options.xml.i
@@ -4,6 +4,7 @@
<help>IPv6 routing parameters</help>
</properties>
<children>
+ #include <include/interface/adjust-mss.xml.i>
#include <include/interface/ipv6-address.xml.i>
#include <include/interface/ipv6-disable-forwarding.xml.i>
#include <include/interface/ipv6-dup-addr-detect-transmits.xml.i>
diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in
index 1bbfa63af..ac8fa378b 100644
--- a/interface-definitions/interfaces-pppoe.xml.in
+++ b/interface-definitions/interfaces-pppoe.xml.in
@@ -70,6 +70,7 @@
<help>IPv4 routing parameters</help>
</properties>
<children>
+ #include <include/interface/adjust-mss.xml.i>
#include <include/interface/source-validation.xml.i>
</children>
</node>
@@ -86,6 +87,7 @@
#include <include/interface/ipv6-address-autoconf.xml.i>
</children>
</node>
+ #include <include/interface/adjust-mss.xml.i>
</children>
</node>
<leafNode name="source-interface">
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index a1928ba51..53b57a83f 100755
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -436,6 +436,62 @@ class Interface(Control):
"""
return self.set_interface('arp_cache_tmo', tmo)
+ def set_tcp_ipv4_mss(self, mss):
+ """
+ Set IPv4 TCP MSS value advertised when TCP SYN packets leave this
+ interface. Value is in bytes.
+
+ A value of 0 will disable the MSS adjustment
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').set_tcp_ipv4_mss(1340)
+ """
+ iptables_bin = 'iptables'
+ base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = self._cmd(f'{iptables_bin}-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ # remove OLD MSS mangling configuration
+ line = line.replace('-A FORWARD', '-D FORWARD')
+ self._cmd(f'{iptables_bin} -t mangle {line}')
+
+ cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS'
+ if mss == 'clamp-mss-to-pmtu':
+ self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu')
+ elif int(mss) > 0:
+ # probably add option to clamp only if bigger:
+ low_mss = str(int(mss) + 1)
+ self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}')
+
+ def set_tcp_ipv6_mss(self, mss):
+ """
+ Set IPv6 TCP MSS value advertised when TCP SYN packets leave this
+ interface. Value is in bytes.
+
+ A value of 0 will disable the MSS adjustment
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').set_tcp_mss(1320)
+ """
+ iptables_bin = 'ip6tables'
+ base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = self._cmd(f'{iptables_bin}-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ # remove OLD MSS mangling configuration
+ line = line.replace('-A FORWARD', '-D FORWARD')
+ self._cmd(f'{iptables_bin} -t mangle {line}')
+
+ cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS'
+ if mss == 'clamp-mss-to-pmtu':
+ self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu')
+ elif int(mss) > 0:
+ # probably add option to clamp only if bigger:
+ low_mss = str(int(mss) + 1)
+ self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}')
+
def set_arp_filter(self, arp_filter):
"""
Filter ARP requests
@@ -1202,6 +1258,16 @@ class Interface(Control):
# checked before
self.set_vrf(config.get('vrf', ''))
+ # Configure MSS value for IPv4 TCP connections
+ tmp = dict_search('ip.adjust_mss', config)
+ value = tmp if (tmp != None) else '0'
+ self.set_tcp_ipv4_mss(value)
+
+ # Configure MSS value for IPv6 TCP connections
+ tmp = dict_search('ipv6.adjust_mss', config)
+ value = tmp if (tmp != None) else '0'
+ self.set_tcp_ipv6_mss(value)
+
# Configure ARP cache timeout in milliseconds - has default value
tmp = dict_search('ip.arp_cache_timeout', config)
value = tmp if (tmp != None) else '30'
diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py
index 65575cf99..6acf7d1c7 100644
--- a/python/vyos/ifconfig/pppoe.py
+++ b/python/vyos/ifconfig/pppoe.py
@@ -17,9 +17,7 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class PPPoEIf(Interface):
- default = {
- 'type': 'pppoe',
- }
+ iftype = 'pppoe'
definition = {
**Interface.definition,
**{
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 7f69b8444..63f742a8d 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -556,13 +556,16 @@ class BasicInterfaceTest:
if not self._test_ip:
self.skipTest('not supported')
+ arp_tmo = '300'
+ mss = '1420'
+
for interface in self._interfaces:
- arp_tmo = '300'
path = self._base_path + [interface]
for option in self._options.get(interface, []):
self.cli_set(path + option.split())
# Options
+ self.cli_set(path + ['ip', 'adjust-mss', mss])
self.cli_set(path + ['ip', 'arp-cache-timeout', arp_tmo])
self.cli_set(path + ['ip', 'disable-arp-filter'])
self.cli_set(path + ['ip', 'disable-forwarding'])
@@ -576,6 +579,12 @@ class BasicInterfaceTest:
self.cli_commit()
for interface in self._interfaces:
+ base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = cmd('sudo iptables-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ self.assertIn(f'--set-mss {mss}', line)
+
tmp = read_file(f'/proc/sys/net/ipv4/neigh/{interface}/base_reachable_time_ms')
self.assertEqual(tmp, str((int(arp_tmo) * 1000))) # tmo value is in milli seconds
@@ -607,19 +616,28 @@ class BasicInterfaceTest:
if not self._test_ipv6:
self.skipTest('not supported')
+ mss = '1400'
+ dad_transmits = '10'
+
for interface in self._interfaces:
- dad_transmits = '10'
path = self._base_path + [interface]
for option in self._options.get(interface, []):
self.cli_set(path + option.split())
# Options
+ self.cli_set(path + ['ipv6', 'adjust-mss', mss])
self.cli_set(path + ['ipv6', 'disable-forwarding'])
self.cli_set(path + ['ipv6', 'dup-addr-detect-transmits', dad_transmits])
self.cli_commit()
for interface in self._interfaces:
+ base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = cmd('sudo ip6tables-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ self.assertIn(f'--set-mss {mss}', line)
+
tmp = read_file(f'/proc/sys/net/ipv6/conf/{interface}/forwarding')
self.assertEqual('0', tmp)
diff --git a/src/conf_mode/firewall_options.py b/src/conf_mode/firewall_options.py
deleted file mode 100755
index 67bf5d0e2..000000000
--- a/src/conf_mode/firewall_options.py
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-import sys
-import os
-import copy
-
-from vyos.config import Config
-from vyos import ConfigError
-from vyos.util import call
-
-from vyos import airbag
-airbag.enable()
-
-default_config_data = {
- 'intf_opts': [],
- 'new_chain4': False,
- 'new_chain6': False
-}
-
-def get_config(config=None):
- opts = copy.deepcopy(default_config_data)
- if config:
- conf = config
- else:
- conf = Config()
- if not conf.exists('firewall options'):
- # bail out early
- return opts
- else:
- conf.set_level('firewall options')
-
- # Parse configuration of each individual instance
- if conf.exists('interface'):
- for intf in conf.list_nodes('interface'):
- conf.set_level('firewall options interface {0}'.format(intf))
- config = {
- 'intf': intf,
- 'disabled': False,
- 'mss4': '',
- 'mss6': ''
- }
-
- # Check if individual option is disabled
- if conf.exists('disable'):
- config['disabled'] = True
-
- #
- # Get MSS value IPv4
- #
- if conf.exists('adjust-mss'):
- config['mss4'] = conf.return_value('adjust-mss')
-
- # We need a marker that a new iptables chain needs to be generated
- if not opts['new_chain4']:
- opts['new_chain4'] = True
-
- #
- # Get MSS value IPv6
- #
- if conf.exists('adjust-mss6'):
- config['mss6'] = conf.return_value('adjust-mss6')
-
- # We need a marker that a new ip6tables chain needs to be generated
- if not opts['new_chain6']:
- opts['new_chain6'] = True
-
- # Append interface options to global list
- opts['intf_opts'].append(config)
-
- return opts
-
-def verify(tcp):
- # syntax verification is done via cli
- return None
-
-def apply(tcp):
- target = 'VYOS_FW_OPTIONS'
-
- # always cleanup iptables
- call('iptables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
- call('iptables --table mangle --flush {} >&/dev/null'.format(target))
- call('iptables --table mangle --delete-chain {} >&/dev/null'.format(target))
-
- # always cleanup ip6tables
- call('ip6tables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
- call('ip6tables --table mangle --flush {} >&/dev/null'.format(target))
- call('ip6tables --table mangle --delete-chain {} >&/dev/null'.format(target))
-
- # Setup new iptables rules
- if tcp['new_chain4']:
- call('iptables --table mangle --new-chain {} >&/dev/null'.format(target))
- call('iptables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
-
- for opts in tcp['intf_opts']:
- intf = opts['intf']
- mss = opts['mss4']
-
- # Check if this rule iis disabled
- if opts['disabled']:
- continue
-
- # adjust TCP MSS per interface
- if mss:
- call('iptables --table mangle --append {} --out-interface {} --protocol tcp '
- '--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
-
- # Setup new ip6tables rules
- if tcp['new_chain6']:
- call('ip6tables --table mangle --new-chain {} >&/dev/null'.format(target))
- call('ip6tables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
-
- for opts in tcp['intf_opts']:
- intf = opts['intf']
- mss = opts['mss6']
-
- # Check if this rule iis disabled
- if opts['disabled']:
- continue
-
- # adjust TCP MSS per interface
- if mss:
- call('ip6tables --table mangle --append {} --out-interface {} --protocol tcp '
- '--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
-
- return None
-
-if __name__ == '__main__':
-
- try:
- c = get_config()
- verify(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/migration-scripts/firewall/5-to-6 b/src/migration-scripts/firewall/5-to-6
new file mode 100755
index 000000000..ccb86830a
--- /dev/null
+++ b/src/migration-scripts/firewall/5-to-6
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# T3090: migrate "firewall options interface <name> adjust-mss" to the
+# individual interface.
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+from vyos.ifconfig import Section
+
+if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['firewall', 'options', 'interface']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+for interface in config.list_nodes(base):
+ if config.exists(base + [interface, 'disable']):
+ continue
+
+ if config.exists(base + [interface, 'adjust-mss']):
+ section = Section.section(interface)
+ tmp = config.return_value(base + [interface, 'adjust-mss'])
+ config.set(['interfaces', section, interface, 'ip', 'adjust-mss'], value=tmp)
+
+ if config.exists(base + [interface, 'adjust-mss6']):
+ section = Section.section(interface)
+ tmp = config.return_value(base + [interface, 'adjust-mss6'])
+ config.set(['interfaces', section, interface, 'ipv6', 'adjust-mss'], value=tmp)
+
+config.delete(['firewall', 'options'])
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)