Setting up your firewall with Shorewall on Linux (Debian)

Printer-friendly versionPDF version

My server is behind a NAT router so a firewall running on it is kind of redundant. But I didn't want to take any chances. The server should have a firewall of its own. So even on a LAN environment if other connected PCs are compromised than your server needn't suffer because of that. And if you directly connect than hopefully this guide will help you. (Although I will try to get verification from the shorewall people if what I did is ok, since I could not find a single example of such a configuration )

The Topology

In case you are not behind a nat router and connect directly to the internet you will profit from the firewall setup I am going to describe. If not directly connected to the internet and using a NAT router like me, I think your server will still be safer in your LAN environment with a few open ports, in case any other computers on the LAN get compromised. Your server needn't suffer for this. So following is what my topology looks like:

 

firewall topology

The modem is always connected to the internet. When it is started up, it creates a WAN connection with my network provider. Than I just plug a LAN cable from my server to the modem which is also a NAT router. I have configured for a fixed LAN IP for my server on this modem and than just opened and forward the traffic on port 22, 80, 443 to this IP. (See your modem guide to do this.)

Alternative to Shorewall

All the above being said the world of firewalls seemed daunting in linux. I was used to the ease of "Zonealarm" on windows. Well I looked around and found "ufw" and a gui interface "gufw" for it. Was excited ok, maybe something like zonealarm. But I was mistaken. And Debian anyways had a package that was older than what is documented on the gufw website. So everything was out of sync. The newer UI documented atleast seem easier as it seemed to add 2 way rules for every entry. With the old ui it required me to type both of these rules. I ditched it. It was my second choice anyways.

Presenting Shorewall

My first preference was shorewall. But it seemed big and complicated. So I tried avoiding it with my choice above but I couldn't have been more wrong. I admit I spent quite some time reading the guides and documentation but it was totally worth it. For one thing the scenario/topolgy I had in mind was not even documented in the shorewall guide. During my read I began to doubt if I could even use it. But I decided to play with it and see what happens.

The quick start shorewall guide talks about settings for different number of interfaces and packs configuration file examples for the same at the location "/usr/share/doc/shorewall/examples/". This location is true for debian atleast. To mention additionally I am going to be configuring shorewall for ipv4 and and thinking about disabling ipv6 on my server.

Configuration for Shorewall

The "one interface guide" seemed close to my topology at hand but not quite. It talked about having a PPTP connection and all configurations were thereof. True I had had modems where I did have to create a pptp connection when the connection started but the cable modem from my company was already registering itself on the cable companies WAN. I.e I was already on the internet when my LAN cable connects to the LAN ports on this cable modem/router. But if you do have pptp than you need those configuration files and not what I am going to describe below.

So lets start configuring. The configuration files for the "one interface guide" can be found at location "/usr/share/doc/shorewall/examples/one-interface" directory. Following is the list of files in this location:

webuser@ahsanscorner:/usr/share/doc/shorewall/examples/one-interface$ ls -al
total 80
drwxr-xr-x 2 root root  4096 Jan 31 23:04 .
drwxr-xr-x 6 root root  4096 Jan 31 23:04 ..
-rw-r--r-- 1 root root   859 Oct 21  2012 interfaces
-rw-r--r-- 1 root root  5570 Oct 21  2012 interfaces.annotated.gz
-rw-r--r-- 1 root root   806 Oct 21  2012 policy
-rw-r--r-- 1 root root  2822 Oct 21  2012 policy.annotated.gz
-rw-r--r-- 1 root root  1126 Oct 21  2012 README.txt
-rw-r--r-- 1 root root  1198 Oct 21  2012 rules
-rw-r--r-- 1 root root 10626 Oct 21  2012 rules.annotated.gz
-rw-r--r-- 1 root root 17014 Oct 21  2012 shorewall.conf.annotated.gz
-rw-r--r-- 1 root root  1669 Oct 21  2012 shorewall.conf.gz
-rw-r--r-- 1 root root   737 Oct 21  2012 zones
-rw-r--r-- 1 root root  2706 Oct 21  2012 zones.annotated.gz


Step 1 : Configuration files

Copy all the files from "/usr/share/doc/shorewall/examples/one-interface/" to "/etc/shorewall/" folder. Remove the unneeded gz file and README.txt files if you want to.

Step 2 : The interface file

Edit the file "/etc/shorewall/interfaces". Put your interface name in there, in my case it is already eth0, so nothing to change there, although I added a few options in there as also below:

# For information about entries in this file, type "man shorewall-interfaces"
###############################################################################
FORMAT 2
###############################################################################
#ZONE   INTERFACE       OPTIONS
net     eth0            dhcp,tcpflags,nosmurfs,routefilter,logmartians,sourceroute=0


The option I added extra was "routefilter". Since cat "cat  /proc/sys/net/ipv4/conf/all/rp_filter" for me on my odroid server was showing a non-zero value I also put in the routefilter option as recommended by the man page. You can see the man page by doing "man shorewall-interfaces"

 

Step 3 : The zones file

Next file to look at is "/etc/shorewall/zones".  There is no need for any change here for us. The contents of this files are as below :

#ZONE   TYPE    OPTIONS                 IN                      OUT
#                                       OPTIONS                 OPTIONS
fw      firewall
net     ipv4


This just says that we have 2 zones in this setup. A firewall zone and an internet zone.

 

Step 4 : The policy file

The next file to configure is the policy file. This file is consulted before any rules are consulted (rules follow shortly) . Again edit the file"/etc/shorewall/policy" and modify the contents to say as below:

#SOURCE         DEST            POLICY          LOG LEVEL       LIMIT:BURST
$FW             net             ACCEPT
net             $FW             DROP            info
# The FOLLOWING POLICY MUST BE LAST
all             all             DROP            info


The first line after the comment header says that if source is my server machine running the firewall ($FW) and destination is the internet ( the net zone we stated in zones file ), allow the connection.

In the next line you will notice that instead of the "all" keyword for the DEST column I changed it to read $FW ( from the example file we copied ) . So what I say here is that if source is internet and the destination is my firewalled server machine than DROP the packet as a policy and log the action.

The last line is by default there. DROP everything else you see.

 

Step 5 : The rules file

The next file to configure is the rules file. Start editing the file "/etc/shorewall/rules" and add the following contents :

########################################################
#ACTION         SOURCE          DEST            PROTO   
#                                                       
#SECTION ALL
#SECTION ESTABLISHED
#SECTION RELATED
SECTION NEW

# Drop Ping from the "bad" net zone.. and prevent your log from being flooded..

Ping(DROP)      net             $FW

# Permit all ICMP traffic FROM the firewall TO the net zone

ACCEPT          $FW             net             icmp

# SSH access to your firewall/server from the Internet, using SSH
SSH/ACCEPT     net             $FW


# Web access to your firewall/server from the Internet, using SSH
Web/ACCEPT     net             $FW

#Network Time protocol
NTP/ACCEPT     net             $FW


#Network Time protocol
NTP/ACCEPT     net             $FW

#
#       Accept DNS connections from the firewall to the network
#
DNS(ACCEPT)     $FW             net

 

So we just created rules that over-ride the default policy of blocking all traffic from the net zone to our $FW machine. So we allowed ICMP traffic and we allowed web access plus SSH access to our firewalled server machine. Make note we placed our rules under the section called "SECTION NEW", meaning for newly created connections these rules would apply. Actually the SSH and Web rules are the only ones that are needed for my server.

 

Step 6 : Enabling startup

With the configuration out of the way, you need to now enable your shorewall configurations. For that goto "/etc/shorewall/shorewall.conf" and edit the property "STARTUP_ENABLED=No" to say "STARTUP_ENABLED=Yes".

 

Step 7 : Firing it all up

Before we start up shorewall lets just list what iptables output for us:

root $ : 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 

Starting it up

The above means the firewall is off basically. So lets fireup our file wall now and again see what the above command produces :

root $ : service shorewall start
Starting "Shorewall firewall": done.

root $ : iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
net2fw     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
Drop       all  --  anywhere             anywhere
LOG        all  --  anywhere             anywhere             LOG level info prefix "Shorewall:INPUT:DROP:"
DROP       all  --  anywhere             anywhere

Chain FORWARD (policy DROP)
target     prot opt source               destination
Drop       all  --  anywhere             anywhere
LOG        all  --  anywhere             anywhere             LOG level info prefix "Shorewall:FORWARD:DROP:"
DROP       all  --  anywhere             anywhere

Chain OUTPUT (policy DROP)
target     prot opt source               destination
fw2net     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
Drop       all  --  anywhere             anywhere
LOG        all  --  anywhere             anywhere             LOG level info prefix "Shorewall:OUTPUT:DROP:"
DROP       all  --  anywhere             anywhere

Chain Broadcast (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             ADDRTYPE match dst-type BROADCAST
DROP       all  --  anywhere             anywhere             ADDRTYPE match dst-type MULTICAST
DROP       all  --  anywhere             anywhere             ADDRTYPE match dst-type ANYCAST
DROP       all  --  anywhere             base-address.mcast.net/4

Chain Drop (4 references)
target     prot opt source               destination
           all  --  anywhere             anywhere
reject     tcp  --  anywhere             anywhere             tcp dpt:auth /* Auth */
Broadcast  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere             icmp fragmentation-needed /* Needed ICMP types */
ACCEPT     icmp --  anywhere             anywhere             icmp time-exceeded /* Needed ICMP types */
Invalid    all  --  anywhere             anywhere
DROP       udp  --  anywhere             anywhere             multiport dports loc-srv,microsoft-ds /* SMB */
DROP       udp  --  anywhere             anywhere             udp dpts:netbios-ns:netbios-ssn /* SMB */
DROP       udp  --  anywhere             anywhere             udp spt:netbios-ns dpts:1024:65535 /* SMB */
DROP       tcp  --  anywhere             anywhere             multiport dports loc-srv,netbios-ssn,microsoft-ds /* SMB */
DROP       udp  --  anywhere             anywhere             udp dpt:1900 /* UPnP */
NotSyn     tcp  --  anywhere             anywhere
DROP       udp  --  anywhere             anywhere             udp spt:domain /* Late DNS Replies */

Chain Invalid (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             ctstate INVALID

Chain NotSyn (1 references)
target     prot opt source               destination
DROP       tcp  --  anywhere             anywhere             tcpflags:! FIN,SYN,RST,ACK/SYN

Chain dynamic (1 references)
target     prot opt source               destination

Chain fw2net (1 references)
target     prot opt source               destination
ACCEPT     udp  --  anywhere             anywhere             udp dpts:bootps:bootpc
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain /* DNS */
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain /* DNS */
ACCEPT     all  --  anywhere             anywhere

Chain logdrop (0 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere

Chain logflags (5 references)
target     prot opt source               destination
LOG        all  --  anywhere             anywhere             LOG level info ip-options prefix "Shorewall:logflags:DROP:"
DROP       all  --  anywhere             anywhere

Chain logreject (0 references)
target     prot opt source               destination
reject     all  --  anywhere             anywhere

Chain net2fw (1 references)
target     prot opt source               destination
dynamic    all  --  anywhere             anywhere             ctstate INVALID,NEW
smurfs     all  --  anywhere             anywhere             ctstate INVALID,NEW
ACCEPT     udp  --  anywhere             anywhere             udp dpts:bootps:bootpc
tcpflags   tcp  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DROP       icmp --  anywhere             anywhere             icmp echo-request /* Ping */
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh /* SSH */
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http /* Web */
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https /* Web */
ACCEPT     udp  --  anywhere             anywhere             udp dpt:ntp /* NTP */
Drop       all  --  anywhere             anywhere
LOG        all  --  anywhere             anywhere             LOG level info prefix "Shorewall:net2fw:DROP:"
DROP       all  --  anywhere             anywhere

Chain reject (2 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             ADDRTYPE match src-type BROADCAST
DROP       all  --  base-address.mcast.net/4  anywhere
DROP       igmp --  anywhere             anywhere
REJECT     tcp  --  anywhere             anywhere             reject-with tcp-reset
REJECT     udp  --  anywhere             anywhere             reject-with icmp-port-unreachable
REJECT     icmp --  anywhere             anywhere             reject-with icmp-host-unreachable
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain shorewall (0 references)
target     prot opt source               destination

Chain smurflog (2 references)
target     prot opt source               destination
LOG        all  --  anywhere             anywhere             LOG level info prefix "Shorewall:smurfs:DROP:"
DROP       all  --  anywhere             anywhere

Chain smurfs (1 references)
target     prot opt source               destination
RETURN     all  --  default              anywhere
smurflog   all  --  anywhere             anywhere            [goto]  ADDRTYPE match src-type BROADCAST
smurflog   all  --  base-address.mcast.net/4  anywhere            [goto]

Chain tcpflags (1 references)
target     prot opt source               destination
logflags   tcp  --  anywhere             anywhere            [goto]  tcpflags: FIN,SYN,RST,PSH,ACK,URG/FIN,PSH,URG
logflags   tcp  --  anywhere             anywhere            [goto]  tcpflags: FIN,SYN,RST,PSH,ACK,URG/NONE
logflags   tcp  --  anywhere             anywhere            [goto]  tcpflags: SYN,RST/SYN,RST
logflags   tcp  --  anywhere             anywhere            [goto]  tcpflags: FIN,SYN/FIN,SYN
logflags   tcp  --  anywhere             anywhere            [goto]  tcp spt:0flags: FIN,SYN,RST,ACK/SYN

 

Stoping it

 

For completions sake, just to show you, if you want to turn the firewall off at some point in time, you could do it as below:

$ root : service shorewall stop
Stopping "Shorewall firewall": done.


Summary

So shorewall generated for me a whooping amount of rules that I hardly would have imagined to create by hand using ufw. Maybe ufw does do that in backend by default. But I am not comparing these tools. To each his own. Shorewall with a minimal set of configurations was able to produce a handful of rules that seemed to work for me. How I figured these are work for me, I did a test. But thats another article and you can read about it here.

 

Update

  • Notice in rules section I added the ntp rule later on so that our server can sync its time on startup.
  • Additionally the rule to make DNS queries from firewall to net zone.

 

References

  • Also after some more reading, I found that this shorewall document shows exactly what I have implemented here.

Tags:

Top level category:

Add new comment