Latest revision |
Your text |
Line 1: |
Line 1: |
− | 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. | + | 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... | | 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... |
Line 11: |
Line 11: |
| 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. | | 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 of IP addresses: vzfirewall == | + | == Simple firewall configuration independent to IP addresses: vzfirewall == |
| | | |
− | <code>Vzfirewall</code> tool allows you to open/close ports for incoming connections with no dependencies to foreign IP addresses. E.g. you may allow a hostname <code>release.prod.example.com</code> to connect to port 5432 of VE 1234 and leave all other ports closed by modifying <code>1234.conf</code> file adding multiline <code>FIREWALL</code> directives into it: | + | <code>Vzfirewall</code> tool allows you to open/close ports for incoming connections with no dependencies to foreign IP addresses. E.g. you may allow a hostname <code>release.prod.example.com</code> to connect to port 5432 of VE 1234 and leave all other ports closed by modifying <code>1234.conf</code> file adding multiline <code>FIREWALL</code> directive into it: |
| | | |
| <pre> | | <pre> |
Line 33: |
Line 33: |
| You must then run <code>vzfirewall -a</code> on your hardware node to apply changes made in <code>*.conf</code>. | | You must then run <code>vzfirewall -a</code> on your hardware node to apply changes made in <code>*.conf</code>. |
| | | |
− | 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 <code>vzfirewall -a</code> again after movement. It is also reboot-safe, as the rules are applied to <code>/etc/sysconfig/iptables</code> (at RHEL systems). | + | 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 <code>vzfirewall -a</code> again after movement. It is also reboot-safe, because applied to <code>/etc/sysconfig/iptables</code> (at RHEL systems). |
| | | |
| Vzfirewall and its documentation are available at [http://en.dklab.ru/lib/dklab_vzfirewall/ http://en.dklab.ru/lib/dklab_vzfirewall/]. | | Vzfirewall and its documentation are available at [http://en.dklab.ru/lib/dklab_vzfirewall/ http://en.dklab.ru/lib/dklab_vzfirewall/]. |
Line 45: |
Line 45: |
| See also this OpenVZ Forum posting - http://forum.openvz.org/index.php?t=msg&goto=16406& | | See also this OpenVZ Forum posting - http://forum.openvz.org/index.php?t=msg&goto=16406& |
| | | |
− | == Setting up a HN-based firewall ==
| + | You've got it in one. Couldn't have put it betetr. |
− | | |
− | This setup emulates (to the containers anyway) an external hardware firewall. It protects the HN from any access and then defines what services and ports are allowed/banned for individual containers. This leaves the firewall controlled by the site administrator, not be individual containers and the hackers who've gotten into them. ;)
| |
− | | |
− | First off, let's disable Fedora's existing <code>iptables</code> service:
| |
− | <pre>
| |
− | service iptables stop
| |
− | chkconfig iptables off
| |
− | </pre>
| |
− | | |
− | Now create the new <code>firewall</code> service. This code should be <code>/etc/init.d/firewall</code> and then should be chmod'd 755.
| |
− | <pre>
| |
− | #!/bin/sh
| |
− | # firewall Start iptables firewall
| |
− | # chkconfig: 2345 97 87
| |
− | # description: Starts, stops and saves iptables firewall
| |
− | # This script sets up the firewall for the INPUT chain (which is for
| |
− | # the HN itself) and then processes the config files under
| |
− | # /etc/firewall.d to set up additional rules in the FORWARD chain
| |
− | # to allow access to containers' services.
| |
− | # http://wiki.openvz.org/Setting_up_an_iptables_firewall
| |
− | | |
− | . /etc/init.d/functions
| |
− | | |
− | # the IP block allocated to this server
| |
− | SEGMENT="192.168.0.0/24"
| |
− | # the IP used by the hosting server itself
| |
− | THISHOST="192.168.0.1"
| |
− | # services that should be allowed to the HN;
| |
− | # services for containers are configured in /etc/firewall.d/*
| |
− | OKPORTS="53"
| |
− | # hosts allowed full access through the firewall,
| |
− | # to all containers and to this server
| |
− | DMZS="12.34.56.78 90.123.45.67"
| |
− | | |
− | purge() {
| |
− | echo -n "Firewall: Purging and allowing all traffic"
| |
− | iptables -P OUTPUT ACCEPT
| |
− | iptables -P FORWARD ACCEPT
| |
− | iptables -P INPUT ACCEPT
| |
− | iptables -F
| |
− | success ; echo
| |
− | }
| |
− | | |
− | setup() {
| |
− | echo -n "Firewall: Setting default policies to DROP"
| |
− | iptables -P INPUT DROP
| |
− | iptables -P FORWARD DROP
| |
− | iptables -I INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED
| |
− | iptables -I FORWARD -j ACCEPT -m state --state ESTABLISHED,RELATED
| |
− | iptables -I INPUT -j ACCEPT -i lo
| |
− | iptables -I FORWARD -j ACCEPT --source $SEGMENT
| |
− | success ; echo
| |
− | | |
− | echo "Firewall: Allowing access to HN"
| |
− | for port in $OKPORTS ; do
| |
− | echo -n " port $port"
| |
− | iptables -I INPUT -j ACCEPT -s $SEGMENT -d $THISHOST --protocol tcp --destination-port $port
| |
− | iptables -I INPUT -j ACCEPT -s $SEGMENT -d $THISHOST --protocol udp --destination-port $port
| |
− | success ; echo
| |
− | done
| |
− | for ip in $DMZS ; do
| |
− | echo -n " DMZ $ip"
| |
− | iptables -I INPUT -i eth0 -j ACCEPT -s $ip
| |
− | iptables -I FORWARD -i eth0 -j ACCEPT -s $ip
| |
− | success ; echo
| |
− | done
| |
− | | |
− | CTSETUPS=`echo /etc/firewall.d/*`
| |
− | if [ "$CTSETUPS" != "/etc/firewall.d/*" ] ; then
| |
− | echo "Firewall: Setting up container firewalls"
| |
− | for i in $CTSETUPS ; do
| |
− | . $i
| |
− | echo -n " $CTNAME CT$CTID"
| |
− | if [ -n "$BANNED" ]; then
| |
− | for source in $BANNED ; do iptables -I FORWARD -j DROP --destination $CTIP --source $source ; done
| |
− | fi
| |
− | if [ -n "$OPENPORTS" ]; then
| |
− | for port in $OPENPORTS ; do iptables -I FORWARD -j ACCEPT --protocol tcp --destination $CTIP --destination-port $port ; done
| |
− | for port in $OPENPORTS ; do iptables -I FORWARD -j ACCEPT --protocol udp --destination $CTIP --destination-port $port ; done
| |
− | fi
| |
− | if [ -n "$DMZS" ]; then
| |
− | for source in $DMZS ; do iptables -I FORWARD -j ACCEPT --protocol tcp --destination $CTIP --source $source ; done
| |
− | for source in $DMZS ; do iptables -I FORWARD -j ACCEPT --protocol udp --destination $CTIP --source $source ; done
| |
− | fi
| |
− | [ $? -eq 0 ] && success || failure
| |
− | echo
| |
− | done
| |
− | fi
| |
− | }
| |
− | | |
− | case "$1" in
| |
− | start)
| |
− | echo "Starting firewall..."
| |
− | purge
| |
− | setup
| |
− | ;;
| |
− | stop)
| |
− | echo "Stopping firewall..."
| |
− | purge
| |
− | ;;
| |
− | restart)
| |
− | $0 stop
| |
− | $0 start
| |
− | ;;
| |
− | status)
| |
− | iptables -n -L
| |
− | ;;
| |
− | *)
| |
− | echo "Usage: $0 <start|stop|restart|status>"
| |
− | ;;
| |
− | esac
| |
− | </pre>
| |
− | | |
− | Note: This will only allow access to the HN from the hosts/networks defined in SEGMENT. If you'd like to open up the OKPORTS on the HN to everybody, you can remove the ''-s $SEGMENT'' parameters from the iptables commands under the "Firewall: Allowing access to HN" section. The modified lines would look like this:
| |
− | | |
− | <pre>
| |
− | iptables -I INPUT -j ACCEPT -d $THISHOST --protocol tcp --destination-port $port
| |
− | iptables -I INPUT -j ACCEPT -d $THISHOST --protocol udp --destination-port $port
| |
− | </pre>
| |
− | | |
− | The above script can be called like this:
| |
− | <pre>
| |
− | service firewall start
| |
− | service firewall stop
| |
− | service firewall restart
| |
− | service firewall status
| |
− | </pre>
| |
− | | |
− | It will set up the firewall for the HN according to the parameters you specified for OKPORTS, DMZs, etc. and then it will call each file under /etc/firewall.d and process its configuration.
| |
− | | |
− | So create a file under /etc/firewall.d The exact filename isn't important, as long as it's meaningful to you, e.g. <code>ExampleCompany</code> or <code>ve12</code> and give it content like this:
| |
− | | |
− | <pre>
| |
− | # This file is processed by /etc/init.d/firewall
| |
− | CTID="1" # the container's ID#
| |
− | CTNAME="Customer1" # A human-friendly label for the container
| |
− | CTIP="192.168.1.34" # the IP address for this container
| |
− | OPENPORTS="80 443" # ports that should be universally opened
| |
− | # to the entire Internet
| |
− | DMZS="1.2.3.0/24 5.6.7.8/32" # IPs and blocks that should have full access
| |
− | # to the container's services
| |
− | BANNED="" # IPs and blocks that should be entirely
| |
− | # blocked from the container's services
| |
− | </pre>
| |
− | | |
− | And there you go.
| |
− | | |
− | Note: You can only put one IP address inside the CTIP variable, but if your container has multiple IP addresses you can create a copy of the file for each IP address.
| |
− | | |
− | Go ahead and start the firewall and check its status:
| |
− | <pre>
| |
− | service firewall restart
| |
− | service firewall status
| |
− | </pre>
| |
− | | |
− | As you can see, you can now add and edit the configurations for individual containers very easily. This method proves a lot easier to manage than Fedora's iptables-config mechamism!
| |
− | | |
− | To make the firewall service automatically start when the HN boots, run
| |
− | <pre>
| |
− | chkconfig --add firewall
| |
− | </pre>
| |
− | | |
− | === Debian Notes ===
| |
− | | |
− | The setup above works fine for Debian as well, however /etc/init.d/functions is missing. Here is a very simple version that you can use:
| |
− | | |
− | # /etc/init.d/functions
| |
− |
| |
− | success() {
| |
− | echo -n "...success"
| |
− | }
| |
− | failure() {
| |
− | echo -n "...failure"
| |
− | }
| |
| | | |
| == Setting up a firewall that allows per-container configuration == | | == Setting up a firewall that allows per-container configuration == |
Line 240: |
Line 66: |
| | | |
| If you do not, you will get an error like this: "iptables: No chain/target/match by that name" | | If you do not, you will get an error like this: "iptables: No chain/target/match by that name" |
− | * Note: xt_tcpudp module seem to be included in the kernel packages of Debian 6, but not of CentOS 6.
| |
| | | |
| 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: | | 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: |
Line 253: |
Line 78: |
| modprobe xt_state | | modprobe xt_state |
| </pre> | | </pre> |
− |
| |
− |
| |
− | Above information is outdated, to enable iptables you need to make sure that CT.conf(CT - id of your container, 100 for example) contains following line:
| |
− |
| |
− | <pre>
| |
− | NETFILTER="full"
| |
− | </pre>
| |
− |
| |
− | When this done, you should reboot your container and iptables should work properly.
| |
| | | |
| == See also == | | == See also == |
| | | |
| * [[Traffic accounting with iptables]] | | * [[Traffic accounting with iptables]] |
− | * [http://www.readymakers.com/blog/how-to-enable-iptables-in-openvz-container/ How to enable IPtables in OpenVZ container] (Frank Taveras) - Lack of modprobe modules on HN.
| |
| | | |
| [[Category: Networking]] | | [[Category: Networking]] |