Linux Home Server HOWTO
Previous
Home Next

Chapter 6 - Firewall Concepts

Packet Forwarding
Packet Filtering
Network Address Translation
Source NAT
IP Masquerading
Destination NAT
Example Firewall Script

With all the possible security threats roaming around the Internet today, a security firewall should be considered a mandatory necessity for any computer systems connected to the Internet. A firewall is a networking device which is used to separate private networks from external access by providing a certain level of security rules and controls.

A simple firewall can be configured to block all access to certain networks, workstations and communication ports. A more complex firewall is capable of inspecting each individual packet that attempts to pass through it and ensures that they are correctly formatted and appropriate to the services provided for (or by) the internal network, this is called a packet filtering firewall.

This chapter will explain some of the concepts for iptables and packet forwarding which can be used to secure your private network. The example configurations provided in each section are only designed to provide an introduction into each of those specific sections, while an example firewall script has been included which will provide simple but effective security for your networked system.

Note !! Many of the newer broadband modems provide built-in firewall features that allow for stateful packet inspection and detailed network address translations, which are capable of providing a high security level for your internal network.

Packet Forwarding

Packet forwarding is a simple concept where the server allows data packets to pass from one network to another. As with the diagram below, packets from the private network are allowed to be forwarded through the server and out to the ISP and vice versa.

                                   /-----------------------\
          /-----------------\      |   Server (Routing)    |      /-----------------\
          | Private Network |------|  eth1 : 192.168.1.1   |      | ISP Connection  |
          | 192.168.1.0/24  |      |-----------------------|      | REMOTE IP ADDR  |
          \-----------------/      | eth0 : 123.123.123.2  |------| 123.123.123.1   |
                                   \-----------------------/      \-----------------/

There are a few initial considerations. First, the server must have networks or gateways defined in its routing table so it can make an informed decision where the packet needs to be passed to. Second, the server must have packet forwarding enabled. Thirdly, if the routed packets came from an RFC1918 private subnet, they must be translated into globally routed IP addresses (NAT covered later) before they will be accepted out on the Internet.

Packet forwarding can be enabled either manually as required by the superuser, or automatically when the system starts the networking service. To manually enable or disable packet forwarding, use the respective commands listed below.

[bash]# echo 1 > /proc/sys/net/ipv4/ip_forward

[bash]# echo 0 > /proc/sys/net/ipv4/ip_forward

To enable automatic packet forwarding for whenever the network service is active, make the following changes in your /etc/sysctl.conf file.

[bash]# vi /etc/sysctl.conf

net.ipv4.ip_forward = 1

Note !! It is common practice for users to have manual control over packet forwarding, and to active or disable the function within their firewall control scripts. However setting packet forwarding to start automatically will be more suitable for a dedicated server.

Packet Filtering

Packet filtering is also a reasonably simple concept (true), however it can be very daunting for new users that don't fully understand how it works, so let's cover the basics first and build it up.

In packet forwarding the kernel is either allowed to move packets between different subnets or is not, and if it is, the decisions are made from the kernel's routing table. In packet filtering an application called iptables (www.netfilter.org) stores a list of programmed rules which are individually tested against every packet that either tries to enter, pass through, or exit any of the system's network devices. Each rule is used to test the packet in a sequential order and if the packet matches any of the rules it is either accepted or rejected depending on the global policy and rule definitions. iptables is your firewall application and is one of the networking frameworks for your Linux kernel.

iptables essentially has this name because it stores the rulesets into a group of three tables which each provide different capabilities depending on the rules and the order they are applied. We will only examine the filter and nat tables here, the mangle table is used for specialised packet alteration which is beyond our scope. The following table displays the filter iptables and the three built-in chains.

Table Name
Chain Name
Chain Details
filter
INPUT
For any packet coming into the system
FORWARD
For any packet that is being routed through the system
OUTPUT
For any packet that is leaving the system

To list the filter table and its rules you can use the following command.

[bash]# iptables -t filter -nvL

The filter table is the default table when working with iptables, so there is no need to add '-t filter' at the command prompt.

[bash]# iptables -nvL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination 

You should see an output similar to above, if not then stop the iptables service and output the table again. From the listing you can see the three built in chains, and their default policies are all set to ACCEPT, which means the firewall is inactive.

[bash]# /etc/init.d/iptables stop

The output from the top listing does not provide much information, so let's populate the table with some of our own rules. Type the following commands at the prompt then output a listing of the table again.

01- [bash]# iptables -P INPUT DROP
02- [bash]# iptables -P FORWARD DROP
03- [bash]# iptables -P OUTPUT DROP
04- [bash]# iptables -A INPUT  -i lo -j ACCEPT
05- [bash]# iptables -A OUTPUT -o lo -j ACCEPT
06- [bash]# iptables -A INPUT  -i ppp0 -p tcp --sport 80 -j ACCEPT
07- [bash]# iptables -A OUTPUT -o ppp0 -p tcp --dport 80 -j ACCEPT
08- [bash]# iptables -A INPUT  -i eth1 -s 192.168.1.0/24 -p tcp --dport 3128 -j ACCEPT
09- [bash]# iptables -A OUTPUT -o eth1 -d 192.168.1.0/24 -p tcp --sport 3128 -j ACCEPT

[bash]# iptables -nvL

01-

04-
06-
08-

02-


03-

05-
07-
09-
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0           tcp spt:80
    0     0 ACCEPT     tcp  --  eth1   *       192.168.1.0/24       0.0.0.0/0           tcp dpt:3128

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     tcp  --  *      ppp0    0.0.0.0/0            0.0.0.0/0           tcp dpt:80
    0     0 ACCEPT     tcp  --  *      eth1    0.0.0.0/0            192.168.1.0/24      tcp spt:3128

The nine commands which you typed above have been numbered along with their output so they can be easily identified in the second table.

Lines 01-03: The first three commands set the default (-P) policy on all the chains to DROP everything, unless suitable rules inside the chain will ACCEPT them. This is the most secure method of filtering as any packet that is now to pass through any of the chains, must have a specific rule written for it.

Lines 04-05: These two commands have (-A) appended two ACCEPT rules. The OUTPUT rule (05) allows any packet to (-o) leave via the loopback device and the INPUT rule (04) allows packets to re-enter (-i) via the loopback.

Because the chains are using a default DROP policy, they restrict the server from accessing any of its own services running on the local host, like DNS. A basic rule like this allows the server to access all loopback services without restriction.

Lines 06-07: The next two (-A) appended rules are more specific, lets look at the outbound one first. The OUTPUT rule (07) specifies that any packet going out the (-o) ppp0 interface using (-p) protocol TCP is ACCEPTed if its going to port 80. The INPUT rule (06) specifies that any packet coming in the (-i) ppp0 interface using (-p) protocol TCP is ACCEPTed if its coming from port 80.

You should be able to pick this up, it says that we are allowed to access external web servers from our own server, but there are no forward rules for the internal network to surf the Internet. We should also allow our internal network the ability to access external web servers too shouldn't we? Let's look at the next rules then.

Lines 08-09: The last INPUT rule (08) which has been (-A) appended to the chain allows any packets from the (-s) source network of 192.168.1.0/24 if they enter through the (-i) eth1 device and if they are the TCP (-p) protocol and are going to the (--dport) destination port of 3128.  The matching OUTPUT rule (09) has been (-A) appended to the chain and allows any packets that are going out (-o) the eth1 interface to (-d) destination network 192.168.1.0/24 using the TCP (-p) protocol if it came from the (--sport) source port of 3128.

These two are fairly detailed rules, they say that anyone on the internal network (192.168.1.0/24) is allowed to send packets to the squid proxy server (3128) through the internal eth1 interface and the results can be returned to the workstation.

If you use a strict DROP policy like above, its important to note that you may need two rules that complement each other in order for data to flow out and back in again.

A Walk Through

To better understand the above filtering example, its best to walk the configuration through the same way a packet would be subject to the filtering table's definitions, one rule at a time. Remember, every packet of data has certain attributes, source/destination addresses, source/destination ports, the interfaces they are coming in and out and the type of protocol being used, the filtering will reject any packet whose attributes dont match any of the rules in our chains.

A person using the workstation (in the network example below) wishes to access the resources of the web server located on the Internet, can a direct connection be established? No, all the policies are set to DROP and there is no FORWARD rules defined, so it simply can not occur.

Can the proxy server access the web server on the Internet? Yes, the proxy server has the rights to access anything which is TCP based operating at port 80 out through the ppp0 link, which is to a web server. Can you see the ACCEPT rules for the packet's attributes in the complementing INPUT and OUTPUT chains?

                                   /-----------------------\
          /-----------------\      |  Proxy Server (3128)  |      /---------------\
          |   Workstation   |------|  eth1 : 192.168.1.1   |      |  Web Server   |
          |   192.168.1.10  |      |  ppp0 : 123.123.123.2 |------| (TCP port 80) |
          \-----------------/      |    lo : 127.0.0.1     |      \---------------/
                                   \-----------------------/

The only way now for the workstation to access anything, is via the proxy server application running at port 3128, which in turn can access any web server resources on the Internet and return the requested information to the workstation. Are the required rules in the table?

How does this work without any forwarding rules? Easy, the proxy server is an application that requests resources on behalf of a client, so the request comes into the proxy from the client, and now the request goes out to the web server from the proxy, as though it was requesting the information itself. This happens at the application layer, because its the proxy application which forwards the clients original request, so forwarding at the IP layer is not required here.

Hopefully you have been able to pick up the filtering concepts mentioned above, if you have, well done. The proxy server situation was a little tricky, but was introduced to give you an understanding that particular packets and resources can still be shaped to suit your security requirements by incorporating them into your network design.

Thats a brief introduction to packet filtering, the ability to write and chain together rules that selectively accept or deny any packets that do not meet the security requirements for your network.

What happens to the filter table when you type these following commands? View the table's output after each one and see if you can recognise the effects of the rules, and which direction the packets can pass (i.e., are they going to an internal or external resource). View "man iptables" for further assistance.

[bash]# iptables -I INPUT  2 -i ppp0 -p tcp --dport ftp -j ACCEPT
[bash]# iptables -I OUTPUT 2 -o ppp0 -p tcp --sport ftp -j ACCEPT

[bash]# iptables -D INPUT  -i ppp0 -p tcp --sport 80 -j ACCEPT
[bash]# iptables -D OUTPUT -o ppp0 -p tcp --dport 80 -j ACCEPT

[bash]# iptables -A INPUT  -p icmp --icmp-type any -j ACCEPT
[bash]# iptables -A OUTPUT -p icmp --icmp-type any -j ACCEPT

[bash]# iptables -I INPUT  -m state --state INVALID -j LOG --log-prefix "INVALID Input: "
[bash]# iptables -I INPUT  -m state --state INVALID -j DROP

[bash]# iptables -F
[bash]# /etc/init.d/iptables restart

Network Address Translation

Network Address Translation (NAT) is the ability to change a data packets destination or source IP address on-the-fly, so the packet looks like it came from (or is going to) a different address than the original (also works on port numbers).

There are many reasons why we should use NAT, here are a few:
The iptables package also provides support for NAT and has a built-in nat table just for that purpose. Below is a listing of the default chains that are found in the nat table and an explanation of how they are applied.

Table Name
Chain Name
Chain Details
nat
PREROUTING
For altering packets as they are entering the system (before filter INPUT)
POSTROUTING
For altering packets as they are exiting the system (after filter OUTPUT)
OUTPUT
For altering  packets before leaving the local system (before the routing table)

As the naming suggests, the PREROUTING and POSTROUTING chains are applied before or after any kernel routing decisions are made, so the packets can then be routed to match any new changes which have been made to the destination or source addresses.

To list the contents of the nat table, issue the following command at the prompt.

[bash]# iptables -t nat -nvL

Source NAT

Source NAT deals with changing the source address of any packets that pass through the NAT device, assuming they meet the criteria of the specified policies and chains. This allows workstations on a private network to send data packets through the NAT device which changes the source address in the packet's header before sending the packet onto the Internet. When the packet reaches its destination and is processed, the distant host returns the packet using the adjusted address as the new destination address, and delivers it back to the NAT device. The NAT device stores a list in memory of all the packets it adjusts, so when they are returned, the packets can be redirected to the real originator of the packets on the internal private network.

Source NAT can be written for inbound and outbound packets, but are more commonly used for outbound.

For a packet to be subject to SNAT, lets consider the following details:
It all sounds rather confusing, so lets go straight to an example. Type the following rules at the command prompt and then display the contents of the filter and nat tables with the last command (typed as one line).

01- [bash]# iptables -P INPUT ACCEPT
02- [bash]# iptables -P FORWARD DROP
03- [bash]# iptables -P OUTPUT ACCEPT
04- [bash]# iptables -A FORWARD -i eth1 -o ppp0 -s 192.168.1.0/24 -p tcp --dport 80 -j ACCEPT
05- [bash]# iptables -A FORWARD -i ppp0 -o eth1 -d 192.168.1.0/24 -p tcp --sport 80 -j ACCEPT
06- [bash]# iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.1.0/24 -j SNAT --to-source 123.123.123.2
07- [bash]# echo 1 > /proc/sys/net/ipv4/ip_forward

[bash]# iptables -nvL ; iptables -t nat -nvL

01-


02-

04-
05-

03-









06-



Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  eth1   ppp0    192.168.1.0/24       0.0.0.0/0           tcp dpt:80
    0     0 ACCEPT     tcp  --  ppp0   eth1    0.0.0.0/0            192.168.1.0/24      tcp spt:80

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination



Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 SNAT       all  --  *      ppp0    192.168.1.0/24       0.0.0.0/0           to:123.123.123.2

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Lines 01-03: The first three commands have now defined the global policies for the three built-in chains for the filter table.

To keep the example a little easier to understand, we are going to accept everything that is classed as INPUT or OUTPUT, and for security we are dropping anything trying to pass through (FORWARD) the NAT unless we allow it.

Lines 04-05: The two forward rules are quite specific. Rule 04 says that any packet that comes in (-i) the eth1 interface and goes (-o) out the ppp0 device from the (-s) source network of 192.168.1.0/24 can be ACCEPTed if its going to (--dport) destination port 80; a web server. Rule 05 is the matching rule allowing the packet to return back through the NAT.

We don't have any INPUT or OUTPUT restrictions here, so we only need to write and match rules that allow packets to pass through (FORWARD) the NAT. In the diagram below, when a HTTP(80) request comes from the private network, it is allowed to pass through the NAT and continue to the web server out on the Internet. But what are the packet's attributes? Its source address is still 192.168.1.x, so when it reaches its destination, the web server does not know where it came from because its a private non-routable RFC1918 IP address, so the server will probably just drop it. No packets will ever be returned.

                                   /-----------------------\
          /-----------------\      |  NAT Gateway Device   |      /---------------\
          | Private Network |------|  eth1 : 192.168.1.1   |      |  Web Server   |
          | 192.168.1.0/24  |      |  ppp0 : 123.123.123.2 |------| (TCP port 80) |
          \-----------------/      \-----------------------/      \---------------/

Line 06: This rule is our solution to the above problem. This rule is applied after the routing decisions have been made and the packet is about to depart for the web server out on the Internet. It says, any packet that goes (-o) out the ppp0 interface from the (-s) 192.168.1.0/24 network is to have the source address rewritten as 123.123.123.2.

Now when the packet reaches the Internet web server, it can be processed normally and returned to 123.123.123.2 (the NAT device), where it will automatically be rewritten again and sent back to the original workstation on the internal private network.

Line 07: This command tells the kernel that it is allowed to forward packets between any of its network devices. These packets are still subject to the iptables rulesets.

Some important points about SNAT to remember are:

IP Masquerading

Put simply, masquerading is a form of SNAT which should be used for all dynamic interfaces where the IP address is likely to be different each time we connect. This is perfect for our dynamic IP broadband accounts, and saves having to rewrite large SNAT rules each time we connect to the Internet. SNAT remembers connection state information (to a degree) if a static connection was to drop, however using masquerading the connection state information is reset each time the interface is (de)activated. Masquerading automates SNAT for dynamic IP connections.

Because masquerading is so easy (true) we are going to use some state tracking attributes in our rules. Type the following rules at the command prompt and display a listing of the filter and nat tables.

01- [bash]# iptables -P INPUT ACCEPT
02- [bash]# iptables -P FORWARD DROP
03- [bash]# iptables -P OUTPUT ACCEPT
04- [bash]# iptables -A FORWARD -i ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT
05- [bash]# iptables -A FORWARD -i eth1 -o ppp0 -s 192.168.1.0/24 -j ACCEPT
06- [bash]# iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.1.0/24 -j MASQUERADE
07- [bash]# echo 1 > /proc/sys/net/ipv4/ip_forward

[bash]# iptables -nvL ; iptables -t nat -nvL

01-


02-

04-
05-

03-









06-




Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  ppp0   *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    0     0 ACCEPT     tcp  --  eth1   ppp0    192.168.1.0/24       0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination



Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE all  --  *      ppp0    192.168.1.0/24       0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination


Lines 01-03: The first three commands have now defined the global policies for the three built-in chains for the filter table.

To keep the example a little easier to understand, we are going to accept everything that is classed as INPUT or OUTPUT, and for security we are dropping anything trying to pass through (FORWARD) the NAT unless we explicitly allow it.

Line 04: Rule 04 deals with the connection state and says, any packet that comes in the (-i) ppp0 interface must (-m) match a certain state, and the state must ensure the packet is in response to an already RELATED or ESTABLISHED connection.

Basically only allow packets to be forwarded into the private network if the packet is in response to an already RELATED or ESTABLISH connection. This rule will not allow any NEW connections to be initiated from the external network a connection must already existed, so any packet coming inside will be in response to a current connection that could have only be initiated from the internal network.

Line 05: This is a simple rule that will forward any packets from the (-i) eth1 interface and out the (-o) ppp0 interface if they are from the (-s) 192.168.1.0/24 source network.

This is rule does not detail any connection state so it will allow all connection types, but most important is the NEW connection state that it can pass. This rule allows internal workstations to create new connections, and matches rule 4 which allow the packets to return.

Line 06: This rule does the exact same as if it were a SNAT rule, however being a MASQUERADE rule means it will use the IP address that is currently assigned to the ppp0 interface when the packet passes through the NAT device.

Any packets that now pass from the internal private network out into the Internet will have its source address rewritten as the external IP address of the NAT device.

Line 07: This command tells the kernel that it is allowed to forward packets between any of its network devices. These packets are still subject to the iptables rulesets.

Remember, masquerading should always be used for dynamic IP connections.

Dangerous Masquerading Rule

Beware of this rule, it is too relaxed and does not specify which direction the packets should be masqueraded. In fact, this rule allows masquerading in BOTH directions. Always specify an (-o) out interface parameter to make the rule work in one direction only.

[bash]# iptables -t nat -A POSTROUTING -j MASQUERADE

Warning !! WARNING: The above rule is dangerous, it allows masquerading in both directions.

Destination NAT

Destination NAT deals with changing the destination address of any packets before they are subjected to any routing decisions. This allows specific traffic to be rewritten so it suits a particular rule and can then be redirected depending on the global policies and destinations required.

In its most typical application, DNAT is normally used to change incoming packets that are destined for a particular service or host, and it rewrites the destination addresses so the packets can pass to a different host located inside the private network, normally a DMZ.

When DNAT occurs, the original host (which is located external of the private network) is not aware the packets have been redirected and that the returning data is from a different server. It should be transparent to the originator.

The following commands can be typed at the command prompt, and the filter and nat tables displayed using the last command.

01- [bash]# iptables -P INPUT ACCEPT
02- [bash]# iptables -P FORWARD DROP
03- [bash]# iptables -P OUTPUT ACCEPT
04- [bash]# iptables -A FORWARD -i eth1 -o ppp0 -s 192.168.1.0/24 -j ACCEPT
05- [bash]# iptables -A FORWARD -i ppp0 -o eth1 -p tcp --dport 80 -j ACCEPT
06- [bash]# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2:80
07- [bash]# echo 1 > /proc/sys/net/ipv4/ip_forward

[bash]# iptables -nvL ; iptables -t nat -nvL

01-


02-

04-
05-

03-






06-







Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  eth1   ppp0    192.168.1.0/24       0.0.0.0/0
    0     0 ACCEPT     tcp  --  ppp0   eth1    0.0.0.0/0            192.168.1.0/24      tcp dpt:80

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination



Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DNAT       tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80 to:192.168.1.2:80

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination


Lines 01-03: The first three commands have now defined the global policies for the three built-in chains for the filter table.

To keep the example a little easier to understand, we are going to accept everything that is classed as INPUT or OUTPUT, and for security we are dropping anything trying to pass through the NAT unless we allow it.

Line 04-05: The first FORWARD rule (04) allows any packets coming in the (-i) eth1 interface and out the (-o) ppp0 interface if they have come from the internal (-s) source 192.168.1.0/24 network. The second FORWARD rule (05) allows any packets coming in the (-i) ppp0 interface and out the (-o) eth1 interface that are using the TCP (-p) protocol if they are going to (--dport) destination port 80.

These two rules complement each other, the first allows outgoing packets to be forwarded from the internal network and the second rule allows incoming packets to be forwarded into the private network but only if they are going to a web server (port 80).

Is this going to work? Well lets look at the incoming packet's attributes with the following diagram. The remote host that originally sent the data requested a web page URL of "http://www.example.com" which resolved to the IP address of 123.123.123.2 and the packet was sent on its way. When it arrives at the NAT device, the destination address is still 123.123.123.2 so it must be handled by that IP address or rejected. But the web server is inside the network, what do we do?

                                   /-----------------------\
      /---------------------\      |  Server (Routing)     |      /-----------------\
      | Internal Web Server |------|  eth1 : 192.168.1.1   |      | Remote Computer |
      |   192.168.1.2(80)   |      |  ppp0 : 123.123.123.2 |------| (Internet Zone) |
      \---------------------/      \-----------------------/      \-----------------/

This is where DNAT is able to change the destination address of the incoming packet, and put the new address in its place (192.168.1.2(80)). Because DNAT is PREROUTING, the packet is now subjected to the kernel routing table which points the new packet to the internal network. Lastly, there must exist a rule in the FORWARD chain which will allow the packet to pass through, and there is, rule 05.

Line 06: This is a PREROUTING rule in the nat table, if any packets come in through the (-i) ppp0 interface and are (-p) TCP packets going to (--dport) destination of port 80, then they are to be rewritten and sent to the host 192.168.1.2:80 instead.

Line 07: This command tells the kernel that it is allowed to forward packets between any of its network devices. These packets are still subject to the iptables rulesets.

DNAT declarations are reasonably easy because the destination header can be rewritten before the routing table is queried. Some important points to remember are:


Example Firewall Script

The following is an example firewall script which uses all of the concepts covered already in this chapter. It should therefore be relatively easy to understand, implement and maintain.

The firewall script is designed to separate and secure the private network (eth1) from the Internet traffic (ppp0), while providing some flexibility for the internal network which is being masqueraded.

[bash]# vi /root/firewall.sh
#!/bin/sh
#
#       Example Firewall Script

###############################################################
### Define interfaces here
EXT_DEV=ppp0
INT_DEV=eth1
INT_NET=192.168.1.0/24

### Loading firewall modules
modprobe ip_conntrack
modprobe ip_conntrack_ftp

###############################################################
### Enable Packet Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

### Remove all previous rules, and delete any user defined chains
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X

### Set the default policies to drop
iptables -P INPUT   DROP
iptables -P OUTPUT  DROP
iptables -P FORWARD DROP

### Loopback device OK
iptables -A INPUT  -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT

### Allow all ICMP Traffic (optional) - IN, OUT and THROUGH.
iptables -A INPUT   -p icmp --icmp-type any -j ACCEPT
iptables -A OUTPUT  -p icmp --icmp-type any -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type any -j ACCEPT

### Allow all Internal traffic to Server
iptables -A INPUT  -i $INT_DEV -s $INT_NET -d $INT_NET -j ACCEPT
iptables -A OUTPUT -o $INT_DEV -s $INT_NET -d $INT_NET -j ACCEPT

###############################################################
### OUTBOUND Rule: Allow ALL packets out the external device
iptables -A OUTPUT  -o $EXT_DEV -j ACCEPT
iptables -A FORWARD -i $INT_DEV -o $EXT_DEV -j ACCEPT

###############################################################
### MASQUERADING: All packets from the internal network will
### appear as if they had originated from the firewall.
iptables -t nat -A POSTROUTING -o $EXT_DEV -s $INT_NET -j MASQUERADE

###############################################################
### INBOUND Rule: Allow ALL EXT packets if a connection already exists (See "NEW" Inbound Rules)
iptables -A INPUT   -i $EXT_DEV -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $EXT_DEV -m state --state RELATED,ESTABLISHED -j ACCEPT


#
### INBOUND Rules: Allow ONLY NEW packets on these ports.
#

# New INBOUND Connection: FTP (with TLS)
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 20  -j ACCEPT
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 21  -j ACCEPT

# New INBOUND Connection: Secure Shell
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 22  -j ACCEPT

# New INBOUND Connection: SMTP and SMTPS (over TLS/SSL)
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 25  -j ACCEPT
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 465 -j ACCEPT

# New INBOUND Connection: HTTP (Plain and SSL)
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 80  -j ACCEPT
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 443 -j ACCEPT

# New INBOUND Connection: LDAPS Server (over SSL)
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 636 -j ACCEPT

# New INBOUND Connection: IMAPS Email Clients (over SSL)
iptables -A INPUT -i $EXT_DEV -m state --state NEW -m tcp -p tcp --syn --dport 993 -j ACCEPT

###
#    Squid Transparent Proxy: Enable rule for transparent proxy redirection
# Redirect all WWW (port 80) OUTBOUNT packets to the Squid Server on port 3128
#iptables -t nat -A PREROUTING -i $INT_DEV -s $INT_NET -p tcp --dport 80  -j REDIRECT --to-port 3128


#
### INBOUND DNAT (redirection) Rules: Allow ONLY NEW packets on these ports and redirect to internal services.
#

### INBOUND Rule: Redirect ALL packets to the INTERNAL workstation - HTTP
#iptables -t nat -A PREROUTING -i $EXT_DEV -p tcp --dport 80 -j DNAT --to-destination wkstn1.example.com:80
#iptables -A FORWARD -i $EXT_DEV -o $INT_DEV -p tcp --dport 80 -j ACCEPT

### INBOUND Rule: Redirect ALL packets to the INTERNAL workstation - HTTPS
#iptables -t nat -A PREROUTING -i $EXT_DEV -p tcp --dport 443 -j DNAT --to-destination wkstn1.example.com:443
#iptables -A FORWARD -i $EXT_DEV -o $INT_DEV -p tcp --dport 443 -j ACCEPT

After the firewall script has been executed and the new firewall rules are active, the iptable settings can be saved so they are automatically implemented when the firewall is next started.

[bash]# sh /root/firewall.sh
[bash]# /etc/init.d/iptables save

You should now restart the iptables service and see if the tables and chains are the same.

[bash]# /etc/init.d/iptables restart
[bash]# iptables -nvL ; iptables -t nat -nvL

If you intend to use the initscripts to automatically start the iptables service, then any firewall modules that are needed will have to be manually added to the init script.

[bash]# vi /etc/init.d/iptables

IPTABLES_MODULES="ip_conntrack ip_conntrack_ftp"

You can check to see if the modules loaded automatically by listing all of modules currently being used by the kernel.

[bash]# lsmod



Previous
Home Next