Experimental software, only used for testing! ============================================= Quick Intro =========== VM firewall rules are read from /etc/pve/firewall/.fw Security group rules are read from /etc/pve/firewall/groups.fw Host firewall rules are read from /etc/pve/local/host.fw You can find examples in the example/ dir Use the following command to mange the firewall: To test the firewall configuration: ./pvefw compile To start or update the firewall: ./pvefw start To update the firewall rules (the firewall is not started if it is not already running): ./pvefw update To stop the firewall: ./pvefw stop Implementation details ====================== We write iptables rules directly, an generate the following chains as entry points in the 'forward' table: PVEFW-INPUT PVEFW-OUTPUT PVEFW-FORWARD We do not touch other (user defined) chains. Each VM can have its own firewall definition file in /etc/pve/firewall/.fw That file has a section [RULES] to define firewall rules. Format is: TYPE ACTION IFACE SOURCE DEST PROTO D-PORT S-PORT * TYPE: IN|OUT|GROUP * ACTION: action or macro * IFACE: vm network interface (net0 - net5), or '-' for all interfaces * SOURCE: source IP address, or '-' for any source * DEST: dest IP address, or '-' for any destination address * PROTO: see /etc/protocols * D-PORT: destination port * S-PORT: source port A rule for inbound traffic looks like this: IN SSH(ACCEPT) net0 Outbound rules looks like: OUT SSH(ACCEPT) Problems =================== There are a number of restrictions when using iptables to filter bridged traffic. The physdev match feature does not work correctly when traffic is routed from host to bridge: * when a packet being sent through a bridge entered the firewall on another interface and was being forwarded to the bridge. * when a packet originating on the firewall itself is being sent through a bridge. So we disable the firewall if we detect such case (bridge with assigned IP address). You can enable it again (if you do not care) by setting "allow_bridge_route: 1" in "host.fw". The correct workaround is to remove the IP address from the bridge device, and use a veth device which is plugged into the bridge: ---/etc/network/interfaces---- ... auto vmbr0 iface vmbr0 inet manual bridge_ports bond0 bridge_stp off bridge_fd 0 # this create the veth device and plug it into vmbr0 auto pm0 iface pm0 inet static address 192.168.10.10 netmask 255.255.255.0 gateway 192.168.10.1 VETH_BRIDGETO vmbr0 auto vmbr1 iface vmbr1 inet manual bridge_ports none bridge_stp off bridge_fd 0 # setup masqueraded bridge port vmbr1/pm1 using pm0 # NOTE: this needs kernel 3.10.0 or newer (for conntrack --zone) auto pm1 iface pm1 inet static address 10.10.10.1 netmask 255.255.255.0 VETH_BRIDGETO vmbr1 VETH_MASQUERADE pm0 ... --------------------------------