let flowtable_devices = fw4.resolve_offload_devices();
let available_helpers = filter(fw4.helpers(), h => h.available);
let defined_ipsets = fw4.ipsets();
+ let zones_with_limits = filter(fw4.zones(), z => z.log_limit);
-%}
table inet fw4
flowtable ft {
hook ingress priority 0;
devices = {{ fw4.set(flowtable_devices, true) }};
+ counter;
{% if (fw4.default_option("flow_offloading_hw")): %}
flags offload;
{% endif %}
{% for (let set in defined_ipsets): %}
set {{ set.name }} {
+{% if (set.comment): %}
+ comment {{ fw4.quote(set.comment, true) }}
+{% endif %}
type {{ fw4.concat(set.types) }}
{% if (set.maxelem > 0): %}
size {{ set.maxelem }}
{% endfor %}
+{% if (length(zones_with_limits)): %}
+ #
+ # Limits
+ #
+
+{% for (let zone in zones_with_limits): %}
+ limit {{ zone.name }}.log_limit {
+ comment "{{ zone.name }} log limit"
+ rate {{ zone.log_limit.rate }}/{{ zone.log_limit.unit }}
+ }
+
+{% endfor %}
+
+{% endif %}
#
# User includes
#
tcp flags & (fin | syn | rst | ack) == syn jump syn_flood comment "!fw4: Rate limit TCP syn packets"
{% endif %}
{% for (let rule in fw4.rules("input")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% for (let zone in fw4.zones()): for (let rule in zone.match_rules): %}
{%+ include("zone-jump.uc", { fw4, zone, rule, direction: "input" }) %}
ct state invalid drop comment "!fw4: Drop flows with invalid conntrack state"
{% endif %}
{% for (let rule in fw4.rules("forward")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: (rule.src?.zone?.log_limit ? rule.src.zone : rule.dest?.zone), rule }) %}
{% endfor %}
{% for (let zone in fw4.zones()): for (let rule in zone.match_rules): %}
{%+ include("zone-jump.uc", { fw4, zone, rule, direction: "forward" }) %}
ct state invalid drop comment "!fw4: Drop flows with invalid conntrack state"
{% endif %}
{% for (let rule in fw4.rules("output")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% for (let zone in fw4.zones()): %}
{% for (let rule in zone.match_rules): %}
chain input_{{ zone.name }} {
{% fw4.includes('chain-prepend', `input_${zone.name}`) %}
{% for (let rule in fw4.rules(`input_${zone.name}`)): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone, rule }) %}
{% endfor %}
{% if (zone.dflags.dnat): %}
ct status dnat accept comment "!fw4: Accept port redirections"
chain output_{{ zone.name }} {
{% fw4.includes('chain-prepend', `output_${zone.name}`) %}
{% for (let rule in fw4.rules(`output_${zone.name}`)): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone, rule }) %}
{% endfor %}
{% fw4.includes('chain-append', `output_${zone.name}`) %}
jump {{ zone.output }}_to_{{ zone.name }}
chain forward_{{ zone.name }} {
{% fw4.includes('chain-prepend', `forward_${zone.name}`) %}
{% for (let rule in fw4.rules(`forward_${zone.name}`)): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone, rule }) %}
{% endfor %}
{% if (zone.dflags.dnat): %}
ct status dnat accept comment "!fw4: Accept port forwards"
{% endif %}
{% fw4.includes('chain-append', `forward_${zone.name}`) %}
jump {{ zone.forward }}_to_{{ zone.name }}
+{% if (fw4.forward_policy() != "accept" && (zone.log & 1)): %}
+ {%+ if (zone.log_limit): %}limit name "{{ zone.name }}.log_limit" {%+ endif -%}
+ log prefix "{{ fw4.forward_policy() }} {{ zone.name }} forward: "
+{% endif %}
}
{% if (zone.dflags.helper): %}
chain helper_{{ zone.name }} {
{% for (let rule in fw4.rules(`helper_${zone.name}`)): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone, rule }) %}
{% endfor %}
}
{% if (zone.dflags[verdict]): %}
chain {{ verdict }}_to_{{ zone.name }} {
{% for (let rule in zone.match_rules): %}
+{% if (verdict == "accept" && (zone.masq || zone.masq6) && !zone.masq_allow_invalid): %}
+ {%+ include("zone-drop-invalid.uc", { fw4, zone, rule }) %}
+{% endif %}
{%+ include("zone-verdict.uc", { fw4, zone, rule, egress: true, verdict }) %}
{% endfor %}
}
type nat hook postrouting priority srcnat; policy accept;
{% fw4.includes('chain-prepend', 'srcnat') %}
{% for (let redirect in fw4.redirects("srcnat")): %}
- {%+ include("redirect.uc", { fw4, redirect }) %}
+ {%+ include("redirect.uc", { fw4, zone: null, redirect }) %}
{% endfor %}
{% for (let zone in fw4.zones()): %}
{% if (zone.dflags.snat): %}
chain dstnat_{{ zone.name }} {
{% fw4.includes('chain-prepend', `dstnat_${zone.name}`) %}
{% for (let redirect in fw4.redirects(`dstnat_${zone.name}`)): %}
- {%+ include("redirect.uc", { fw4, redirect }) %}
+ {%+ include("redirect.uc", { fw4, zone, redirect }) %}
{% endfor %}
{% fw4.includes('chain-append', `dstnat_${zone.name}`) %}
}
chain srcnat_{{ zone.name }} {
{% fw4.includes('chain-prepend', `srcnat_${zone.name}`) %}
{% for (let redirect in fw4.redirects(`srcnat_${zone.name}`)): %}
- {%+ include("redirect.uc", { fw4, redirect }) %}
+ {%+ include("redirect.uc", { fw4, zone, redirect }) %}
{% endfor %}
{% if (zone.masq): %}
{% for (let saddrs in zone.masq4_src_subnets): %}
{% if (zone.dflags.notrack): %}
chain notrack_{{ zone.name }} {
{% for (let rule in fw4.rules(`notrack_${zone.name}`)): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone, rule }) %}
{% endfor %}
}
type filter hook prerouting priority mangle; policy accept;
{% fw4.includes('chain-prepend', 'mangle_prerouting') %}
{% for (let rule in fw4.rules("mangle_prerouting")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% fw4.includes('chain-append', 'mangle_prerouting') %}
}
type filter hook postrouting priority mangle; policy accept;
{% fw4.includes('chain-prepend', 'mangle_postrouting') %}
{% for (let rule in fw4.rules("mangle_postrouting")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% fw4.includes('chain-append', 'mangle_postrouting') %}
}
type filter hook input priority mangle; policy accept;
{% fw4.includes('chain-prepend', 'mangle_input') %}
{% for (let rule in fw4.rules("mangle_input")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% fw4.includes('chain-append', 'mangle_input') %}
}
type route hook output priority mangle; policy accept;
{% fw4.includes('chain-prepend', 'mangle_output') %}
{% for (let rule in fw4.rules("mangle_output")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% fw4.includes('chain-append', 'mangle_output') %}
}
type filter hook forward priority mangle; policy accept;
{% fw4.includes('chain-prepend', 'mangle_forward') %}
{% for (let rule in fw4.rules("mangle_forward")): %}
- {%+ include("rule.uc", { fw4, rule }) %}
+ {%+ include("rule.uc", { fw4, zone: null, rule }) %}
{% endfor %}
{% for (let zone in fw4.zones()): %}
{% if (zone.mtu_fix): %}