nftables.conf
· 4.9 KiB · Text
Raw
#!/usr/sbin/nft -f
flush ruleset
define ip6_mask = ffff:ffff:ffff:ffff::
define public_http = 8080
define public_https = 8443
define public_ssh = 3222
define system_ssh = 49152
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport 80 redirect to :$public_http
tcp dport 443 redirect to :$public_https
tcp dport 22 redirect to :$public_ssh
}
}
table inet firewall {
set ssh_ratelimit_v4 {
type ipv4_addr
size 65535
flags dynamic,timeout
timeout 60m
}
set ssh_ratelimit_v6 {
type ipv6_addr
size 65535
flags dynamic,timeout
timeout 60m
}
set blackhole_v4 {
type ipv4_addr
size 65535
flags dynamic,timeout
timeout 24h
}
set blackhole_v6 {
type ipv6_addr
size 65535
flags dynamic,timeout
timeout 24h
}
set public_ssh_ratelimit_v4 {
type ipv4_addr
size 65535
flags dynamic,timeout
timeout 10m
}
set public_ssh_ratelimit_v6 {
type ipv6_addr
size 65535
flags dynamic,timeout
timeout 10m
}
set public_ssh_connections_v4 {
type ipv4_addr
size 65535
flags dynamic
}
set public_ssh_connections_v6 {
type ipv6_addr
size 65535
flags dynamic
}
chain inbound_rules_v4 {
icmp type echo-request limit rate 15/second accept
}
chain inbound_rules_v6 {
icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
icmpv6 type echo-request limit rate 15/second accept
}
chain inbound_system_ssh_v4 {
ct state new tcp dport $system_ssh add @ssh_ratelimit_v4 \
{ ip saddr limit rate 1/hour burst 1 packets } counter accept
counter drop
}
chain inbound_system_ssh_v6 {
ct state new tcp dport $system_ssh add @ssh_ratelimit_v6 \
{ ip6 saddr & ffff:ffff:ffff:ffff:: limit rate 1/hour burst 1 packets } counter accept
counter drop
}
chain inbound_public_ssh_v4 {
# Set a concurrent cap for each ip
tcp dport $public_ssh ct state new add @public_ssh_connections_v4 { ip saddr ct count over 4 } counter reject with tcp reset
# Set a per ip connection ratelimit
tcp dport $public_ssh ct state new update @public_ssh_ratelimit_v4 { ip saddr limit rate over 20/minute burst 5 packets } counter reject with tcp reset
tcp dport $public_ssh accept
counter drop
}
chain inbound_public_ssh_v6 {
# Set a concurrent cap for each ip
tcp dport $public_ssh ct state new add @public_ssh_connections_v6 { ip6 saddr & $ip6_mask ct count over 4 } counter reject with tcp reset
# Set a per ip connection ratelimit
tcp dport $public_ssh ct state new update @public_ssh_ratelimit_v6 { ip6 saddr & $ip6_mask limit rate over 20/minute burst 5 packets } counter reject with tcp reset
tcp dport $public_ssh accept
counter drop
}
chain inbound_blackhole_v4 {
# blacklist tcp traffic for 24h
ct state new tcp flags & (fin | syn | rst | ack) == syn update @blackhole_v4 \
{ ip saddr timeout 24h } counter drop
# blacklist udp traffic
ct state new meta l4proto udp update @blackhole_v4 \
{ ip saddr timeout 24h } counter drop
counter drop
}
chain inbound_blackhole_v6 {
# TCP SYN to any unauthorized port: blacklist the /64 for 24h.
ct state new tcp flags & (fin | syn | rst | ack) == syn update @blackhole_v6 \
{ ip6 saddr & $ip6_mask timeout 24h } counter drop
# UDP to any unauthorized port: blacklist the /64 for 24h.
ct state new meta l4proto udp update @blackhole_v6 \
{ ip6 saddr & $ip6_mask timeout 24h } counter drop
counter drop
}
chain inbound {
type filter hook input priority filter; policy drop;
# Allow specific networks to go unblocked
iifname "lo" accept
iifname "tailscale0" accept
# Allow replies
ct state vmap { invalid : drop, established : accept, related : accept }
# Basic ping allowances
meta nfproto ipv4 jump inbound_rules_v4
meta nfproto ipv6 jump inbound_rules_v6
# Allow service ports
tcp dport { $public_http , $public_https } counter accept
# Ratelimit service ssh port (3222)
# Global ssh connection rate limiter
tcp dport $public_ssh ct state new limit rate over 120/minute burst 30 packets counter reject with tcp reset
meta nfproto ipv4 tcp dport $public_ssh goto inbound_public_ssh_v4
meta nfproto ipv6 tcp dport $public_ssh goto inbound_public_ssh_v6
# Block likely bots
ip saddr @blackhole_v4 counter drop
ip6 saddr & $ip6_mask @blackhole_v6 counter drop
# Fail2unban on vps' own ssh port
meta nfproto ipv4 tcp dport $system_ssh goto inbound_system_ssh_v4
meta nfproto ipv6 tcp dport $system_ssh goto inbound_system_ssh_v6
# Decide to add ip to blackhole list (incase of bot)
meta nfproto ipv4 goto inbound_blackhole_v4
meta nfproto ipv6 goto inbound_blackhole_v6
# Block other traffic (default to chain)
}
chain forward {
type filter hook forward priority filter; policy drop;
}
}
| 1 | #!/usr/sbin/nft -f |
| 2 | |
| 3 | flush ruleset |
| 4 | |
| 5 | define ip6_mask = ffff:ffff:ffff:ffff:: |
| 6 | define public_http = 8080 |
| 7 | define public_https = 8443 |
| 8 | define public_ssh = 3222 |
| 9 | define system_ssh = 49152 |
| 10 | |
| 11 | table inet nat { |
| 12 | chain prerouting { |
| 13 | type nat hook prerouting priority dstnat; policy accept; |
| 14 | |
| 15 | tcp dport 80 redirect to :$public_http |
| 16 | tcp dport 443 redirect to :$public_https |
| 17 | tcp dport 22 redirect to :$public_ssh |
| 18 | } |
| 19 | } |
| 20 | |
| 21 | |
| 22 | table inet firewall { |
| 23 | set ssh_ratelimit_v4 { |
| 24 | type ipv4_addr |
| 25 | size 65535 |
| 26 | flags dynamic,timeout |
| 27 | timeout 60m |
| 28 | } |
| 29 | |
| 30 | set ssh_ratelimit_v6 { |
| 31 | type ipv6_addr |
| 32 | size 65535 |
| 33 | flags dynamic,timeout |
| 34 | timeout 60m |
| 35 | } |
| 36 | |
| 37 | set blackhole_v4 { |
| 38 | type ipv4_addr |
| 39 | size 65535 |
| 40 | flags dynamic,timeout |
| 41 | timeout 24h |
| 42 | } |
| 43 | |
| 44 | set blackhole_v6 { |
| 45 | type ipv6_addr |
| 46 | size 65535 |
| 47 | flags dynamic,timeout |
| 48 | timeout 24h |
| 49 | } |
| 50 | |
| 51 | set public_ssh_ratelimit_v4 { |
| 52 | type ipv4_addr |
| 53 | size 65535 |
| 54 | flags dynamic,timeout |
| 55 | timeout 10m |
| 56 | } |
| 57 | |
| 58 | set public_ssh_ratelimit_v6 { |
| 59 | type ipv6_addr |
| 60 | size 65535 |
| 61 | flags dynamic,timeout |
| 62 | timeout 10m |
| 63 | } |
| 64 | |
| 65 | set public_ssh_connections_v4 { |
| 66 | type ipv4_addr |
| 67 | size 65535 |
| 68 | flags dynamic |
| 69 | } |
| 70 | |
| 71 | set public_ssh_connections_v6 { |
| 72 | type ipv6_addr |
| 73 | size 65535 |
| 74 | flags dynamic |
| 75 | } |
| 76 | |
| 77 | chain inbound_rules_v4 { |
| 78 | icmp type echo-request limit rate 15/second accept |
| 79 | } |
| 80 | |
| 81 | chain inbound_rules_v6 { |
| 82 | icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept |
| 83 | icmpv6 type echo-request limit rate 15/second accept |
| 84 | } |
| 85 | |
| 86 | chain inbound_system_ssh_v4 { |
| 87 | ct state new tcp dport $system_ssh add @ssh_ratelimit_v4 \ |
| 88 | { ip saddr limit rate 1/hour burst 1 packets } counter accept |
| 89 | |
| 90 | counter drop |
| 91 | } |
| 92 | |
| 93 | chain inbound_system_ssh_v6 { |
| 94 | ct state new tcp dport $system_ssh add @ssh_ratelimit_v6 \ |
| 95 | { ip6 saddr & ffff:ffff:ffff:ffff:: limit rate 1/hour burst 1 packets } counter accept |
| 96 | |
| 97 | counter drop |
| 98 | } |
| 99 | |
| 100 | chain inbound_public_ssh_v4 { |
| 101 | # Set a concurrent cap for each ip |
| 102 | tcp dport $public_ssh ct state new add @public_ssh_connections_v4 { ip saddr ct count over 4 } counter reject with tcp reset |
| 103 | |
| 104 | # Set a per ip connection ratelimit |
| 105 | tcp dport $public_ssh ct state new update @public_ssh_ratelimit_v4 { ip saddr limit rate over 20/minute burst 5 packets } counter reject with tcp reset |
| 106 | |
| 107 | tcp dport $public_ssh accept |
| 108 | counter drop |
| 109 | } |
| 110 | |
| 111 | chain inbound_public_ssh_v6 { |
| 112 | # Set a concurrent cap for each ip |
| 113 | tcp dport $public_ssh ct state new add @public_ssh_connections_v6 { ip6 saddr & $ip6_mask ct count over 4 } counter reject with tcp reset |
| 114 | |
| 115 | # Set a per ip connection ratelimit |
| 116 | tcp dport $public_ssh ct state new update @public_ssh_ratelimit_v6 { ip6 saddr & $ip6_mask limit rate over 20/minute burst 5 packets } counter reject with tcp reset |
| 117 | |
| 118 | tcp dport $public_ssh accept |
| 119 | counter drop |
| 120 | } |
| 121 | |
| 122 | chain inbound_blackhole_v4 { |
| 123 | # blacklist tcp traffic for 24h |
| 124 | ct state new tcp flags & (fin | syn | rst | ack) == syn update @blackhole_v4 \ |
| 125 | { ip saddr timeout 24h } counter drop |
| 126 | |
| 127 | # blacklist udp traffic |
| 128 | ct state new meta l4proto udp update @blackhole_v4 \ |
| 129 | { ip saddr timeout 24h } counter drop |
| 130 | |
| 131 | counter drop |
| 132 | } |
| 133 | |
| 134 | chain inbound_blackhole_v6 { |
| 135 | # TCP SYN to any unauthorized port: blacklist the /64 for 24h. |
| 136 | ct state new tcp flags & (fin | syn | rst | ack) == syn update @blackhole_v6 \ |
| 137 | { ip6 saddr & $ip6_mask timeout 24h } counter drop |
| 138 | |
| 139 | # UDP to any unauthorized port: blacklist the /64 for 24h. |
| 140 | ct state new meta l4proto udp update @blackhole_v6 \ |
| 141 | { ip6 saddr & $ip6_mask timeout 24h } counter drop |
| 142 | |
| 143 | counter drop |
| 144 | } |
| 145 | |
| 146 | chain inbound { |
| 147 | type filter hook input priority filter; policy drop; |
| 148 | |
| 149 | # Allow specific networks to go unblocked |
| 150 | iifname "lo" accept |
| 151 | iifname "tailscale0" accept |
| 152 | |
| 153 | # Allow replies |
| 154 | ct state vmap { invalid : drop, established : accept, related : accept } |
| 155 | |
| 156 | # Basic ping allowances |
| 157 | meta nfproto ipv4 jump inbound_rules_v4 |
| 158 | meta nfproto ipv6 jump inbound_rules_v6 |
| 159 | |
| 160 | # Allow service ports |
| 161 | tcp dport { $public_http , $public_https } counter accept |
| 162 | |
| 163 | # Ratelimit service ssh port (3222) |
| 164 | # Global ssh connection rate limiter |
| 165 | tcp dport $public_ssh ct state new limit rate over 120/minute burst 30 packets counter reject with tcp reset |
| 166 | meta nfproto ipv4 tcp dport $public_ssh goto inbound_public_ssh_v4 |
| 167 | meta nfproto ipv6 tcp dport $public_ssh goto inbound_public_ssh_v6 |
| 168 | |
| 169 | # Block likely bots |
| 170 | ip saddr @blackhole_v4 counter drop |
| 171 | ip6 saddr & $ip6_mask @blackhole_v6 counter drop |
| 172 | |
| 173 | # Fail2unban on vps' own ssh port |
| 174 | meta nfproto ipv4 tcp dport $system_ssh goto inbound_system_ssh_v4 |
| 175 | meta nfproto ipv6 tcp dport $system_ssh goto inbound_system_ssh_v6 |
| 176 | |
| 177 | # Decide to add ip to blackhole list (incase of bot) |
| 178 | meta nfproto ipv4 goto inbound_blackhole_v4 |
| 179 | meta nfproto ipv6 goto inbound_blackhole_v6 |
| 180 | |
| 181 | # Block other traffic (default to chain) |
| 182 | } |
| 183 | |
| 184 | chain forward { |
| 185 | type filter hook forward priority filter; policy drop; |
| 186 | } |
| 187 | } |
| 188 |