15

I want to make some simple iptables rules to deny all incoming connections and allow outgoing. How can I do that?

22

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.

  • 2
    When I do first line of your rule, i've got disconnected from SSH – holms Oct 6 '14 at 7:26
  • 7
    The question is "deny all incoming connections" and not "deny all incoming connections except SSH" :) – Yohann Dec 4 '14 at 16:17
  • I read warning of @holms about first rule too late... – DenisKolodin Oct 20 '16 at 7:01
  • Note that this has no effect on ipv6 Traffic. Read my answer below if you have ipv6 enabled. – bhelm Jul 19 '18 at 7:41
12

If you’re working remotely via SSH, you might want to add this (-I inserts it before all other rules in INPUT):

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 22.

Otherwise, you might accidentally lose access.

1

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 -s 127.0.0.0/8

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)

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.