diff options
-rw-r--r-- | data/templates/conntrack/nftables-ct-ignore.tmpl | 40 | ||||
-rw-r--r-- | interface-definitions/include/conntrack/log-common.xml.i | 20 | ||||
-rw-r--r-- | interface-definitions/system-conntrack.xml.in | 205 | ||||
-rwxr-xr-x | src/conf_mode/conntrack.py | 12 |
4 files changed, 277 insertions, 0 deletions
diff --git a/data/templates/conntrack/nftables-ct-ignore.tmpl b/data/templates/conntrack/nftables-ct-ignore.tmpl new file mode 100644 index 000000000..59c1cb1d2 --- /dev/null +++ b/data/templates/conntrack/nftables-ct-ignore.tmpl @@ -0,0 +1,40 @@ +#!/usr/sbin/nft -f + +# we first flush the chains content and then render the new statements from CLI +# if applicable +{% set nft_ct_ignore_name = 'VYOS_CT_IGNORE' %} +flush chain raw {{ nft_ct_ignore_name }} +table raw { + chain {{ nft_ct_ignore_name }} { +{% if ignore is defined and ignore.rule is defined and ignore.rule is not none %} +{% for rule, rule_config in ignore.rule.items() %} + # rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is defined and rule_config.description is not none }} +{% set nft_command = '' %} +{% if rule_config.inbound_interface is defined and rule_config.inbound_interface is not none %} +{% set nft_command = nft_command ~ ' iifname ' ~ rule_config.inbound_interface %} +{% endif %} +{% if rule_config.protocol is defined and rule_config.protocol is not none %} +{% set nft_command = nft_command ~ ' ip protocol ' ~ rule_config.protocol %} +{% endif %} +{% if rule_config.destination is defined and rule_config.destination is not none %} +{% if rule_config.destination.address is defined and rule_config.destination.address is not none %} +{% set nft_command = nft_command ~ ' ip daddr ' ~ rule_config.destination.address %} +{% endif %} +{% if rule_config.destination.port is defined and rule_config.destination.port is not none %} +{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' dport { ' ~ rule_config.destination.port ~ ' }' %} +{% endif %} +{% endif %} +{% if rule_config.source is defined and rule_config.source is not none %} +{% if rule_config.source.address is defined and rule_config.source.address is not none %} +{% set nft_command = nft_command ~ ' ip saddr ' ~ rule_config.source.address %} +{% endif %} +{% if rule_config.source.port is defined and rule_config.source.port is not none %} +{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' sport { ' ~ rule_config.source.port ~ ' }' %} +{% endif %} +{% endif %} + {{ nft_command }} counter return comment ignore-{{ rule }} +{% endfor %} +{% endif %} + return + } +} diff --git a/interface-definitions/include/conntrack/log-common.xml.i b/interface-definitions/include/conntrack/log-common.xml.i new file mode 100644 index 000000000..38799f8f4 --- /dev/null +++ b/interface-definitions/include/conntrack/log-common.xml.i @@ -0,0 +1,20 @@ +<!-- include start from conntrack/log-common.xml.i --> +<leafNode name="destroy"> + <properties> + <help>Log connection deletion</help> + <valueless/> + </properties> +</leafNode> +<leafNode name="new"> + <properties> + <help>Log connection creation</help> + <valueless/> + </properties> +</leafNode> +<leafNode name="update"> + <properties> + <help>Log connection updates</help> + <valueless/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/system-conntrack.xml.in b/interface-definitions/system-conntrack.xml.in index daa4177c9..88f96a078 100644 --- a/interface-definitions/system-conntrack.xml.in +++ b/interface-definitions/system-conntrack.xml.in @@ -35,6 +35,128 @@ </properties> <defaultValue>32768</defaultValue> </leafNode> + <node name="ignore"> + <properties> + <help>Customized rules to ignore selective connection tracking</help> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Rule number</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number of conntrack ignore rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Ignore rule number must be between 1 and 999999</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="destination"> + <properties> + <help>Destination parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + <leafNode name="inbound-interface"> + <properties> + <help>Interface to ignore connections tracking on</help> + <completionHelp> + <list>any</list> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> + </leafNode> + #include <include/ip-protocol.xml.i> + <leafNode name="protocol"> + <properties> + <help>Protocol to match (protocol name, number, or "all")</help> + <completionHelp> + <script>${vyos_completion_dir}/list_protocols.sh</script> + <list>all tcp_udp</list> + </completionHelp> + <valueHelp> + <format>all</format> + <description>All IP protocols</description> + </valueHelp> + <valueHelp> + <format>tcp_udp</format> + <description>Both TCP and UDP</description> + </valueHelp> + <valueHelp> + <format>u32:0-255</format> + <description>IP protocol number</description> + </valueHelp> + <valueHelp> + <format><protocol></format> + <description>IP protocol name</description> + </valueHelp> + <valueHelp> + <format>!<protocol></format> + <description>IP protocol name</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + </leafNode> + <node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + </children> + </tagNode> + </children> + </node> + <node name="log"> + <properties> + <help>Log connection tracking events per protocol</help> + </properties> + <children> + <node name="icmp"> + <properties> + <help>Log connection tracking events for ICMP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + <node name="other"> + <properties> + <help>Log connection tracking events for all protocols other than TCP, UDP and ICMP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + <node name="tcp"> + <properties> + <help>Log connection tracking events for TCP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + <node name="udp"> + <properties> + <help>Log connection tracking events for UDP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + </children> + </node> <node name="modules"> <properties> <help>Connection tracking modules</help> @@ -155,6 +277,89 @@ <help>Connection timeout options</help> </properties> <children> + <node name="custom"> + <properties> + <help>Define custom timeouts per connection</help> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Rule number</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number of conntrack rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Ignore rule number must be between 1 and 999999</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="destination"> + <properties> + <help>Destination parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + <leafNode name="inbound-interface"> + <properties> + <help>Interface to ignore connections tracking on</help> + <completionHelp> + <list>any</list> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> + </leafNode> + #include <include/ip-protocol.xml.i> + <leafNode name="protocol"> + <properties> + <help>Protocol to match (protocol name, number, or "all")</help> + <completionHelp> + <script>${vyos_completion_dir}/list_protocols.sh</script> + <list>all tcp_udp</list> + </completionHelp> + <valueHelp> + <format>all</format> + <description>All IP protocols</description> + </valueHelp> + <valueHelp> + <format>tcp_udp</format> + <description>Both TCP and UDP</description> + </valueHelp> + <valueHelp> + <format>u32:0-255</format> + <description>IP protocol number</description> + </valueHelp> + <valueHelp> + <format><protocol></format> + <description>IP protocol name</description> + </valueHelp> + <valueHelp> + <format>!<protocol></format> + <description>IP protocol name</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + </leafNode> + <node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + </children> + </tagNode> + </children> + </node> <leafNode name="icmp"> <properties> <help>ICMP timeout in seconds</help> diff --git a/src/conf_mode/conntrack.py b/src/conf_mode/conntrack.py index c65ef9540..3cb0dd1e2 100755 --- a/src/conf_mode/conntrack.py +++ b/src/conf_mode/conntrack.py @@ -35,6 +35,7 @@ airbag.enable() conntrack_config = r'/etc/modprobe.d/vyatta_nf_conntrack.conf' sysctl_file = r'/run/sysctl/10-vyos-conntrack.conf' +nftables_ct_ignore_file = r'/run/nftables-ct-ignore.conf' # Every ALG (Application Layer Gateway) consists of either a Kernel Object # also called a Kernel Module/Driver or some rules present in iptables @@ -86,11 +87,19 @@ def get_config(config=None): return conntrack def verify(conntrack): + if dict_search('ignore.rule', conntrack) != None: + for rule, rule_config in conntrack['ignore']['rule'].items(): + if dict_search('destination.port', rule_config) or \ + dict_search('source.port', rule_config): + if 'protocol' not in rule_config or rule_config['protocol'] not in ['tcp', 'udp']: + raise ConfigError(f'Port requires tcp or udp as protocol in rule {rule}') + return None def generate(conntrack): render(conntrack_config, 'conntrack/vyos_nf_conntrack.conf.tmpl', conntrack) render(sysctl_file, 'conntrack/sysctl.conf.tmpl', conntrack) + render(nftables_ct_ignore_file, 'conntrack/nftables-ct-ignore.tmpl', conntrack) return None @@ -127,6 +136,9 @@ def apply(conntrack): if not find_nftables_ct_rule(rule): cmd(f'nft insert rule ip raw VYOS_CT_HELPER {rule}') + # Load new nftables ruleset + cmd(f'nft -f {nftables_ct_ignore_file}') + if process_named_running('conntrackd'): # Reload conntrack-sync daemon to fetch new sysctl values resync_conntrackd() |