summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2024-01-22 07:56:32 +0100
committerGitHub <noreply@github.com>2024-01-22 07:56:32 +0100
commit39d0464616be1fc12be201223a84937b43c19382 (patch)
tree1143f24e0fbbb8026da16dc4092ff36d27435bf4
parent4412d1ae8499de3a49d99c37f66b93c6b4693295 (diff)
parent2ec023752bdd400835eb69a8f1f9d2873cef61fa (diff)
downloadvyos-1x-39d0464616be1fc12be201223a84937b43c19382.tar.gz
vyos-1x-39d0464616be1fc12be201223a84937b43c19382.zip
Merge pull request #2856 from c-po/firewall-backports
firewall: T5729: T5681: T5217: backport subsystem from current branch
-rw-r--r--data/config-mode-dependencies/vyos-1x.json88
-rw-r--r--data/templates/firewall/nftables-bridge.j28
-rw-r--r--data/templates/firewall/nftables-nat.j221
-rw-r--r--data/templates/firewall/nftables-nat66.j217
-rw-r--r--data/templates/firewall/nftables-offload.j22
-rw-r--r--data/templates/firewall/nftables-zone.j26
-rw-r--r--data/templates/firewall/nftables.j233
-rw-r--r--data/vyos-firewall-init.conf82
-rw-r--r--interface-definitions/include/firewall/action-forward.xml.i10
-rw-r--r--interface-definitions/include/firewall/action-l2.xml.i4
-rw-r--r--interface-definitions/include/firewall/action.xml.i8
-rw-r--r--interface-definitions/include/firewall/common-rule-bridge.xml.i7
-rw-r--r--interface-definitions/include/firewall/common-rule-inet.xml.i11
-rw-r--r--interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i1
-rw-r--r--interface-definitions/include/firewall/default-action-bridge.xml.i6
-rw-r--r--interface-definitions/include/firewall/default-action.xml.i2
-rw-r--r--interface-definitions/include/firewall/firewall-mark.xml.i2
-rw-r--r--interface-definitions/include/firewall/log.xml.i3
-rw-r--r--interface-definitions/include/firewall/match-interface.xml.i2
-rw-r--r--interface-definitions/include/firewall/match-vlan.xml.i12
-rw-r--r--interface-definitions/include/firewall/offload-target.xml.i2
-rw-r--r--interface-definitions/include/firewall/state.xml.i2
-rw-r--r--interface-definitions/include/firewall/synproxy.xml.i40
-rw-r--r--interface-definitions/include/firewall/tcp-flags.xml.i18
-rw-r--r--interface-definitions/include/firewall/tcp-mss.xml.i25
-rw-r--r--op-mode-definitions/show-log.xml.in264
-rw-r--r--python/vyos/firewall.py13
-rw-r--r--python/vyos/template.py6
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py49
-rwxr-xr-xsmoketest/scripts/cli/test_system_flow-accounting.py2
-rwxr-xr-xsrc/conf_mode/firewall.py31
-rwxr-xr-xsrc/conf_mode/load-balancing_wan.py5
-rwxr-xr-xsrc/conf_mode/nat.py92
-rwxr-xr-xsrc/conf_mode/nat66.py45
-rwxr-xr-xsrc/conf_mode/system_flow-accounting.py2
-rwxr-xr-xsrc/op_mode/firewall.py23
36 files changed, 542 insertions, 402 deletions
diff --git a/data/config-mode-dependencies/vyos-1x.json b/data/config-mode-dependencies/vyos-1x.json
index 81d86cf7e..4fd94d895 100644
--- a/data/config-mode-dependencies/vyos-1x.json
+++ b/data/config-mode-dependencies/vyos-1x.json
@@ -1,40 +1,52 @@
{
- "firewall": {
- "conntrack": ["system_conntrack"],
- "group_resync": ["system_conntrack", "nat", "policy_route"]
- },
- "interfaces_bonding": {
- "ethernet": ["interfaces_ethernet"]
- },
- "interfaces_bridge": {
- "vxlan": ["interfaces_vxlan"]
- },
- "pki": {
- "ethernet": ["interfaces_ethernet"],
- "openvpn": ["interfaces_openvpn"],
- "https": ["service_https"],
- "ipsec": ["vpn_ipsec"],
- "openconnect": ["vpn_openconnect"],
- "sstp": ["vpn_sstp"]
- },
- "qos": {
- "bonding": ["interfaces_bonding"],
- "bridge": ["interfaces_bridge"],
- "dummy": ["interfaces_dummy"],
- "ethernet": ["interfaces_ethernet"],
- "geneve": ["interfaces_geneve"],
- "input": ["interfaces_input"],
- "l2tpv3": ["interfaces_l2tpv3"],
- "loopback": ["interfaces_loopback"],
- "macsec": ["interfaces_macsec"],
- "openvpn": ["interfaces_openvpn"],
- "pppoe": ["interfaces_pppoe"],
- "pseudo-ethernet": ["interfaces_pseudo-ethernet"],
- "tunnel": ["interfaces_tunnel"],
- "vti": ["interfaces_vti"],
- "vxlan": ["interfaces_vxlan"],
- "wireguard": ["interfaces_wireguard"],
- "wireless": ["interfaces_wireless"],
- "wwan": ["interfaces_wwan"]
- }
+ "system_conntrack": {
+ "conntrack_sync": ["service_conntrack-sync"]
+ },
+ "firewall": {
+ "conntrack": ["system_conntrack"],
+ "group_resync": ["system_conntrack", "nat", "policy_route"]
+ },
+ "interfaces_bonding": {
+ "ethernet": ["interfaces_ethernet"]
+ },
+ "interfaces_bridge": {
+ "vxlan": ["interfaces_vxlan"]
+ },
+ "load_balancing_wan": {
+ "conntrack": ["system_conntrack"]
+ },
+ "nat": {
+ "conntrack": ["system_conntrack"]
+ },
+ "nat66": {
+ "conntrack": ["system_conntrack"]
+ },
+ "pki": {
+ "ethernet": ["interfaces_ethernet"],
+ "openvpn": ["interfaces_openvpn"],
+ "https": ["service_https"],
+ "ipsec": ["vpn_ipsec"],
+ "openconnect": ["vpn_openconnect"],
+ "sstp": ["vpn_sstp"]
+ },
+ "qos": {
+ "bonding": ["interfaces_bonding"],
+ "bridge": ["interfaces_bridge"],
+ "dummy": ["interfaces_dummy"],
+ "ethernet": ["interfaces_ethernet"],
+ "geneve": ["interfaces_geneve"],
+ "input": ["interfaces_input"],
+ "l2tpv3": ["interfaces_l2tpv3"],
+ "loopback": ["interfaces_loopback"],
+ "macsec": ["interfaces_macsec"],
+ "openvpn": ["interfaces_openvpn"],
+ "pppoe": ["interfaces_pppoe"],
+ "pseudo-ethernet": ["interfaces_pseudo-ethernet"],
+ "tunnel": ["interfaces_tunnel"],
+ "vti": ["interfaces_vti"],
+ "vxlan": ["interfaces_vxlan"],
+ "wireguard": ["interfaces_wireguard"],
+ "wireless": ["interfaces_wireless"],
+ "wwan": ["interfaces_wwan"]
+ }
}
diff --git a/data/templates/firewall/nftables-bridge.j2 b/data/templates/firewall/nftables-bridge.j2
index 1a4ad2ed9..dec027bf9 100644
--- a/data/templates/firewall/nftables-bridge.j2
+++ b/data/templates/firewall/nftables-bridge.j2
@@ -2,9 +2,8 @@
{% set ns = namespace(sets=[]) %}
{% if bridge.forward is vyos_defined %}
{% for prior, conf in bridge.forward.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_FORWARD_{{ prior }} {
- type filter hook forward priority {{ prior }}; policy {{ def_action }};
+ type filter hook forward priority {{ prior }}; policy accept;
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
{{ rule_conf | nft_rule('FWD', prior, rule_id, 'bri') }}
@@ -13,6 +12,7 @@
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('FWD-filter', 'bri') }}
}
{% endfor %}
{% endif %}
@@ -28,8 +28,8 @@
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule(name_text) }}
+ {{ conf | nft_default_rule(name_text, 'bri') }}
}
{% endfor %}
{% endif %}
-{% endmacro %} \ No newline at end of file
+{% endmacro %}
diff --git a/data/templates/firewall/nftables-nat.j2 b/data/templates/firewall/nftables-nat.j2
index dcf28da88..4254f6a0e 100644
--- a/data/templates/firewall/nftables-nat.j2
+++ b/data/templates/firewall/nftables-nat.j2
@@ -2,27 +2,6 @@
{% import 'firewall/nftables-defines.j2' as group_tmpl %}
-{% if helper_functions is vyos_defined('remove') %}
-{# NAT if going to be disabled - remove rules and targets from nftables #}
-{% set base_command = 'delete rule ip raw' %}
-{{ base_command }} PREROUTING handle {{ pre_ct_ignore }}
-{{ base_command }} OUTPUT handle {{ out_ct_ignore }}
-{{ base_command }} PREROUTING handle {{ pre_ct_conntrack }}
-{{ base_command }} OUTPUT handle {{ out_ct_conntrack }}
-
-delete chain ip raw NAT_CONNTRACK
-
-{% elif helper_functions is vyos_defined('add') %}
-{# NAT if enabled - add targets to nftables #}
-add chain ip raw NAT_CONNTRACK
-add rule ip raw NAT_CONNTRACK counter accept
-{% set base_command = 'add rule ip raw' %}
-{{ base_command }} PREROUTING position {{ pre_ct_ignore }} counter jump VYOS_CT_HELPER
-{{ base_command }} OUTPUT position {{ out_ct_ignore }} counter jump VYOS_CT_HELPER
-{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK
-{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK
-{% endif %}
-
{% if first_install is not vyos_defined %}
delete table ip vyos_nat
{% endif %}
diff --git a/data/templates/firewall/nftables-nat66.j2 b/data/templates/firewall/nftables-nat66.j2
index 27b3eec88..67eb2c109 100644
--- a/data/templates/firewall/nftables-nat66.j2
+++ b/data/templates/firewall/nftables-nat66.j2
@@ -1,22 +1,5 @@
#!/usr/sbin/nft -f
-{% if helper_functions is vyos_defined('remove') %}
-{# NAT if going to be disabled - remove rules and targets from nftables #}
-{% set base_command = 'delete rule ip6 raw' %}
-{{ base_command }} PREROUTING handle {{ pre_ct_conntrack }}
-{{ base_command }} OUTPUT handle {{ out_ct_conntrack }}
-
-delete chain ip6 raw NAT_CONNTRACK
-
-{% elif helper_functions is vyos_defined('add') %}
-{# NAT if enabled - add targets to nftables #}
-add chain ip6 raw NAT_CONNTRACK
-add rule ip6 raw NAT_CONNTRACK counter accept
-{% set base_command = 'add rule ip6 raw' %}
-{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK
-{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK
-{% endif %}
-
{% if first_install is not vyos_defined %}
delete table ip6 vyos_nat
{% endif %}
diff --git a/data/templates/firewall/nftables-offload.j2 b/data/templates/firewall/nftables-offload.j2
index 087fd141c..a893e05b2 100644
--- a/data/templates/firewall/nftables-offload.j2
+++ b/data/templates/firewall/nftables-offload.j2
@@ -6,4 +6,4 @@
{% endif %}
counter
}
-{% endmacro %} \ No newline at end of file
+{% endmacro %}
diff --git a/data/templates/firewall/nftables-zone.j2 b/data/templates/firewall/nftables-zone.j2
index 506ad815e..e78725079 100644
--- a/data/templates/firewall/nftables-zone.j2
+++ b/data/templates/firewall/nftables-zone.j2
@@ -44,7 +44,7 @@
iifname { {{ zone[from_zone].interface | join(",") }} } counter return
{% endfor %}
{% endif %}
- {{ zone_conf | nft_default_rule('zone_' + zone_name) }}
+ {{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
}
chain VZONE_{{ zone_name }}_OUT {
oifname lo counter return
@@ -54,7 +54,7 @@
oifname { {{ zone[from_zone].interface | join(",") }} } counter return
{% endfor %}
{% endif %}
- {{ zone_conf | nft_default_rule('zone_' + zone_name) }}
+ {{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
}
{% else %}
chain VZONE_{{ zone_name }} {
@@ -70,7 +70,7 @@
{% endif %}
{% endfor %}
{% endif %}
- {{ zone_conf | nft_default_rule('zone_' + zone_name) }}
+ {{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
}
{% endif %}
{% endfor %}
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index 4851e3a05..833df3a67 100644
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -5,17 +5,10 @@
{% import 'firewall/nftables-offload.j2' as offload_tmpl %}
{% import 'firewall/nftables-zone.j2' as zone_tmpl %}
-flush chain raw FW_CONNTRACK
-flush chain ip6 raw FW_CONNTRACK
-
flush chain raw vyos_global_rpfilter
flush chain ip6 raw vyos_global_rpfilter
table raw {
- chain FW_CONNTRACK {
- {{ ipv4_conntrack_action }}
- }
-
chain vyos_global_rpfilter {
{% if global_options.source_validation is vyos_defined('loose') %}
fib saddr oif 0 counter drop
@@ -27,10 +20,6 @@ table raw {
}
table ip6 raw {
- chain FW_CONNTRACK {
- {{ ipv6_conntrack_action }}
- }
-
chain vyos_global_rpfilter {
{% if global_options.ipv6_source_validation is vyos_defined('loose') %}
fib saddr oif 0 counter drop
@@ -68,7 +57,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('FWD-filter') }}
+ {{ conf | nft_default_rule('FWD-filter', 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -88,7 +77,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('INP-filter') }}
+ {{ conf | nft_default_rule('INP-filter', 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -108,7 +97,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('OUT-filter') }}
+ {{ conf | nft_default_rule('OUT-filter', 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -128,7 +117,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('PRE-filter') }}
+ {{ conf | nft_default_rule('PRE-filter', 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -144,7 +133,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule(name_text) }}
+ {{ conf | nft_default_rule(name_text, 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -219,7 +208,7 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('FWD-filter', ipv6=True) }}
+ {{ conf | nft_default_rule('FWD-filter', 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -239,7 +228,7 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('INP-filter', ipv6=True) }}
+ {{ conf | nft_default_rule('INP-filter', 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -259,7 +248,7 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('OUT-filter', ipv6=True) }}
+ {{ conf | nft_default_rule('OUT-filter', 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -280,7 +269,7 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule(name_text, ipv6=True) }}
+ {{ conf | nft_default_rule(name_text, 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -308,7 +297,6 @@ table ip6 vyos_filter {
{% endif %}
{% endif %}
{{ group_tmpl.groups(group, True, True) }}
-
{% if zone is vyos_defined %}
{{ zone_tmpl.zone_chains(zone, True, global_options.state_policy is vyos_defined) }}
{% endif %}
@@ -326,7 +314,6 @@ table ip6 vyos_filter {
return
}
{% endif %}
-
}
## Bridge Firewall
@@ -337,4 +324,4 @@ table bridge vyos_filter {
{{ bridge_tmpl.bridge(bridge) }}
{{ group_tmpl.groups(group, False, False) }}
-} \ No newline at end of file
+}
diff --git a/data/vyos-firewall-init.conf b/data/vyos-firewall-init.conf
index b0026fdf3..cd7d5011f 100644
--- a/data/vyos-firewall-init.conf
+++ b/data/vyos-firewall-init.conf
@@ -9,6 +9,7 @@ table ip nat {
}
table inet mangle {
+ # Used by system flow-accounting
chain FORWARD {
type filter hook forward priority -150; policy accept;
}
@@ -28,61 +29,9 @@ table raw {
counter jump vyos_global_rpfilter
}
- chain PREROUTING {
+ # Used by system flow-accounting
+ chain VYOS_PREROUTING_HOOK {
type filter hook prerouting priority -300; policy accept;
- counter jump VYOS_CT_IGNORE
- counter jump VYOS_CT_TIMEOUT
- counter jump VYOS_CT_PREROUTING_HOOK
- counter jump FW_CONNTRACK
- notrack
- }
-
- chain OUTPUT {
- type filter hook output priority -300; policy accept;
- counter jump VYOS_CT_IGNORE
- counter jump VYOS_CT_TIMEOUT
- counter jump VYOS_CT_OUTPUT_HOOK
- counter jump FW_CONNTRACK
- notrack
- }
-
- ct helper rpc_tcp {
- type "rpc" protocol tcp;
- }
-
- ct helper rpc_udp {
- type "rpc" protocol udp;
- }
-
- ct helper tns_tcp {
- type "tns" protocol tcp;
- }
-
- chain VYOS_CT_HELPER {
- ct helper set "rpc_tcp" tcp dport {111} return
- ct helper set "rpc_udp" udp dport {111} return
- ct helper set "tns_tcp" tcp dport {1521,1525,1536} return
- return
- }
-
- chain VYOS_CT_IGNORE {
- return
- }
-
- chain VYOS_CT_TIMEOUT {
- return
- }
-
- chain VYOS_CT_PREROUTING_HOOK {
- return
- }
-
- chain VYOS_CT_OUTPUT_HOOK {
- return
- }
-
- chain FW_CONNTRACK {
- return
}
}
@@ -100,29 +49,8 @@ table ip6 raw {
counter jump vyos_global_rpfilter
}
- chain PREROUTING {
+ # Used by system flow-accounting
+ chain VYOS_PREROUTING_HOOK {
type filter hook prerouting priority -300; policy accept;
- counter jump VYOS_CT_PREROUTING_HOOK
- counter jump FW_CONNTRACK
- notrack
- }
-
- chain OUTPUT {
- type filter hook output priority -300; policy accept;
- counter jump VYOS_CT_OUTPUT_HOOK
- counter jump FW_CONNTRACK
- notrack
- }
-
- chain VYOS_CT_PREROUTING_HOOK {
- return
- }
-
- chain VYOS_CT_OUTPUT_HOOK {
- return
- }
-
- chain FW_CONNTRACK {
- return
}
}
diff --git a/interface-definitions/include/firewall/action-forward.xml.i b/interface-definitions/include/firewall/action-forward.xml.i
index 87da72c97..4e59f3c6f 100644
--- a/interface-definitions/include/firewall/action-forward.xml.i
+++ b/interface-definitions/include/firewall/action-forward.xml.i
@@ -3,7 +3,7 @@
<properties>
<help>Rule action</help>
<completionHelp>
- <list>accept continue jump reject return drop queue offload</list>
+ <list>accept continue jump reject return drop queue offload synproxy</list>
</completionHelp>
<valueHelp>
<format>accept</format>
@@ -37,9 +37,13 @@
<format>offload</format>
<description>Offload packet via flowtable</description>
</valueHelp>
+ <valueHelp>
+ <format>synproxy</format>
+ <description>Synproxy connections</description>
+ </valueHelp>
<constraint>
- <regex>(accept|continue|jump|reject|return|drop|queue|offload)</regex>
+ <regex>(accept|continue|jump|reject|return|drop|queue|offload|synproxy)</regex>
</constraint>
</properties>
</leafNode>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/action-l2.xml.i b/interface-definitions/include/firewall/action-l2.xml.i
index 43fd211b4..84af576c8 100644
--- a/interface-definitions/include/firewall/action-l2.xml.i
+++ b/interface-definitions/include/firewall/action-l2.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from firewall/action-l2.xml.i -->
+<!-- include start from firewall/action.xml.i -->
<leafNode name="action">
<properties>
<help>Rule action</help>
@@ -34,4 +34,4 @@
</constraint>
</properties>
</leafNode>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/action.xml.i b/interface-definitions/include/firewall/action.xml.i
index 5dd1bfaff..e1f0c6cb6 100644
--- a/interface-definitions/include/firewall/action.xml.i
+++ b/interface-definitions/include/firewall/action.xml.i
@@ -3,7 +3,7 @@
<properties>
<help>Rule action</help>
<completionHelp>
- <list>accept continue jump reject return drop queue offload</list>
+ <list>accept continue jump reject return drop queue offload synproxy</list>
</completionHelp>
<valueHelp>
<format>accept</format>
@@ -37,8 +37,12 @@
<format>offload</format>
<description>Offload packet via flowtable</description>
</valueHelp>
+ <valueHelp>
+ <format>synproxy</format>
+ <description>Synproxy connections</description>
+ </valueHelp>
<constraint>
- <regex>(accept|continue|jump|reject|return|drop|queue|offload)</regex>
+ <regex>(accept|continue|jump|reject|return|drop|queue|offload|synproxy)</regex>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/include/firewall/common-rule-bridge.xml.i b/interface-definitions/include/firewall/common-rule-bridge.xml.i
index dcdd970ac..6de770c79 100644
--- a/interface-definitions/include/firewall/common-rule-bridge.xml.i
+++ b/interface-definitions/include/firewall/common-rule-bridge.xml.i
@@ -9,7 +9,12 @@
#include <include/firewall/mac-address.xml.i>
</children>
</node>
-#include <include/generic-disable-node.xml.i>
+<leafNode name="disable">
+ <properties>
+ <help>Option to disable firewall rule</help>
+ <valueless/>
+ </properties>
+</leafNode>
<leafNode name="jump-target">
<properties>
<help>Set jump target. Action jump must be defined to use this setting</help>
diff --git a/interface-definitions/include/firewall/common-rule-inet.xml.i b/interface-definitions/include/firewall/common-rule-inet.xml.i
index 3b5cb724d..6f56ecc85 100644
--- a/interface-definitions/include/firewall/common-rule-inet.xml.i
+++ b/interface-definitions/include/firewall/common-rule-inet.xml.i
@@ -7,7 +7,12 @@
#include <include/firewall/connection-mark.xml.i>
#include <include/firewall/conntrack-helper.xml.i>
#include <include/firewall/nft-queue.xml.i>
-#include <include/generic-disable-node.xml.i>
+<leafNode name="disable">
+ <properties>
+ <help>Option to disable firewall rule</help>
+ <valueless/>
+ </properties>
+</leafNode>
<node name="fragment">
<properties>
<help>IP fragment match</help>
@@ -179,8 +184,10 @@
</leafNode>
</children>
</node>
+#include <include/firewall/synproxy.xml.i>
#include <include/firewall/state.xml.i>
#include <include/firewall/tcp-flags.xml.i>
+#include <include/firewall/tcp-mss.xml.i>
<node name="time">
<properties>
<help>Time to match rule</help>
@@ -249,4 +256,4 @@
</leafNode>
</children>
</node>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i b/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i
index b253ee048..0d749aa27 100644
--- a/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i
+++ b/interface-definitions/include/firewall/common-rule-ipv4-raw.xml.i
@@ -260,6 +260,7 @@
</children>
</node>
#include <include/firewall/tcp-flags.xml.i>
+#include <include/firewall/tcp-mss.xml.i>
<node name="time">
<properties>
<help>Time to match rule</help>
diff --git a/interface-definitions/include/firewall/default-action-bridge.xml.i b/interface-definitions/include/firewall/default-action-bridge.xml.i
index 577165976..858c7aeeb 100644
--- a/interface-definitions/include/firewall/default-action-bridge.xml.i
+++ b/interface-definitions/include/firewall/default-action-bridge.xml.i
@@ -1,7 +1,7 @@
-<!-- include start from firewall/default-action-bridge.xml.i -->
+<!-- include start from firewall/default-action.xml.i -->
<leafNode name="default-action">
<properties>
- <help>Default action for rule-set</help>
+ <help>Default-action for rule-set</help>
<completionHelp>
<list>drop jump return accept continue</list>
</completionHelp>
@@ -31,4 +31,4 @@
</properties>
<defaultValue>drop</defaultValue>
</leafNode>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/default-action.xml.i b/interface-definitions/include/firewall/default-action.xml.i
index 6a49d800e..53a161495 100644
--- a/interface-definitions/include/firewall/default-action.xml.i
+++ b/interface-definitions/include/firewall/default-action.xml.i
@@ -1,7 +1,7 @@
<!-- include start from firewall/default-action.xml.i -->
<leafNode name="default-action">
<properties>
- <help>Default action for rule-set</help>
+ <help>Default-action for rule-set</help>
<completionHelp>
<list>drop jump reject return accept continue</list>
</completionHelp>
diff --git a/interface-definitions/include/firewall/firewall-mark.xml.i b/interface-definitions/include/firewall/firewall-mark.xml.i
index a4cee12d8..36a939ba3 100644
--- a/interface-definitions/include/firewall/firewall-mark.xml.i
+++ b/interface-definitions/include/firewall/firewall-mark.xml.i
@@ -23,4 +23,4 @@
</constraint>
</properties>
</leafNode>
-<!-- include end -->
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/log.xml.i b/interface-definitions/include/firewall/log.xml.i
index 795ed77be..21548f3fb 100644
--- a/interface-definitions/include/firewall/log.xml.i
+++ b/interface-definitions/include/firewall/log.xml.i
@@ -4,4 +4,5 @@
<help>Log packets hitting this rule</help>
<valueless/>
</properties>
-</leafNode> \ No newline at end of file
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/match-interface.xml.i b/interface-definitions/include/firewall/match-interface.xml.i
index 9f720ab37..5da6f51fb 100644
--- a/interface-definitions/include/firewall/match-interface.xml.i
+++ b/interface-definitions/include/firewall/match-interface.xml.i
@@ -40,4 +40,4 @@
</valueHelp>
</properties>
</leafNode>
-<!-- include end -->
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/firewall/match-vlan.xml.i b/interface-definitions/include/firewall/match-vlan.xml.i
index d0820f7d8..44ad02c99 100644
--- a/interface-definitions/include/firewall/match-vlan.xml.i
+++ b/interface-definitions/include/firewall/match-vlan.xml.i
@@ -6,14 +6,14 @@
<children>
<leafNode name="id">
<properties>
- <help>VLAN id</help>
+ <help>Vlan id</help>
<valueHelp>
<format>u32:0-4096</format>
- <description>VLAN id</description>
+ <description>Vlan id</description>
</valueHelp>
<valueHelp>
<format>&lt;start-end&gt;</format>
- <description>VLAN id range to match</description>
+ <description>Vlan id range to match</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--allow-range --range 0-4095"/>
@@ -22,14 +22,14 @@
</leafNode>
<leafNode name="priority">
<properties>
- <help>VLAN priority(pcp)</help>
+ <help>Vlan priority(pcp)</help>
<valueHelp>
<format>u32:0-7</format>
- <description>VLAN priority</description>
+ <description>Vlan priority</description>
</valueHelp>
<valueHelp>
<format>&lt;start-end&gt;</format>
- <description>VLAN priority range to match</description>
+ <description>Vlan priority range to match</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--allow-range --range 0-7"/>
diff --git a/interface-definitions/include/firewall/offload-target.xml.i b/interface-definitions/include/firewall/offload-target.xml.i
index b1ae39100..940ed8091 100644
--- a/interface-definitions/include/firewall/offload-target.xml.i
+++ b/interface-definitions/include/firewall/offload-target.xml.i
@@ -7,4 +7,4 @@
</completionHelp>
</properties>
</leafNode>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/state.xml.i b/interface-definitions/include/firewall/state.xml.i
index 47ce3c91d..dee9722e5 100644
--- a/interface-definitions/include/firewall/state.xml.i
+++ b/interface-definitions/include/firewall/state.xml.i
@@ -27,4 +27,4 @@
<multi/>
</properties>
</leafNode>
-<!-- include end --> \ No newline at end of file
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/synproxy.xml.i b/interface-definitions/include/firewall/synproxy.xml.i
new file mode 100644
index 000000000..a65126ea9
--- /dev/null
+++ b/interface-definitions/include/firewall/synproxy.xml.i
@@ -0,0 +1,40 @@
+<!-- include start from firewall/synproxy.xml.i -->
+<node name="synproxy">
+ <properties>
+ <help>Synproxy options</help>
+ </properties>
+ <children>
+ <node name="tcp">
+ <properties>
+ <help>TCP synproxy options</help>
+ </properties>
+ <children>
+ <leafNode name="mss">
+ <properties>
+ <help>TCP Maximum segment size</help>
+ <valueHelp>
+ <format>u32:501-65535</format>
+ <description>Maximum segment size for synproxy connections</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 501-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="window-scale">
+ <properties>
+ <help>TCP window scale for synproxy connections</help>
+ <valueHelp>
+ <format>u32:1-14</format>
+ <description>TCP window scale</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-14"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/tcp-flags.xml.i b/interface-definitions/include/firewall/tcp-flags.xml.i
index e2ce7b9fd..36546c2e4 100644
--- a/interface-definitions/include/firewall/tcp-flags.xml.i
+++ b/interface-definitions/include/firewall/tcp-flags.xml.i
@@ -1,7 +1,7 @@
<!-- include start from firewall/tcp-flags.xml.i -->
<node name="tcp">
<properties>
- <help>TCP flags to match</help>
+ <help>TCP options to match</help>
</properties>
<children>
<node name="flags">
@@ -114,22 +114,6 @@
</node>
</children>
</node>
- <leafNode name="mss">
- <properties>
- <help>Maximum segment size (MSS)</help>
- <valueHelp>
- <format>u32:1-16384</format>
- <description>Maximum segment size</description>
- </valueHelp>
- <valueHelp>
- <format>&lt;min&gt;-&lt;max&gt;</format>
- <description>TCP MSS range (use '-' as delimiter)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--allow-range --range 1-16384"/>
- </constraint>
- </properties>
- </leafNode>
</children>
</node>
<!-- include end -->
diff --git a/interface-definitions/include/firewall/tcp-mss.xml.i b/interface-definitions/include/firewall/tcp-mss.xml.i
new file mode 100644
index 000000000..dc49b4272
--- /dev/null
+++ b/interface-definitions/include/firewall/tcp-mss.xml.i
@@ -0,0 +1,25 @@
+<!-- include start from firewall/tcp-mss.xml.i -->
+<node name="tcp">
+ <properties>
+ <help>TCP options to match</help>
+ </properties>
+ <children>
+ <leafNode name="mss">
+ <properties>
+ <help>Maximum segment size (MSS)</help>
+ <valueHelp>
+ <format>u32:1-16384</format>
+ <description>Maximum segment size</description>
+ </valueHelp>
+ <valueHelp>
+ <format>&lt;min&gt;-&lt;max&gt;</format>
+ <description>TCP MSS range (use '-' as delimiter)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--allow-range --range 1-16384"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in
index 432a21b59..f0525a6b8 100644
--- a/op-mode-definitions/show-log.xml.in
+++ b/op-mode-definitions/show-log.xml.in
@@ -139,47 +139,267 @@
<properties>
<help>Show log for Firewall</help>
</properties>
+ <command>journalctl --no-hostname --boot -k | egrep "(ipv[46]|bri)-(FWD|INP|OUT|NAM)"</command>
<children>
- <tagNode name="ipv6-name">
+ <node name="bridge">
<properties>
- <help>Show log for a specified firewall (IPv6)</help>
- <completionHelp>
- <path>firewall ipv6-name</path>
- </completionHelp>
+ <help>Show firewall bridge log</help>
</properties>
- <command>cat $(printf "%s\n" /var/log/messages* | sort -nr ) | egrep "\[$5-([0-9]+|default)-[ADR]\]"</command>
+ <command>journalctl --no-hostname --boot -k | egrep "bri-(FWD|INP|OUT|NAM)"</command>
<children>
- <tagNode name="rule">
+ <node name="forward">
+ <properties>
+ <help>Show Bridge forward firewall log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep bri-FWD</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show Bridge firewall forward filter</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep bri-FWD-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall bridge forward filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[bri-FWD-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <tagNode name="name">
<properties>
- <help>Show log for a rule in the specified firewall</help>
+ <help>Show custom Bridge firewall log</help>
<completionHelp>
- <path>firewall ipv6-name ${COMP_WORDS[4]} rule</path>
+ <path>firewall bridge name</path>
</completionHelp>
</properties>
- <command>cat $(printf "%s\n" /var/log/messages* | sort -nr) | grep -e "\[$5-$7-[ADR]\]"</command>
+ <command>journalctl --no-hostname --boot -k | grep bri-NAM-$6</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall bridge name ${COMP_WORDS[5]} rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[bri-NAM-$6-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
</tagNode>
</children>
- </tagNode>
- <tagNode name="name">
+ </node>
+ <node name="ipv4">
<properties>
- <help>Show log for a specified firewall (IPv4)</help>
- <completionHelp>
- <path>firewall name</path>
- </completionHelp>
+ <help>Show firewall IPv4 log</help>
</properties>
- <command>cat $(printf "%s\n" /var/log/messages* | sort -nr ) | egrep "\[$5-([0-9]+|default)-[ADR]\]"</command>
+ <command>journalctl --no-hostname --boot -k | egrep "ipv4-(FWD|INP|OUT|NAM)"</command>
<children>
- <tagNode name="rule">
+ <node name="forward">
<properties>
- <help>Show log for a rule in the specified firewall</help>
+ <help>Show firewall IPv4 forward log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-FWD</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show firewall IPv4 forward filter log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-FWD-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv4 forward filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv4-FWD-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="input">
+ <properties>
+ <help>Show firewall IPv4 input log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-INP</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show firewall IPv4 input filter log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-INP-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv4 input filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv4-INP-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <tagNode name="name">
+ <properties>
+ <help>Show custom IPv4 firewall log</help>
<completionHelp>
- <path>firewall name ${COMP_WORDS[4]} rule</path>
+ <path>firewall ipv4 name</path>
</completionHelp>
</properties>
- <command>cat $(printf "%s\n" /var/log/messages* | sort -nr) | egrep "\[$5-$7-[ADR]\]"</command>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-NAM-$6</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv4 name ${COMP_WORDS[5]} rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv4-NAM-$6-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
</tagNode>
+ <node name="output">
+ <properties>
+ <help>Show firewall IPv4 output log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-OUT</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show firewall IPv4 output filter log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv4-OUT-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv4 output filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv4-OUT-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
</children>
- </tagNode>
+ </node>
+ <node name="ipv6">
+ <properties>
+ <help>Show firewall IPv6 log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "ipv6-(FWD|INP|OUT|NAM)"</command>
+ <children>
+ <node name="forward">
+ <properties>
+ <help>Show firewall IPv6 forward log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-FWD</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show firewall IPv6 forward filter log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-FWD-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv6 forward filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv6-FWD-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="input">
+ <properties>
+ <help>Show firewall IPv6 input log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-INP</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show firewall IPv6 input filter log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-INP-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv6 input filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv6-INP-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <tagNode name="name">
+ <properties>
+ <help>Show custom IPv6 firewall log</help>
+ <completionHelp>
+ <path>firewall ipv6 name</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-NAM-$6</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv6 name ${COMP_WORDS[5]} rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv6-NAM-$6-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </tagNode>
+ <node name="output">
+ <properties>
+ <help>Show firewall IPv6 output log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-OUT</command>
+ <children>
+ <node name="filter">
+ <properties>
+ <help>Show firewall IPv6 output filter log</help>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | grep ipv6-OUT-filter</command>
+ <children>
+ <tagNode name="rule">
+ <properties>
+ <help>Show log for a rule in the specified firewall</help>
+ <completionHelp>
+ <path>firewall ipv6 output filter rule</path>
+ </completionHelp>
+ </properties>
+ <command>journalctl --no-hostname --boot -k | egrep "\[ipv6-OUT-filter-$8-[ADRJC]\]"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
</children>
</node>
<leafNode name="flow-accounting">
diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py
index 4fc1abb15..a2622fa00 100644
--- a/python/vyos/firewall.py
+++ b/python/vyos/firewall.py
@@ -87,6 +87,7 @@ def nft_action(vyos_action):
def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
output = []
+
if ip_name == 'ip6':
def_suffix = '6'
family = 'ipv6'
@@ -261,6 +262,9 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
output.append(f'{proto} {prefix}port {operator} @P_{group_name}')
+ if dict_search_args(rule_conf, 'action') == 'synproxy':
+ output.append('ct state invalid,untracked')
+
if 'hop_limit' in rule_conf:
operators = {'eq': '==', 'gt': '>', 'lt': '<'}
for op, operator in operators.items():
@@ -440,6 +444,15 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
queue_opts = ','.join(rule_conf['queue_options'])
output.append(f'{queue_opts}')
+ # Synproxy
+ if 'synproxy' in rule_conf:
+ synproxy_mss = dict_search_args(rule_conf, 'synproxy', 'tcp', 'mss')
+ if synproxy_mss:
+ output.append(f'mss {synproxy_mss}')
+ synproxy_ws = dict_search_args(rule_conf, 'synproxy', 'tcp', 'window_scale')
+ if synproxy_ws:
+ output.append(f'wscale {synproxy_ws} timestamp sack-perm')
+
else:
output.append('return')
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 4b6dca254..d1b3e8fa8 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -574,10 +574,10 @@ def nft_rule(rule_conf, fw_hook, fw_name, rule_id, ip_name='ip'):
return parse_rule(rule_conf, fw_hook, fw_name, rule_id, ip_name)
@register_filter('nft_default_rule')
-def nft_default_rule(fw_conf, fw_name, ipv6=False):
+def nft_default_rule(fw_conf, fw_name, family):
output = ['counter']
default_action = fw_conf['default_action']
- family = 'ipv6' if ipv6 else 'ipv4'
+ #family = 'ipv6' if ipv6 else 'ipv4'
if 'default_log' in fw_conf:
action_suffix = default_action[:1].upper()
@@ -587,7 +587,7 @@ def nft_default_rule(fw_conf, fw_name, ipv6=False):
output.append(f'{default_action}')
if 'default_jump_target' in fw_conf:
target = fw_conf['default_jump_target']
- def_suffix = '6' if ipv6 else ''
+ def_suffix = '6' if family == 'ipv6' else ''
output.append(f'NAME{def_suffix}_{target}')
output.append(f'comment "{fw_name} default-action {default_action}"')
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index 353fa0b2b..72fbdb37d 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2022 VyOS maintainers and contributors
+# Copyright (C) 2021-2023 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
@@ -277,6 +277,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['type filter hook output priority filter; policy accept;'],
['meta l4proto gre', f'oifname != "{interface}"', 'drop'],
['meta l4proto icmp', f'ct mark {mark_hex}', 'return'],
+ ['log prefix "[ipv4-OUT-filter-default-D]"','OUT-filter default-action drop', 'drop'],
['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'],
['tcp flags syn / syn,ack', 'tcp dport 8888', 'log prefix "[ipv4-NAM-smoketest-2-R]" log level err', 'ip ttl > 102', 'reject'],
@@ -346,6 +347,31 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip vyos_filter')
+ def test_ipv4_synproxy(self):
+ tcp_mss = '1460'
+ tcp_wscale = '7'
+ dport = '22'
+
+ self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'action', 'drop'])
+ self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'protocol', 'tcp'])
+ self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'destination', 'port', dport])
+ self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'synproxy', 'tcp', 'mss', tcp_mss])
+ self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'synproxy', 'tcp', 'window-scale', tcp_wscale])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'action', 'synproxy'])
+
+ self.cli_commit()
+
+ nftables_search = [
+ [f'tcp dport {dport} ct state invalid,untracked', f'synproxy mss {tcp_mss} wscale {tcp_wscale} timestamp sack-perm']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip vyos_filter')
+
+
def test_ipv4_mask(self):
name = 'smoketest-mask'
interface = 'eth0'
@@ -463,6 +489,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'default-action', 'accept'])
self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'source', 'address', '2001:db8::/64'])
+ self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'mark', '!6655-7766'])
self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'action', 'jump'])
self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'jump-target', name])
@@ -474,7 +501,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['ip6 length 1-1999', 'ip6 length != 60000-65535', 'ip6 dscp 0x04-0x0e', 'ip6 dscp != 0x1f-0x23', 'accept'],
['chain VYOS_IPV6_INPUT_filter'],
['type filter hook input priority filter; policy accept;'],
- ['ip6 saddr 2001:db8::/64', f'jump NAME6_{name}'],
+ ['ip6 saddr 2001:db8::/64', 'meta mark != 0x000019ff-0x00001e56', f'jump NAME6_{name}'],
[f'chain NAME6_{name}'],
['ip6 length { 65, 513, 1025 }', 'ip6 dscp { af21, 0x35 }', 'accept'],
[f'log prefix "[ipv6-{name}-default-D]"', 'drop']
@@ -558,8 +585,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip vyos_filter')
# Check conntrack
- self.verify_nftables_chain([['accept']], 'raw', 'FW_CONNTRACK')
- self.verify_nftables_chain([['return']], 'ip6 raw', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['return']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
def test_bridge_basic_rules(self):
name = 'smoketest'
@@ -588,11 +615,13 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
nftables_search = [
['chain VYOS_FORWARD_filter'],
- ['type filter hook forward priority filter; policy drop;'],
+ ['type filter hook forward priority filter; policy accept;'],
[f'vlan id {vlan_id}', 'accept'],
[f'vlan pcp {vlan_prior}', f'jump NAME_{name}'],
+ ['log prefix "[bri-FWD-filter-default-D]"', 'drop', 'FWD-filter default-action drop'],
[f'chain NAME_{name}'],
- [f'ether saddr {mac_address}', f'iifname "{interface_in}"', f'log prefix "[bri-NAM-{name}-1-A]" log level crit', 'accept']
+ [f'ether saddr {mac_address}', f'iifname "{interface_in}"', f'log prefix "[bri-NAM-{name}-1-A]" log level crit', 'accept'],
+ ['accept', f'{name} default-action accept']
]
self.verify_nftables(nftables_search, 'bridge vyos_filter')
@@ -737,8 +766,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip6 vyos_filter')
# Check conntrack
- #self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
- #self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
def test_zone_flow_offload(self):
self.cli_set(['firewall', 'flowtable', 'smoketest', 'interface', 'eth0'])
@@ -773,8 +802,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip6 vyos_filter')
# Check conntrack
- #self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
- #self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_system_flow-accounting.py b/smoketest/scripts/cli/test_system_flow-accounting.py
index d55ea616e..6c761579b 100755
--- a/smoketest/scripts/cli/test_system_flow-accounting.py
+++ b/smoketest/scripts/cli/test_system_flow-accounting.py
@@ -67,7 +67,7 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
# verify configuration
- nftables_output = cmd('sudo nft list chain raw VYOS_CT_PREROUTING_HOOK').splitlines()
+ nftables_output = cmd('sudo nft list chain raw VYOS_PREROUTING_HOOK').splitlines()
for interface in Section.interfaces('ethernet'):
rule_found = False
ifname_search = f'iifname "{interface}"'
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index ee19555c4..acb7dfa41 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2022 VyOS maintainers and contributors
+# Copyright (C) 2021-2023 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
@@ -39,6 +39,7 @@ from vyos.utils.process import process_named_running
from vyos.utils.process import rc_cmd
from vyos import ConfigError
from vyos import airbag
+
airbag.enable()
nftables_conf = '/run/nftables.conf'
@@ -98,7 +99,7 @@ def geoip_updated(conf, firewall):
elif (path[0] == 'ipv6'):
set_name = f'GEOIP_CC6_{path[1]}_{path[2]}_{path[4]}'
out['ipv6_name'].append(set_name)
-
+
updated = True
if 'delete' in node_diff:
@@ -138,6 +139,8 @@ def get_config(config=None):
fqdn_config_parse(firewall)
+ set_dependents('conntrack', conf)
+
return firewall
def verify_rule(firewall, rule_conf, ipv6):
@@ -167,6 +170,16 @@ def verify_rule(firewall, rule_conf, ipv6):
if not dict_search_args(firewall, 'flowtable', offload_target):
raise ConfigError(f'Invalid offload-target. Flowtable "{offload_target}" does not exist on the system')
+ if rule_conf['action'] != 'synproxy' and 'synproxy' in rule_conf:
+ raise ConfigError('"synproxy" option allowed only for action synproxy')
+ if rule_conf['action'] == 'synproxy':
+ if 'state' in rule_conf:
+ raise ConfigError('For action "synproxy" state cannot be defined')
+ if not rule_conf.get('synproxy', {}).get('tcp'):
+ raise ConfigError('synproxy TCP MSS is not defined')
+ if rule_conf.get('protocol', {}) != 'tcp':
+ raise ConfigError('For action "synproxy" the protocol must be set to TCP')
+
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')
@@ -434,17 +447,6 @@ def generate(firewall):
if local_zone in zone_conf['from']:
local_zone_conf['from_local'][zone] = zone_conf['from'][local_zone]
- # Determine if conntrack is needed
- firewall['ipv4_conntrack_action'] = 'return'
- firewall['ipv6_conntrack_action'] = 'return'
-
- for rules, path in dict_search_recursive(firewall, 'rule'):
- if any(('state' in rule_conf or 'connection_status' in rule_conf) for rule_conf in rules.values()):
- if path[0] == 'ipv4':
- firewall['ipv4_conntrack_action'] = 'accept'
- elif path[0] == 'ipv6':
- firewall['ipv6_conntrack_action'] = 'accept'
-
render(nftables_conf, 'firewall/nftables.j2', firewall)
return None
@@ -474,8 +476,7 @@ def apply(firewall):
apply_sysfs(firewall)
- if firewall['group_resync']:
- call_dependents()
+ call_dependents()
# T970 Enable a resolver (systemd daemon) that checks
# domain-group/fqdn addresses and update entries for domains by timeout
diff --git a/src/conf_mode/load-balancing_wan.py b/src/conf_mode/load-balancing_wan.py
index ad9c80d72..5da0b906b 100755
--- a/src/conf_mode/load-balancing_wan.py
+++ b/src/conf_mode/load-balancing_wan.py
@@ -21,6 +21,7 @@ from shutil import rmtree
from vyos.base import Warning
from vyos.config import Config
+from vyos.configdep import set_dependents, call_dependents
from vyos.utils.process import cmd
from vyos.template import render
from vyos import ConfigError
@@ -49,6 +50,8 @@ def get_config(config=None):
if lb.from_defaults(['rule', rule, 'limit']):
del lb['rule'][rule]['limit']
+ set_dependents('conntrack', conf)
+
return lb
@@ -132,6 +135,8 @@ def apply(lb):
cmd('sudo sysctl -w net.netfilter.nf_conntrack_acct=1')
cmd(f'systemctl restart {systemd_service}')
+ call_dependents()
+
return None
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index ffd4a33e7..bd9b5162c 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -18,13 +18,12 @@ import jmespath
import json
import os
-from distutils.version import LooseVersion
-from platform import release as kernel_version
from sys import exit
from netifaces import interfaces
from vyos.base import Warning
from vyos.config import Config
+from vyos.configdep import set_dependents, call_dependents
from vyos.template import render
from vyos.template import is_ip_network
from vyos.utils.kernel import check_kmod
@@ -38,10 +37,7 @@ from vyos import ConfigError
from vyos import airbag
airbag.enable()
-if LooseVersion(kernel_version()) > LooseVersion('5.1'):
- k_mod = ['nft_nat', 'nft_chain_nat']
-else:
- k_mod = ['nft_nat', 'nft_chain_nat_ipv4']
+k_mod = ['nft_nat', 'nft_chain_nat']
nftables_nat_config = '/run/nftables_nat.conf'
nftables_static_nat_conf = '/run/nftables_static-nat-rules.nft'
@@ -53,18 +49,27 @@ valid_groups = [
'port_group'
]
-def get_handler(json, chain, target):
- """ Get nftable rule handler number of given chain/target combination.
- Handler is required when adding NAT/Conntrack helper targets """
- for x in json:
- if x['chain'] != chain:
- continue
- if x['target'] != target:
- continue
- return x['handle']
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
- return None
+ base = ['nat']
+ nat = conf.get_config_dict(base, key_mangling=('-', '_'),
+ get_first_key=True,
+ with_recursive_defaults=True)
+ set_dependents('conntrack', conf)
+
+ if not conf.exists(base):
+ nat['deleted'] = ''
+ return nat
+
+ nat['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True)
+
+ return nat
def verify_rule(config, err_msg, groups_dict):
""" Common verify steps used for both source and destination NAT """
@@ -105,7 +110,7 @@ def verify_rule(config, err_msg, groups_dict):
group_obj = dict_search_args(groups_dict, group, group_name)
if group_obj is None:
- raise ConfigError(f'Invalid {error_group} "{group_name}" on firewall rule')
+ raise ConfigError(f'Invalid {error_group} "{group_name}" on nat rule')
if not group_obj:
Warning(f'{error_group} "{group_name}" has no members!')
@@ -129,62 +134,11 @@ def verify_rule(config, err_msg, groups_dict):
if count != 100:
Warning(f'Sum of weight for nat load balance rule is not 100. You may get unexpected behaviour')
-def get_config(config=None):
- if config:
- conf = config
- else:
- conf = Config()
-
- base = ['nat']
- nat = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True,
- with_recursive_defaults=True)
-
- # read in current nftable (once) for further processing
- tmp = cmd('nft -j list table raw')
- nftable_json = json.loads(tmp)
-
- # condense the full JSON table into a list with only relevand informations
- pattern = 'nftables[?rule].rule[?expr[].jump].{chain: chain, handle: handle, target: expr[].jump.target | [0]}'
- condensed_json = jmespath.search(pattern, nftable_json)
-
- if not conf.exists(base):
- if get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_HELPER'):
- nat['helper_functions'] = 'remove'
-
- # Retrieve current table handler positions
- nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_HELPER')
- nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK')
- nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_HELPER')
- nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'NAT_CONNTRACK')
- nat['deleted'] = ''
- return nat
-
- nat['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True,
- no_tag_node_value_mangle=True)
-
- # check if NAT connection tracking helpers need to be set up - this has to
- # be done only once
- if not get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK'):
- nat['helper_functions'] = 'add'
-
- # Retrieve current table handler positions
- nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_IGNORE')
- nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_PREROUTING_HOOK')
- nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_IGNORE')
- nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_OUTPUT_HOOK')
-
- return nat
-
def verify(nat):
if not nat or 'deleted' in nat:
# no need to verify the CLI as NAT is going to be deactivated
return None
- if 'helper_functions' in nat:
- if not (nat['pre_ct_ignore'] or nat['pre_ct_conntrack'] or nat['out_ct_ignore'] or nat['out_ct_conntrack']):
- raise Exception('could not determine nftable ruleset handlers')
-
if dict_search('source.rule', nat):
for rule, config in dict_search('source.rule', nat).items():
err_msg = f'Source NAT configuration error in rule {rule}:'
@@ -265,6 +219,8 @@ def apply(nat):
os.unlink(nftables_nat_config)
os.unlink(nftables_static_nat_conf)
+ call_dependents()
+
return None
if __name__ == '__main__':
diff --git a/src/conf_mode/nat66.py b/src/conf_mode/nat66.py
index ed716b2a2..4c1ead258 100755
--- a/src/conf_mode/nat66.py
+++ b/src/conf_mode/nat66.py
@@ -23,6 +23,7 @@ from netifaces import interfaces
from vyos.base import Warning
from vyos.config import Config
+from vyos.configdep import set_dependents, call_dependents
from vyos.template import render
from vyos.utils.process import cmd
from vyos.utils.kernel import check_kmod
@@ -36,18 +37,6 @@ k_mod = ['nft_nat', 'nft_chain_nat']
nftables_nat66_config = '/run/nftables_nat66.nft'
-def get_handler(json, chain, target):
- """ Get nftable rule handler number of given chain/target combination.
- Handler is required when adding NAT66/Conntrack helper targets """
- for x in json:
- if x['chain'] != chain:
- continue
- if x['target'] != target:
- continue
- return x['handle']
-
- return None
-
def get_config(config=None):
if config:
conf = config
@@ -57,35 +46,10 @@ def get_config(config=None):
base = ['nat66']
nat = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
- # read in current nftable (once) for further processing
- tmp = cmd('nft -j list table ip6 raw')
- nftable_json = json.loads(tmp)
-
- # condense the full JSON table into a list with only relevand informations
- pattern = 'nftables[?rule].rule[?expr[].jump].{chain: chain, handle: handle, target: expr[].jump.target | [0]}'
- condensed_json = jmespath.search(pattern, nftable_json)
+ set_dependents('conntrack', conf)
if not conf.exists(base):
- nat['helper_functions'] = 'remove'
- nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_HELPER')
- nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK')
- nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_HELPER')
- nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'NAT_CONNTRACK')
nat['deleted'] = ''
- return nat
-
- # check if NAT66 connection tracking helpers need to be set up - this has to
- # be done only once
- if not get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK'):
- nat['helper_functions'] = 'add'
-
- # Retrieve current table handler positions
- nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_IGNORE')
- nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_PREROUTING_HOOK')
- nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_IGNORE')
- nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_OUTPUT_HOOK')
- else:
- nat['helper_functions'] = 'has'
return nat
@@ -94,10 +58,6 @@ def verify(nat):
# no need to verify the CLI as NAT66 is going to be deactivated
return None
- if 'helper_functions' in nat and nat['helper_functions'] != 'has':
- if not (nat['pre_ct_conntrack'] or nat['out_ct_conntrack']):
- raise Exception('could not determine nftable ruleset handlers')
-
if dict_search('source.rule', nat):
for rule, config in dict_search('source.rule', nat).items():
err_msg = f'Source NAT66 configuration error in rule {rule}:'
@@ -147,6 +107,7 @@ def apply(nat):
return None
cmd(f'nft -f {nftables_nat66_config}')
+ call_dependents()
return None
diff --git a/src/conf_mode/system_flow-accounting.py b/src/conf_mode/system_flow-accounting.py
index f29fc94fb..206f513c8 100755
--- a/src/conf_mode/system_flow-accounting.py
+++ b/src/conf_mode/system_flow-accounting.py
@@ -38,7 +38,7 @@ uacctd_conf_path = '/run/pmacct/uacctd.conf'
systemd_service = 'uacctd.service'
systemd_override = f'/run/systemd/system/{systemd_service}.d/override.conf'
nftables_nflog_table = 'raw'
-nftables_nflog_chain = 'VYOS_CT_PREROUTING_HOOK'
+nftables_nflog_chain = 'VYOS_PREROUTING_HOOK'
egress_nftables_nflog_table = 'inet mangle'
egress_nftables_nflog_chain = 'FORWARD'
diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py
index d426b62e5..36bb013fe 100755
--- a/src/op_mode/firewall.py
+++ b/src/op_mode/firewall.py
@@ -113,19 +113,14 @@ def output_firewall_name(family, hook, priority, firewall_conf, single_rule_id=N
if hook in ['input', 'forward', 'output']:
def_action = firewall_conf['default_action'] if 'default_action' in firewall_conf else 'accept'
- row = ['default', def_action, 'all']
- rule_details = details['default-action']
- row.append(rule_details.get('packets', 0))
- row.append(rule_details.get('bytes', 0))
- rows.append(row)
+ else:
+ def_action = firewall_conf['default_action'] if 'default_action' in firewall_conf else 'drop'
+ row = ['default', def_action, 'all']
+ rule_details = details['default-action']
+ row.append(rule_details.get('packets', 0))
+ row.append(rule_details.get('bytes', 0))
- elif 'default_action' in firewall_conf and not single_rule_id:
- row = ['default', firewall_conf['default_action'], 'all']
- if 'default-action' in details:
- rule_details = details['default-action']
- row.append(rule_details.get('packets', 0))
- row.append(rule_details.get('bytes', 0))
- rows.append(row)
+ rows.append(row)
if rows:
header = ['Rule', 'Action', 'Protocol', 'Packets', 'Bytes', 'Conditions']
@@ -314,7 +309,7 @@ def show_firewall_group(name=None):
family = ['ipv6']
group_type = 'network_group'
else:
- family = ['ipv4', 'ipv6']
+ family = ['ipv4', 'ipv6', 'bridge']
for item in family:
# Look references in firewall
@@ -540,4 +535,4 @@ if __name__ == '__main__':
elif args.action == 'show_statistics':
show_statistics()
elif args.action == 'show_summary':
- show_summary() \ No newline at end of file
+ show_summary()