ubuntu iptables



Setting up a good firewall is an essential step to take in securing any modern operating system. Most Linux distributions ship with a few different firewall tools that we can use to configure our firewalls. In this guide, we’ll be covering the iptables firewall.

Iptables is a standard firewall included in most Linux distributions by default (a modern variant called nftables will begin to replace it). It is actually a front end to the kernel-level netfilter hooks that can manipulate the Linux network stack. It works by matching each packet that crosses the networking interface against a set of rules to decide what to do.

In the previous guide, we learned how iptables rules work to block unwanted traffic. In this guide, we’ll move on to a practical example to demonstrate how to create a basic rule set for an Ubuntu 14.04 server. The resulting firewall will allow SSH and HTTP traffic.

Note: This tutorial covers IPv4 security. In Linux, IPv6 security is maintained separately from IPv4. For example, “iptables” only maintains firewall rules for IPv4 addresses but it has an IPv6 counterpart called “ip6tables”, which can be used to maintain firewall rules for IPv6 network addresses.

If your VPS is configured for IPv6, please remember to secure both your IPv4 and IPv6 network interfaces with the appropriate tools. For more information about IPv6 tools, refer to this guide: How To Configure Tools to Use IPv6 on a Linux VPS


Before you start using this tutorial, you should have a separate, non-root superuser account—a user with sudo privileges—set up on your server. If you need to set this up, follow this guide: Initial Server Setup with Ubuntu 14.04.

Basic iptables Commands

Now that you have a good understanding of iptables concepts, we should cover the basic commands that will be used to form complex rule sets and to manage the iptables interface in general.

First, you should be aware that iptables commands must be run with root privileges. This means you need to log in as root, use su or sudo -i to gain a root shell, or precede all commands with sudo. We are going to use sudo in this guide since that is the preferred method on an Ubuntu system.

A good starting point is to list the current rules that are configured for iptables. You can do that with the -L flag:

  • sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

As you can see, we have our three default chains (INPUT,OUTPUT, and FORWARD). We also can see each chain’s default policy (each chain has ACCEPT as its default policy). We also see some column headers, but we don’t see any actual rules. This is because Ubuntu doesn’t ship with a default rule set.

We can see the output in a format that reflects the commands necessary to enable each rule and policy by instead using the -S flag:

  • sudo iptables -S

To replicate the configuration, we’d just need to type sudo iptables followed by each of the lines in the output. (Depending on the configuration, it may actually slightly more complicated if we are connected remotely so that we don’t institute a default drop policy before the rules are in place to catch and allow our current connection.)

If you do have rules in place and wish to scrap them and start over, you can flush the current rules by typing:

  • sudo iptables -F

Once again, the default policy is important here, because, while all of the rules are deleted from your chains, the default policy will not change with this command. That means that if you are connected remotely, you should ensure that the default policy on your INPUT and OUTPUT chains are set to ACCEPT prior to flushing your rules. You can do this by typing:

    • sudo iptables -P INPUT ACCEPT
    • sudo iptables -P OUTPUT ACCEPT
  • sudo iptables -F

You can then change the default drop policy back to DROP after you’ve established rules that explicitly allow your connection. We’ll go over how to do that in a moment.

Make your First Rule

We’re going to start to build our firewall policies. As we said above, we’re going to be working with the INPUT chain since that is the funnel that incoming traffic will be sent through. We are going to start with the rule that we’ve talked about a bit above: the rule that explicitly accepts your current SSH connection.

The full rule we need is this:

  • sudo iptables -A INPUT -m conntrack –ctstate ESTABLISHED,RELATED -j ACCEPT

This may look incredibly complicated, but most of it will make sense when we go over the components:

  • -A INPUT: The -A flag appends a rule to the end of a chain. This is the portion of the command that tells iptables that we wish to add a new rule, that we want that rule added to the end of the chain, and that the chain we want to operate on is the INPUT chain.
  • -m conntrack: iptables has a set of core functionality, but also has a set of extensions or modules that provide extra capabilities.

In this portion of the command, we’re stating that we wish to have access to the functionality provided by the conntrack module. This module gives access to commands that can be used to make decisions based on the packet’s relationship to previous connections.

  • –ctstate: This is one of the commands made available by calling the conntrack module. This command allows us to match packets based on how they are related to packets we’ve seen before.

We pass it the value of ESTABLISHED to allow packets that are part of an existing connection. We pass it the value of RELATED to allow packets that are associated with an established connection. This is the portion of the rule that matches our current SSH session.

  • -j ACCEPT: This specifies the target of matching packets. Here, we tell iptables that packets that match the preceding criteria should be accepted and allowed through.

We put this rule at the beginning because we want to make sure the connections we are already using are matched, accepted, and pulled out of the chain before reaching any DROP rules.

We can see the changes if we list the rules:

  • sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Now that you know the general syntax, let’s continue by adding some more cases where we want to accept the connection.

Accept Other Necessary Connections

We have told iptables to keep open any connections that are already open and to allow new connections related to those connections. However, we need to create some rules to establish when we want to accept new connections that don’t meet those criteria.

We want to keep two ports open specifically. We want to keep our SSH port open (we’re going to assume in this guide that this is the default 22. If you’ve changed this in your SSH configuration, modify your value here). We are also going to assume that this computer is running a web server on the default port 80. If this is not the case for you, you don’t have to add that rule.

The two lines we’re going to use to add these rules are:

    • sudo iptables -A INPUT -p tcp –dport 22 -j ACCEPT
  • sudo iptables -A INPUT -p tcp –dport 80 -j ACCEPT

As you can see, these are very similar to our first rule, but perhaps more simple. The new options are:

  • -p tcp: This option matches packets if the protocol being used is TCP. This is a connection-based protocol that will be used by most applications because it allows for reliable communication.
  • –dport: This option is available if the -p tcp flag is given. It gives a further requirement of matching the destination port for the matching packet. The first rule matches for TCP packets destined for port 22, while the second rule matches TCP traffic pointed towards port 80.

There is one more accept rule that we need to ensure that our server can function correctly. Often, services on the computer communicate with each other by sending network packets to each other. They do this by utilizing a pseudo network interface called the loopback device, which directs traffic back to itself rather than to other computers.

So if one service wants to communicate with another service that is listening for connections on port 4555, it can send a packet to port 4555 of the loopback device. We want this type of behavior to be allowed, because it is essential for the correct operation of many programs.

The rule we need to add is this:

  • sudo iptables -I INPUT 1 -i lo -j ACCEPT

This looks a bit different than our other commands. Let’s go over what it is doing:

  • -I INPUT 1: The -I flag tells iptables to insert a rule. This is different than the -A flag which appends a rule to the end. The -I flag takes a chain and the rule position where you want to insert the new rule.

In this case, we’re adding this rule as the very first rule of the INPUT chain. This will bump the rest of the rules down. We want this at the top because it is fundamental and should not be affected by subsequent rules.

  • -i lo: This component of the rule matches if the interface that the packet is using is the “lo” interface. The “lo” interface is another name for the loopback device. This means that any packet using that interface to communicate (packets generated on our server, for our server) should be accepted.

To see our current rules, we should use the -S flag. This is because the -L flag doesn’t include some information, like the interface that a rule is tied to, which is an important part of the rule we just added:

  • sudo iptables -S
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

Implementing a Drop Rule

We now have four separate rules that explicitly accept packets based on certain criteria. However, our firewall currently is not blocking anything.

If a packet enters the INPUT chain and doesn’t match one of the four rules that we made, it is being passed to our default policy, which is to accept the packet anyways. We need to change this.

There are two different ways that we can do this, with some pretty important differences.

The first way we could do this is to modify the default policy of our INPUT chain. We can do this by typing:

  • sudo iptables -P INPUT DROP

This will catch any packets that fall through our INPUT chain, and drop them. This is what we call a default drop policy. One of the implications of this type of a design is that it falls back on dropping packets if the rules are flushed.

This may be more secure, but also can have serious consequences if you don’t have another way of accessing your server. With DigitalOcean, you can log in through our web console to get access to your server if this happens. The web console acts as a virtual local connection, so iptables rules will not affect it.

You may like your server to automatically drop all connections in the event that the rules are dumped. This would prevent your server from being left wide open. This also means that you can easily append rules to the bottom of the chain easily while still dropping packets as you’d like.

The alternative approach is to keep the default policy for the chain as accept and add a rule that drops every remaining packet to the bottom of the chain itself.

If you changed the default policy for the INPUT chain above, you can set it back to follow along by typing:

  • sudo iptables -P INPUT ACCEPT

Now, you can add a rule to the bottom of the chain that will drop any remaining packets:

  • sudo iptables -A INPUT -j DROP

The result under normal operating conditions is exactly the same as a default drop policy. This rule works by matching every remaining packet that reaches it. This prevents a packet from ever dropping all of the way through the chain to reach the default policy.

Basically, this is used to keep the default policy to accept traffic. That way, if there are any problems and the rules are flushed, you will still be able to access the machine over the network. This is a way of implementing a default action without altering the policy that will be applied to an empty chain.

Of course, this also means that any rule that any additional rule that you wish to add to the end of the chain will have to be added before the drop rule. You can do this either by temporarily removing the drop rule:

    • sudo iptables -D INPUT -j DROP
    • sudo iptables -A INPUT new_rule_here
  • sudo iptables -A INPUT -j DROP

Or, you can insert rules that you need at the end of the chain (but prior to the drop) by specifying the line number. To insert a rule at line number 4, you could type:

  • sudo iptables -I INPUT 4 new_rule_here

If you are having trouble knowing which line number each rule is, you can tell iptables to number the rules by typing:

  • sudo iptables -L –line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
4    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

This can be helpful to make sure you are adding your rule at the appropriate position.

Listing and Deleting Iptables Rules

If you want to learn the details about listing and deleting iptables rules, check out this tutorial: How To List and Delete Iptables Firewall Rules.

Saving your Iptables Configuration

By default, the rules that you add to iptables are ephemeral. This means that when you restart your server, your iptables rules will be gone.

This is actually a feature for some user because it gives them an avenue to get back in if they have accidentally locked themselves out of the server. However, most users will want a way to automatically save the rules you have created and to load them when the server starts.

There are a few ways to do this, but the easiest way is with the iptables-persistent package. You can download this from Ubuntu’s default repositories:

    • sudo apt-get update
  • sudo apt-get install iptables-persistent

During the installation, you will be asked if you would like to save your current rules to be automatically loaded. If you are happy with your current configuration (and you have tested your ability to create independent SSH connections, you can select to save your current rules.

It will also ask you if you want to save the IPv6 rules that you have configured. These are configured through a separate utility called ip6tables which controls the flow of IPv6 packets in almost the same way.

Once the installation is complete, you will have a new service called iptables-persistent that is configured to run at boot. This service will load in your rules and apply them when the server is started.

Saving Updates

If you ever update your firewall and want to preserve the changes, you must save your iptables rules for them to be persistent.

Save your firewall rules with this command:

  • sudo invoke-rc.d iptables-persistent save


You should now have a good starting point to developing a firewall that addresses your needs. There are many other firewall utilities and some that may be easier, but iptables is a good learning tool, if only because it exposes some of the underlying netfilter structure and because it is present in so many systems.


在ubuntu中由于不存在 /etc/init.d/iptales文件,所以无法使用service等命令来启动iptables,需要用modprobe命令。


modprobe ip_tables


iptables -F

iptables -X

iptables -Z

iptables -P INPUT ACCEPT



modprobe -r ip_tables

依次执行以上命令即可关闭iptables,否则在执行modproble -r ip_tables时将会提示  FATAL: Module ip_tables is in use.

使用 ubuntu 已经有两个星期了, 才忽然发现原来一直都没有安装防火墙, 赶紧去找些资料看看, 下面给出我自己的 iptables设置,供和我一样新来的兄弟们参考,水平有限,多多指教。(对于防火墙的设置,有两种策略:一种是全部通讯口都允许使用,只是阻止一些我们知道的不安全的或者容易被利用的口;另外一种,则是先屏蔽所有的通讯口,而只是允许我们需要使用的通讯端口。这里使用的是第二种原则,如果你需要开启其他端口,请先参考计算机通讯口说明,然后自己添加。)

#删除原来 iptables 里面已经有的规则
iptables -F
iptables -X#抛弃所有不符合三种链规则的数据包
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

#设置:本地进程 lo  的 INPUT 和 OUTPUT 链接 ; eth1的INPUT链
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -m state –state ESTABLISHED,RELATED -jACCEPT
iptables -A INPUT -i eth1 -m state –state NEW,INVALID -j LOG
iptables -A OUTPUT -o lo -j ACCEPT

#对其他主要允许的端口的 OUTPUT设置:
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 53 -jACCEPT
iptables -A OUTPUT -o eth1 -p UDP –sport 1024:65535 –dport 53 -jACCEPT

iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 80 -jACCEPT

iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 443 -jACCEPT

#Email 接受 和发送
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 110 -jACCEPT
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 25 -jACCEPT

# FTP 数据和控制
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 20 -jACCEPT
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 21 -jACCEPT

iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 68 -jACCEPT
iptables -A OUTPUT -o eth1 -p UDP –sport 1024:65535 –dport 68 -jACCEPT

#POP3S Email安全接收
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 995 -jACCEPT

#时间同步服务器 NTP
iptables -A OUTPUT -o eth1 -p TCP –sport 1024:65535 –dport 123 -jACCEPT

#拒绝 eth1 其他剩下的
iptables -A OUTPUT -o eth1 –match state –state NEW,INVALID -jLOG


iptables-save >/etc/iptables.up.rule # 存在你想存的地方
iptables-restore </etc/iptables.up.rules #调用

因为iptables 在每次机器重新启动以后,需要再次输入或者调用,为了方便操作,使用

sudo gedit /etc/network/interfaces

auto ath0
    iface ath0 inet dhcp


pre-up iptables-restore </etc/iptables.up.rules #启动自动调用已存储的iptables
post-down iptables-save >/etc/iptables.up.rule #关机时,把当前iptables 储存


25 Responses so far.

  1. quest bars says:
    Hello there! Would you mind if I share your blog with my
    zynga group? There’s a lot of people that I think would really appreciate your content.

    Please let me know. Thanks

  2. quest bars says:
    Nice post. I learn something totally new and challenging on websites I stumbleupon on a
    daily basis. It will always be helpful to read articles from other writers and use something from their websites.
  3. quest bars says:
    Valuable info. Lucky me I found your web site by chance, and I’m shocked why this twist of fate didn’t came about in advance!
    I bookmarked it.
  4. Very good article. I will be dealing with many of
    these issues as well..
  5. Howdy! This is my 1st comment here so I just wanted to give a
    quick shout out and tell you I truly enjoy reading your posts.

    Can you recommend any other blogs/websites/forums that deal with
    the same topics? Thanks a ton!

  6. It’s going to be end of mine day, however before ending I am reading this enormous article to increase
    my knowledge.
  7. Oh my goodness! Impressive article dude!
    Many thanks, However I am having problems with your RSS. I don’t know why I can’t join it.

    Is there anybody else getting the same RSS issues? Anyone
    who knows the solution can you kindly respond? Thanks!!

  8. Thanks a bunch for sharing this with all people you actually recognise what you’re speaking approximately!
    Bookmarked. Please also seek advice from my site =).
    We will have a hyperlink exchange arrangement between us
  9. Hi! I just wanted to ask if you ever have any trouble with hackers?
    My last blog (wordpress) was hacked and I ended up
    losing a few months of hard work due to no backup. Do you
    have any solutions to protect against hackers?
  10. Thanks for sharing your thoughts on Limewire Free Music Downloads.
  11. Greetings! Very useful advice within this post!
    It’s the little changes which will make the greatest changes.
    Many thanks for sharing!
  12. Aw, this was a really nice post. Taking a few minutes and actual effort
    to make a good article… but what can I say… I hesitate a whole lot and
    don’t seem to get nearly anything done.
  13. My developer is trying to persuade me to move to .net from PHP.
    I have always disliked the idea because of the
    costs. But he’s tryiong none the less. I’ve been using WordPress
    on a variety of websites for about a year and am worried about switching to another platform.
    I have heard good things about blogengine.net.
    Is there a way I can import all my wordpress posts into it?
    Any help would be greatly appreciated!
  14. It’s awesome to go to see this web site and reading the views of
    all colleagues regarding this paragraph, while I am also eager of getting know-how.
  15. excellent points altogether, you just won a brand
    new reader. What could you recommend about your put
    up that you just made some days ago? Any sure?
  16. Heya i am for the first time here. I came across this board and I
    in finding It truly useful & it helped me out much. I’m hoping to present something again and help
    others like you helped me.
  17. I am extremely impressed together with your writing skills as smartly
    as with the structure for your blog. Is that this a paid subject
    or did you customize it yourself? Either way stay up the nice high quality writing, it’s rare to peer a great blog like this one today..
  18. I will immediately snatch your rss feed as I can not in finding your e-mail subscription link or newsletter service.
    Do you have any? Kindly let me know in order that I may subscribe.
  19. Howdy! I know this is kinda off topic but I was wondering
    which blog platform are you using for this website?
    I’m getting tired of WordPress because I’ve had problems with hackers and I’m looking at alternatives
    for another platform. I would be awesome if you could point me in the direction of a good platform.
  20. I really like your blog.. very nice colors & theme. Did you
    make this website yourself or did you hire someone to do it for you?
    Plz respond as I’m looking to construct my own blog and would
    like to know where u got this from. many thanks
  21. Do you mind if I quote a few of your articles
    as long as I provide credit and sources back to
    your webpage? My website is in the very same area of interest as yours and my visitors
    would truly benefit from some of the information you present here.
    Please let me know if this ok with you. Thanks a lot!
  22. Howdy would you mind stating which blog platform you’re using?

    I’m going to start my own blog in the near future but I’m having a hard time selecting between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your design seems different then most blogs and I’m looking for something completely unique.

    P.S My apologies for getting off-topic but I had to ask!

  23. Howdy this is somewhat of off topic but I was wanting to know
    if blogs use WYSIWYG editors or if you have to manually code with HTML.
    I’m starting a blog soon but have no coding expertise so I wanted
    to get advice from someone with experience. Any
    help would be greatly appreciated!
  24. I got what you intend,saved to my bookmarks, very decent web site.