Setting up an iptables firewall
This document consists of two parts. The first is setting up a firewall (using iptables) on the HN, which will restrict traffic to the containers. The effect would emulate, as far as the containers and their customers are concerned, an external hardware firewall controlled by the sysadmin. The second is setting up a firewall that protects the HN itself but still allows traffic to the containers, thus allowing individual containers to define their own iptables.
While the firewalls shown here can be accomplished using iptables manually (or using Fedora core's iptables service), the methods presented here are especially modular and easy to modify. This is important when you have 20+ containers and a lot of other things to be doing...
The scripts and pathnames given here are for Fedora Core 6, though they can probably be applied to most similar SysV-like systems with little modification.
Contents
A little background
On our systems, we use the HN to provide privileged services which are not appropriate for access by the containers. For example, the HN acts as a backup server, runs Nagios for health monitoring, has a webserver for managing the 3ware RAID controller, etc. The containers are leased to customers, who can't entirely be trusted, especially if they get hacked. As such, our scenario is one in which the HN must be protected from all access (even from the containers) except for a few trusted hosts (e.g. my home-office).
The exception to this is the nameserver, which we want open to the world. We use it as a caching nameserver for our containers and also to host DNS for a few customer domain.
Simple firewall configuration independent to IP addresses: vzfirewall
Vzfirewall
tool allows you to open/close ports for incoming connections with no dependencies to foreign IP addresses. E.g. you may allow a hostname release.prod.example.com
to connect to port 5432 of VE 1234 and leave all other ports closed by modifying 1234.conf
file adding multiline FIREWALL
directive into it:
... PRIVVMPAGES="300000:300000" HOSTNAME="example.com" ... FIREWALL=" ... # Allow access to PostgreSQL port only from release.prod # and release.test machines. You may use domain names here. [5432] release.prod.example.com release.test.example.com ... "
You must then run vzfirewall -a
on your hardware node to apply changes made in *.conf
.
Note that it is recommended to use hostnames instead of IP addresses here, so the configuration is persistent for VE movements to different IP-address: you just need to run vzfirewall -a
again after movement. It is also reboot-safe, because applied to /etc/sysconfig/iptables
(at RHEL systems).
Vzfirewall and its documentation are available at http://en.dklab.ru/lib/dklab_vzfirewall/.
An alternative from the author of Shorewall
For those who might find the solution provided in this wiki article unsatisfactory (for whatever reason), the creator of Shorewall (Tom Eastep) has written a nice article explaining how to use Shorewall on an OpenVZ host node to manage the host node, containers, and more... with quite a complex setup as an example. The article IS NOT an introduction to Shorewall for beginners, so some pre-existing knowledge and understanding of Shorewall may be required.
Shorewall and OpenVZ by Tom Eastep - http://www.shorewall.net/OpenVZ.html
See also this OpenVZ Forum posting - http://forum.openvz.org/index.php?t=msg&goto=16406&
You've got it in one. Couldn't have put it betetr.
Setting up a firewall that allows per-container configuration
This setup configures iptables on the HN to disallow access to all hosts, including the containers. However, it allows all traffic into the containers so they may define their own iptables rules and therefore manage their own firewall.
iptables -P FORWARD ACCEPT iptables -F FORWARD
This will remove all rules for the FORWARD chain so all packets can pass back and forth between containers and the outside world.
If you want to use a firewall inside a container, please load these modules BEFORE starting the container:
modprobe xt_tcpudp modprobe ip_conntrack
If you do not, you will get an error like this: "iptables: No chain/target/match by that name"
If you want to use stateful firewall rules (and you should!) you will also need to make sure that 'ipt_state' is in the 'IPTABLES' option in your vz.conf file:
IPTABLES="ipt_REJECT ipt_tos ipt_limit ipt_multiport iptable_filter iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length ipt_state"
Also make sure the 'xt_state' module is loaded on the host:
modprobe xt_state