summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/system-conntrack.xml.in334
-rwxr-xr-xsmoketest/scripts/cli/test_system_conntrack.py239
-rwxr-xr-xsrc/conf_mode/conntrack.py139
-rwxr-xr-xsrc/migration-scripts/conntrack/2-to-337
4 files changed, 749 insertions, 0 deletions
diff --git a/interface-definitions/system-conntrack.xml.in b/interface-definitions/system-conntrack.xml.in
new file mode 100644
index 000000000..daa4177c9
--- /dev/null
+++ b/interface-definitions/system-conntrack.xml.in
@@ -0,0 +1,334 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="system">
+ <children>
+ <node name="conntrack" owner="${vyos_conf_scripts_dir}/conntrack.py">
+ <properties>
+ <help>Connection Tracking Engine Options</help>
+ <!-- Before NAT and conntrack-sync are configured -->
+ <priority>218</priority>
+ </properties>
+ <children>
+ <leafNode name="expect-table-size">
+ <properties>
+ <help>Size of connection tracking expect table</help>
+ <valueHelp>
+ <format>u32:1-50000000</format>
+ <description>Number of entries allowed in connection tracking expect table</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-50000000"/>
+ </constraint>
+ </properties>
+ <defaultValue>2048</defaultValue>
+ </leafNode>
+ <leafNode name="hash-size">
+ <properties>
+ <help>Hash size for connection tracking table</help>
+ <valueHelp>
+ <format>u32:1-50000000</format>
+ <description>Size of hash to use for connection tracking table</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-50000000"/>
+ </constraint>
+ </properties>
+ <defaultValue>32768</defaultValue>
+ </leafNode>
+ <node name="modules">
+ <properties>
+ <help>Connection tracking modules</help>
+ </properties>
+ <children>
+ <leafNode name="ftp">
+ <properties>
+ <help>FTP connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="h323">
+ <properties>
+ <help>H.323 connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="nfs">
+ <properties>
+ <help>NFS connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="pptp">
+ <properties>
+ <help>PPTP connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="sip">
+ <properties>
+ <help>SIP connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="sqlnet">
+ <properties>
+ <help>SQLnet connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="tftp">
+ <properties>
+ <help>TFTP connection tracking</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="table-size">
+ <properties>
+ <help>Size of connection tracking table</help>
+ <valueHelp>
+ <format>u32:1-50000000</format>
+ <description>Number of entries allowed in connection tracking table</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-50000000"/>
+ </constraint>
+ </properties>
+ <defaultValue>262144</defaultValue>
+ </leafNode>
+ <node name="tcp">
+ <properties>
+ <help>TCP options</help>
+ </properties>
+ <children>
+ <leafNode name="half-open-connections">
+ <properties>
+ <help>Maximum number of TCP half-open connections</help>
+ <valueHelp>
+ <format>u32:1-2147483647</format>
+ <description>Generic connection timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-2147483647"/>
+ </constraint>
+ </properties>
+ <defaultValue>512</defaultValue>
+ </leafNode>
+ <leafNode name="loose">
+ <properties>
+ <help>Policy to track previously established connections</help>
+ <completionHelp>
+ <list>enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Allow tracking of previously established connections</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Do not allow tracking of previously established connections</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(enable|disable)$</regex>
+ </constraint>
+ </properties>
+ <defaultValue>enable</defaultValue>
+ </leafNode>
+ <leafNode name="max-retrans">
+ <properties>
+ <help>TCP maximum retransmit attempts</help>
+ <valueHelp>
+ <format>u32:1-2147483647</format>
+ <description>Generic connection timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-2147483647"/>
+ </constraint>
+ </properties>
+ <defaultValue>3</defaultValue>
+ </leafNode>
+ </children>
+ </node>
+ <node name="timeout">
+ <properties>
+ <help>Connection timeout options</help>
+ </properties>
+ <children>
+ <leafNode name="icmp">
+ <properties>
+ <help>ICMP timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>ICMP timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>30</defaultValue>
+ </leafNode>
+ <leafNode name="other">
+ <properties>
+ <help>Generic connection timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>Generic connection timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>600</defaultValue>
+ </leafNode>
+ <node name="tcp">
+ <properties>
+ <help>TCP connection timeout options</help>
+ </properties>
+ <children>
+ <leafNode name="close-wait">
+ <properties>
+ <help>TCP CLOSE-WAIT timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP CLOSE-WAIT timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>60</defaultValue>
+ </leafNode>
+ <leafNode name="close">
+ <properties>
+ <help>TCP CLOSE timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP CLOSE timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>10</defaultValue>
+ </leafNode>
+ <leafNode name="established">
+ <properties>
+ <help>TCP ESTABLISHED timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP ESTABLISHED timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>432000</defaultValue>
+ </leafNode>
+ <leafNode name="fin-wait">
+ <properties>
+ <help>TCP FIN-WAIT timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP FIN-WAIT timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>120</defaultValue>
+ </leafNode>
+ <leafNode name="last-ack">
+ <properties>
+ <help>TCP LAST-ACK timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP LAST-ACK timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>30</defaultValue>
+ </leafNode>
+ <leafNode name="syn-recv">
+ <properties>
+ <help>TCP SYN-RECEIVED timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP SYN-RECEIVED timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>60</defaultValue>
+ </leafNode>
+ <leafNode name="syn-sent">
+ <properties>
+ <help>TCP SYN-SENT timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP SYN-SENT timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>120</defaultValue>
+ </leafNode>
+ <leafNode name="time-wait">
+ <properties>
+ <help>TCP TIME-WAIT timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>TCP TIME-WAIT timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>120</defaultValue>
+ </leafNode>
+ </children>
+ </node>
+ <node name="udp">
+ <properties>
+ <help>UDP timeout options</help>
+ </properties>
+ <children>
+ <leafNode name="other">
+ <properties>
+ <help>UDP generic timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>UDP generic timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>30</defaultValue>
+ </leafNode>
+ <leafNode name="stream">
+ <properties>
+ <help>UDP stream timeout in seconds</help>
+ <valueHelp>
+ <format>u32:1-21474836</format>
+ <description>UDP stream timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21474836"/>
+ </constraint>
+ </properties>
+ <defaultValue>180</defaultValue>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py
new file mode 100755
index 000000000..a2380981b
--- /dev/null
+++ b/smoketest/scripts/cli/test_system_conntrack.py
@@ -0,0 +1,239 @@
+#!/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/>.
+
+import os
+import unittest
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+
+from vyos.configsession import ConfigSession
+from vyos.util import cmd
+from vyos.util import read_file
+
+base_path = ['system', 'conntrack']
+
+def get_sysctl(parameter):
+ tmp = parameter.replace(r'.', r'/')
+ return read_file(f'/proc/sys/{tmp}')
+
+class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):
+ def tearDown(self):
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ def test_conntrack_options(self):
+ conntrack_config = {
+ 'net.netfilter.nf_conntrack_expect_max' : {
+ 'cli' : ['expect-table-size'],
+ 'test_value' : '8192',
+ 'default_value' : '2048',
+ },
+ 'net.nf_conntrack_max' :{
+ 'cli' : ['table-size'],
+ 'test_value' : '500000',
+ 'default_value' : '262144',
+ },
+ 'net.ipv4.tcp_max_syn_backlog' :{
+ 'cli' : ['tcp', 'half-open-connections'],
+ 'test_value' : '2048',
+ 'default_value' : '512',
+ },
+ 'net.netfilter.nf_conntrack_tcp_loose' :{
+ 'cli' : ['tcp', 'loose'],
+ 'test_value' : 'disable',
+ 'default_value' : '1',
+ },
+ 'net.netfilter.nf_conntrack_tcp_max_retrans' :{
+ 'cli' : ['tcp', 'max-retrans'],
+ 'test_value' : '1024',
+ 'default_value' : '3',
+ },
+ 'net.netfilter.nf_conntrack_icmp_timeout' :{
+ 'cli' : ['timeout', 'icmp'],
+ 'test_value' : '180',
+ 'default_value' : '30',
+ },
+ 'net.netfilter.nf_conntrack_generic_timeout' :{
+ 'cli' : ['timeout', 'other'],
+ 'test_value' : '1200',
+ 'default_value' : '600',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_close_wait' :{
+ 'cli' : ['timeout', 'tcp', 'close-wait'],
+ 'test_value' : '30',
+ 'default_value' : '60',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_close' :{
+ 'cli' : ['timeout', 'tcp', 'close'],
+ 'test_value' : '20',
+ 'default_value' : '10',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_established' :{
+ 'cli' : ['timeout', 'tcp', 'established'],
+ 'test_value' : '1000',
+ 'default_value' : '432000',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_fin_wait' :{
+ 'cli' : ['timeout', 'tcp', 'fin-wait'],
+ 'test_value' : '240',
+ 'default_value' : '120',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_last_ack' :{
+ 'cli' : ['timeout', 'tcp', 'last-ack'],
+ 'test_value' : '300',
+ 'default_value' : '30',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_syn_recv' :{
+ 'cli' : ['timeout', 'tcp', 'syn-recv'],
+ 'test_value' : '100',
+ 'default_value' : '60',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_syn_sent' :{
+ 'cli' : ['timeout', 'tcp', 'syn-sent'],
+ 'test_value' : '300',
+ 'default_value' : '120',
+ },
+ 'net.netfilter.nf_conntrack_tcp_timeout_time_wait' :{
+ 'cli' : ['timeout', 'tcp', 'time-wait'],
+ 'test_value' : '303',
+ 'default_value' : '120',
+ },
+ 'net.netfilter.nf_conntrack_udp_timeout' :{
+ 'cli' : ['timeout', 'udp', 'other'],
+ 'test_value' : '90',
+ 'default_value' : '30',
+ },
+ 'net.netfilter.nf_conntrack_udp_timeout_stream' :{
+ 'cli' : ['timeout', 'udp', 'stream'],
+ 'test_value' : '200',
+ 'default_value' : '180',
+ },
+ }
+
+ for parameter, parameter_config in conntrack_config.items():
+ self.cli_set(base_path + parameter_config['cli'] + [parameter_config['test_value']])
+
+ # commit changes
+ self.cli_commit()
+
+ # validate configuration
+ for parameter, parameter_config in conntrack_config.items():
+ tmp = parameter_config['test_value']
+ # net.netfilter.nf_conntrack_tcp_loose has a fancy "disable" value,
+ # make this work
+ if tmp == 'disable':
+ tmp = '0'
+ self.assertEqual(get_sysctl(f'{parameter}'), tmp)
+
+ # delete all configuration options and revert back to defaults
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ # validate configuration
+ for parameter, parameter_config in conntrack_config.items():
+ self.assertEqual(get_sysctl(f'{parameter}'), parameter_config['default_value'])
+
+
+ def test_conntrack_module_enable(self):
+ # conntrack helper modules are disabled by default
+ modules = {
+ 'ftp' : {
+ 'driver' : ['nf_nat_ftp', 'nf_conntrack_ftp'],
+ },
+ 'h323' : {
+ 'driver' : ['nf_nat_h323', 'nf_conntrack_h323'],
+ },
+ 'nfs' : {
+ 'iptables' : ['-A VYATTA_CT_HELPER -p udp -m udp --dport 111 -j CT --helper rpc',
+ '-A VYATTA_CT_HELPER -p tcp -m tcp --dport 111 -j CT --helper rpc'],
+ },
+ 'pptp' : {
+ 'driver' : ['nf_nat_pptp', 'nf_conntrack_pptp'],
+ },
+ 'sip' : {
+ 'driver' : ['nf_nat_sip', 'nf_conntrack_sip'],
+ },
+ 'sqlnet' : {
+ 'iptables' : ['-A VYATTA_CT_HELPER -p tcp -m tcp --dport 1536 -j CT --helper tns',
+ '-A VYATTA_CT_HELPER -p tcp -m tcp --dport 1525 -j CT --helper tns',
+ '-A VYATTA_CT_HELPER -p tcp -m tcp --dport 1521 -j CT --helper tns'],
+ },
+ 'tftp' : {
+ 'driver' : ['nf_nat_tftp', 'nf_conntrack_tftp'],
+ },
+ }
+
+ # load modules
+ for module in modules:
+ self.cli_set(base_path + ['modules', module])
+
+ # commit changes
+ self.cli_commit()
+
+ # verify modules are loaded on the system
+ for module, module_options in modules.items():
+ if 'driver' in module_options:
+ for driver in module_options['driver']:
+ self.assertTrue(os.path.isdir(f'/sys/module/{driver}'))
+ if 'iptables' in module_options:
+ rules = cmd('sudo iptables-save -t raw')
+ for ruleset in module_options['iptables']:
+ self.assertIn(ruleset, rules)
+
+ # unload modules
+ for module in modules:
+ self.cli_delete(base_path + ['modules', module])
+
+ # commit changes
+ self.cli_commit()
+
+ # verify modules are not loaded on the system
+ for module, module_options in modules.items():
+ if 'driver' in module_options:
+ for driver in module_options['driver']:
+ self.assertFalse(os.path.isdir(f'/sys/module/{driver}'))
+ if 'iptables' in module_options:
+ rules = cmd('sudo iptables-save -t raw')
+ for ruleset in module_options['iptables']:
+ self.assertNotIn(ruleset, rules)
+
+ def test_conntrack_hash_size(self):
+ hash_size = '65536'
+ hash_size_default = '32768'
+
+ self.cli_set(base_path + ['hash-size', hash_size])
+
+ # commit changes
+ self.cli_commit()
+
+ # verify new configuration - only effective after reboot, but
+ # a valid config file is sufficient
+ tmp = read_file('/etc/modprobe.d/vyatta_nf_conntrack.conf')
+ self.assertIn(hash_size, tmp)
+
+ # Test default value by deleting the configuration
+ self.cli_delete(base_path + ['hash-size'])
+
+ # commit changes
+ self.cli_commit()
+
+ # verify new configuration - only effective after reboot, but
+ # a valid config file is sufficient
+ tmp = read_file('/etc/modprobe.d/vyatta_nf_conntrack.conf')
+ self.assertIn(hash_size_default, tmp)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/conf_mode/conntrack.py b/src/conf_mode/conntrack.py
new file mode 100755
index 000000000..68877f794
--- /dev/null
+++ b/src/conf_mode/conntrack.py
@@ -0,0 +1,139 @@
+#!/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/>.
+
+import os
+
+from sys import exit
+
+from vyos.config import Config
+from vyos.configdict import dict_merge
+from vyos.util import cmd
+from vyos.util import run
+from vyos.util import process_named_running
+from vyos.util import dict_search
+from vyos.template import render
+from vyos.xml import defaults
+from vyos import ConfigError
+from vyos import airbag
+airbag.enable()
+
+conntrack_config = r'/etc/modprobe.d/vyatta_nf_conntrack.conf'
+sysctl_file = r'/run/sysctl/10-vyos-conntrack.conf'
+
+# Every ALG (Application Layer Gateway) consists of either a Kernel Object
+# also called a Kernel Module/Driver or some rules present in iptables
+module_map = {
+ 'ftp' : {
+ 'ko' : ['nf_nat_ftp', 'nf_conntrack_ftp'],
+ },
+ 'h323' : {
+ 'ko' : ['nf_nat_h323', 'nf_conntrack_h323'],
+ },
+ 'nfs' : {
+ 'iptables' : ['VYATTA_CT_HELPER --table raw --proto tcp --dport 111 --jump CT --helper rpc',
+ 'VYATTA_CT_HELPER --table raw --proto udp --dport 111 --jump CT --helper rpc'],
+ },
+ 'pptp' : {
+ 'ko' : ['nf_nat_pptp', 'nf_conntrack_pptp'],
+ },
+ 'sip' : {
+ 'ko' : ['nf_nat_sip', 'nf_conntrack_sip'],
+ },
+ 'sqlnet' : {
+ 'iptables' : ['VYATTA_CT_HELPER --table raw --proto tcp --dport 1521 --jump CT --helper tns',
+ 'VYATTA_CT_HELPER --table raw --proto tcp --dport 1525 --jump CT --helper tns',
+ 'VYATTA_CT_HELPER --table raw --proto tcp --dport 1536 --jump CT --helper tns'],
+ },
+ 'tftp' : {
+ 'ko' : ['nf_nat_tftp', 'nf_conntrack_tftp'],
+ },
+}
+
+def resync_conntrackd():
+ tmp = run('/usr/libexec/vyos/conf_mode/conntrack_sync.py')
+ if tmp > 0:
+ print('ERROR: error restarting conntrackd!')
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['system', 'conntrack']
+
+ conntrack = conf.get_config_dict(base, key_mangling=('-', '_'),
+ get_first_key=True)
+
+ # We have gathered the dict representation of the CLI, but there are default
+ # options which we need to update into the dictionary retrived.
+ default_values = defaults(base)
+ conntrack = dict_merge(default_values, conntrack)
+
+ return conntrack
+
+def verify(conntrack):
+ return None
+
+def generate(conntrack):
+ render(conntrack_config, 'conntrack/vyos_nf_conntrack.conf.tmpl', conntrack)
+ render(sysctl_file, 'conntrack/sysctl.conf.tmpl', conntrack)
+
+ return None
+
+def apply(conntrack):
+ # Depending on the enable/disable state of the ALG (Application Layer Gateway)
+ # modules we need to either insmod or rmmod the helpers.
+ for module, module_config in module_map.items():
+ if dict_search(f'modules.{module}', conntrack) is None:
+ if 'ko' in module_config:
+ for mod in module_config['ko']:
+ # Only remove the module if it's loaded
+ if os.path.exists(f'/sys/module/{mod}'):
+ cmd(f'rmmod {mod}')
+ if 'iptables' in module_config:
+ for rule in module_config['iptables']:
+ # Only install iptables rule if it does not exist
+ tmp = run(f'iptables --check {rule}')
+ if tmp == 0: cmd(f'iptables --delete {rule}')
+ else:
+ if 'ko' in module_config:
+ for mod in module_config['ko']:
+ cmd(f'modprobe {mod}')
+ if 'iptables' in module_config:
+ for rule in module_config['iptables']:
+ # Only install iptables rule if it does not exist
+ tmp = run(f'iptables --check {rule}')
+ if tmp > 0: cmd(f'iptables --insert {rule}')
+
+ if process_named_running('conntrackd'):
+ # Reload conntrack-sync daemon to fetch new sysctl values
+ resync_conntrackd()
+
+ # We silently ignore all errors
+ # See: https://bugzilla.redhat.com/show_bug.cgi?id=1264080
+ cmd(f'sysctl -f {sysctl_file}')
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
diff --git a/src/migration-scripts/conntrack/2-to-3 b/src/migration-scripts/conntrack/2-to-3
new file mode 100755
index 000000000..8a8b43279
--- /dev/null
+++ b/src/migration-scripts/conntrack/2-to-3
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+# Conntrack syntax version 3
+# Enables all conntrack modules (previous default behaviour) and omits manually disabled modules.
+
+import sys
+
+from vyos.configtree import ConfigTree
+from vyos.version import get_version
+
+if len(sys.argv) < 1:
+ print('Must specify file name!')
+ sys.exit(1)
+
+filename = sys.argv[1]
+
+with open(filename, 'r') as f:
+ config = ConfigTree(f.read())
+
+module_path = ['system', 'conntrack', 'modules']
+
+# Go over all conntrack modules available as of v1.3.0.
+for module in ['ftp', 'h323', 'nfs', 'pptp', 'sip', 'sqlnet', 'tftp']:
+ # 'disable' is being phased out.
+ if config.exists(module_path + [module, 'disable']):
+ config.delete(module_path + [module])
+ # If it wasn't manually 'disable'd, it was enabled by default.
+ else:
+ config.set(module_path + [module])
+
+try:
+ if config.exists(module_path):
+ with open(filename, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ sys.exit(1)