Bug 1067441

Summary: nwfilter with direction out are put in all iptables chains
Product: [Community] Virtualization Tools Reporter: Stephan Sachse <ste.sachse>
Component: libvirtAssignee: Libvirt Maintainers <libvirt-maint>
Status: CLOSED NOTABUG QA Contact:
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: unspecifiedCC: acathrow, stefanb
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-03-11 11:39:35 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Stephan Sachse 2014-02-20 13:10:42 UTC
os: centos-6.5
kernel: 3.13.2-3.el6.x86_64
libvirt: 1.2.1 (+ lxc: Add virCgroupSetOwner())

i have a running fedora20 container with user namespace enabled. now i try to add some simple nwfilter

virsh # nwfilter-dumpxml nwfilter-test-fedora2
<filter name='nwfilter-test-fedora2' chain='root'>
  <uuid>ccbd255f-4be5-4f0f-8835-770ea40cb2c9</uuid>
  <rule action='accept' direction='in' priority='500'>
    <all state='ESTABLISHED,RELATED' comment='test: in accept'/>
  </rule>
  <rule action='accept' direction='in' priority='500'>
    <tcp state='NEW' dstportstart='22' comment='test: in NEW ssh'/>
  </rule>
  <rule action='accept' direction='out' priority='500'>
    <all state='ESTABLISHED,RELATED' comment='test: out accept'/>
  </rule>
  <rule action='accept' direction='out' priority='500'>
    <all state='NEW' comment='test: out NEW'/>
  </rule>
</filter>

all in rules are installed fine. but all out rules are installed into all iptables chains. the installed out rules have wrong -j targets. RETURN instead of ACCEPT.

here is the output of iptables-save

*filter
:INPUT ACCEPT [1797:164513]
:FORWARD ACCEPT [4160:430271]
:OUTPUT ACCEPT [1288:131936]
:FI-veth0-fedora2 - [0:0]
:FO-veth0-fedora2 - [0:0]
:HI-veth0-fedora2 - [0:0]
:libvirt-host-in - [0:0]
:libvirt-in - [0:0]
:libvirt-in-post - [0:0]
:libvirt-out - [0:0]
-A INPUT -j libvirt-host-in 
-A FORWARD -j libvirt-in 
-A FORWARD -j libvirt-out
-A FORWARD -j libvirt-in-post
-A FI-veth0-fedora2 -m state --state RELATED,ESTABLISHED -m comment --comment "test: out accept" -j RETURN
-A FI-veth0-fedora2 -m state --state NEW -m comment --comment "test: out NEW" -j RETURN
-A FO-veth0-fedora2 -m state --state RELATED,ESTABLISHED -m comment --comment "test: in accept" -j ACCEPT
-A FO-veth0-fedora2 -p tcp -m tcp --dport 22 -m state --state NEW -m comment --comment "test: in NEW ssh" -j ACCEPT
-A HI-veth0-fedora2 -m state --state RELATED,ESTABLISHED -m comment --comment "test: out accept" -j RETURN
-A HI-veth0-fedora2 -m state --state NEW -m comment --comment "test: out NEW" -j RETURN
-A libvirt-host-in -m physdev --physdev-in veth0-fedora2 -g HI-veth0-fedora2
-A libvirt-in -m physdev --physdev-in veth0-fedora2 -g FI-veth0-fedora2
-A libvirt-in-post -m physdev --physdev-in veth0-fedora2 -j ACCEPT  
-A libvirt-out -m physdev --physdev-out veth0-fedora2 --physdev-is-bridged -g FO-veth0-fedora2
COMMIT

next try is a simple rule to accept all with direction out

virsh # nwfilter-dumpxml nwfilter-test-fedora2
<filter name='nwfilter-test-fedora2' chain='root'>
  <uuid>ccbd255f-4be5-4f0f-8835-770ea40cb2c9</uuid>
  <rule action='accept' direction='out' priority='500'>
    <all comment='test: out accept'/>
  </rule>
</filter>

again, the rule is installed in all iptables chains. but now with strange state, conntrack and ctdir matches. and as in the first example: with wrong -j targets. here is the output of iptables-save (truncated)

-A FI-veth0-fedora2 -m state --state NEW,ESTABLISHED -m conntrack --ctdir ORIGINAL-m comment --comment "test: out accept" -j RETURN
-A FO-veth0-fedora2 -m state --state ESTABLISHED -m conntrack --ctdir REPLY-m comment --comment "test: out accept" -j ACCEPT
-A HI-veth0-fedora2 -m state --state NEW,ESTABLISHED -m conntrack --ctdir ORIGINAL-m comment --comment "test: out accept" -j RETURN

Comment 1 Stefan Berger 2014-03-10 00:42:03 UTC
For the above shown filters all iptables rules are correctly generated.

The RETURN in (FI-vnet0 -- speak *F*orwarded traffic *I*ncoming through vnet0) is added since traffic originating from a VM on the local host may have another VM on the local host as destination. So we cannot accept the traffic here because the destination VM may have a policy not allowing to receive this traffic.
 Only once traffic has been filtered for the receiving VM (FO-vethX - speak *F*orwarded traffic *O*utgoing through vnetX) will it be ACCEPT'ed.
This makes the rules look more complicated. When the rules are generated it is not known whether another VM on the same host will be the recipient.

The 2nd filter leaves control to creating the rules for accepting stateful filtered rules up to libvirt and that's why it generated such rules. The rule in FI-vnet0-fedora2 is for accepting (subject to further filtering,so a RETURN)  all traffic originating from the VM per its filtering policy. The rule in FO-vnet0-fedora2 is for allowing the incoming traffic to be responded to, so it's for accepting traffic in the return path. HI-vnet0-fedora2 is similar to FI-vnet0-fedora2 in that it accepts all traffic originating from the VM per its filtering policy but destined for the local host where the traffic now has to pass the filtering rules of the INPUT chain on the host. So also here ACCEPT is not used right away since this would mean ACCEPTing the traffic on the local host, but RETURN is used instead so that we can use this filter from the INPUT chain.