I have nginx serving files with uwsgi and I wanted to lock my server down just to allow SSH and Nginx to run.


# Flush all rules
$i -F
$i -X

# Setup default filter policy

# Allow unlimited traffic on loopback
$i -A INPUT -i lo -j ACCEPT
$i -A OUTPUT -o lo -j ACCEPT

# Open up ports for nginx
$i -A INPUT -p tcp --dport 443 -j ACCEPT
$i -A INPUT -p tcp --dport 80 -j ACCEPT
$i -A INPUT -p tcp --dport 22 -j ACCEPT

# Make sure nothing comes or goes out of this box

It's quite a minimal example but it looks like it would do the job. Are there any improvements to be had?


3 Answers 3


There is a miniscule chance of a failure between /sbin/iptable -P INPUT DROP and /sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT. It really isn't likely, as there's not much that could go wrong, but it's theoretically possible. If you are remotely administering this server over SSH, then you might get locked out of your own machine. Therefore, I suggest deferring the following sequence of commands:

  1. /sbin/iptables -P INPUT ACCEPT
    /sbin/iptables -P OUTPUT ACCEPT
  2. /sbin/iptables -F; /sbin/iptables -X
  3. Set up the rules
  4. /sbin/iptables -P INPUT DROP
    /sbin/iptables -P FORWARD DROP

In contrast to @eckes, who worries about leaving the server vulnerable for a moment, I worry about possibly losing SSH access to it. If you are raising the firewall for the first time, my sequence introduces no new window of vulnerability. If you are reinitializing the firewall, the window of vulnerability between steps 1 and 3 would only be a split second, not enough for a meaningful attack.

  • \$\begingroup\$ Thank you for the reply @200_success. Are we saying move this line to the very bottom "/sbin/iptable -P INPUT DROP"? \$\endgroup\$
    – J.Zil
    Mar 23, 2014 at 14:12
  • \$\begingroup\$ @JamesWillson I've clarified my advice in the answer. \$\endgroup\$ Mar 23, 2014 at 15:45
  • \$\begingroup\$ Bad argument 'ACCEPT'. I don’t think that the syntax with the {INPUT,OUTPUT} works as you describe it. \$\endgroup\$ Jan 30 at 8:49
  • 1
    \$\begingroup\$ @PhilippLudwig Sorry, that was my non-standard shorthand notation for two commands. I've revised the answer to be clearer. \$\endgroup\$ Jan 31 at 22:12
  • \$\begingroup\$ A few dropped packets should be fine (TCP will transmit, UDP must be prepared for drops). Whereas allowing ingress of hostile packets is more likely harmful. \$\endgroup\$ Feb 1 at 12:20

In addition to other answers, I want to caution you about the blanket:


The following services should be running on your system and will need access:

  • DNS
  • NTP
  • DHCP?
  • others.

It is my experience that blanket/policy DENY for outbound traffic requires a signfificant effort for maintenance. Are you prepared for that.

Altough it is not the most secure view on the world, I don't think there is much point in restricting out-bound traffic. If a 'hacker' has gained enough access to your system to enable outbound systems you were not expecting, then the chances are that they can just open up your IPTables anyway. The frustration is not worth it.

Ping allow ping from inside and from outside

iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
  • 2
    \$\begingroup\$ Great point on the DNS. NTP and DHCP, thank you. I'll look into the outbound traffic \$\endgroup\$
    – J.Zil
    Mar 23, 2014 at 14:15

I typically recommend to first set the policy and then flush the rules. This reduces the chance that you flush all deny rules with a open policy (also it is unlikely). In order to reduce impact on sessions:

  1. set all chain policies to DROP
  2. flush rules, remove custom chains
  3. append new chains and rules
  4. (optionally depending on rules-*) change policies to REJECT and/or RETURN

Your rules will most likely not work as you need to allow the outgoing response packages to the incoming connections as well.

-* i typically add explicit rules to deny packets because then I can see their counters.

  • \$\begingroup\$ Hi @eckes, thank you for the reply. So are you saying a should move the flush rules to below the "# Setup default filter policy" bit or instead all the way to the bottom. Would you also be kind enough to explain what you mean about the outgoing response packages please? \$\endgroup\$
    – J.Zil
    Mar 23, 2014 at 14:10
  • \$\begingroup\$ @JamesWillson yes for security reasons setting up the policy should come before the flush. Optionally you can also do "set policy to deny, flush rules, setup rules, set policy to reject" This would avoid intermediate rejects. \$\endgroup\$
    – eckes
    Mar 24, 2014 at 12:11
  • \$\begingroup\$ @JamesWillson I mean if you allow incoming packages to the SSH port you also need to allow the answer packages for this connection to go out. You typically do this with a state established rule. BTW: most distros have some sort of sample rules shipped, it is easier to expand on them. \$\endgroup\$
    – eckes
    Mar 24, 2014 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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