From d95752bea6cef76f8549e94f3329824fefdb72ec Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Thu, 28 Mar 2024 10:34:59 -0400 Subject: [PATCH] move IP-based DNS connection limits to nftables This reuses the approach in cd59960e7bb26d675bb71e0cdce344b1887c641e for SSH connection limits with the same rationale. PowerDNS also lacks a way to allowlist an address and was limiting our ADoT reverse proxy to only being able to make 16 connections to the backend. We could have worked around that by proxing every TCP DNS connection but it makes more sense to switch to doing this via nftables where new TCP connections can be completely avoided. TCP DNS will be perfectly fine without window scaling and Selective Acknowledgements for clients without TCP timestamps enabled. --- nftables-ns1.conf | 23 +++++++++++++++++++---- nftables-ns2.conf | 23 +++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/nftables-ns1.conf b/nftables-ns1.conf index 13a43d7..a294f41 100644 --- a/nftables-ns1.conf +++ b/nftables-ns1.conf @@ -21,6 +21,16 @@ table inet filter { flags dynamic } + set ip-connlimit-dns { + type ipv4_addr + flags dynamic + } + + set ip6-connlimit-dns { + type ipv6_addr + flags dynamic + } + chain prerouting-raw { type filter hook prerouting priority raw @@ -33,8 +43,8 @@ table inet filter { fib daddr . iif type != { local, broadcast, multicast } counter drop udp dport 53 notrack accept - tcp dport { 53, 80, 443, 853 } notrack accept - tcp dport 22 tcp flags syn notrack accept + tcp dport { 80, 443 } notrack accept + tcp dport { 22, 53, 853 } tcp flags syn notrack accept meta l4proto { icmp, ipv6-icmp } notrack accept } @@ -43,7 +53,7 @@ table inet filter { oif lo notrack accept udp sport 53 notrack accept - tcp sport { 53, 80, 443, 853 } notrack accept + tcp sport { 80, 443 } notrack accept meta l4proto { icmp, ipv6-icmp } notrack accept } @@ -53,16 +63,21 @@ table inet filter { iif lo tcp dport 22 tcp flags syn ip saddr != $ip-allowlist-ssh add @ip-connlimit-ssh { ip saddr ct count over 1 } reject with tcp reset iif lo tcp dport 22 tcp flags syn ip6 saddr != $ip6-allowlist-ssh add @ip6-connlimit-ssh { ip6 saddr and ffff:ffff:ffff:ffff:ffff:: ct count over 1 } reject with tcp reset + iif lo tcp dport { 53, 853 } tcp flags syn add @ip-connlimit-dns { ip saddr ct count over 16 } reject with tcp reset + iif lo tcp dport { 53, 853 } tcp flags syn add @ip6-connlimit-dns { ip6 saddr ct count over 16 } reject with tcp reset iif lo accept udp dport 53 accept - tcp dport { 53, 80, 443, 853 } accept + tcp dport { 80, 443 } accept meta l4proto { icmp, ipv6-icmp } accept ct state vmap { established : accept, related : accept, new : goto graceful-reject } tcp dport 22 ip saddr @ip-connlimit-ssh reject with tcp reset tcp dport 22 ip6 saddr and ffff:ffff:ffff:ffff:ffff:: @ip6-connlimit-ssh reject with tcp reset tcp dport 22 synproxy mss 1460 wscale 7 timestamp sack-perm + tcp dport { 53, 853 } ip saddr @ip-connlimit-dns reject with tcp reset + tcp dport { 53, 853 } ip6 saddr @ip6-connlimit-dns reject with tcp reset + tcp dport { 53, 853 } synproxy mss 1460 wscale 7 timestamp sack-perm } chain forward { diff --git a/nftables-ns2.conf b/nftables-ns2.conf index b980e0a..9a08933 100644 --- a/nftables-ns2.conf +++ b/nftables-ns2.conf @@ -23,6 +23,16 @@ table inet filter { flags dynamic } + set ip-connlimit-dns { + type ipv4_addr + flags dynamic + } + + set ip6-connlimit-dns { + type ipv6_addr + flags dynamic + } + chain prerouting-raw { type filter hook prerouting priority raw @@ -38,8 +48,8 @@ table inet filter { tcp dport 22 ip daddr 198.251.90.93 reject with tcp reset udp dport 53 notrack accept - tcp dport { 53, 80, 443, 853 } notrack accept - tcp dport 22 tcp flags syn notrack accept + tcp dport { 80, 443 } notrack accept + tcp dport { 22, 53, 853 } tcp flags syn notrack accept meta l4proto { icmp, ipv6-icmp } notrack accept } @@ -48,7 +58,7 @@ table inet filter { oif lo notrack accept udp sport 53 notrack accept - tcp sport { 53, 80, 443, 853 } notrack accept + tcp sport { 80, 443 } notrack accept meta l4proto { icmp, ipv6-icmp } notrack accept } @@ -58,16 +68,21 @@ table inet filter { iif lo tcp dport 22 tcp flags syn ip saddr != $ip-allowlist-ssh add @ip-connlimit-ssh { ip saddr ct count over 1 } reject with tcp reset iif lo tcp dport 22 tcp flags syn ip6 saddr != $ip6-allowlist-ssh add @ip6-connlimit-ssh { ip6 saddr and ffff:ffff:ffff:ffff:ffff:: ct count over 1 } reject with tcp reset + iif lo tcp dport { 53, 853 } tcp flags syn add @ip-connlimit-dns { ip saddr ct count over 16 } reject with tcp reset + iif lo tcp dport { 53, 853 } tcp flags syn add @ip6-connlimit-dns { ip6 saddr ct count over 16 } reject with tcp reset iif lo accept udp dport 53 accept - tcp dport { 53, 80, 443, 853 } accept + tcp dport { 80, 443 } accept meta l4proto { icmp, ipv6-icmp } accept ct state vmap { established : accept, related : accept, new : goto graceful-reject } tcp dport 22 ip saddr @ip-connlimit-ssh reject with tcp reset tcp dport 22 ip6 saddr and ffff:ffff:ffff:ffff:ffff:: @ip6-connlimit-ssh reject with tcp reset tcp dport 22 synproxy mss 1460 wscale 7 timestamp sack-perm + tcp dport { 53, 853 } ip saddr @ip-connlimit-dns reject with tcp reset + tcp dport { 53, 853 } ip6 saddr @ip6-connlimit-dns reject with tcp reset + tcp dport { 53, 853 } synproxy mss 1460 wscale 7 timestamp sack-perm } chain forward {