
default deny nftables firewall every server needs
most servers are wide open and nobody notices until it's too late
here's a fun exercise. spin up a fresh linux server, don't touch the firewall, and just watch the auth logs for 24 hours. you'll see bots from five continents knocking on ssh, probing for redis, poking at random ports hoping something's misconfigured. that's just the internet's background radiation now. a default deny firewall is the difference between "meh, bots gonna bot" and "wait why is there a cryptominer on my box."
nftables is the tool for this on modern linux. it replaced iptables a while back and honestly it's just better, one syntax for ipv4 and ipv6, cleaner rule structure, and faster packet matching under the hood. if you're still copy pasting iptables rules from a 2014 stackoverflow answer, it's time to upgrade.
the core idea: default deny
the whole philosophy here is simple, deny everything by default, then explicitly allow the tiny handful of things you actually need. this flips the usual "allow everything, block the bad stuff" mindset, which never works because you can't block what you haven't seen yet. default deny doesn't care what's new or clever, if it's not on the list, it doesn't get in.
for a typical server that means five rules total. let's break down what each one does and why skipping it will absolutely ruin your day.
rule 1: policy drop on input
this is the foundation. you set the input chain's default policy to drop, meaning any packet that doesn't match an explicit allow rule gets silently dropped. no response, no port scan confirmation, nothing. from the outside your server just looks like it doesn't exist for anything you haven't opened up.
rule 2: allow established, related
this one keeps your existing connections alive. when your server makes an outbound request, like pulling updates or calling an api, the reply traffic coming back needs to get through the input chain too. this rule says "if this packet belongs to a connection we already started, let it in." without it, literally nothing works, not even outbound curl requests, because the responses get blocked on the way back in.
rule 3: allow loopback
loopback traffic is your server talking to itself, 127.0.0.1 stuff. tons of local services depend on this: databases talking to app servers on the same box, monitoring agents, internal apis. block loopback and you'll get a wall of confusing errors that look like application bugs but are actually your firewall eating traffic that never even left the machine.
rule 4: allow ssh
this is the one that saves your relationship with your own server. if you forget this rule, you lock yourself out the second you apply the policy, and now you're driving to a data center or begging your cloud provider for console access. allow port 22 (or whatever port you've moved ssh to, which you should do) before you flip that default to drop, not after.
# conceptual structure, not copy-paste-and-go
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 accept
icmp type echo-request accept
icmpv6 type echo-request accept
}
}
rule 5: allow icmp
a lot of people block icmp entirely thinking it's a security win. it's mostly not, and it breaks things you rely on, like ping for basic reachability checks and path mtu discovery, which helps prevent weird packet fragmentation issues that cause mysterious connection stalls. allow icmp echo requests and you keep the diagnostics without opening any real attack surface.
the takeaway
a default deny nftables setup isn't some advanced hardening trick, it's baseline hygiene, right up there with using ssh keys instead of passwords. the five rules here cover the 95% case: your own connections keep working, local services don't break, you don't get locked out, and diagnostics still function. everything else stays closed until you explicitly decide otherwise.
go check your own servers right now. run nft list ruleset and see what's actually open. if the answer is "everything," you've got homework tonight. close it down, test your ssh access in a second session before you close the first one, and sleep a little better knowing your attack surface is five rules wide instead of wide open.