Linux : Iptables # 4 Block all incoming traffic but allow ssh
This is very common scenario which permit access to a remote machine only by SSH. You would like to block all incoming traffic to your system except ssh connection. Here is simple ruleset to do this (do not enter them immediately).
Add following rules to your iptables shell script:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
First rule will accept incoming (INPUT) tcp connection on port 22 (ssh server) and second rule will send response of incoming ssh server to client (OUTPUT) from our ssh server source port 22.
However, iptables with kernel 2.4/2.6 provides very powerful facility to filter rule based upon different connection states such as established or new connection etc. Here is complete small script to do this task:
#!/bin/sh
# My system IP/set ip address of server
SERVER_IP="65.55.12.13"
# Flushing all rules
iptables -F
iptables -X
# Setting default filter policy
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
# Allow unlimited traffic on loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Allow incoming ssh only
iptables -A INPUT -p tcp -s 0/0 -d $SERVER_IP --sport 513:65535 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s $SERVER_IP -d 0/0 --sport 22 --dport 513:65535 -m state --state ESTABLISHED -j ACCEPT
# make sure nothing comes or goes out of this box
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
This script is purely strict firewall. It only allows incoming ssh. No other incoming service or ping request or no outgoing service or request allowed. Incoming ssh connection can be either new or already established one and that is what specified by state rule '-m state --state NEW,ESTABLISHED'. Outgoing ssh connection state can be established only. By default this script allows everyone to ssh in by rule -s 0/0. If you want this access limited by IP or network address then replace -s 0/0 with IP address. For example allow incoming ssh from IP 202.54.1.20:
# Allow incoming ssh only from IP 202.54.1.20
iptables -A INPUT -p tcp -s 202.54.1.20 -d $SERVER_IP --sport 513:65535 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s $SERVER_IP -d 202.54.1.20 --sport 22 --dport 513:65535 -m state --state ESTABLISHED -j ACCEPT
Want to stay up to date with the latest Linux tips, news and announcements? Subscribe to our free e-mail newsletter or RSS feed to get all updates.
You can Email this page to a friend.
You may also be interested in other helpful articles:
- Linux Iptables block all network traffic
- Linux Iptables block incoming access to selected or specific ip address
- How to: Linux Iptables block common attacks
- Linux: Iptables # 11 How to Block or open http/web service
- How do I build a Simple Linux Firewall for DSL/Dial-up connection?
Discussion on This Article:
Leave a Reply
We encourage your comments, and suggestions. But please stay on topic, be polite, and avoid spam. Thank you very much for stopping by our site!


How about opening outgoing ssh? I tried the rule to reverse it but not working. i mean i need to ssh in on dsl box as well as ssh out!
Try
iptables -A OUTPUT -p tcp -d $SERVER_IP -s 0/0 –dport 22 –sport 513:65535 -m state –state ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -d 0/0 -s $SERVER_IP –dport 513:65535 –sport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
Following are correct two rules:
iptables -A OUTPUT -p tcp -s $SERVER_IP -d 0/0 –sport 513:65535 –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -s 0/0 -d $SERVER_IP –sport 22 –dport 513:65535 -m state –state ESTABLISHED -j ACCEPT
Appreciate your post.
If you have specified a default deny policy;
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
then why do you need the bottom two lines?
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
Thanks.
You have some funky characters on this page double “-” is being replaced by an mdash or something … this causes a copy and paste of the rules to fail (at least on my console)
you have ” –sport”, there should be two characters before sport, with extra spaces this should be ” - - s p o r t”
Cheers
pbhj,
I have migrated from blogger.com publishing to wordpress so there are some problems. I had fixed the same.
Appreciate your post.
Hi,
I want to configured the firewall but there is a 5 server on wan & also at lan.
How I connect this all m/c through firewall for wan for ssh service.
or which reule I inser for ssh_key.
Nand
I tried the script on my linux box and it locked me out of SSH access totally. Use with caution.
Hi,
I have a router wrt54gl with openwrt(kernel 2.4.x) and I can’t seem to block other lan users.
router ip is 10.77.77.1 / netmask 255.255.255.0
squid server is 10.77.77.228 3128 port
iptables -F
iptables -Z
iptables -X
iptables -t nat -F
iptables -t nat -Z
iptables -t nat -X
iptables -A INPUT -s 10.77.77.228 -j ACCEPT
iptables -A INPUT -d 10.77.77.228 -j ACCEPT
iptables -A OUTPUT -s 10.77.77.1 -j ACCEPT
iptables -A OUTPUT -d 10.77.77.228 -j ACCEPT
iptables -A INPUT -s 10.77.77.1/24 -d 10.77.77.1 -j ACCEPT
iptables -A INPUT -s 10.77.77.1/24 -d 10.77.77.228 -p tcp –dport 3128 -j ACCEPT
iptables -A OUTPUT -d 10.77.77.1/24 -s 10.77.77.1 -j ACCEPT
iptables -A INPUT -p udp –sport 67:68 –dport 67:68 -j ACCEPT
iptables -A OUTPUT -p udp –sport 67:68 –dport 67:68 -j ACCEPT
iptables -A INPUT -p udp –dport 53 -j ACCEPT
iptables -A OUTPUT -p udp –dport 53 -j ACCEPT
iptables -A INPUT -p tcp –dport 80 -j ACCEPT
iptables -A INPUT -p tcp –dport 3128 -j ACCEPT
iptables -A OUTPUT -p tcp –dport 3128 -d 10.77.77.228 -j ACCEPT
iptables -A OUTPUT -p tcp –dport 80 -d ! 10.77.77.228 -j DROP
iptables -A OUTPUT -p tcp –dport 3128 -d ! 10.77.77.228 -j DROP
#this one redirect port 80 to 3128 squid server
iptables -t nat -A PREROUTING -s ! 10.77.77.228 -p tcp –dport 80 -j DNAT –to 10.77.77.228:3128
iptables -t nat -A POSTROUTING -s 10.77.77.1/24 -d 10.77.77.228 -j MASQUERAD
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
I just want to allow 10.77.77.228, and all others to be blocked for all protocols, all ports except 80 port tcp, 53 udp(dns), 67,68 udp(dhcp). The above rules don’t work. I am still able to ping,ftp or p2p from any host from the lan.
I would like to propose an alternative howto that I know that I would benefit from, probably many others too. I have several dedicated servers at a provider that charges $100/month for a firewall for EACH SERVER. This is like 1/3 to 1/2 the cost of each server. All I want is one machine reachable from the net at large to serve as my ssh entrance, and my web server load balancer. So I want to cut off all the other machines from inbound connections from the net. So they need to be able to accept connections on the internal subnet to get load balanced to. But they also need to be able to get out to the real world to download the occasional item, and also hit REST apis of various types. Maybe other stuff. I would think this is fairly typical, but I bet a lot of people shell out the ducats for the firewall service. Ouch, I says.
So basically I want to say:
allow only inbound connections on subnet X
That’s it.
fyi, I am a security idiot. Maybe that was apparent by my question.
thanks
dumbfounder