I want to make some simple iptables rules to deny all incoming connections and allow outgoing. How can I do that?
Try this with root access :
# Set default chain policies iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # Accept on localhost iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # Allow established sessions to receive traffic iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Note that this will brutally cut all running connections - this includes things like the SSH connection you may use to administer the server. Only use this if you have access to a local console.
See Miphix' answer for how to add an exception for SSH.
If you’re working remotely via SSH, you might want to add this (
-I inserts it before all other rules in
iptables -I INPUT -p tcp --dport 22 -j ACCEPT
If your SSH service is listening on another port, you’ll have to use that port instead of
Otherwise, you might accidentally lose access.
Both answers above somehow correct, but they don't accurate enough to origin answer. (Sorry i havn't enough reputation to add comment, so writing complete answer).
I my case i met overloaded apache server, over-floated with cron jobs, over-utilizing cpu. Threads limits were stored in SQL database, but i met limit of its connections. I wanted to limit incoming apache connections from local host (this part is optional), but keep all other connection possible. Including those which were actually established.
I did it with command
sudo iptables -I INPUT -p tcp --dport 80 -m state --state NEW -j REJECT
It means: for each incoming tcp package on the port 80, load
state module, and if this is the first package (incoming connection) reject it. For localhost you might just use
And for real world use, in some cases you might add 'INVALID' to the states,
NEW,INVALID, because one can send "malicious" packages, trying bypass your rule. And also replace with
-j DROP to save your outbound traffic (it wont send rejection beacon)
Be aware that the other answers do not cover IPv6! If your system accepts IPv6 traffic, not a single iptables rule will apply to ipv6 traffic.
instead of using iptables / ip6tables directly, i recommend using iptables-restore and save. These tools allow to specify a iptables configuration with multiple rules and easily load it with one command.
create a file (i named it iptables.rules) with the following content:
*filter # drop forwarded traffic. you only need it of you are running a router :FORWARD DROP [0:0] # Accept all outgoing traffic :OUTPUT ACCEPT [623107326:1392470726908] # Block all incoming traffic, all protocols (tcp, udp, icmp, ...) everything. # This is the base rule we can define exceptions from. :INPUT DROP [11486:513044] # do not block already running connections (important for outgoing) -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # do not block localhost -A INPUT -i lo -j ACCEPT # do not block icmp for ping and network diagnostics. Remove if you do not want this # note that -p icmp has no effect on ipv6, so we need an extra ipv6 rule -4 -A INPUT -p icmp -j ACCEPT -6 -A INPUT -p ipv6-icmp -j ACCEPT # allow some incoming ports for services that should be public available -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT # commit changes COMMIT
Note i have added some extra example if you want to allow ICMP and traffic to specific ports.
now you can load it with these commands:
iptables-restore < iptables.rules ip6tables-restore < iptables.rules
Now your rules cover also ipv6 and are easy to manage.
Additional note to Debian users: if you are satisfied with your rules, you can
apt install iptables-persistent so the rules get restored after reboot. The rules are not auto-saved on shutdown, so run
netfilter-persistent save to update the persistent rules.