Linux

Stuff about Linux

A Simple Shorewall Firewall

I've built Linux / IPTables based routers / firewalls many times over the years. I figured it was probably time I documented building a simple SOHO solution.

I use Shorewall because it makes dealing with IPTables simple. As much as I like IPTables its rule syntax is f**king awful. Shorewall offers a layer of abstraction on IPTables and makes common use cases trivial. It offers more features than other solutions such a ufw.

For the sake of this example, our Linux box has the following network interfaces:

  • ppp0 - the intertubes
  • eth0 - our private internal network
  • eth1 - our public guest network
  • tun0 - our OpenVPN server

Core shorewall config

In the main shorewall configuration file (/etc/shorewall/shorewall.conf), ensure the following properties are set as follows:

STARTUP_ENABLED=Yes
IP_FORWARDING=On

Setting up zones

Shorewall's world is all about zones, a zone is merely a network that we are going to firewall between. In this example we have the following zones:

  • net - the internet
  • loc - our local network
  • gst - our guest network
  • vpn - our VPN network

The zones configuration file (/etc/shorewall/zones) will look like:

#
# Shorewall version 4 - Zones File
#
# For information about this file, type "man shorewall-zones"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-zones.html
#
###############################################################################
#ZONE   TYPE            OPTIONS         IN                      OUT
#                                       OPTIONS                 OPTIONS
fw       firewall
net      ipv4
loc      ipv4
gst      ipv4
vpn      ipv4

Note that the fw zone means this local machine.

Now we have zones defined, we need to assign our interfaces to our zones. The file (/etc/shorewall/interfaces) configures these assignments and will look like:

#
# Shorewall version 4 - Interfaces File
#
# For information about entries in this file, type "man shorewall-interfaces"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-interfaces.html
#
###############################################################################
#ZONE   INTERFACE       BROADCAST       OPTIONS
net     ppp0            detect
loc     eth0            detect
gst     eth1            detect
vpn     tun0            detect

Setting up policies

Policies specify the default rule action for traffic between zones. In our example by default we will:

  • permit traffic from the local network to the internet
  • permit traffic from the guest network to the internet
  • permit traffic from the vpn network to the local network

The file (/etc/shorewall/policy) will look like:

#
# Shorewall version 4 - Policy File
#
# For information about entries in this file, type "man shorewall-policy"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-policy.html
#
###############################################################################
#SOURCE DEST    POLICY          LOG     LIMIT:          CONNLIMIT:
#                               LEVEL   BURST           MASK
loc     net     ACCEPT
gst     net     ACCEPT
vpn     loc     ACCEPT
fw      all     ACCEPT
net     all     DROP
all     all     REJECT

Note that all is a pseudo-zone which means any zone, as such the last line means that by default traffic between zones will be rejected.

Setting up rules

Rules are exceptions to policy, defining specific traffic which will be allowed through. In this example, we are going to permit ICMP Ping and SSH traffic from any network to access the local machine. We will also forward ports 80 and 443 into a specific server in the local network

The rules configuration file (/etc/shorewall/rules) will look like:

#
# Shorewall version 4 - Rules File
#
# For information on the settings in this file, type "man shorewall-rules"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-rules.html
#
######################################################################################################################################################################################
#ACTION         SOURCE                  DEST                    PROTO   DEST          SOURCE            ORIGINAL        RATE       USER/    MARK    CONNLIMIT       TIME         HEADERS         SWITCH
#                                                                       PORT          PORT(S)           DEST            LIMIT      GROUP
#SECTION ALL
#SECTION ESTABLISHED
#SECTION RELATED
SECTION NEW
ACCEPT          all                     fw                      tcp     22            -                 -
ACCEPT          all                     fw                      icmp    0,8           -                 -
DNAT:info       net                     loc:172.30.14.187       tcp     80,443        -                 -

Setting up NAT

Due to the joys of IPv4, we need to masquerade local traffic to access the internet. The shorewall masq configuration file (/etc/shorewall/masq) will look like:

#
# Shorewall version 4 - Masq file
#
# For information about entries in this file, type "man shorewall-masq"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-masq.html
#
#############################################################################################
#INTERFACE:DEST         SOURCE          ADDRESS         PROTO   PORT(S) IPSEC   MARK    USER/
#                                                                                       GROUP
ppp0                    172.30.0.0/16

Note the specified source network matches traffic from our local and guest networks.

Thats all folks

It reall is that straight forward, simply run shorewall restart to make the new ruleset active

Setting the CPUID of a XEN guest

After some reading around I've discovered it is possible to configure the CPU vendor and model information that a XEN guest sees.

Most Linux sysadmins will be familiar with cat /proc/cpuinfo to get information about the systems processors. This gives information about the CPU vendor, model and features. For example my desktop gives:

[cellis@cedesktop ~]$ cat /proc/cpuinfo 
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 15
model           : 67
model name      : AMD Athlon(tm) 64 X2 Dual Core Processor 5200+
- snip -

This information is actually exposed via cpuid instruction . This instruction takes a command in the EAX register and populates the EAX, EBX, ECX and EDX registers with the requested data.

If EAX is set to zero, the CPU vendor string is returned. This is a 12 byte ASCII string. Which is stored in the EBX, EDX, ECX (that is certainly logical, I suspect a hangup from the circuit complexity).

The CPU model string is a little more complex, it is a 48 byte ASCII string.

This string is obtained by executing the cpuid instruction 3 times, with EAX set to: 0x80000002, 0x80000003 and 0x80000004.

XEN has the cpuid config option , which defines the values of EAX, EBX, ECX and EDX for specific values of EAX.

Lets take the following XEN config:

cpuid=['0:eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,ebx=01110010011101000110111001001001, 
ecx=00000000000000000000000000000000,edx=00000000011110100110100101100010']

This causes the XEN guest to see the CPU vendor string 'Intrbiz', by providing the cpuid register values when EAX = 0.

As such, my XEN VM now reports:

xenvm1:~ # cat /proc/cpuinfo
processor       : 0
vendor_id       : Intrbiz
cpu family      : 0
model           : 0
model name      : Intrbiz XEN virtual CPU
stepping        : 0

The hard part of setting this, is working out the values of the registers. It takes time to convert the text to binary and get the orderings correct.

Instead, you can generate the XEN config right here:

Simply enter your desired CPU vendor and model string and the XEN config will be generated

CPU Vendor: Model:


							

Leaping CPU

As have many people around the world, I've found a number of my computers having high CPU load since the Leap Second.

Specifically I've found, the following to be using well over 100% CPU usage:

  • Java
  • Ruby
  • MySQL
  • Firefox
  • Akonadi (Uses MySQL)

Researching the issue, it seems there is an issue in the Linux kernel affecting futexes with the Leap Second. This is a new issue, not to be confused with other issues which have previously been patched. Futexes are a form of userspace lock, which are used heavily by the likes of Java, etc. This flaw seems to be in essentially every kernel since 2.6.22.

Note: This is a kernel bug, it is not a bug in Java or any other application.

A patch is already on the LKML: [PATCH] [RFC] Potential fix for leapsecond caused futex related load spikes

There is a work around for the issue, which is to simply set the date on the server, using the following:

date `date +\"%m%d%H%M%C%y.%S\"`

or (if you prefer)

reboot

Setting the time certainly sorted my problems, that took Firefox from 163% CPU to 1% and similar for Ruby and Java. Note that just restarting the Java or whatever process will not solve the problem.

This is because setting the system time, will call a kernel function: clock_was_set() ensuring the hrtimer subsystem is correct. Futexes often use the hrtimer subsystem in a loop, these sub-second waits are expiring immediately, causing high CPU usage. More detail