From 7d024a324412f4902b9ba212277901bbbe2f949c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 21 Apr 2019 13:19:12 +0200 Subject: [firewall] T314: add firewall options for MSS clamping * clamp MSS IPv4 set firewall options interface pppoe0 adjust-mss '1452' * clamp MSS IPv6 set firewall options interface pppoe0 adjust-mss6 '1452' * disable entire rule set firewall options interface pppoe0 disable Output ------ $ sudo iptables-save -t mangle # Generated by iptables-save v1.4.21 on Sun Apr 21 12:56:25 2019 *mangle :PREROUTING ACCEPT [1217:439885] :INPUT ACCEPT [290:52459] :FORWARD ACCEPT [920:375774] :OUTPUT ACCEPT [301:100053] :POSTROUTING ACCEPT [1221:475827] :VYOS_FW_OPTIONS - [0:0] -A FORWARD -j VYOS_FW_OPTIONS -A VYOS_FW_OPTIONS -o pppoe0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1452 COMMIT Completed on Sun Apr 21 12:56:25 2019 (cherry picked from commit 476aa4c3a561ea0ef0bf9b4c26ec8b78d18a5d02) --- Makefile | 1 + interface-definitions/firewall-options.xml | 55 +++++++++++ src/conf_mode/firewall_options.py | 142 +++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 interface-definitions/firewall-options.xml create mode 100755 src/conf_mode/firewall_options.py diff --git a/Makefile b/Makefile index 681df855b..2e49a204c 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ interface_definitions: find $(CURDIR)/interface-definitions/ -type f -name "*.xml" | xargs -I {} $(CURDIR)/scripts/build-command-templates {} $(CURDIR)/schema/interface_definition.rng $(TMPL_DIR) || exit 1 # XXX: delete top level node.def's that now live in other packages + rm -f $(TMPL_DIR)/firewall/node.def rm -f $(TMPL_DIR)/interfaces/node.def rm -f $(TMPL_DIR)/protocols/node.def rm -f $(TMPL_DIR)/protocols/static/node.def diff --git a/interface-definitions/firewall-options.xml b/interface-definitions/firewall-options.xml new file mode 100644 index 000000000..2936cc703 --- /dev/null +++ b/interface-definitions/firewall-options.xml @@ -0,0 +1,55 @@ + + + + + + + Firewall options/Packet manipulation + 990 + + + + + Interface clamping options + + + + + + + + Disable this rule + + + + + + Adjust MSS for IPv4 transit packets + + 500-1460 + TCP Maximum segment size in bytes + + + + + + + + + Adjust MSS for IPv6 transit packets + + 1280-1492 + TCP Maximum segment size in bytes + + + + + + + + + + + + + diff --git a/src/conf_mode/firewall_options.py b/src/conf_mode/firewall_options.py new file mode 100755 index 000000000..e2c306904 --- /dev/null +++ b/src/conf_mode/firewall_options.py @@ -0,0 +1,142 @@ +#!/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 . +# + +import sys +import os +import copy + +from vyos.config import Config +from vyos import ConfigError + +default_config_data = { + 'intf_opts': [], + 'new_chain4': False, + 'new_chain6': False +} + +def get_config(): + opts = copy.deepcopy(default_config_data) + conf = Config() + if not conf.exists('firewall options'): + return None + 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 + os.system('iptables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target)) + os.system('iptables --table mangle --flush {} >&/dev/null'.format(target)) + os.system('iptables --table mangle --delete-chain {} >&/dev/null'.format(target)) + + # always cleanup ip6tables + os.system('ip6tables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target)) + os.system('ip6tables --table mangle --flush {} >&/dev/null'.format(target)) + os.system('ip6tables --table mangle --delete-chain {} >&/dev/null'.format(target)) + + # Setup new iptables rules + if tcp['new_chain4']: + os.system('iptables --table mangle --new-chain {} >&/dev/null'.format(target)) + os.system('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: + os.system('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']: + os.system('ip6tables --table mangle --new-chain {} >&/dev/null'.format(target)) + os.system('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: + os.system('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) -- cgit v1.2.3