Iptables – Why are these ip6tables rules blocking ssh over IPv6 when the iptables version allows it over IPv4

iptablesipv6

I have the following iptables rules, which are intended to allow all traffic on lo, eth1 and eth2 and to allow outgoing traffic on eth0 but block incoming traffic on eth0 except to ports 22, 80, 443, 1194, 5222 and 5269. The rules successfully allow ssh access via port 22 over IPv4.

# Generated by iptables-save v1.4.12 on Sat Nov 16 13:03:07 2013
*raw
:PREROUTING ACCEPT [247:18556]
:OUTPUT ACCEPT [278:35544]
COMMIT
# Completed on Sat Nov 16 13:03:07 2013
# Generated by iptables-save v1.4.12 on Sat Nov 16 13:03:07 2013
*mangle
:PREROUTING ACCEPT [247:18556]
:INPUT ACCEPT [247:18556]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [278:35544]
:POSTROUTING ACCEPT [278:35544]
COMMIT
# Completed on Sat Nov 16 13:03:07 2013
# Generated by iptables-save v1.4.12 on Sat Nov 16 13:03:07 2013
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [1:164]
:POSTROUTING ACCEPT [1:164]
COMMIT
# Completed on Sat Nov 16 13:03:07 2013
# Generated by iptables-save v1.4.12 on Sat Nov 16 13:03:07 2013
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m state --state INVALID -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p icmp -m limit --limit 1/sec -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 1194 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5222 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5269 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -m pkttype --pkt-type broadcast -j DROP
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o eth1 -j ACCEPT
-A OUTPUT -o eth2 -j ACCEPT
-A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Sat Nov 16 13:03:07 2013

I copied them to ip6tables and added and bunch of ipv6-icmp rules to allow dynamic configuration of the IPv6 address.

# Generated by ip6tables-save v1.4.12 on Sat Nov 16 13:03:12 2013
*raw
:PREROUTING ACCEPT [60:5920]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Sat Nov 16 13:03:12 2013
# Generated by ip6tables-save v1.4.12 on Sat Nov 16 13:03:12 2013
*mangle
:PREROUTING ACCEPT [60:5920]
:INPUT ACCEPT [4:320]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
# Completed on Sat Nov 16 13:03:12 2013
# Generated by ip6tables-save v1.4.12 on Sat Nov 16 13:03:12 2013
*filter
:INPUT DROP [4:320]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 1194 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5222 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 5269 -m state --state NEW,ESTABLISHED -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 1 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 2 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 3 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 4 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 133 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 134 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 135 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 136 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 137 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 141 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 142 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 130 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 131 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 132 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 143 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 148 -j ACCEPT
-6 -A INPUT -p ipv6-icmp --icmpv6-type 149 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 151 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 152 -j ACCEPT
-6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 153 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o eth1 -j ACCEPT
-A OUTPUT -o eth2 -j ACCEPT
-A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Sat Nov 16 13:03:12 2013

The line for TCP port 22 is the same. Yet, these rules block ssh over IPv6.

Why? What do I need to do differently to allow the same TCP ports over IPv6 as over IPv4?

An older question suggests that I'm missing some vital ipv6-icmp stuff still, but it's unclear to me what, since the answer uses a different syntax.

Best Answer

The ipv6 rules w.r.t. ssh look okay to me. I suspect that there might be a flaw in the complete setup which is possibly related to the interface from which you tried to access your machine.

Your rules do not implement the policy you described.

[...] iptables rules, which are intended to allow all traffic on lo, eth1 and eth2

Your INPUT rules don't implement these permissions for the interfaces eth1 and eth2. Any port except 22, 80, 443, 1194, 5222 and 5269 is not reachable via eth1 and eth2.

[...] but block incoming traffic on eth0 except to ports 22, 80, 443, 1194, 5222 and 5269.

Try to constrain the port permissions in INPUT to only eth0 to test whether your setup works as intended. You may want to use -m multiport --dports 22,80,443,1194,5222,5269 to make the rules more readable. In INPUT you already accept ESTABLISHED traffic. Thus, when writing rules for individual ports, it is sufficient to match on --state NEW (without ESTABLISHED) packets.

[...] and to allow outgoing traffic on eth0

This is also not implemented in the ruleset. It may accidentally work because the rule -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT accepts almost every packet.


General further debugging steps:

  • make sure that you loaded your IPv6 script with ip6tables. Due to your use of -6, you can also load it with iptables, which ignores all rules starting with -6
  • Don't lock yourself your when you make changes. At the moment, you likely only have accidental ssh access from eth0 because of the -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT rule.
  • Check iptables -L -v -n and look at the rule counters to see which rules apply. If necessary, add rules without an action or LOG rules to get more counters/information.
  • Try to accept any ipv6-icmp for a moment to figure out whether the problem relates to icmp.
  • ssh has the -4 and -6 flags to force the use of IPv4/IPv6. Make sure your machine did not accidentally fall back to the wrong IP version during testing.
  • If you have refactored your rules and the IPv6 problem-ssh problem remains, you may want to change this question to something like: "Do my rules implement my intended policy?" and ask the IPv6-ssh question again (in a new thread) with your new rules.