My OpenVZ VPS is blocking outbound IPv6 traffic, but correctly filtering inbound IPv6 traffic.

Below is my ip6tables-restore script.

-A INPUT -i lo -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 51413 -j ACCEPT
-A INPUT -p udp -m udp --dport 51413 -j ACCEPT
-A INPUT -m limit --limit 5/min
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited

ICMPv6 traffic is still able to pass both inbound and outbound.

When I flush these rules using -F, outbound traffic flows fine.

What am I missing here?

EDIT: It appears that ip6tables is marking ESTABLISHED packets as INVALID. Consequently, the outbound traffic is NOT actually being blocked. The reply packets are not allowed inbound again, hence appearing like blocked outbound traffic. Allowing INVALID packets inbound solves the outbound issue, but also renders the inbound filter useless.

  • Can you give a bit more detail as to how you've diagnosed 'outbound traffic'? Do you mean you can't initiate TCP connections to remote ipv6 endpoints?
    – growse
    Jun 29, 2011 at 16:39
  • wget http://ipv6.google.com fails, as does SSHing or telnetting to any ipv6 host (forced IPv6 with -6).
    – jmccrohan
    Jun 29, 2011 at 21:09
  • Just to confirm, without ip6tables, things work as expected? Jun 29, 2011 at 23:33
  • Yeah. Basically this is caused by the kernel not supporting stateful ip6tables.
    – jmccrohan
    Jun 30, 2011 at 1:16

4 Answers 4


Which version of the kernel are you using, older versions did not have conntrack stateful firewall support in netfilter for IPv6 so the rule to allow RELATED,ESTABLISHED traffic would not work and you'd need to allow ! --syn -dport 1024:65535 and udp traffic instead.

You may need to specify the state module when allowing the traffic, for example here is a config from an RHEL6 host that does work.

ip6tables -t filter -F INPUT
ip6tables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -t filter -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -t filter -A INPUT -i lo -j ACCEPT
ip6tables -t filter -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
ip6tables -t filter -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
ip6tables -t filter -A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
ip6tables -t filter -A INPUT -j LOG --log-prefix=v6_input_deny --log-level=4
ip6tables -t filter -A INPUT -j REJECT --reject-with icmp6-adm-prohibited
  • 1
    You might be on to something here. I've just noticed that the packets are being marked as INVALID instead of ESTABLISHED. I've updated the original post accordingly. Kernel version 2.6.32-238.12.1.el5
    – jmccrohan
    Jun 29, 2011 at 23:04
  • Is that the oracle kernel? 2.6.32 in RHEL6 does support conntrack for IPv6. 2.6.18 in RHEL5 does not.
    – mtinberg
    Jul 5, 2011 at 20:54
  • I'm not sure what kernel is it. It is a OpenVZ container VPS so I know little about the host kernel.
    – jmccrohan
    Jul 6, 2011 at 10:15
  • I stumbled upon this with Linode's kernels too.
    – Steve-o
    Aug 25, 2011 at 3:44

It appears you are using CentOS5 or another RHEL5 variant.

Netfilter's connection tracking in RHEL5 is broken and will never be fixed. As a result, the typical iptables rule like -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT will not work and ip6tables/connfilter will simply consider them 'INVALID'. In the following example, notice how Netfilter mistakenly marks valid packets as 'INVALID' instead of 'ESTABLISHED':

# ip6tables-save |grep state
-A INPUT -s ::/0 -d ::/0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -s ::/0 -d ::/0 -m state --state INVALID -j ACCEPT 
# curl -6 www.google.com >/dev/null 2>&1

# ip6tables --list --numeric -v
Chain INPUT (2 references)
 pkts bytes target     prot opt in     out     source               destination         
0     0 ACCEPT     all      lo     *       ::/0                 ::/0               
3   208 ACCEPT     icmpv6   *      *       ::/0                 ::/0               
0     0 ACCEPT     ah       *      *       ::/0                 ::/0               
0     0 ACCEPT     all      *      *       ::/0                 ::/0               state RELATED,ESTABLISHED 
61 65747 ACCEPT    all      *      *       ::/0                 ::/0               state INVALID 

If you run tcpdump for IPv6 traffic, you'll see the 'SYN' packet to the remote host, the 'SYN-ACK' response packet from the remote host. At this point with the default ip6tables, the packet won't match any existing rules and will therefore fall into the last rule --- -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp6-adm-prohibited.

Why the heck are these packets INVALID? It's a bug in that version of Red Hat, and it was never fixed.

As a workaround, you can try to ignore inbound SYN, which tip-toes around the connection tracking problem:

-A INPUT -s ::/0 -d ::/0 -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p tcp -m tcp ! --syn -s 2001:1:1:1::/48 -j ACCEPT

Optionally, some people also accept UDP packets as well:

-A RH-Firewall-1-INPUT -p udp -m udp

But at some point this starts to look like a security hazard. If you're accepting all traffic like this, why bother with a firewall at all?


You have to accept tcp, sctp and udp traffic

-A OUTPUT -p tcp -j ACCEPT 
-A OUTPUT -p udp -j ACCEPT 
-A OUTPUT -p sctp -j ACCEPT

  • Doesn't make any difference unfortunately.
    – jmccrohan
    Jun 29, 2011 at 21:28

Try replacing

-A INPUT -p ipv6-icmp -j ACCEPT


-A INPUT -p icmpv6 -j ACCEPT

ICMP is a lot more central to IPv6 than it was to IPv4, and the above is what I have on my local ip6tables script.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .