Rule accepting input HTTP in ip6tables not enough to allow IPv6 requests
I am facing an IPv6 accessibility problem with my server.
- The server is IPv6-capable and is capable of contacting/being contacted by third-parties on IPv6 (
ping6
andtraceroute6
tested on my Debian stable Wheezy, up-to-date) - The DNS IPv6
AAAA
entry for the website is existing and functioning properly - The webserver (nginx) is listening on the IPv6 link and is ready to handle the requests the same way as it is for IPv4
-
ip6tables
INPUT
table is configured to allow HTTP requests just like iptables (default policyDROP
+ TCP 80ACCEPT
rule):Chain INPUT (policy DROP 648 packets, 46788 bytes) pkts bytes target prot opt in out source destination 6 480 ACCEPT tcp * * ::/0 ::/0 tcp dpt:80
I narrowed the problem down to the fact that if I set the default policy to ACCEPT
, the HTTP connection works, otherwise not.
Thus, it seems than some other port redirections might be required? oO
Could that be related to some kernel configuration of the routing/IPv6 stack?
Here is the output of sudo ip6tables --line-numbers -nvL
:
Chain INPUT (policy DROP 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 8169 784K ACCEPT all * * ::/0 ::/0 state RELATED,ESTABLISHED
2 0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:22
3 0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:80
4 0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:443
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Solution 1:
Folks, you must not ignore ICMPv6 as you did for legacy IP - ICMPv6 and particularly the Neighbor Discovery Protocol (NDP) is vital for the proper functioning of IPv6. (The NDP, among other things, is a substitute for ARP.)
This means, you must allow at least for ICMPv6 types 133-136 from link local (i.e. fe80::/10
). Moreover, you must allow certain error messages to arrive, as for instance routers don't fragment any more. You also don't want to drop link local multicast messages.
The full story is told in RFC 4890.
Below is an excerpt from one of my machines, a vm host that acts as a router:
#! /bin/sh
drop () {
/sbin/ip6tables --jump DROP --append "$@";
}
accept () {
/sbin/ip6tables --jump ACCEPT --append "$@";
}
chain () {
/sbin/ip6tables --new-chain "$@"
}
ICMP_RATELIMIT="--match limit --limit 2/s"
# ...
# Validate ingoing ICMPv6 messages
#
chain ICMPv6_IN
# error messages
# allow error messages that are related to previously seen traffic
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type destination-unreachable --match conntrack --ctstate ESTABLISHED,RELATED $ICMP_RATELIMIT
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type packet-too-big --match conntrack --ctstate ESTABLISHED,RELATED $ICMP_RATELIMIT
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type ttl-exceeded --match conntrack --ctstate ESTABLISHED,RELATED $ICMP_RATELIMIT
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type parameter-problem --match conntrack --ctstate ESTABLISHED,RELATED $ICMP_RATELIMIT
# accept neighbor discovery
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type neighbor-solicitation $ICMP_RATELIMIT
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type neighbor-advertisement $ICMP_RATELIMIT
# accept router discovery
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type router-solicitation '!' --src ff00::/8 --in-interface cafe0 $ICMP_RATELIMIT
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type router-advertisement --src fe80::/10 --in-interface wlp3s0 $ICMP_RATELIMIT
# ping
# accept replies to my ping requests
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type echo-reply --match conntrack --ctstate ESTABLISHED,RELATED
# allow ping from my network(s)
accept ICMPv6_IN --src $COUNTERMODE --protocol icmpv6 --icmpv6-type echo-request $ICMP_RATELIMIT
# allow link-local unicast ping
accept ICMPv6_IN --dst fe80::/10 --protocol icmpv6 --icmpv6-type echo-request $ICMP_RATELIMIT
## allow multicast ping from local link
#accept ICMPv6_IN --dst ff00::/8 --src fe80::/10 --protocol icmpv6 --icmpv6-type echo-request $ICMP_RATELIMIT
# multicast listener discovery v1
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type 130 --in-interface cafe0
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type 131 --in-interface cafe0
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type 132 --in-interface cafe0
# multicast listener discovery v2
accept ICMPv6_IN --protocol icmpv6 --icmpv6-type 143 --in-interface cafe0
# drop everything else
drop ICMPv6_IN