Linux firewalls use iptables. The best way of creating a firewall with iptables is to write a scripts.
The first thing you need to do in your script is to write a routine that deletes out any previous firewall rules (flushing) and then blocks everything. Once you have blocked everything, you can start building your firewall to filter and allow connections as needed.
Creating a script Create a script called firewall.sh. Change permissions on the file so that it is executable with the chmod command as follows: chmod 777 firewall.sh
Save the file in /usr/local/sbin directory. If you do this you will be able to run the script from anywhere within the directory structure by typing “firewall.sh”
Declaring your network cards
In order for your firewall script to be more readable you could declare your network cards at the top of the script as follows:
EXT=eth0 INT=eth2 DMZ=eth1
From now on you use $EXT when referring to eth0 and $INT when referring to eth1, and so on.
Flushing all your rules
The next thing is to flush the Filter table. You will also need to flush any NAT tables. This can be accomplished with the “iptables -F” command. Type the following into your script. The -F serves to flush the tables.
Logging One of the important things needed on a firewall is a logging system. To set up logging on your firewall you need to add the following right a the bottom of your firewall.
iptables -A INPUT -j LOG –log-prefix “Denied INPUT:” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT:” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD:”
Enabling logging for your firewall will enable trouble shooting. By default, on some distros, the firewall logging is captured in the /var/log/messages file. SuSE logs firewall errors in another location, “/var/messages/firewall”
Setting up a default policy to block all The default policy for the INPUT, OUTPUT and FORWARD filters table should be DROP/DENY all packets. After you have flushed all the tables you can set the firewall to “drop all” by default. Once you have set the firewall to drop all by default you can go about opening the ports you need.
Below the section for flushing your firewall you can add the following to “drop” all in each of the filter tables:
iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP
Anything that doesn’t match any of the policies that follow, will be subject to the default policy, which in this case is “DROP”. In this case because we haven’t created any policies yet, everything will be dropped.
Your firewall.sh file should look like the following: ——————————————————————————————- #!/bin/bash EXT=eth0 INT=eth2 DMZ=eth1 # flush iptables -t nat -F iptables -t mangle -F iptables -t filter -F # Default policy set to DROP all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP # Logging rules – always at the END of the script iptables -A INPUT -j LOG –log-prefix “Denied INPUT: ” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT: ” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD: “ ——————————————————————————————-
INPUT and OUTPUT
We want to be able to ping another computer from our firewall server, we also want to be able to receive a reply from the computer we ping.
You can accomplish this with OUTPUT and INPUT Policies If your firewall server offers services other than a firewall or if you are putting a firewall on a “standalone” server, you will need to filter connections coming in to the service/s your server offers as well as filter connection originating from the server’s service/s. This is usually the case as you would normally have “ssh” setup on the firewall server for administration purposes. You might want to allow pings to and from the server. Another example of this would be if your server acted as a proxy server, web server or mail server in addition to being a firewall. For connections originating from the server’s service you will need to use the “OUTPUT” policy to filter outbound connections.
For connections to the server’s services you will need to use the “INPUT” policy.
In other words, the INPUT and OUTPUT policies only effects the “loca” computer, and not any connections that pass through the “local” computer/firewall (for this you need a FORWARD policy).
OUTPUT Policy
To allow outbound connections from your computer you need to add a rule similar to the following:
iptables -A OUTPUT -p tcp –dport 22 -j ACCEPT
The above rule will allow the protocol TCP, port 22 outbound. The following rule will allow ping traffic out:
It makes sense that if you want a computer to ping and be pinged you then you will need to allow both ping and pong inbound and outbound. ————————————————————————————————— #!/bin/bash EXT=eth0 INT=eth2 DMZ=eth1 # flush iptables -t nat -F iptables -t mangle -F iptables -t filter -F # Default policy set to DROP all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP # Allow us to ping other machines iptables -A OUTPUT -o $EXT -p icmp –icmp-type ping -j ACCEPT iptables -A INPUT -i $EXT -p icmp –icmp-type pong -j ACCEPT # Allow other machine to ping us iptables -A INPUT -i $EXT -p icmp –icmp-type ping -j ACCEPT iptables -A OUTPUT -o $EXT -p icmp –icmp-type pong -j ACCEPT # Logging rules – always at the END of the script iptables -A INPUT -j LOG –log-prefix “Denied INPUT: ” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT: ” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD: “ ————————————————————————————————
In the above example you could leave off the icmp type and just allow all icmp traffic inbound and out bound as follows:
iptables -A INPUT -i $EXT -p icmp -j ACCEPT iptables -A OUTPUT -o $EXT -p icmp -j ACCEPT
Without specifying the icmp type the firewall will allow all icmp types, this means that the above rules will allow pings and pongs in and out on the external network card
TIP – You will need to allow �loopback� connections with a rule similar to the following:
iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT
These rule will allow service on the computer to communicate via loopback if needed. These rule should be place near the top of the script under the “block all” policy. Some service will not work correctly if this is not enabled. ESTABLISHED and RELATED rules Some services will listen on one port and offer a service on another port, sometimes these ports are random. You don’t want these ports to be open all the time as this would constitute a security risk. ESTABLISHED and RELATED rules will allow you to open these ports for the duration of the connection. In other words, allow the connection on another port that is normally closed, if the requested port is part of or related to another already established connection. You can also use the ESTABLISHED and RELATED rule to allow the reply from a ping, this is because the reply (pong) is related to the ping. This means you can get rid of the “pong accept” rule if you use the ESTABLISHED and RELATED rule. The syntax for this is as follows:
iptables -A INPUT -m state -i $EXT –state ESTABLISHED,RELATED -j ACCEPT
Notice that you can specify the following:
1. The state with the –state option 2. The interface with the -i option
You will need one for each filter. (INPUT and OUTPUT) his should be added to your firewall script. Your firewall script should now look like the following:
————————————————————————————————— #!/bin/bash EXT=eth0 INT=eth2 DMZ=eth1 # flush iptables -t nat -F iptables -t mangle -F iptables -t filter -F # Default policy set to DROP all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP #Loopback accept rule iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT # Allow us to ping other machines iptables -A OUTPUT -o $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A INPUT -i $EXT -p icmp –icmp-type pong -j ACCEPT # Allow other machine to ping us iptables -A INPUT -i $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A OUTPUT -o $EXT -p icmp –icmp-type pong -j ACCEPT # Allow reply packets to established and/or related connections iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT # Logging rules – always at the END of the script iptables -A INPUT -j LOG –log-prefix “Denied INPUT: ” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT: ” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD: “ ————————————————————————————————-
Suppose you want to configure your firewall for the following: a) You want to be able to ssh (port 22 TCP) from a remote trusted computer. Hint, use -s in the rule. b) You want users on your computer to be able to use the Internet for web (port 80 TCP), ftp (port 21 TCP ) and DNS lookup (port 53 TCP and UDP). Your firewall script should now look like the following:
———————————————————————————————— #!/bin/bash EXT=eth0 INT=eth2 DMZ=eth1 # flush iptables -t nat -F iptables -t mangle -F iptables -t filter -F # Default policy set to DROP all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP #Loopback accept rule iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT # Allow us to ping other machines iptables -A OUTPUT -o $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A INPUT -i $EXT -p icmp –icmp-type pong -j ACCEPT # Allow other machine to ping us iptables -A INPUT -i $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A OUTPUT -o $EXT -p icmp –icmp-type pong -j ACCEPT # Allow reply packets to established and/or related connections iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT #Allow external users to ssh to this server # Probably should specify source addresses of trusted hosts iptables -A INPUT -i $EXT -s 192.168.19.43 -p tcp –dport 22 -j ACCEPT # Allow this server to access external services # Connect to remote servers on ssh # Access web and ftp sites for software downloads and updates # Do DNS lookups iptables -A OUTPUT -o $EXT -p tcp -m multiport –dports 22,80,53 -j ACCEPT iptables -A OUTPUT -o $EXT -p udp -m multiport –dports 53 -j ACCEPT # Logging rules – always at the END of the script iptables -A INPUT -j LOG –log-prefix “Denied INPUT: ” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT: ” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD: “ —————————————————————————————————–
POSTROUTING NAT and FORWARD Your LAN users will need to connect to the Internet. Since you have only 1 �Public� IP address you will need to make it appear that your LAN users are connection to the Internet with the Public IP address. This is called “MASQUERADING”.
Setting up a POSTROUTING NAT Policy on your firewall will accomplish this. In the firewall rule we use “SNAT” (source NAT). You will also need to include a FORWARD policy.
We will assume that your server has 3 network card. If you have more than one network card you will need to enable IP forwarding. This will allow you to move packets between your two network cards. Put in the following at the top of your firewall script.
echo “1″ > /proc/sys/net/ipv4/ip_forward
Alternatively you can make this permanent by editing the /etc/sysctl.conf file and make sure there is a line that reads:
net.ipv6.conf.all.forwarding = 1
For the purposes of this example we will be adding “echo “1″ /proc/sys/net/ipv4/ip_forward” to the firewall script
POSTROUTING NAT (Masquerade)
You would like all LAN Internet browsers to appear as if they are browsing from one “Public” IP address. POSTROUTING, or SNAT, changes the source address of the connection to a different IP address. There is two ways of doing this: 1. MASQUERADE – Using the “MASQUERADE” option will change the source IP address of the connection to the IP address of the interface mentioned in the rule “-o eth0″. See examples below. 2. SNAT – Using “SNAT” requires you to specify an IP address to be used as the source IP address of the connection. So to allow POSTROUTING NAT or masquerading you need to add one of the following to your firewall:
The first option allows masquerading using the IP address of the Output device. The second option specifies the IP Address to use. This is a “POSTROUTING” rule because you need to decide on the route the connection needs to take before you masquerade the computer on the LAN behind your public IP address. For example you want to browse to a web site, so you use a DNS server to resolve the domain name to an IP Address. Once the IP address of the remote server has been established and it’s been determined that your connection needs to pass through your default gateway your firewall masquerades your computer behind your public IP address. Packets from your computer to the remote server will have their source IP addresses changed to reflect your networks public IP address. Although you don’t need to specify the “-s 192.168.0.0/24″ (source on on lan), it is better to put this in for security reasons.
FORWARD policy In order for your users to be able to connect to the Internet (another computer the other side of the firewall) you will need to add a FORWARD rule to your firewall. You can lso specify the port, protocol and interface you wish to allow. iptables -A FORWARD -i $INT -o $EXT -p tcp –dport 110 -j ACCEPT
In the example above you are allowing traffic coming in on $INT connecting through to, and out on $EXT, using port 110 with protocol tcp. “-i” = incoming interface and “-o” = outbound interface.
To allow pings, you will need to specify the icmp protocol as follows:
ESTABLISHED and RELATED again You will also need to add an ESTABLISHED and RELATED rule for the FORWARD policy as follows:
iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT
Your firewall should now look something like the following: —————————————————————————————————– #!/bin/bash EXT=eth0 INT=eth2 DMZ=eth1 echo “1″ > /proc/sys/net/ipv4/ip_forward # flush iptables -t nat -F iptables -t mangle -F iptables -t filter -F # Default policy set to DROP all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP #Loopback accept rule iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT # Allow us to ping other machines iptables -A OUTPUT -o $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A INPUT -i $EXT -p icmp –icmp-type pong -j ACCEPT # Allow other machine to ping us iptables -A INPUT -i $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A OUTPUT -o $EXT -p icmp –icmp-type pong -j ACCEPT # Allow reply packets to established and/or related connections iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT #Allow external users to ssh to this server # Probably should specify source addresses of trusted hosts iptables -A INPUT -i $EXT -s 192.168.19.43 -p tcp –dport 22 -j ACCEPT # Allow this server to access external services # Connect to remote servers on ssh # Access web and ftp sites for software downloads and updates # Do DNS lookups iptables -A OUTPUT -o $EXT -p tcp -m multiport –dports 22,80,53 -j ACCEPT iptables -A OUTPUT -o $EXT -p udp -m multiport –dports 53 -j ACCEPT # Allow our users to ping external sites iptables -A FORWARD -i $INT -o $EXT -s 192.168.0.0/24 -p icmp –icmp-type ping -j ACCEPT # Masquerade outbound connections iptables -t nat -A POSTROUTING -o $EXT -s 192.168.0.0/24 -j MASQUERADE # Allow internal users access to Internet services iptables -A FORWARD -i $INT -o $EXT -s 192.168.0.0/24 -p tcp -m multiport –dports 80,53,22 -j ACCEPT iptables -A FORWARD -i $INT -o $EXT -s 192.168.0.0/24 -p udp -m multiport –dports 53 -j ACCEPT # Allow trusted LAN users to access services on firewall iptables -A INPUT -i $INT -s 192.168.0.100 -p tcp –dport 22 -j ACCEPT # Logging rules – always at the END of the script iptables -A INPUT -j LOG –log-prefix “Denied INPUT: ” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT: ” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD: ” ———————————————————————————————
PREROUTING NAT and FORWARD PREROUTING NAT
You should keep the servers you want to make available to the Internet in the DMZ. This allows you to make the servers in the DMZ available to the outside work while protecting your LAN. Normally you would put your mail sever and web server in the DMZ. LAN users will also need access to the DMZ to collect their mail, administer the DMZ servers etc.
If your company’s mail server is in the DMZ it will have a private IP address. On the other hand, if you were to do a dig on your domain name you would see that all zone records point to your public IP address, the IP address of the external network card of your firewall. This means any connection to your DMZ servers will stop at your firewall unless you can direct requests for those services to the appropriate server in the DMZ. To accomplish this we use PREROUTING NAT. In the firewall rule we use “DNAT” (destination NAT)
This is called PREROUTING because routing decisions take place after the destination IP address in the protocol header has been changed to the IP address of the server in the DMZ. Doing PREROUTING NAT for LAN users is not necessary if you have the necessary routing tables in place. But if you were to use PREROUTING NAT for LAN users you would replace “-i $EXT” to “-i $INT”. Notice that you can specify multiple ports in the rule by using the -m multiport option. You can also specify a different port for the DMZ server by putting a colon after the DMZ IP address, as per the following example:
FORWARD Policy again For the above to work, make sure you have the appropriate forward policies in place for connections originating on the internal and external interfaces.
Your firewall should now look something like the following: ——————————————————————————————————- #!/bin/bash EXT=eth0 INT=eth2 DMZ=eth1 echo “1″ > /proc/sys/net/ipv4/ip_forward # flush iptables -t nat -F iptables -t mangle -F iptables -t filter -F # Default policy set to DROP all iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP #Loopback accept rule iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT # Allow us to ping other machines iptables -A OUTPUT -o $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A INPUT -i $EXT -p icmp –icmp-type pong -j ACCEPT # Allow other machine to ping us iptables -A INPUT -i $EXT -p icmp –icmp-type ping -j ACCEPT #iptables -A OUTPUT -o $EXT -p icmp –icmp-type pong -j ACCEPT # Allow reply packets to established and/or related connections iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT #Allow external users to ssh to this server # Probably should specify source addresses of trusted hosts iptables -A INPUT -i $EXT -s 192.168.19.43 -p tcp –dport 22 -j ACCEPT # Allow this server to access external services # Connect to remote servers on ssh # Access web and ftp sites for software downloads and updates # Do DNS lookups iptables -A OUTPUT -o $EXT -p tcp -m multiport –dports 22,80,53 -j ACCEPT iptables -A OUTPUT -o $EXT -p udp -m multiport –dports 53 -j ACCEPT # Allow our users to ping external sites iptables -A FORWARD -i $INT -o $EXT -s 192.168.0.0/24 -p icmp –icmp-type ping -j ACCEPT # Masquerade outbound connections iptables -t nat -A POSTROUTING -o $EXT -s 192.168.0.0/24 -j MASQUERADE # Allow internal users access to Internet services iptables -A FORWARD -s $INT -o $EXT -s 192.168.0.0/24 -p tcp -m multiport –dports 80,53 -j ACCEPT iptables -A FORWARD -s $INT -o $EXT -s 192.168.0.0/24 -p udp -m multiport –dports 53 -j ACCEPT # Allow trusted LAN users to access services on firewall iptables -A INPUT -i $INT -s 192.168.0.100 -p tcp –dport 22 -j ACCEPT # Allow external users access to DMZ servers iptables -A FORWARD -i $EXT -o $DMZ -d 192.168.10.3 -p tcp -m multiport –dports 110,80 -j ACCEPT iptables -t nat -A PREROUTING -i $EXT -p tcp -m multiport –dports 110,80 -j DNAT –to 192.168.10.3 # Allow LAN users access to DMZ servers, no need for using PREROUTING NAT. iptables -A FORWARD -i $LAN -o $DMZ -p tcp -m multiport –dports 110,80 -j ACCEPT # Logging rules – always at the END of the script iptables -A INPUT -j LOG –log-prefix “Denied INPUT: ” iptables -A OUTPUT -j LOG –log-prefix “Denied OUTPUT: ” iptables -A FORWARD -j LOG –log-prefix “Denied FORWARD: ” —————————————————————————————————–
Additional useful information
Forcing users to use a firewall.
Proxy users could take out the proxy server settings from their Internet explorer, and as long as they know the DNS servers they need to use, could connect to the Internet directly, thus by passing the proxy security. One way to overcome this is to use PREROUTING NAT to redirect any requests for port 80 to port 3128 on the proxy server. You will need to set your squid proxy server to “transparent”. OR, you could just not allow port 80 in your forward policy
opening certain ports Certain services need to have certain ports open on the firewall the following are some
examples: Proxy server – depending on the ports you have configured your proxy server with, you’ll need to have these opened on the firewall in order for users to connect to the Proxy server. Standard ports are TCP 3128 or 8080. Samba server – For file sharing some users might need access to port 137 and 138 UDP and port 139 and 445 TCP. Depending on where the Samba server is and whether the firewall server is a Samba server it’s self you will need to allow access to these protocols and ports through your firewall. Web access - Ports used by web servers are generally 80, 8080 and 443 for secure web sites. FTP usually uses port 21. Mail servers - Depending on the type of mail server, you might need to open port 110 and 25 VPN – You need to open your firewall for the ports and protocols you need for vpn. Generally you will need to open protocol 47 (p47), TCP 1723 for PPTP. For L2TP/ipsec you need to open Protocol 50 (P50), UDP 4500 and 5000. VNC and Remote Desktop – VNC usually uses 5901 or 5910. Remote Desktop uses 3389.
Closing certain ports Once you have configured your firewall you will need to make sure that certain ports in particular are closed. An example of this is the port your Proxy server uses. While this port needs to be open for the LAN users and the server it’s self, if it is situated on the same computer as your firewall, it MUST be closed to “outside” traffic. The reason for this is that dubious individuals will try and use your proxy server to access the Internet to send Spam etc. If this happens it will appear that the malicious activity is coming from your network and you WILL get black listed.