#!/usr/sbin/nft -f #flush ruleset destroy table inet myfilter define NIC_LAN = {{ nft_nic_lan }} define LAN_IP4 = {{ nft_lan_ip4 }} define LAN_IP6 = {{ nft_lan_ip6 }} define _INSIDE = { $NIC_LAN, "docker0", "br-*" } define NIC_WAN = {{ nft_nic_wan }} #define IP4_GW = <固定されたIPv4アドレスがあれば> #define IP6_GW = <固定されたIPv6アドレスがあれば> define SV4_BACKEND = {{ nft_backend.ipv4 }} define SV6_BACKEND = {{ nft_backend.ipv6 }} table inet myfilter { # 内部向けに開放するポート set lan_allow { typeof meta l4proto . th dport flags interval elements = { {% for element in nft_lan_allow_elements %} {% set entry = element.proto_port ~ "," %} {% set tabs = 3 - (((entry | length) / 8) | int) %} {{ entry }}{{ " " * tabs }}# {{ element.comment }} {% endfor %} } } # 外部向けに開放するポート set wan_allow { typeof meta l4proto . th dport flags interval elements = { {% for element in nft_wan_allow_elements %} {% set entry = element.proto_port ~ "," %} {% set tabs = 3 - (((entry | length) / 8) | int) %} {{ entry }}{{ " " * tabs }}# {{ element.comment }} {% endfor %} } } # 内部から外部への転送を許可するポート set fwd_allow { typeof meta l4proto . th dport flags interval elements = { {% for element in nft_fwd_allow_elements %} {% set entry = element.proto_port ~ "," %} {% set tabs = 3 - (((entry | length) / 8) | int) %} {{ entry }}{{ " " * tabs }}# {{ element.comment }} {% endfor %} } } # # 内部から外部への転送を拒否するポート # set fwd_block { # typeof meta l4proto . th dport # flags interval # elements = { # {% for element in nft_fwd_block_elements %} # {% set entry = element.proto_port ~ "," %} # {% set tabs = 3 - (((entry | length) / 8) | int) %} # {{ entry }}{{ " " * tabs }}# {{ element.comment }} # {% endfor %} # } # } # 外部から内部へDNATするポート set nat_allow { typeof meta l4proto . th dport flags interval elements = { {% for element in nft_nat_allow_elements %} {% set entry = element.proto_port ~ "," %} {% set tabs = 3 - (((entry | length) / 8) | int) %} {{ entry }}{{ " " * tabs }}# {{ element.comment }} {% endfor %} } } # このルーターが受け取るパケットを判定して処理するチェーン chain input { type filter hook input priority filter; policy drop; # ループバックはすべて許可 iif lo accept # 不正パケットの破棄 ct state invalid jump logging_invalid # 確立済みの通信を許可 ct state established,related accept # ICMPの許可 meta nfproto ipv4 icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-reply, echo-request } accept meta nfproto ipv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, echo-request, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, 148, 149 } accept ip6 saddr fe80::/10 icmpv6 type { 130, 131, 132, 143, 151, 152, 153 } accept # DHCPv6(dhcpv6-client) iif $NIC_WAN ip6 saddr fe80::/10 udp dport 546 accept # DHCPv6(dhcpv6-server) iif $NIC_LAN ip6 saddr fe80::/10 udp dport 547 accept # 接続を許可 iifname $_INSIDE meta l4proto . th dport @lan_allow ct state new accept iif $NIC_WAN meta l4proto . th dport @wan_allow ct state new accept # 拒否したパケットをログ出力 jump logging_input_block } # 転送を処理するチェーン chain forward { type filter hook forward priority filter; policy drop; # 確立済みの通信を許可 ct state established,related accept # 不正パケットの破棄(普通に大量に発生のため無言ドロップ) ct state invalid drop # ICMPの許可 meta nfproto ipv4 icmp type { destination-unreachable, time-exceeded, parameter-problem, echo-reply, #echo-request } accept meta nfproto ipv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, #echo-request, } accept ip saddr $_INSIDE meta nfproto ipv4 icmp type echo-request accept ip6 saddr $_INSIDE meta nfproto ipv6 icmpv6 type echo-request accept # 内部から外部への接続を許可(許可されたポートのみ) iifname $_INSIDE oif $NIC_WAN meta l4proto . th dport @fwd_allow ct state new accept # 外部から内部への接続を許可 iifname $NIC_WAN oif $NIC_LAN meta l4proto . th dport @nat_allow ct state new accept # 内部から外部への接続を許可 jump logging_forward_block } # chain forward { # type filter hook forward priority filter; policy drop; # # # 確立済みの通信を許可 # ct state established,related accept # # # 不正パケットの破棄(大量に発生) # ct state invalid drop # # # ICMPの許可 # meta nfproto ipv4 icmp type { # destination-unreachable, time-exceeded, parameter-problem, # echo-reply, #echo-request # } accept # # meta nfproto ipv6 icmpv6 type { # destination-unreachable, packet-too-big, time-exceeded, parameter-problem, # echo-reply, #echo-request, # } accept # # iifname $_INSIDE meta nfproto ipv4 icmp type echo-request accept # iifname $_INSIDE meta nfproto ipv6 icmpv6 type echo-request accept # # # 内部から外部への転送を拒否(禁止されたポートのみ) # iifname $_INSIDE oif $NIC_WAN meta l4proto . th dport @fwd_block jump logging_forward_block # # # 外部から内部への接続を許可 # iifname $NIC_WAN oif $NIC_LAN meta l4proto . th dport @nat_allow ct state new accept # # # 内部から外部への接続を許可 # iifname $_INSIDE oif $NIC_WAN ct state new accept # } # 内部ネットワークに受け入れるパケットの宛先IPアドレスを書き換えるチェーン chain prerouting { type nat hook prerouting priority dstnat; policy accept; meta nfproto ipv4 iifname $NIC_WAN meta l4proto . th dport @nat_allow dnat to $SV4_BACKEND meta nfproto ipv6 iifname $NIC_LAN meta l4proto . th dport @nat_allow dnat to $SV6_BACKEND } # 外部ネットワークに出て行くパケットの発信元IPアドレスを書き換えるチェーン chain postrouting { type nat hook postrouting priority srcnat; policy accept; oif $NIC_WAN ip saddr $IP4_LAN masquerade oif $NIC_WAN ip6 saddr $IP6_LAN masquerade # oif $NIC_WAN ip saddr $IP4_LAN snat to $IP4_GW # oif $NIC_WAN ip6 saddr $IP6_LAN snat to $IP6_GW } # 許可されない接続をログ出力するチェーン chain logging_input_block { # 外で降っている「雨」は無視し、内側からの不正アクセスをログ出力する iifname !=$_INSIDE drop limit rate 3/minute burst 10 packets log prefix "[NFT INP-BLK] " drop } # 許可されない転送をログ出力するチェーン chain logging_forward_block { limit rate 3/minute burst 10 packets log prefix "[NFT FWD-BLK] " drop } # タイミングによって発生する無効パケットで問題なしと判断したもの set invalid_silent { typeof meta l4proto . th sport . th dport flags interval elements = { {% for element in nft_invalid_silent_elements %} {% set entry = element.proto_port ~ "," %} {% set tabs = 3 - (((entry | length) / 8) | int) %} {{ entry }}{{ " " * tabs }}# {{ element.comment }} {% endfor %} } } # [通常はログを出さない/現在様子見]不正なパケットをログ出力するチェーン chain logging_invalid { # 問題ないパケットは無視し、まだ判断していないパケットをログ出力する meta l4proto . th sport . th dport @invalid_silent drop limit rate 3/minute burst 10 packets log prefix "[NFT INVALID] " drop } }