summaryrefslogtreecommitdiff
path: root/data/templates/firewall
diff options
context:
space:
mode:
Diffstat (limited to 'data/templates/firewall')
-rw-r--r--data/templates/firewall/nftables-bridge.j235
-rw-r--r--data/templates/firewall/nftables-defines.j214
-rw-r--r--data/templates/firewall/nftables-nat.j22
-rw-r--r--data/templates/firewall/nftables-offload.j29
-rw-r--r--data/templates/firewall/nftables-policy.j210
-rw-r--r--data/templates/firewall/nftables-vrf-zones.j24
-rw-r--r--data/templates/firewall/nftables-zone.j277
-rw-r--r--data/templates/firewall/nftables.j2113
8 files changed, 235 insertions, 29 deletions
diff --git a/data/templates/firewall/nftables-bridge.j2 b/data/templates/firewall/nftables-bridge.j2
new file mode 100644
index 000000000..1a4ad2ed9
--- /dev/null
+++ b/data/templates/firewall/nftables-bridge.j2
@@ -0,0 +1,35 @@
+{% macro bridge(bridge) %}
+{% 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 }};
+{% 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') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['FWD_' + prior + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ }
+{% endfor %}
+{% endif %}
+
+{% if bridge.name is vyos_defined %}
+{% for name_text, conf in bridge.name.items() %}
+ chain NAME_{{ name_text }} {
+{% 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('NAM', name_text, rule_id, 'bri') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['NAM_' + name_text + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule(name_text) }}
+ }
+{% endfor %}
+{% endif %}
+{% endmacro %} \ No newline at end of file
diff --git a/data/templates/firewall/nftables-defines.j2 b/data/templates/firewall/nftables-defines.j2
index 0a7e79edd..a20c399ae 100644
--- a/data/templates/firewall/nftables-defines.j2
+++ b/data/templates/firewall/nftables-defines.j2
@@ -1,7 +1,7 @@
-{% macro groups(group, is_ipv6) %}
+{% macro groups(group, is_ipv6, is_l3) %}
{% if group is vyos_defined %}
{% set ip_type = 'ipv6_addr' if is_ipv6 else 'ipv4_addr' %}
-{% if group.address_group is vyos_defined and not is_ipv6 %}
+{% if group.address_group is vyos_defined and not is_ipv6 and is_l3 %}
{% for group_name, group_conf in group.address_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set A_{{ group_name }} {
@@ -14,7 +14,7 @@
}
{% endfor %}
{% endif %}
-{% if group.ipv6_address_group is vyos_defined and is_ipv6 %}
+{% if group.ipv6_address_group is vyos_defined and is_ipv6 and is_l3 %}
{% for group_name, group_conf in group.ipv6_address_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set A6_{{ group_name }} {
@@ -27,7 +27,7 @@
}
{% endfor %}
{% endif %}
-{% if group.domain_group is vyos_defined %}
+{% if group.domain_group is vyos_defined and is_l3 %}
{% for name, name_config in group.domain_group.items() %}
set D_{{ name }} {
type {{ ip_type }}
@@ -46,7 +46,7 @@
}
{% endfor %}
{% endif %}
-{% if group.network_group is vyos_defined and not is_ipv6 %}
+{% if group.network_group is vyos_defined and not is_ipv6 and is_l3 %}
{% for group_name, group_conf in group.network_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set N_{{ group_name }} {
@@ -59,7 +59,7 @@
}
{% endfor %}
{% endif %}
-{% if group.ipv6_network_group is vyos_defined and is_ipv6 %}
+{% if group.ipv6_network_group is vyos_defined and is_ipv6 and is_l3 %}
{% for group_name, group_conf in group.ipv6_network_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set N6_{{ group_name }} {
@@ -72,7 +72,7 @@
}
{% endfor %}
{% endif %}
-{% if group.port_group is vyos_defined %}
+{% if group.port_group is vyos_defined and is_l3 %}
{% for group_name, group_conf in group.port_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set P_{{ group_name }} {
diff --git a/data/templates/firewall/nftables-nat.j2 b/data/templates/firewall/nftables-nat.j2
index f0be3cf5d..dcf28da88 100644
--- a/data/templates/firewall/nftables-nat.j2
+++ b/data/templates/firewall/nftables-nat.j2
@@ -62,6 +62,6 @@ table ip vyos_nat {
return
}
-{{ group_tmpl.groups(firewall_group, False) }}
+{{ group_tmpl.groups(firewall_group, False, True) }}
}
{% endif %}
diff --git a/data/templates/firewall/nftables-offload.j2 b/data/templates/firewall/nftables-offload.j2
new file mode 100644
index 000000000..087fd141c
--- /dev/null
+++ b/data/templates/firewall/nftables-offload.j2
@@ -0,0 +1,9 @@
+{% macro flowtable(name, config) %}
+ flowtable VYOS_FLOWTABLE_{{ name }} {
+ hook ingress priority 0; devices = { {{ config.interface | join(', ') }} };
+{% if config.offload is vyos_defined('hardware') %}
+ flags offload;
+{% endif %}
+ counter
+ }
+{% endmacro %} \ No newline at end of file
diff --git a/data/templates/firewall/nftables-policy.j2 b/data/templates/firewall/nftables-policy.j2
index 699349e2b..9e28899b0 100644
--- a/data/templates/firewall/nftables-policy.j2
+++ b/data/templates/firewall/nftables-policy.j2
@@ -28,11 +28,14 @@ table ip vyos_mangle {
{{ rule_conf | nft_rule('route', route_text, rule_id, 'ip') }}
{% endfor %}
{% endif %}
+{% if conf.default_log is vyos_defined %}
+ counter log prefix "[ipv4-{{ (route_text)[:19] }}-default]"
+{% endif %}
}
{% endfor %}
{% endif %}
-{{ group_tmpl.groups(firewall_group, False) }}
+{{ group_tmpl.groups(firewall_group, False, True) }}
}
table ip6 vyos_mangle {
@@ -57,9 +60,12 @@ table ip6 vyos_mangle {
{{ rule_conf | nft_rule('route6', route_text, rule_id, 'ip6') }}
{% endfor %}
{% endif %}
+{% if conf.default_log is vyos_defined %}
+ counter log prefix "[ipv6-{{ (route_text)[:19] }}-default]"
+{% endif %}
}
{% endfor %}
{% endif %}
-{{ group_tmpl.groups(firewall_group, True) }}
+{{ group_tmpl.groups(firewall_group, True, True) }}
}
diff --git a/data/templates/firewall/nftables-vrf-zones.j2 b/data/templates/firewall/nftables-vrf-zones.j2
index eecf47b78..3bce7312d 100644
--- a/data/templates/firewall/nftables-vrf-zones.j2
+++ b/data/templates/firewall/nftables-vrf-zones.j2
@@ -7,11 +7,11 @@ table inet vrf_zones {
# Chain for inbound traffic
chain vrf_zones_ct_in {
type filter hook prerouting priority raw; policy accept;
- counter ct zone set iifname map @ct_iface_map
+ counter ct original zone set iifname map @ct_iface_map
}
# Chain for locally-generated traffic
chain vrf_zones_ct_out {
type filter hook output priority raw; policy accept;
- counter ct zone set oifname map @ct_iface_map
+ counter ct original zone set oifname map @ct_iface_map
}
}
diff --git a/data/templates/firewall/nftables-zone.j2 b/data/templates/firewall/nftables-zone.j2
new file mode 100644
index 000000000..506ad815e
--- /dev/null
+++ b/data/templates/firewall/nftables-zone.j2
@@ -0,0 +1,77 @@
+{% macro zone_chains(zone, ipv6=False, state_policy=False) %}
+{% set fw_name = 'ipv6_name' if ipv6 else 'name' %}
+{% set suffix = '6' if ipv6 else '' %}
+ chain VYOS_ZONE_FORWARD {
+ type filter hook forward priority 1; policy accept;
+{% if state_policy %}
+ jump VYOS_STATE_POLICY{{ suffix }}
+{% endif %}
+{% for zone_name, zone_conf in zone.items() %}
+{% if 'local_zone' not in zone_conf %}
+ oifname { {{ zone_conf.interface | join(',') }} } counter jump VZONE_{{ zone_name }}
+{% endif %}
+{% endfor %}
+ }
+ chain VYOS_ZONE_LOCAL {
+ type filter hook input priority 1; policy accept;
+{% if state_policy %}
+ jump VYOS_STATE_POLICY{{ suffix }}
+{% endif %}
+{% for zone_name, zone_conf in zone.items() %}
+{% if 'local_zone' in zone_conf %}
+ counter jump VZONE_{{ zone_name }}_IN
+{% endif %}
+{% endfor %}
+ }
+ chain VYOS_ZONE_OUTPUT {
+ type filter hook output priority 1; policy accept;
+{% if state_policy %}
+ jump VYOS_STATE_POLICY{{ suffix }}
+{% endif %}
+{% for zone_name, zone_conf in zone.items() %}
+{% if 'local_zone' in zone_conf %}
+ counter jump VZONE_{{ zone_name }}_OUT
+{% endif %}
+{% endfor %}
+ }
+{% for zone_name, zone_conf in zone.items() %}
+{% if zone_conf.local_zone is vyos_defined %}
+ chain VZONE_{{ zone_name }}_IN {
+ iifname lo counter return
+{% if zone_conf.from is vyos_defined %}
+{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall[fw_name] is vyos_defined %}
+ iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].interface | join(",") }} } counter return
+{% endfor %}
+{% endif %}
+ {{ zone_conf | nft_default_rule('zone_' + zone_name) }}
+ }
+ chain VZONE_{{ zone_name }}_OUT {
+ oifname lo counter return
+{% if zone_conf.from_local is vyos_defined %}
+{% for from_zone, from_conf in zone_conf.from_local.items() if from_conf.firewall[fw_name] is vyos_defined %}
+ oifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ oifname { {{ zone[from_zone].interface | join(",") }} } counter return
+{% endfor %}
+{% endif %}
+ {{ zone_conf | nft_default_rule('zone_' + zone_name) }}
+ }
+{% else %}
+ chain VZONE_{{ zone_name }} {
+ iifname { {{ zone_conf.interface | join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6) }}
+{% if zone_conf.intra_zone_filtering is vyos_defined %}
+ iifname { {{ zone_conf.interface | join(",") }} } counter return
+{% endif %}
+{% if zone_conf.from is vyos_defined %}
+{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall[fw_name] is vyos_defined %}
+{% if zone[from_zone].local_zone is not defined %}
+ iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].interface | join(",") }} } counter return
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ zone_conf | nft_default_rule('zone_' + zone_name) }}
+ }
+{% endif %}
+{% endfor %}
+{% endmacro %} \ No newline at end of file
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index a82a5537b..4851e3a05 100644
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -1,6 +1,9 @@
#!/usr/sbin/nft -f
{% import 'firewall/nftables-defines.j2' as group_tmpl %}
+{% import 'firewall/nftables-bridge.j2' as bridge_tmpl %}
+{% 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
@@ -43,12 +46,20 @@ delete table ip vyos_filter
{% endif %}
table ip vyos_filter {
{% if ipv4 is vyos_defined %}
+{% if flowtable is vyos_defined %}
+{% for name, flowtable_conf in flowtable.items() %}
+{{ offload_tmpl.flowtable(name, flowtable_conf) }}
+{% endfor %}
+{% endif %}
+
{% set ns = namespace(sets=[]) %}
{% if ipv4.forward is vyos_defined %}
{% for prior, conf in ipv4.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 global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
{% 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) }}
@@ -57,15 +68,18 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('FWD-filter') }}
}
{% endfor %}
{% endif %}
{% if ipv4.input is vyos_defined %}
{% for prior, conf in ipv4.input.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_INPUT_{{ prior }} {
- type filter hook input priority {{ prior }}; policy {{ def_action }};
+ type filter hook input priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
{% 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('INP',prior, rule_id) }}
@@ -74,15 +88,18 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('INP-filter') }}
}
{% endfor %}
{% endif %}
{% if ipv4.output is vyos_defined %}
{% for prior, conf in ipv4.output.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_OUTPUT_{{ prior }} {
- type filter hook output priority {{ prior }}; policy {{ def_action }};
+ type filter hook output priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
{% 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('OUT', prior, rule_id) }}
@@ -91,6 +108,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('OUT-filter') }}
}
{% endfor %}
{% endif %}
@@ -100,9 +118,8 @@ table ip vyos_filter {
}
{% if ipv4.prerouting is vyos_defined %}
{% for prior, conf in ipv4.prerouting.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_PREROUTING_{{ prior }} {
- type filter hook prerouting priority {{ prior }}; policy {{ def_action }};
+ type filter hook prerouting 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('PRE', prior, rule_id) }}
@@ -111,7 +128,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule(prior) }}
+ {{ conf | nft_default_rule('PRE-filter') }}
}
{% endfor %}
{% endif %}
@@ -154,7 +171,25 @@ table ip vyos_filter {
{% endfor %}
{% endif %}
{% endif %}
-{{ group_tmpl.groups(group, False) }}
+{{ group_tmpl.groups(group, False, True) }}
+
+{% if zone is vyos_defined %}
+{{ zone_tmpl.zone_chains(zone, False, global_options.state_policy is vyos_defined) }}
+{% endif %}
+{% if global_options.state_policy is vyos_defined %}
+ chain VYOS_STATE_POLICY {
+{% if global_options.state_policy.established is vyos_defined %}
+ {{ global_options.state_policy.established | nft_state_policy('established') }}
+{% endif %}
+{% if global_options.state_policy.invalid is vyos_defined %}
+ {{ global_options.state_policy.invalid | nft_state_policy('invalid') }}
+{% endif %}
+{% if global_options.state_policy.related is vyos_defined %}
+ {{ global_options.state_policy.related | nft_state_policy('related') }}
+{% endif %}
+ return
+ }
+{% endif %}
}
{% if first_install is not vyos_defined %}
@@ -162,12 +197,20 @@ delete table ip6 vyos_filter
{% endif %}
table ip6 vyos_filter {
{% if ipv6 is vyos_defined %}
+{% if flowtable is vyos_defined %}
+{% for name, flowtable_conf in flowtable.items() %}
+{{ offload_tmpl.flowtable(name, flowtable_conf) }}
+{% endfor %}
+{% endif %}
+
{% set ns = namespace(sets=[]) %}
{% if ipv6.forward is vyos_defined %}
{% for prior, conf in ipv6.forward.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_IPV6_FORWARD_{{ prior }} {
- type filter hook forward priority {{ prior }}; policy {{ def_action }};
+ type filter hook forward priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY6
+{% endif %}
{% 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 ,'ip6') }}
@@ -176,15 +219,18 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('FWD-filter', ipv6=True) }}
}
{% endfor %}
{% endif %}
{% if ipv6.input is vyos_defined %}
{% for prior, conf in ipv6.input.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_IPV6_INPUT_{{ prior }} {
- type filter hook input priority {{ prior }}; policy {{ def_action }};
+ type filter hook input priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY6
+{% endif %}
{% 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('INP', prior, rule_id ,'ip6') }}
@@ -193,15 +239,18 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('INP-filter', ipv6=True) }}
}
{% endfor %}
{% endif %}
{% if ipv6.output is vyos_defined %}
{% for prior, conf in ipv6.output.items() %}
-{% set def_action = conf.default_action %}
chain VYOS_IPV6_OUTPUT_{{ prior }} {
- type filter hook output priority {{ prior }}; policy {{ def_action }};
+ type filter hook output priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY6
+{% endif %}
{% 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('OUT', prior, rule_id ,'ip6') }}
@@ -210,6 +259,7 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
+ {{ conf | nft_default_rule('OUT-filter', ipv6=True) }}
}
{% endfor %}
{% endif %}
@@ -257,5 +307,34 @@ table ip6 vyos_filter {
{% endfor %}
{% endif %}
{% endif %}
-{{ group_tmpl.groups(group, True) }}
+{{ 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 %}
+{% if global_options.state_policy is vyos_defined %}
+ chain VYOS_STATE_POLICY6 {
+{% if global_options.state_policy.established is vyos_defined %}
+ {{ global_options.state_policy.established | nft_state_policy('established') }}
+{% endif %}
+{% if global_options.state_policy.invalid is vyos_defined %}
+ {{ global_options.state_policy.invalid | nft_state_policy('invalid') }}
+{% endif %}
+{% if global_options.state_policy.related is vyos_defined %}
+ {{ global_options.state_policy.related | nft_state_policy('related') }}
+{% endif %}
+ return
+ }
+{% endif %}
+
+}
+
+## Bridge Firewall
+{% if first_install is not vyos_defined %}
+delete table bridge vyos_filter
+{% endif %}
+table bridge vyos_filter {
+{{ bridge_tmpl.bridge(bridge) }}
+{{ group_tmpl.groups(group, False, False) }}
+
} \ No newline at end of file