#!/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 vyos_global_rpfilter flush chain ip6 raw vyos_global_rpfilter table raw { chain vyos_global_rpfilter { {% if global_options.source_validation is vyos_defined('loose') %} fib saddr oif 0 counter drop {% elif global_options.source_validation is vyos_defined('strict') %} fib saddr . iif oif 0 counter drop {% endif %} return } } table ip6 raw { chain vyos_global_rpfilter { {% if global_options.ipv6_source_validation is vyos_defined('loose') %} fib saddr oif 0 counter drop {% elif global_options.ipv6_source_validation is vyos_defined('strict') %} fib saddr . iif oif 0 counter drop {% endif %} return } } {% if first_install is not vyos_defined %} 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() %} chain VYOS_FORWARD_{{ prior }} { 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) }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['FWD_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('FWD-' + prior, 'ipv4') }} } {% endfor %} {% endif %} {% if ipv4.input is vyos_defined %} {% for prior, conf in ipv4.input.items() %} chain VYOS_INPUT_{{ prior }} { 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) }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['INP_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('INP-' + prior, 'ipv4') }} } {% endfor %} {% endif %} {% if ipv4.output is vyos_defined %} {% for prior, conf in ipv4.output.items() %} chain VYOS_OUTPUT_{{ prior }} { type filter hook output priority {{ prior }}; policy accept; {% if global_options.state_policy is vyos_defined and prior == 'filter' %} 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) }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['OUT_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('OUT-' + prior, 'ipv4') }} } {% endfor %} {% endif %} {% if ipv4.prerouting is vyos_defined %} {% for prior, conf in ipv4.prerouting.items() %} chain VYOS_PREROUTING_{{ prior }} { 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) }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['PRE_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('PRE-' + prior, 'ipv4') }} } {% endfor %} {% endif %} chain VYOS_FRAG_MARK { type filter hook prerouting priority -450; policy accept; ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return } {% if ipv4.name is vyos_defined %} {% for name_text, conf in ipv4.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) }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['NAM_' + name_text + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('NAM-' + name_text, 'ipv4') }} } {% endfor %} {% endif %} {% for set_name in ns.sets %} set RECENT_{{ set_name }} { type ipv4_addr size 65535 flags dynamic } {% endfor %} {% for set_name in ip_fqdn %} set FQDN_{{ set_name }} { type ipv4_addr flags interval } {% endfor %} {% if geoip_updated.name is vyos_defined %} {% for setname in geoip_updated.name %} set {{ setname }} { type ipv4_addr flags interval } {% endfor %} {% endif %} {% endif %} {{ 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 %} 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() %} chain VYOS_IPV6_FORWARD_{{ prior }} { 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') }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['FWD_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('FWD-' + prior, 'ipv6') }} } {% endfor %} {% endif %} {% if ipv6.input is vyos_defined %} {% for prior, conf in ipv6.input.items() %} chain VYOS_IPV6_INPUT_{{ prior }} { 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') }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['INP_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('INP-' + prior, 'ipv6') }} } {% endfor %} {% endif %} {% if ipv6.output is vyos_defined %} {% for prior, conf in ipv6.output.items() %} chain VYOS_IPV6_OUTPUT_{{ prior }} { type filter hook output priority {{ prior }}; policy accept; {% if global_options.state_policy is vyos_defined and prior == 'filter' %} 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') }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['OUT_ ' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('OUT-' + prior, 'ipv6') }} } {% endfor %} {% endif %} {% if ipv6.prerouting is vyos_defined %} {% for prior, conf in ipv6.prerouting.items() %} chain VYOS_IPV6_PREROUTING_{{ prior }} { 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, 'ip6') }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['PRE_' + prior + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('PRE-' + prior, 'ipv6') }} } {% endfor %} {% endif %} chain VYOS_FRAG6_MARK { type filter hook prerouting priority -450; policy accept; exthdr frag exists meta mark set 0xffff1 return } {% if ipv6.name is vyos_defined %} {% for name_text, conf in ipv6.name.items() %} chain NAME6_{{ 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, 'ip6') }} {% if rule_conf.recent is vyos_defined %} {% set ns.sets = ns.sets + ['NAM_' + name_text + '_' + rule_id] %} {% endif %} {% endfor %} {% endif %} {{ conf | nft_default_rule('NAM-' + name_text, 'ipv6') }} } {% endfor %} {% endif %} {% for set_name in ns.sets %} set RECENT6_{{ set_name }} { type ipv6_addr size 65535 flags dynamic } {% endfor %} {% for set_name in ip6_fqdn %} set FQDN_{{ set_name }} { type ipv6_addr flags interval } {% endfor %} {% if geoip_updated.ipv6_name is vyos_defined %} {% for setname in geoip_updated.ipv6_name %} set {{ setname }} { type ipv6_addr flags interval } {% endfor %} {% 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 %} {% 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 { {% if bridge is vyos_defined %} {% if bridge.forward is vyos_defined %} {% for prior, conf in bridge.forward.items() %} chain VYOS_FORWARD_{{ prior }} { 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, 'bri') }} {% endfor %} {% endif %} {{ conf | nft_default_rule('FWD-' + prior, 'bri') }} } {% endfor %} {% endif %} {% if bridge.input is vyos_defined %} {% for prior, conf in bridge.input.items() %} chain VYOS_INPUT_{{ prior }} { 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, 'bri') }} {% endfor %} {% endif %} {{ conf | nft_default_rule('INP-' + prior, 'bri') }} } {% endfor %} {% endif %} {% if bridge.output is vyos_defined %} {% for prior, conf in bridge.output.items() %} chain VYOS_OUTPUT_{{ prior }} { type filter hook output priority {{ prior }}; policy accept; {% if global_options.apply_to_bridged_traffic is vyos_defined %} {% if 'invalid_connections' in global_options.apply_to_bridged_traffic %} ct state invalid udp sport 67 udp dport 68 counter accept ct state invalid ether type arp counter accept {% endif %} {% endif %} {% 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, 'bri') }} {% endfor %} {% endif %} {{ conf | nft_default_rule('OUT-' + prior, 'bri') }} } {% endfor %} {% endif %} {% if bridge.prerouting is vyos_defined %} {% for prior, conf in bridge.prerouting.items() %} chain VYOS_PREROUTING_{{ prior }} { 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, 'bri') }} {% endfor %} {% endif %} {{ conf | nft_default_rule('PRE-' + prior, 'bri') }} } {% 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('NAM-' + name_text, 'bri') }} } {% endfor %} {% endif %} {% endif %} {{ group_tmpl.groups(group, False, False) }} {{ group_tmpl.groups(group, True, False) }} {% 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 %} }