24

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

5 Answers 5

40

Try this with root access:

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.

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

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
  • It's should be comment not answer. Dec 22, 2022 at 20:42
7

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.

2

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)

0

Deny specific website:

# iptables -A OUTPUT -p tcp -d www.twitter.com --dport 443 -j DROP
# iptables -A OUTPUT -p tcp -d twitter.com --dport 443 -j DROP
# service iptables save
# service iptables restart
# iptables -L

Reference

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .