Translation(s): none

Version 2.6 of the Linux kernel uses iptables to provide its firewall facilities. For more information on iptables, see Iptables is a quite robust and functional and will form the core of your machine's firewall and routing functionality. Iptables is installed by default as part of the minimal Debian installation, so there's no further installation needed.

Iptables is very powerful, but can be difficult to configure. Shorewall tries to make that easier. To start, install the shorewall package:

Firewall:~# aptitude update
Firewall:~# aptitude install shorewall

Shorewall installation will warn you that the program will not start unless you change the /etc/default/shorewall file.

Firewall:~# nano -w /etc/default/shorewall


startup = 0


startup = 1

save, and exit.

On Stretch, at least for now, 2017-06-20, you need to run:

systemctl enable shorewall

instead. The startup = setting in /etc/default/shorewall is ignored. Test.

Shorewall files are stored in two separate places:

In the Debian package version of shorewall, /etc/shorewall is rather empty. Default configuration files in /usr/share/doc/shorewall/default-config (in Wheezy, there are several sample configurations, found in /usr/share/doc/shorewall/examples) if you choose to use them. However, for this ?HowTo we are going to create them from scratch instead of copying those files over.

Organizing your Network with Zones

Shorewall uses zones as a way of defining different portions of our network. Our simple example will have three zones: internet, dmz, and local. Shorewall can easily be extended to support many more zones such as a DMZ or a VPN zone. This configuration is performed in /etc/shorewall/zones:

Firewall:~# nano -w /etc/shorewall/zones

All we have to do here is name our zones and specify their IP version types:

fw firewall
net ipv4
dmz ipv4
loc ipv4

The first one is a special zone that represents your machine, and thus uses "firewall" as its type. The other three zones are for our three network interfaces. One for the Net, one for our DMZ, and one for our local network. That's it, save and exit.

Associating Zones with Interfaces

Next, we have to add our physical interfaces. This is done via /etc/shorewall/interfaces:

Firewall:~# nano -w /etc/shorewall/interfaces

Now we have to associate our zones with their respective ethernet interface. In this example our "eth0" interface is for our "net" zone, our "eth1" is for our DMZ, and "eth2" interface is connected to our "loc" zone. We are also going to set them to automatically detect the network settings, and also make it so that they will never block dhcp traffic.

net eth0 detect dhcp,routefilter,tcpflags
dmz eth1 detect dhcp
loc eth2 detect dhcp

Notice that there are a few extra options on the "net" zone. These options help filter out some of the invalid packets and garbage we see on the Internet. Interface configuration is done, so save and close the file.

Creating Default Policies

Now comes the ever important firewall policy. The policy forms the basis for how all traffic on our network will be treated. This is not for fine grained control, we'll get to that later. This just sets the baseline actions for a zone.

Firewall:~# nano -w /etc/shorewall/policy

Here are the default policies we are going to use for our example. They are made up of three columns: Source Zone, Destination Zone, and Action.

net all DROP
dmz all REJECT
loc all REJECT
fw all ACCEPT
all all REJECT

The first line says we are going to drop all traffic from the Internet. We don't trust external traffic from the internet, so this should make sense. When we see internet traffic that doesn't match any specific rules (later), we want it DROPPED. Now, whats the difference between REJECT and DROP? REJECT will let the person know that their traffic is not allow. The DROP action simply throws the traffic in the bin bucket (you know, the garbage can) and doesn't bother telling the person. That makes it a little harder for an attacker to figure out how your firewall is configured.

The second and third lines say that we are going to REJECT all traffic coming from our local network and our DMZ, no matter where its headed. This might sound funny, as most people trust their local traffic. In fact, most individuals and companies would configure this with an ACCEPT action. But I am a firm believer that if you are going to learn how to secure your network, don't only do it half way. And remember, most attacks come from inside your network. But keep in mind, if you do not add rules later on for every protocol you want your workstations to use, their traffic will kindly rejected. For example, if you want your users to surf the web, you are going to have to create rules allowing them to use HTTP, HTTPS, and DNS.

The forth rule is for the firewall machine itself, which is "fw" by default. You have the option of adding that to the policy as well. It says all traffic generated by the machine is allowed. You can also leave this out and configure a more strict rule (in the rules file) to only allow certain traffic, but keep in mind if you do not add some type of policy or rule, you will not be able to use any network based features of the system. For example apt will no longer work if fw traffic is not ACCEPTed. The rest of this tutorial assumes this option is added.

And finally, any traffic not matching the above is rejected. This should always be added as the last rule, just in case you forgot a zone.

Creating Rules (where you will spend most your time in the future!)

So, we are going to DROP or REJECT everything except traffic originating from our firewall. I guess that means that we need to create some exceptions and specify what we do want to allow. These are called rules, and configure in the /etc/shorewall/rules file.

Firewall:~# nano -w /etc/shorewall/rules

Lets add the following rules:

ACCEPT loc net tcp 80,443
ACCEPT loc fw udp 53
ACCEPT all dmz tcp 80

Ok, line one says we are going to accept all HTTP(80) and HTTPS(443) traffic from our local network to the internet. Line two allows us to do DNS lookups to our firewall (assuming that you setup a DNS server there). And line three allows everyone (both internet users and local users) to connect to the webserver in our DMZ.

Notice that this configuration only allows the servers in your DMZ to serve up web pages. They can't do anything else, not even surf the web. While this is a much more secure setting, you may need to add a rule so you can download updates to the servers. If so, I would recommend limiting it to a specific IP if possible. Add the following line if you want your servers to be able to download updates from

ACCEPT dmz net: tcp 80

If the DNS server used by the local network is not located on the firewall but on the web, line two in the rules example above can be replaced with the following:

DNS(ACCEPT) loc net

This will allow DNS requests to be sent from the local network to the web.

Remember, the more we restrict the traffic through our firewall, the safer you are. Take a look the default rules file in your documentation directory for more examples:

Firewall:~# less /usr/share/doc/shorewall/default-config/rules


Our system uses PAT (port address translation). This is featured as the default on most small home and SOHO firewall devices. Basically, PAT allows our router to translate between our external IP address (on eth0) and all our internal addresses (connecting to eth1). This feature is often referred to (incorrectly) as NAT, or Network Address Translation. Please note that PAT/NAT are not required to operate a firewall, but you will have to set up alternative methods of routing instead. In Shorewall, PAT is configured in /etc/shorewall/masq:

Firewall:~# nano -w /etc/shorewall/masq

We have to tell shorewall that we want all traffic coming from inside the network (on eth1) to be translated out through the interface on eth0). We do this simply by specifying the interfaces:

eth0 eth1
eth0 eth2

It is important to note that as always, there are more advanced possibilities here than what we're the documentation! Also, don't be fooled by /etc/shorewall/nat. This file is for providing Network Address Translation, which translates internal IP addresses to external IP addresses directly, rather than using a single external address and translating the ports. I recommend Wikipedia and Google if you want to learn more.

Turning on Forwarding

Finally we get to the last necessary file, /etc/shorewall/shorewall.conf. This file manages global shorewall options, and you should read it through completely.

Firewall:~# nano -w /etc/shorewall/shorewall.conf

We need to find the section of the file that talks about "IP_FORWARDING" and change it from "Off" to "On". If you don't, your packets won't be able to get from one interface to the other.


Read through the whole file and customize it as you wish. When you're done, save your work. That should complete the basic firewall configuration. You should run "shorewall check" to see if you've made any typos. It won't catch all possible errors, but it helps:

Checking Your Configs and Starting Shorewall

Firewall:~# shorewall check

If you get "Configuration Validated" you can go ahead and start Shorewall:

Firewall:~# /etc/init.d/shorewall start

Note that Shorewall should run automatically every time the system boots, so you won't have to do it manually. If you want to change your settings without rebooting, just use "restart" instead of start in the above command.