How to Restrict IPTables to Only Allow Localhost Access on Specific Ports


2 views

Many developers struggle with iptables configuration when trying to secure services. The complexity of iptables syntax and the overwhelming documentation often make this firewall tool seem more intimidating than it needs to be.

Here's the fundamental rule you need to allow only localhost access to a specific port (let's use port 8080 as an example):

iptables -A INPUT -p tcp --dport 8080 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP

The first rule accepts TCP connections to port 8080 only when they originate from 127.0.0.1 (localhost). The second rule explicitly drops all other connection attempts to that port. The order matters - rules are processed sequentially.

For complete protection, you should also add IPv6 rules:

ip6tables -A INPUT -p tcp --dport 8080 -s ::1 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 8080 -j DROP

These rules won't survive a reboot. On Ubuntu/Debian systems, install and use iptables-persistent:

sudo apt-get install iptables-persistent
sudo netfilter-persistent save

Check your rules with:

iptables -L -n -v | grep 8080

You should see the ACCEPT rule for 127.0.0.1 and the DROP rule for all other sources.

Instead of silently dropping connections, you can use REJECT to send a refusal packet:

iptables -A INPUT -p tcp --dport 8080 -j REJECT --reject-with icmp-port-unreachable

For multiple ports, use multiport:

iptables -A INPUT -p tcp -m multiport --dports 8080,8081 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 8080,8081 -j DROP

Many developers (myself included) find IPTables documentation notoriously dense. The man pages read like cryptographic puzzles, yet we often just need practical solutions for common security scenarios.

When running sensitive services (database admin interfaces, development servers, or monitoring tools), limiting access to localhost is security 101. Here's how to implement this properly:

For port 3000 (replace with your target port):

# Clear existing rules for the chain
iptables -F INPUT

# Allow established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow localhost traffic
iptables -A INPUT -i lo -j ACCEPT

# Drop all other traffic to target port
iptables -A INPUT -p tcp --dport 3000 -j DROP

-i lo: The magic interface that represents localhost
--dport: Your application's listening port
The DROP policy (vs REJECT) prevents port scanning detection

For a Node.js development server on port 8080:

iptables -N NODE_PROTECT
iptables -A INPUT -p tcp --dport 8080 -j NODE_PROTECT
iptables -A NODE_PROTECT -i lo -j ACCEPT
iptables -A NODE_PROTECT -j DROP

1. From localhost: curl http://localhost:8080 (should work)
2. From another machine: nc -zv your_server_ip 8080 (should fail)

On Ubuntu/Debian systems:
iptables-save > /etc/iptables.rules
Add to /etc/network/interfaces:
pre-up iptables-restore < /etc/iptables.rules

Don't forget about ip6tables! The same rules apply:

ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -p tcp --dport 3000 -j DROP