Skip to content

Commit

Permalink
T3900: T6394: extend functionalities in firewall; move netfilter sysc…
Browse files Browse the repository at this point in the history
…tl timeout parameters defined in conntrack to firewall global-opton section.
  • Loading branch information
nicolas-fort committed Jun 4, 2024
1 parent 6871c55 commit 770edf0
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 123 deletions.
20 changes: 1 addition & 19 deletions data/templates/conntrack/sysctl.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,7 @@

net.netfilter.nf_conntrack_expect_max = {{ expect_table_size }}
net.netfilter.nf_conntrack_max = {{ table_size }}

net.ipv4.tcp_max_syn_backlog = {{ tcp.half_open_connections }}

net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose is vyos_defined('enable') else '0' }}
net.netfilter.nf_conntrack_tcp_max_retrans = {{ tcp.max_retrans }}

net.netfilter.nf_conntrack_icmp_timeout = {{ timeout.icmp }}
net.netfilter.nf_conntrack_generic_timeout = {{ timeout.other }}

net.netfilter.nf_conntrack_tcp_timeout_close_wait = {{ timeout.tcp.close_wait }}
net.netfilter.nf_conntrack_tcp_timeout_close = {{ timeout.tcp.close }}
net.netfilter.nf_conntrack_tcp_timeout_established = {{ timeout.tcp.established }}
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = {{ timeout.tcp.fin_wait }}
net.netfilter.nf_conntrack_tcp_timeout_last_ack = {{ timeout.tcp.last_ack }}
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = {{ timeout.tcp.syn_recv }}
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = {{ timeout.tcp.syn_sent }}
net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ timeout.tcp.time_wait }}

net.netfilter.nf_conntrack_udp_timeout = {{ timeout.udp.other }}
net.netfilter.nf_conntrack_udp_timeout_stream = {{ timeout.udp.stream }}

net.netfilter.nf_conntrack_acct = {{ '1' if flow_accounting is vyos_defined else '0' }}
net.netfilter.nf_conntrack_acct = {{ '1' if flow_accounting is vyos_defined else '0' }}
28 changes: 28 additions & 0 deletions data/templates/firewall/sysctl-firewall.conf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Autogenerated by firewall.py

# gloabl options
net.ipv4.icmp_echo_ignore_all = {{ 0 if global_options.all_ping == 'enable' else 1 }}
net.ipv4.icmp_echo_ignore_broadcasts = {{ 0 if global_options.broadcast_ping == 'enable' else 1 }}
net.ipv4.conf.all.bc_forwarding = {{ 1 if global_options.directed_broadcast == 'enable' else 0 }}
net.ipv4.conf.*.accept_source_route = {{ 1 if global_options.ip_src_route == 'enable' else 0 }}
net.ipv6.conf.*.accept_redirects = {{ 1 if global_options.ipv6_receive_redirects == 'enable' else 0 }}
net.ipv6.conf.*.accept_source_route = {{ 0 if global_options.ipv6_src_route == 'enable' else -1 }}
net.ipv4.conf.all.log_martians = {{ 1 if global_options.log_martians == 'enable' else 0 }}
net.ipv4.conf.*.accept_redirects = {{ 1 if global_options.receive_redirects == 'enable' else 0 }}
net.ipv4.conf.*.send_redirects = {{ 1 if global_options.send_redirects == 'enable' else 0 }}
net.ipv4.tcp_syncookies = {{ 1 if global_options.syn_cookies == 'enable' else 0 }}
net.ipv4.tcp_rfc1337 = {{ 1 if global_options.twa_hazards_protection == 'enable' else 0 }}

## Timeout values:
net.netfilter.nf_conntrack_icmp_timeout = {{ global_options.timeout.icmp }}
net.netfilter.nf_conntrack_generic_timeout = {{ global_options.timeout.other }}
net.netfilter.nf_conntrack_tcp_timeout_close_wait = {{ global_options.timeout.tcp.close_wait }}
net.netfilter.nf_conntrack_tcp_timeout_close = {{ global_options.timeout.tcp.close }}
net.netfilter.nf_conntrack_tcp_timeout_established = {{ global_options.timeout.tcp.established }}
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = {{ global_options.timeout.tcp.fin_wait }}
net.netfilter.nf_conntrack_tcp_timeout_last_ack = {{ global_options.timeout.tcp.last_ack }}
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = {{ global_options.timeout.tcp.syn_recv }}
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = {{ global_options.timeout.tcp.syn_sent }}
net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ global_options.timeout.tcp.time_wait }}
net.netfilter.nf_conntrack_udp_timeout = {{ global_options.timeout.udp.other }}
net.netfilter.nf_conntrack_udp_timeout_stream = {{ global_options.timeout.udp.stream }}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
</valueHelp>
<valueHelp>
<format>notrack</format>
<description>Igone connection tracking</description>
<description>Ignore connection tracking</description>
</valueHelp>
<constraint>
<regex>(accept|continue|jump|notrack|reject|return|drop|queue)</regex>
Expand Down
8 changes: 8 additions & 0 deletions interface-definitions/include/firewall/global-options.xml.i
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@
</properties>
<defaultValue>enable</defaultValue>
</leafNode>
<node name="timeout">
<properties>
<help>Connection timeout options</help>
</properties>
<children>
#include <include/firewall/timeout-common-protocols.xml.i>
</children>
</node>
<leafNode name="twa-hazards-protection">
<properties>
<help>RFC1337 TCP TIME-WAIT assasination hazards protection</help>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- include start from conntrack/timeout-common-protocols.xml.i -->
<!-- include start from firewall/timeout-common-protocols.xml.i -->
<leafNode name="icmp">
<properties>
<help>ICMP timeout in seconds</help>
Expand Down Expand Up @@ -169,4 +169,3 @@
</leafNode>
</children>
</node>
<!-- include end -->
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- include start from include/version/firewall-version.xml.i -->
<syntaxVersion component='firewall' version='15'></syntaxVersion>
<syntaxVersion component='firewall' version='16'></syntaxVersion>
<!-- include end -->
1 change: 0 additions & 1 deletion interface-definitions/system_conntrack.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,6 @@
</node>
</children>
</node>
#include <include/conntrack/timeout-common-protocols.xml.i>
</children>
</node>
</children>
Expand Down
96 changes: 92 additions & 4 deletions smoketest/scripts/cli/test_firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from vyos.configsession import ConfigSessionError
from vyos.utils.process import run
from vyos.utils.file import read_file

sysfs_config = {
'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'default': '0', 'test_value': 'disable'},
Expand All @@ -38,6 +39,10 @@
'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337', 'default': '0', 'test_value': 'enable'}
}

def get_sysctl(parameter):
tmp = parameter.replace(r'.', r'/')
return read_file(f'/proc/sys/{tmp}')

class TestFirewall(VyOSUnitTestSHIM.TestCase):
@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -240,7 +245,7 @@ def test_ipv4_basic_rules(self):
self.cli_set(['firewall', 'ipv4', 'output', 'raw', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'ipv4', 'output', 'raw', 'rule', '1', 'protocol', 'udp'])

self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'action', 'drop'])
self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'action', 'notrack'])
self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'protocol', 'tcp'])
self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'destination', 'port', '23'])

Expand Down Expand Up @@ -270,7 +275,7 @@ def test_ipv4_basic_rules(self):
['OUT-raw default-action drop', 'drop'],
['chain VYOS_PREROUTING_raw'],
['type filter hook prerouting priority raw; policy accept;'],
['tcp dport 23', 'drop'],
['tcp dport 23', 'notrack'],
['PRE-raw default-action accept', 'accept'],
['chain NAME_smoketest'],
['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[ipv4-NAM-smoketest-1-A]" log level debug', 'ip ttl 15', 'accept'],
Expand Down Expand Up @@ -474,7 +479,7 @@ def test_ipv6_basic_rules(self):
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'outbound-interface', 'name', interface])

self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'default-action', 'drop'])
self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'rule', '1', 'action', 'notrack'])
self.cli_set(['firewall', 'ipv6', 'output', 'raw', 'rule', '1', 'protocol', 'udp'])

self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'action', 'drop'])
Expand All @@ -498,7 +503,7 @@ def test_ipv6_basic_rules(self):
['log prefix "[ipv6-OUT-filter-default-D]"','OUT-filter default-action drop', 'drop'],
['chain VYOS_IPV6_OUTPUT_raw'],
['type filter hook output priority raw; policy accept;'],
['udp', 'accept'],
['udp', 'notrack'],
['OUT-raw default-action drop', 'drop'],
['chain VYOS_IPV6_PREROUTING_raw'],
['type filter hook prerouting priority raw; policy accept;'],
Expand Down Expand Up @@ -770,6 +775,89 @@ def test_sysfs(self):
with open(path, 'r') as f:
self.assertNotEqual(f.read().strip(), conf['default'], msg=path)

def test_timeout_sysctl(self):
timeout_config = {
'net.netfilter.nf_conntrack_icmp_timeout' :{
'cli' : ['global-options', 'timeout', 'icmp'],
'test_value' : '180',
'default_value' : '30',
},
'net.netfilter.nf_conntrack_generic_timeout' :{
'cli' : ['global-options', 'timeout', 'other'],
'test_value' : '1200',
'default_value' : '600',
},
'net.netfilter.nf_conntrack_tcp_timeout_close_wait' :{
'cli' : ['global-options', 'timeout', 'tcp', 'close-wait'],
'test_value' : '30',
'default_value' : '60',
},
'net.netfilter.nf_conntrack_tcp_timeout_close' :{
'cli' : ['global-options', 'timeout', 'tcp', 'close'],
'test_value' : '20',
'default_value' : '10',
},
'net.netfilter.nf_conntrack_tcp_timeout_established' :{
'cli' : ['global-options', 'timeout', 'tcp', 'established'],
'test_value' : '1000',
'default_value' : '432000',
},
'net.netfilter.nf_conntrack_tcp_timeout_fin_wait' :{
'cli' : ['global-options', 'timeout', 'tcp', 'fin-wait'],
'test_value' : '240',
'default_value' : '120',
},
'net.netfilter.nf_conntrack_tcp_timeout_last_ack' :{
'cli' : ['global-options', 'timeout', 'tcp', 'last-ack'],
'test_value' : '300',
'default_value' : '30',
},
'net.netfilter.nf_conntrack_tcp_timeout_syn_recv' :{
'cli' : ['global-options', 'timeout', 'tcp', 'syn-recv'],
'test_value' : '100',
'default_value' : '60',
},
'net.netfilter.nf_conntrack_tcp_timeout_syn_sent' :{
'cli' : ['global-options', 'timeout', 'tcp', 'syn-sent'],
'test_value' : '300',
'default_value' : '120',
},
'net.netfilter.nf_conntrack_tcp_timeout_time_wait' :{
'cli' : ['global-options', 'timeout', 'tcp', 'time-wait'],
'test_value' : '303',
'default_value' : '120',
},
'net.netfilter.nf_conntrack_udp_timeout' :{
'cli' : ['global-options', 'timeout', 'udp', 'other'],
'test_value' : '90',
'default_value' : '30',
},
'net.netfilter.nf_conntrack_udp_timeout_stream' :{
'cli' : ['global-options', 'timeout', 'udp', 'stream'],
'test_value' : '200',
'default_value' : '180',
},
}

for parameter, parameter_config in timeout_config.items():
self.cli_set(['firewall'] + parameter_config['cli'] + [parameter_config['test_value']])

# commit changes
self.cli_commit()

# validate configuration
for parameter, parameter_config in timeout_config.items():
tmp = parameter_config['test_value']
self.assertEqual(get_sysctl(f'{parameter}'), tmp)

# delete all configuration options and revert back to defaults
self.cli_delete(['firewall', 'global-options', 'timeout'])
self.cli_commit()

# validate configuration
for parameter, parameter_config in timeout_config.items():
self.assertEqual(get_sysctl(f'{parameter}'), parameter_config['default_value'])

### Zone
def test_zone_basic(self):
self.cli_set(['firewall', 'ipv4', 'name', 'smoketest', 'default-action', 'drop'])
Expand Down
60 changes: 0 additions & 60 deletions smoketest/scripts/cli/test_system_conntrack.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,66 +68,6 @@ def test_conntrack_options(self):
'test_value' : '128',
'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():
Expand Down
39 changes: 5 additions & 34 deletions src/conf_mode/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,15 @@
from vyos.utils.dict import dict_search_args
from vyos.utils.dict import dict_search_recursive
from vyos.utils.process import call
from vyos.utils.process import cmd
from vyos.utils.process import rc_cmd
from vyos import ConfigError
from vyos import airbag

airbag.enable()

nftables_conf = '/run/nftables.conf'

sysfs_config = {
'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'enable': '0', 'disable': '1'},
'broadcast_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts', 'enable': '0', 'disable': '1'},
'directed_broadcast' : {'sysfs': '/proc/sys/net/ipv4/conf/all/bc_forwarding', 'enable': '1', 'disable': '0'},
'ip_src_route': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_source_route'},
'ipv6_receive_redirects': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_redirects'},
'ipv6_src_route': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_source_route', 'enable': '0', 'disable': '-1'},
'log_martians': {'sysfs': '/proc/sys/net/ipv4/conf/all/log_martians'},
'receive_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_redirects'},
'send_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/send_redirects'},
'syn_cookies': {'sysfs': '/proc/sys/net/ipv4/tcp_syncookies'},
'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337'}
}
sysctl_file = r'/run/sysctl/10-vyos-firewall.conf'

valid_groups = [
'address_group',
Expand Down Expand Up @@ -467,33 +455,16 @@ def generate(firewall):
local_zone_conf['from_local'][zone] = zone_conf['from'][local_zone]

render(nftables_conf, 'firewall/nftables.j2', firewall)
render(sysctl_file, 'firewall/sysctl-firewall.conf.j2', firewall)
return None

def apply_sysfs(firewall):
for name, conf in sysfs_config.items():
paths = glob(conf['sysfs'])
value = None

if name in firewall['global_options']:
conf_value = firewall['global_options'][name]
if conf_value in conf:
value = conf[conf_value]
elif conf_value == 'enable':
value = '1'
elif conf_value == 'disable':
value = '0'

if value:
for path in paths:
with open(path, 'w') as f:
f.write(value)

def apply(firewall):
install_result, output = rc_cmd(f'nft --file {nftables_conf}')
if install_result == 1:
raise ConfigError(f'Failed to apply firewall: {output}')

apply_sysfs(firewall)
# Apply firewall global-options sysctl settings
cmd(f'sysctl -f {sysctl_file}')

call_dependents()

Expand Down
2 changes: 1 addition & 1 deletion src/conf_mode/system_conntrack.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def verify(conntrack):
if not group_obj:
Warning(f'{error_group} "{group_name}" has no members!')

Warning(f'It is prefered to defined {inet} conntrack ignore rules in the <firewall {inet} prerouting raw> section')
Warning(f'It is prefered to define {inet} conntrack ignore rules in <firewall {inet} prerouting raw> section')

if dict_search_args(conntrack, 'timeout', 'custom', inet, 'rule') != None:
for rule, rule_config in conntrack['timeout']['custom'][inet]['rule'].items():
Expand Down
Loading

0 comments on commit 770edf0

Please sign in to comment.