This is part 4 of the router series; part 1, part 2 and part 3 are also available
Contents
Conventions
I’m once again reminding you of the conventions used in this series. If you
followed the guide up to now you should already know that ppp0
(or
eth0
if you’re not using PPP) is the internet-facing interface, whereas
eth1
is the LAN-facing one. We will use home.net
as our domain and
router
as the hostname of the gateway.
Introduction
Everything discussed on part 3 dealt with the configuration of the interfaces on the router itself. In order to have your router actually do anything you will need to set up a functional firewall especially since the ISP has most probably shoved you behind a single IPv4 address. In order to allow the LAN clients to share this address we have to enable masquerading which performs the Address Translation (the AT in NAT) between the external address and the private addresses of the local network. In addition to that we will configure some common rules and perform some port forwarding for good measure.
Although raw iptables rules are feasible for a stateful firewall the verbosity of said rules makes them somewhat cumbersome to manage. So for this guide I am using Shorewall which is an abstraction layer above iptables. There are many other options such as nftables, ufw and FireHOL if Shorewall is not really appealing to you. In fact I might have actually tried FireHOL if I was aware of it before setting up my system with Shorewall. In any case I have found Shorewall to strike a good balance between ease of configuration, security and features.
Shorewall has separate executables for IPv4 and IPv6 built around a common
core. This is why in most distributions Shorewall is split into three packages:
shorewall-core
, shorewall
and shorewall6
. There is a very
comprehensive guide on their website
on how to build a two-interface firewall which I recommend to read to get an
understanding of what we are trying to achieve. I will illustrate some basic
configuration points but these are in no case are a replacement for the proper
documentation of Shorewall. The two-interface configuration is one of the most
common encountered and it should be included as a guide in the Shorewall
documentation package. A shorewall configuration comprises of a series of
configuration files the most important of which are:
shorewall.conf
: General Shorewall configuration (man shorewall.conf
)interfaces
: List of involved interfaces (man shorewall-interfaces
)policy
: Firewall policy configuration, ie. default rules (man shorewall-policy
)rules
: Firewall rules, open ports and port forwarding (man shorewall-rules
)snat
: SNAT configuration; used for masquerading (man shorewall-snat
)zones
: Network zones definition; defines the conceptual zones of the network topology, such as the firewall zone (fw), the internet zone (net) or the LAN (loc) (man shorewall-zones
)
There are a series of other files as well that deal with QoS and priority
queues as well as finer tuning of the firewall (startup scripts etc). Since we
won’t use them you can just copy the empty templates from the shorewall
documentation usually found in
/usr/share/doc/shorewall/Samples/two-interfaces
.
IPv4 and NAT
I will focus first on the IPv4 firewall, the configuration of which resides in
/etc/shorewall/
.
We will start with the main configuration file shorewall.conf
. This is a very
long file with all the basic settings of Shorewall so I will list the values
that you should at the absolute minimum edit. Shorewall provides very sane
defaults for the rest.
IPv4 Main configuration file: shorewall.conf
# This must be set to Yes to allow the registration of shorewall as a boot
# service
STARTUP_ENABLED=Yes
# Level of verbosity; unless you are debugging your firewall anything else
# above 1 is overkill
VERBOSITY=1
# 7 - debug (Debug-level messages)
# 6 - info (Informational)
# 5 - notice (Normal but significant Condition)
# 4 - warning (Warning Condition)
# 3 - err (Error Condition)
# 2 - crit (Critical Conditions)
# 1 - alert (must be handled immediately)
# 0 - emerg (System is unusable)
LOG_LEVEL="info"
# This is set from sysctl.conf so tell shorewall to leave that as is
# Set it to "On" if you encounter problems.
IP_FORWARDING=Keep
IPv4 Zone definition: zones
This is the zone definition file. We define three zones the firewall itself
(fw
), internet (net
) and LAN (loc
), so go ahead and append the following.
Please note that you must also keep the headers of the file intact to ensure
proper parsing
#ZONE TYPE OPTIONS IN_OPTIONS OUT_OPTIONS
fw firewall
net ipv4
loc ipv4
IPv4 Interface definition: interfaces
Here we assign the interface to their respective zones along with some extra
options to enhance
the security of the firewall. If you run a DHCP server in your network (you
most definitely will) you must add the dhcp
option to the interface connected
to the LAN. Obviously if you are not using PPP you will need to replace ppp0
with the actual external interface (probably eth0
).
#ZONE INTERFACE OPTIONS
net ppp0 tcpflags,nosmurfs,routefilter,logmartians,sourceroute=0
loc eth1 dhcp,tcpflags,nosmurfs,routefilter,logmartians
IPv4 Default policy: policy
These are the default rules of the firewall (the iptables -P
equivalent).
The last rule must be always present.
#SOURCE DEST POLICY LOGLEVEL RATE CONNLIMIT
loc net ACCEPT
fw net ACCEPT
fw loc ACCEPT
net all DROP $LOG_LEVEL
# This line must always be present
all all REJECT $LOG_LEVEL
In a nutshell we allow all outbound traffic from both the LAN (loc -> net
)
and the router itself (fw -> net
). Additionally we allow traffic flowing from
the router to the LAN (fw -> loc
). Finally we drop all incoming traffic (net
-> all
) and log it according to the LOG_LEVEL
define in shorewall.conf
.
IPv4 Network Address Translation: snat
SNAT is only relevant to IPv4 since we most probably only have one address
available. In this particular case we transform all traffic originating from
192.168.1.0/24
(our LAN) to the address of the ppp0
interface which is the
IP address assigned to us from our ISP.
#ACTION SOURCE DEST PROTO PORT IPSEC MARK USER SWITCH ORIGDEST PROBABILITY
MASQUERADE 192.168.1.0/24 ppp0
If you have more than one IP address and you want them to be assigned to
particular unicast addresses you will have to add additional SNAT
rules (not
MASQUERADE
). See the relevant
documentation for more
details on that.
IPv4 Firewall rules: rules
The final file contains the open port policy for your both your LAN hosts and the router itself. The format of the rules are either
SERVICE(ACTION) SOURCE DESTINATION PROTOCOL
or
ACTION SOURCE DESTINATION PROTOCOL PORT
Here is a minimal set of annotated rules. As always there is very comprehensive documentation on the possible rule incantations on the shorewall website
#ACTION SOURCE DEST PROTO DPORT SPORT ORIGDEST RATE USER MARK CONNLIMIT TIME HEADERS SWITCH HELPER
# These must always be in that order
?SECTION ALL
?SECTION ESTABLISHED
?SECTION RELATED
?SECTION INVALID
?SECTION UNTRACKED
# Rules are applied to NEW connections. Already established connections are
# automatically ACCEPTed
?SECTION NEW
# Drop invalid TCP packets originating from the internet
Invalid(DROP) net all tcp
# Allow outbound DNS requests
DNS(ACCEPT) $FW net
DNS(ACCEPT) loc $FW
# Allow SSH connections from the local network into the router
SSH(ACCEPT) loc $FW
# Same with ping
Ping(ACCEPT) loc $FW
# And with NTP requests
NTP(ACCEPT) loc $FW
# DROP all pings from the internet into our LAN
Ping(DROP) net $FW
Ping(DROP) net loc
# ACCEPT ICMP packets from the router to both the LAN and the internet
ACCEPT $FW loc icmp
ACCEPT $FW net icmp
# Port forwarding (DNAT)
# Forward incoming connections to port 12345 to the same port of host 192.168.1.6
DNAT net loc:192.168.1.6:12345 tcp 12345
# Forward incoming connections to port 9912 to port 54321 of host 192.168.1.9
DNAT net loc:192.168.1.9:54321 tcp 9912
IPv6 Firewall
The IPv6 configuration lies in /etc/shorewall6
and almost everything from the
IPv4 ruleset applies here as well with some exceptions.
IPv6 Main configuration file: shorewall.conf
There are no particular differences between the IPv4 and IPv6 cases. Just copy the file over!
IPv6 Zone definition: zones
Just copy zones
file from /etc/shorewall
and replace all instances of
ipv4
with ipv6
. Done!
IPv6 Interface definition: interfaces
Some of the options from /etc/shorewall
do not apply here and you will need
to add forward=1
to both interfaces resulting in the following file
#ZONE INTERFACE OPTIONS
net ppp0 tcpflags,forward=1,sourceroute=0
loc eth1 dhcp,tcpflags,forward=1
Note that dhcp
on eth1
is not really necessary if you are using
autoconfiguration for your hosts. For the sake of completeness I will show how
to setup DHCPv6 later on so you might as well leave it there for the time
being.
IPv6 Default policy: policy
Exactly the same as in IPv4. Just copy the file over.
IPv6 Network address translation: snat
Technically you can do NAT on IPv6 although there is no point to do so as you
probably have a bazillion available address anyway. So just leave snat
empty.
IPv6 Firewall rules: rules
Rule configuration is pretty much the same as in IPv4 with two notable exceptions
- You must allow
ipv6-icmp
packets from$FW
to bothloc
andnet
because otherwise autoconfiguration of IPv6 addresses will not work. So remove theicmp
rules from your ruleset and replace them withipv6-icmp
. - There is no need for port forward as we have real internet routable
addresses for all our hosts (isn’t that marvelous!?). Since you are not
doing port forwarding you just need to allow traffic from the net into your
local network for the ports of your preference. A rule like
ACCEPT net loc tcp 9912
will allow all connections to port 9912 on your LAN from the internet. You can limit these to the hosts of your preference by adding the:[IPv6Address]
suffix toloc
, for instanceloc:[2001:db8::3]
.
Accessing your modem’s configuration
As a final remark, if you are using an xDSL or cable connection you might have
noticed that you can no longer access your modem’s configuration web page (or
ssh server for that matter). This is because, if you followed this guide up to
now, it is residing on a different subnet than yours. There are some minimal
alterations that must be made to shorewall configuration to allow for such
functionality. If you look back at part 3 you might
remember that we assigned the address 192.168.0.2
to the interface connected
to the modem (eth0
). I will assume that your modem is in the same subnet,
for example 192.168.0.100
. We need to edit fice files zones
, interfaces
,
snat
, policy
, rules
. As the modem is in a different subnet we will need
to define a new corresponding zone; let’s call it modem
.
#ZONE TYPE OPTIONS IN_OPTIONS OUT_OPTIONS
modem ipv4
Then we declare the interface corresponding to this zone
#ZONE INTERFACE OPTIONS
modem eth0
Since we defined a new zone we need to setup a default policy for that zone.
The only required policy is to allow traffic from within the firewall to the
modem. So add the following to policy
.
#SOURCE DEST POLICY LOGLEVEL RATE CONNLIMIT
fw modem ACCEPT
If you need full access from the local network (loc
) to the modem you can
additionally append:
loc modem ACCEPT
Personally I feel that it might be better to limit access to your modem to a limited number of computers, especially since the security record of most network equipment aimed at consumers leaves a lot to be desired. But this is up to you!
As the modem probably won’t accept connections outside its subnet we need a
SNAT rule to do the translation from 192.168.1.0/24
to 192.168.0.0/24
. So
add the following to snat
SNAT(192.168.0.2) 192.168.1.0/24 eth0:192.168.0.1 tcp
The above will translate addresses originating from 192.168.1.0/24
to
192.168.0.0/24
through the eth0
interface that has the address
192.168.0.1
in that subnet. I’ve added tcp
to limit access to TCP
connections only but feel free to use what you like.
If you don’t need to restrict access to your modem you can stop here. Restart
shorewall and point your browser to your modem’s webpage. Should you need more
granular control you will need to additionally edit rules
to specify IPs or
MAC addresses that have access to the modem
zone (since by default such
requests will be REJECT
ed). In the example below we will be allowing SSH
access to the computer with IP 192.168.1.8
and web access to the computer
with MAC address AA:BB:CC:DD:EE:FF
. Adjust to your needs!
SSH(ACCEPT) loc:192.168.18 modem
HTTP(ACCEPT) loc:~aa-bb-cc-dd-ee-ff modem
Please note that MAC addresses must be prefixed with ~
and separated by -
instead of :
. Have fun!
This is the end of part 4. Again if you are following this guide with Alpine
linux this is probably a good time to save your settings. Go ahead and lbu
commit
them. You can then proceed onto part 5 where we
will setup a DHCP server and a DNS caching server using dnsmasq
.