mirror of
https://github.com/GrapheneOS/infrastructure.git
synced 2024-10-01 00:55:42 -04:00
398acc6fe8
This provides consistency with DDoS protection services placed in front of the services rather than the behavior changing based on whether DDoS protection is active. This doesn't help with protecting against attacks since they'll almost always be targeting ports with services active or exhausting inbound bandwidth via UDP reflection attacks. This appears to be the standard approach used by most large tech companies.
133 lines
5.4 KiB
Plaintext
133 lines
5.4 KiB
Plaintext
#!/usr/bin/nft -f
|
|
|
|
flush ruleset
|
|
|
|
table inet filter {
|
|
set ip-connlimit-ssh {
|
|
type ipv4_addr
|
|
flags dynamic
|
|
}
|
|
|
|
set ip6-connlimit-ssh {
|
|
type ipv6_addr
|
|
flags dynamic
|
|
}
|
|
|
|
set ip-connlimit-main {
|
|
type ipv4_addr
|
|
flags dynamic
|
|
}
|
|
|
|
set ip6-connlimit-main {
|
|
type ipv6_addr
|
|
flags dynamic
|
|
}
|
|
|
|
chain prerouting-raw {
|
|
type filter hook prerouting priority raw
|
|
|
|
# drop packets without a reverse path (strict reverse path filtering)
|
|
fib saddr . iif oif missing counter drop
|
|
|
|
iif lo notrack accept
|
|
|
|
# drop packets to address not configured on incoming interface (strong host model)
|
|
#
|
|
# ordered after accepting loopback to permit using external IPs via loopback
|
|
fib daddr . iif type != { local, broadcast, multicast } counter drop
|
|
|
|
# handle new TCP connections beyond rate limit via synproxy to avoid conntrack table exhaustion
|
|
tcp dport { 22, 80, 443 } tcp flags syn limit rate over 1024/second burst 128 packets counter notrack accept
|
|
|
|
meta l4proto { icmp, ipv6-icmp } notrack accept
|
|
}
|
|
|
|
chain input {
|
|
type filter hook input priority filter
|
|
policy drop
|
|
|
|
tcp dport { 22, 80, 443 } goto input-tcp-service
|
|
iif lo accept
|
|
meta l4proto { icmp, ipv6-icmp } accept
|
|
ct state vmap { new : drop, established : accept, related : accept }
|
|
}
|
|
|
|
chain input-tcp-service {
|
|
iif lo goto input-tcp-service-loopback
|
|
|
|
# for synproxy, SYN is untracked and first ACK is invalid which are handled via fallthrough
|
|
ct state vmap { new : goto input-tcp-service-new, established : goto input-tcp-service-established, related : accept }
|
|
|
|
tcp dport 22 ip saddr @ip-connlimit-ssh counter reject with tcp reset
|
|
tcp dport 22 ip6 saddr and ffff:ffff:ffff:ffff:ffff:: @ip6-connlimit-ssh counter reject with tcp reset
|
|
tcp dport { 80, 443 } ip saddr @ip-connlimit-main counter reject with tcp reset
|
|
tcp dport { 80, 443 } ip6 saddr and ffff:ffff:ffff:ffff:: @ip6-connlimit-main counter reject with tcp reset
|
|
synproxy mss 1460 wscale 7 timestamp sack-perm
|
|
}
|
|
|
|
chain input-tcp-service-new {
|
|
tcp dport 22 ip saddr @ip-connlimit-ssh counter reject with tcp reset
|
|
tcp dport 22 ip6 saddr and ffff:ffff:ffff:ffff:ffff:: @ip6-connlimit-ssh counter reject with tcp reset
|
|
tcp dport { 80, 443 } ip saddr @ip-connlimit-main counter reject with tcp reset
|
|
tcp dport { 80, 443 } ip6 saddr and ffff:ffff:ffff:ffff:: @ip6-connlimit-main counter reject with tcp reset
|
|
accept
|
|
}
|
|
|
|
# add connections established without synproxy to connection limit sets with limits enforced
|
|
chain input-tcp-service-established {
|
|
ct mark 0x1 accept
|
|
tcp dport 22 add @ip-connlimit-ssh { ip saddr ct count over 1 } counter reject with tcp reset
|
|
tcp dport 22 add @ip6-connlimit-ssh { ip6 saddr and ffff:ffff:ffff:ffff:ffff:: ct count over 1 } counter reject with tcp reset
|
|
tcp dport { 80, 443 } add @ip-connlimit-main { ip saddr ct count over 32 } counter reject with tcp reset
|
|
tcp dport { 80, 443 } add @ip6-connlimit-main { ip6 saddr and ffff:ffff:ffff:ffff:: ct count over 32 } counter reject with tcp reset
|
|
ct mark set 0x1 accept
|
|
}
|
|
|
|
# add connections established with synproxy to connection limit sets with limits enforced
|
|
chain input-tcp-service-loopback {
|
|
tcp flags != syn accept
|
|
tcp dport 22 add @ip-connlimit-ssh { ip saddr ct count over 1 } counter reject with tcp reset
|
|
tcp dport 22 add @ip6-connlimit-ssh { ip6 saddr and ffff:ffff:ffff:ffff:ffff:: ct count over 1 } counter reject with tcp reset
|
|
tcp dport { 80, 443 } add @ip-connlimit-main { ip saddr ct count over 32 } counter reject with tcp reset
|
|
tcp dport { 80, 443 } add @ip6-connlimit-main { ip6 saddr and ffff:ffff:ffff:ffff:: ct count over 32 } counter reject with tcp reset
|
|
ct mark set 0x1 accept
|
|
}
|
|
|
|
chain forward {
|
|
type filter hook forward priority filter
|
|
policy drop
|
|
}
|
|
|
|
chain output-raw {
|
|
type filter hook output priority raw
|
|
|
|
oif lo goto output-raw-loopback
|
|
skuid != { root, systemd-network, unbound, chrony, http, synapse, matterbridge } counter goto graceful-reject
|
|
meta l4proto { icmp, ipv6-icmp } notrack accept
|
|
}
|
|
|
|
chain output-raw-loopback {
|
|
skuid unbound meta l4proto { tcp, udp } th sport 53 th dport >= 1024 th dport != 8008 notrack accept
|
|
skuid { chrony, synapse, matterbridge } meta l4proto { tcp, udp } th sport >= 1024 th sport != 8008 th dport 53 notrack accept
|
|
|
|
skuid postgres udp sport >= 1024 udp sport != 8008 udp dport >= 1024 udp dport != 8008 notrack accept
|
|
|
|
skuid synapse tcp sport 8008 tcp dport >= 1024 tcp dport != 8008 notrack accept
|
|
skuid http tcp sport >= 1024 tcp sport != 8008 tcp dport 8008 notrack accept
|
|
skuid mjolnir tcp sport >= 1024 tcp sport != 8008 tcp dport 8008 notrack accept
|
|
|
|
skuid http tcp sport 443 tcp dport >= 1024 tcp dport != 8008 notrack accept
|
|
skuid matterbridge tcp sport >= 1024 tcp sport != 8008 tcp dport 443 notrack accept
|
|
skuid synapse tcp sport >= 1024 tcp sport != 8008 tcp dport 443 notrack accept
|
|
|
|
skuid != root counter goto graceful-reject
|
|
notrack accept
|
|
}
|
|
|
|
chain graceful-reject {
|
|
meta l4proto udp reject
|
|
meta l4proto tcp reject with tcp reset
|
|
reject
|
|
}
|
|
}
|