Syndicate content

How to setup a Linux firewall

Introduction

If you setup a Linux box, you want to setup a firewall before you connect your computer to the Internet. If you are setting up a remote server, it should only have the SSH port open. Connect to it, setup the fire, then only install the other servers and open ports as required (and only ports that need to be connected from the outside.)

Any port that you open without the firewall already setup is at risk. You may want to install PHP and along will come a database which may open a port to the Internet. Something that you just don't want to happen.

Setup Firewall

To prepare your setup, follow these simple steps:

# Become root
sudo su -
Password: ***

# Go to network settings
cd /etc/network

# Create rule files
vim ip4tables.rules
vim ip6tables.rules
# (see below for editing)

# Create a firewall script to setup the rules
vim firewall

# Change the firewall mode
chmod 755 firewall
# (you may want to use 700 instead, and 600 for ip?tables.rules)

# Edit the interfaces file
vim interfaces

Unfortunately, you will have to learn how to setup iptables rules. That being said, I have a few example here. One important thing, you do NOT want to use ESTABLISH and RELATED the wrong way and that's very easy to do that...

ip4tables.rules

The IPv4 and IPv6 rules are very similar. Some features are only available in one or the other and of course the IPv4 uses IP addresses in IPv4 format and IPv6 uses addresses in IPv6 format.

To convert IP addresses, you may install the ipv6calc tool. It is not really that practical, but it works as expected.

sudo apt-get install ipv6calc
ipv6calc --in ipv4addr 192.168.0.1 --out ipv6addr --action conv6to4
2002:c0a8:1::

Note: The ip6tables does not expect the square brackets we often see around IPv6 addresses.

Rules in iptables are checked one after another. The first rule that has an ACCEPT, a DROP, or a REJECT stops the process. Other rules such as a LOG and a RETURN let the process continue.

To open a port so someone from the outside can access your server, you want to add an ACCEPT rule. Say your computer has IP address 10.0.0.1 and you want to allow connections to an Apache server:

-A INPUT -i eth0 -p tcp -m tcp --dport 80 -d 10.0.0.1 --syn -j ACCEPT

Once a user connected to your server, the following packets will not match this rule. Instead you need a rule that allows already connected users to continue to send packets. However, before you do such a thing, you have to block connections to any other TCP port. This is done like this:

# Whatever the port, any other NEW connections are rejected immediatly
-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp -d 10.0.0.1 -j REJECT

So any other connections on any other port (say port 22 or 25) are rejected.

Now we can allow further packets to go through with an ESTABLISHED state:

-A INPUT -i eth0 -p tcp -m state --state ESTABLISHED -m tcp ! --syn -d 10.0.0.1 -j ACCEPT

This last rule is dangerous since an established connection on any TCP port is considered acceptable for any other connection to happen. In other words, with the previous REJECT rule with --state NEW, this newer rule would fail to prevent connections to your other ports (including port 22 and 25...)

Not only that, in many cases other documentations precognize to use RELATED as well. RELATED is useful only if you know exactly what you are doing. The one example given in the iptables documentation is the FTP protocol which has one control connection and one data connection. The data connection can be viewed as a RELATED connection and allowed if the user already has a connection to your FTP server. However, the truth is that is safe only if you specify the port:

# Our FTP server
-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp -d 10.0.0.1 --dport 21 -j ACCEPT
# Out FTP data server
-A INPUT -i eth0 -p tcp -m state --state NEW,RELATED -m tcp -d 10.0.0.1 --dport 20 -j ACCEPT
# Prevent any other connections
-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp -d 10.0.0.1 -j REJECT
# Allow more data to flow through existing connections
-A INPUT -i eth0 -p tcp -m state --state ESTABLISHED -m tcp ! --syn -d 10.0.0.1 -j ACCEPT
# Reject anything else
-A INPUT -i eth0 -p all -j REJECT

Note that this is relatively safe since port 20 will be your FTP server and it only talks FTP. Only people who are already connected on the control port can also connect to the data port. However, that does not make the FTP protocol any safer. Instead, users should look into another protocol altogether (HTTP, SFTP...)

So really ESTABLISHED,RELATED that we see everywhere does not make sense. If it is already ESTABLISHED, how can it also not be related?

[my old sample below contradict this statement, I still have to update all of that...]

Old Firewall Entry

There is probably a way to do that "cleanly". There is a good community description of the iptables command line. However, they tell you to auto-load and auto-save, or use the command line and then save the tables. And they give you a script to do this and that. I prefer my simple solution (he! he!).

What I do is create a file named iptables (and ipv6tables) under /etc/network (seems reasonable.) And in there I type in the command line options that I want to use. This means if you get an error, you don't have to retype and or move the cursor slowly between command line options, you use your preferred editor, like vim for instance (best editor ever, right?!)

A line in that iptables file really simply looks like the command line of the iptable tool when used in your console. For instance, to allow nothing else than port 80 connections and assuming your computer is on network 192.168.0.0, do this:

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# Allow the local network (totally open)
-A INPUT -i lo -s 192.168.1.1 -j ACCEPT
-A INPUT -i lo -s 192.168.2.1 -j ACCEPT
-A INPUT -i lo -s 192.168.3.1 -j ACCEPT
... (repeat as many times as you have local networks) ...
-A INPUT -i lo -s 127.0.0.1 -j ACCEPT
-A INPUT -i lo -j REJECT

# Allow external connections to Apache
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -d 192.168.1.1 --syn -j ACCEPT
-A INPUT -i eth0 -p tcp -m state --state ESTABLISHED,RELATED -m tcp ! --syn -d 192.168.1.1 -j ACCEPT
-A INPUT -i eth0 -p all -j REJECT
WARNING
Note that I do not say that will work for you. There is no guarantee here that this is correct in any way. Especially, the eth0 entry is what most people end up using. You may need to use eth1, eth2, bg0, bg1, or whatever else that you happen to have on your system. I suggest you read the documentation of iptables a few times before thinking that what you've done is right.

You may find it useful to allow your BIND and email servers too. But this is not part of this How To. Once you have a "good" setup (one that iptables gobbles), add rules as necessary. In general, it is a very good idea to start with close to no rules and add only what you need so your servers and clients work.

But ping does not work anymore?! Ah! Yes. The Unix tool called ping requires the icmp protocol to be open. I personally like to have it open. This is what you need to add before the REJECT line in the previous example:

-A INPUT -i eth0 -p icmp -j ACCEPT

For good security (at least to my point of view) it is a good idea to stop illegal addresses from connecting. This means at least all the addresses that are reserved for local networks (Intranet). The following shows what to do:

:bad_tcp_packets - [0:0]

-A INPUT -j bad_tcp_packets
-A FORWARD -j bad_tcp_packets

-A bad_tcp_packets -i eth0 -s 192.168.0.0/16 -j LOG --log-prefix "bad_tcp_packet: " --log-uid
-A bad_tcp_packets -i eth0 -s 192.168.0.0/16 -j DROP
-A bad_tcp_packets -i eth0 -s 10.0.0.0/8 -j DROP
-A bad_tcp_packets -i eth0 -s 172.16.0.0/12 -j DROP

In general, the FORWARD chain should never get such bad packets. But you are never too secure, are you?

Next I setup my OUTPUT rules. These are very similar, just use OUTPUT instead of INPUT and add the few entries you need and at the end of the chain use a LOG and DROP or REJECT. It is important to setup the OUTPUT because you may want to block some internal computers from accessing the outside. Also, that will give you accounting of all the traffic going around. You may see 1,000 hits on your Apache server, and notice 10,000 output packets. This is normal, but you wouldn't know if you hadn't any OUTPUT rules. The accounting also includes how many bytes are being transferred. This grows to Gb pretty quickly on my server.

The FORWARD chain is different from the INPUT and OUTPUT (IMPORTANT: See more information about IP forwarding below. Especially how to make it work on older system as the kernel would turn it OFF by default.) It actually requires a NAT entry. And just in case you did not know yet, this allows you to plug X computers on a server and have that server forward the packets from these X computers to the Internet (or whatever network.) It is much better, if you can, to have two NICs in this case. One NIC goes to the Internet and one NIC goes to your Intranet. Otherwise, it is difficult to protect the network as well as I can do it... First you enter rules in the FORWARD chain like for INPUT and OUTPUT. At first, you can leave that all empty since in general the FORWARD chain is safer than the other two. Make sure that the FORWARD is working, then protect it.

The NAT entry is similar to what we've seen so far. You may have noticed the '*filter' at the very beginning of the descriptions of this chapter. This means you are defining the filters. (Yeah, I know.) Filters will block packets, but they won't actually do anything to allow packet forwarding. That requires the '*nat' entries.

*nat
:POSTROUTING - [0,0]
-A POSTROUTING -o eth0 -s 192.168.2.2  -j SNAT --to-source 192.168.1.1
-A POSTROUTING -o eth0 -s 192.168.2.3  -j SNAT --to-source 192.168.1.1
-A POSTROUTING -o eth0 -s 192.168.2.4  -j SNAT --to-source 192.168.1.1
...

Obviously, you need to change the IP addresses to match your network. Yet, this will tell the server to forward packets from 192.168.2.2 (and .3, .4) to 192.168.1.1 which is the server or gateway in this case.

Alright! Now that you have typed all the firewall rules, you need to COMMIT them. Add the word COMMIT on a line by itself. This means "make all these rules I just added current". If an error occurred while installing these rules, then the COMMIT fails and your firewall is not modified. Here the problem is if you reboot and there is an error. NO RULE WILL BE ADDED TO YOUR FIREWALL. So, please try to remember that each time you change a rule, you MUST run iptables on that file to make sure that, if it ever happens, on next reboot it works (how often do you reboot Ubuntu anyway?! On my end one instance did last a little over 300 days, but because the kernel gets updates, you are generally bound to reboot relatively often anyway...)

One last note about security, you should NOT use addresses 1, 2, 3, 4, etc. in order. Instead, choose whatever random number which is still available (i.e. 199, 201, 57, etc.) This makes it harder for hackers to penetrate any one of these systems, just in case. If the firewall works well anyway, it should not be a problem.

Syndicate content

Diverse Realty

Diverse Realty Team

Want a New Home?
Want to Sell Your House?

Call Alex at
+1 (916)
220 6482

Alexis Wilke, Realtor
Salesperson
Lic. # 02024063

Cory Marcus, Broker
Lic. # 01079165

     

Terms of Site Index

Find the page/content you are looking for with our index.