Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions data/templates/firewall/nftables.j2
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,25 @@ table ip vyos_filter {
{% endfor %}
{% endif %}

{% if ipv4.forward.filter.disable_conntrack is vyos_defined or ipv4.input.filter.disable_conntrack is vyos_defined %}
chain VYOS_DISABLE_CONNTRACK_INP_FWD {
type filter hook prerouting priority -320; policy accept;
{% if ipv4.forward.filter.disable_conntrack is vyos_defined %}
fib daddr . iif type unicast notrack counter comment "DISABLE-CT-FWD"
{% endif %}
{% if ipv4.input.filter.disable_conntrack is vyos_defined %}
fib daddr . iif type local notrack counter comment "DISABLE-CT-INP"
{% endif %}
}
{% endif %}

{% if ipv4.output.filter.disable_conntrack is vyos_defined %}
chain VYOS_DISABLE_CONNTRACK_OUT {
type filter hook output priority -320; policy accept;
notrack counter comment "DISABLE-CT-OUT"
}
{% endif %}

{% for set_name in ns.sets %}
set RECENT_{{ set_name }} {
type ipv4_addr
Expand Down Expand Up @@ -308,6 +327,25 @@ table ip6 vyos_filter {
{% endfor %}
{% endif %}

{% if ipv6.forward.filter.disable_conntrack is vyos_defined or ipv6.input.filter.disable_conntrack is vyos_defined %}
chain VYOS_DISABLE_CONNTRACK_INP_FWD_V6 {
type filter hook prerouting priority -320; policy accept;
{% if ipv6.forward.filter.disable_conntrack is vyos_defined %}
fib daddr . iif type unicast notrack counter comment "DISABLE-CT-FWD-V6"
{% endif %}
{% if ipv6.input.filter.disable_conntrack is vyos_defined %}
fib daddr . iif type local notrack counter comment "DISABLE-CT-INP-V6"
{% endif %}
}
{% endif %}

{% if ipv6.output.filter.disable_conntrack is vyos_defined %}
chain VYOS_DISABLE_CONNTRACK_OUT_V6 {
type filter hook output priority -320; policy accept;
notrack counter comment "DISABLE-CT-OUT-V6"
}
{% endif %}

{% for set_name in ns.sets %}
set RECENT6_{{ set_name }} {
type ipv6_addr
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- include start from firewall/disable-conntrack.xml.i -->
<leafNode name="disable-conntrack">
<properties>
<help>Disable conntrack within this chain</help>
<valueless/>
</properties>
</leafNode>
<!-- include end -->
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<help>IPv4 firewall forward filter</help>
</properties>
<children>
#include <include/firewall/disable-conntrack.xml.i>
#include <include/firewall/default-action-base-chains.xml.i>
#include <include/firewall/default-log.xml.i>
#include <include/generic-description.xml.i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<help>IPv4 firewall input filter</help>
</properties>
<children>
#include <include/firewall/disable-conntrack.xml.i>
#include <include/firewall/default-action-base-chains.xml.i>
#include <include/firewall/default-log.xml.i>
#include <include/generic-description.xml.i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<help>IPv4 firewall output filter</help>
</properties>
<children>
#include <include/firewall/disable-conntrack.xml.i>
#include <include/firewall/default-action-base-chains.xml.i>
#include <include/firewall/default-log.xml.i>
#include <include/generic-description.xml.i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<help>IPv6 firewall forward filter</help>
</properties>
<children>
#include <include/firewall/disable-conntrack.xml.i>
#include <include/firewall/default-action-base-chains.xml.i>
#include <include/firewall/default-log.xml.i>
#include <include/generic-description.xml.i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<help>IPv6 firewall input filter</help>
</properties>
<children>
#include <include/firewall/disable-conntrack.xml.i>
#include <include/firewall/default-action-base-chains.xml.i>
#include <include/firewall/default-log.xml.i>
#include <include/generic-description.xml.i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<help>IPv6 firewall output filter</help>
</properties>
<children>
#include <include/firewall/disable-conntrack.xml.i>
#include <include/firewall/default-action-base-chains.xml.i>
#include <include/firewall/default-log.xml.i>
#include <include/generic-description.xml.i>
Expand Down
50 changes: 50 additions & 0 deletions smoketest/scripts/cli/test_firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -1404,5 +1404,55 @@ def test_remote_group(self):
self.verify_nftables(nftables_v6_search, 'ip6 vyos_filter')


def test_disable_conntrack_per_chain(self):
# If conntrack is disabled in either the input or output chain,
# state cannot be matched in either the input or outchain
self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '1', 'state', 'established'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()

self.cli_discard()

# If conntrack is disabled in the forward chain,
# state cannot be matched in the forward chain
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'state', 'established'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()

self.cli_discard()

# Disable conntrack in all chains for both ipv4 and ipv6
self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'disable-conntrack'])
self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'disable-conntrack'])

self.cli_commit()

nftables_search = [
['VYOS_DISABLE_CONNTRACK_INP_FWD'],
['VYOS_DISABLE_CONNTRACK_OUT'],
['fib daddr . iif type unicast notrack counter'],
['fib daddr . iif type local notrack counter ']
]

self.verify_nftables(nftables_search, 'ip vyos_filter')

nftables_search = [
['VYOS_DISABLE_CONNTRACK_INP_FWD_V6'],
['VYOS_DISABLE_CONNTRACK_OUT_V6'],
['fib daddr . iif type unicast notrack counter'],
['fib daddr . iif type local notrack counter ']
]

self.verify_nftables(nftables_search, 'ip6 vyos_filter')


if __name__ == '__main__':
unittest.main(verbosity=2)
32 changes: 32 additions & 0 deletions src/conf_mode/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from vyos.firewall import fqdn_config_parse
from vyos.firewall import geoip_update
from vyos.template import render
from vyos.utils.dict import dict_search
from vyos.utils.dict import dict_search_args
from vyos.utils.dict import dict_search_recursive
from vyos.utils.file import write_file
Expand Down Expand Up @@ -267,6 +268,24 @@ def verify_rule(firewall, family, hook, priority, rule_id, rule_conf):
if rule_conf.get('protocol', {}) != 'tcp':
raise ConfigError('For action "synproxy" the protocol must be set to TCP')

if 'state' in rule_conf:
disable_conntrack = dict_search(f'{family}.{hook}.{priority}.disable_conntrack', firewall)
conntrack_disabled_list = []

# Check if conntrack is disabled in the input or output chain
for nft_chain in ['input', 'output']:
if dict_search(f'{family}.{nft_chain}.filter.disable_conntrack', firewall) == {}:
conntrack_disabled_list.append(nft_chain)

# If conntrack is disabled in the input or output chain,
# state cannot be matched in the input or output chain
if hook in ['input', 'output'] and conntrack_disabled_list:
raise ConfigError(f'state cannot be matched in {hook} when conntrack is disabled in input or output chains')
# If conntrack is disabled in the forward chain,
# state cannot be matched in the forward chain
if hook == 'forward' and disable_conntrack == {}:
raise ConfigError(f'state cannot be matched in {hook} when conntrack is disabled in {hook} chain')

if 'queue_options' in rule_conf:
if 'queue' not in rule_conf['action']:
raise ConfigError('queue-options defined, but action queue needed and it is not defined')
Expand Down Expand Up @@ -480,6 +499,19 @@ def verify(firewall):
for ifname in interfaces:
verify_hardware_offload(ifname)

if dict_search('global_options.state_policy', firewall) is not None:
# Generate list of chains where conntrack is disabled
conntrack_disabled_list = []
for inet_family in ['ipv4', 'ipv6']:
for nft_chain in ['input', 'forward', 'output']:
if dict_search(f'{inet_family}.{nft_chain}.filter.disable_conntrack', firewall) == {}:
conntrack_disabled_list.append(f'{inet_family}-{nft_chain}')

# If conntrack is disabled in any chain,
# print a warning message
if conntrack_disabled_list:
Warning(f'global-state: conntrack is disabled in the following chains: {", ".join(conntrack_disabled_list)}')

if 'offload' in firewall.get('global_options', {}).get('state_policy', {}):
offload_path = firewall['global_options']['state_policy']['offload']
if 'offload_target' not in offload_path:
Expand Down
Loading