Linux Labs

Server security / Stage 1 of 10

Auditing listening services

Not running Starting usually ~20 s
Leave the lesson

Step 4 of 7 · theory · 6 min

The filter: let through only what is needed

Not every service can be rebound. Then a filter on the server itself closes the port — an nftables ruleset.

Tables, chains and rule order are covered in the “Allow what is needed, keep the block” lesson. For a server facing the internet, the ruleset starts from a ban: the input chain policy is drop, and the permissions are a list. Here is the ruleset of a mail server that needs SSH and SMTP (port 25) from outside:

text
#!/usr/sbin/nft -f
flush ruleset

table inet filter {
	chain input {
		type filter hook input priority filter; policy drop;
		iif lo accept
		ct state established,related accept
		tcp dport { 22, 25 } accept
	}
}

iif lo accept lets through the machine's connections to itself — that is how the application reaches the database on 127.0.0.1. ct state established,related accept uses connection tracking to let through replies to connections the server started and packets of sessions already open: without this line the server gets no answer from any outside server. The last rule is the ports from the inventory that are needed outside.

Rules live in the kernel until a reboot. At boot the nftables service takes them from /etc/nftables.conf: you check the file with sudo nft -c -f /etc/nftables.conf and turn the service on with sudo systemctl enable --now nftables.

Warning

On a remote server, policy drop without a permission for port 22 closes SSH: a new session will not open, and without the ct state line the current one breaks too. Only the console will get you back in. Before loading, check the file with nft -c, and keep the current session open until you log in with a second one.

Check yourself 1 question

A ruleset with policy drop is loaded, port 8080 is not on the allow list, and the panel still listens on 0.0.0.0:8080. What will nc -zv -w 2 192.0.2.1 8080 print on the outside machine?

  • The filter decides before the program does: a packet dropped in hook input never reaches the socket.

  • The server kernel sends a refusal when the packet arrives and nobody listens on the port. Here the panel listens, but the filter dropped the packet, so there is no answer at all.

The drop policy discards the packet silently, and the outside machine waits until the timeout. The kernel sends Connection refused only when the packet arrives and nobody listens on the port.

Key points

  • A deny-by-default ruleset: policy drop, iif lo accept, ct state established,related accept and the list of needed ports.
  • Persistent rules are the /etc/nftables.conf file plus the enabled nftables service; check the file with nft -c -f.
Ubuntu 24.04
Loading…