I have a DigitalOcean droplet which is used for a few things, primarily as a web host and SMTP server. I have recently started dabbling in IPv6 and have successfully configured it on the VPS; ping6
works great to google.com, etc. The local LAN network is configured with IPv6 via slaac and can ping and connect to the DO droplet without issue.
Where I’m running into issues is with setting up ip6tables
. I did a basic configuration which only allows SSH, Web, and SMTP, but after adding the rules, everything stops being able to connect to the VPS over IPv6. As soon as I flush the tables, it’s fine. It also seems that if I setup a connection (like web or ssh) before adding the rules, the connections work after the rules are added, it only for a little bit. I’m not sure what’s blocking the connections at this point, any guidance would be helpful.
ip6tables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1880 121K ACCEPT all * * ::/0 ::/0 ctstate RELATED,ESTABLISHED
2 136 ACCEPT all lo * ::/0 ::/0
1 84 ACCEPT tcp * * ::/0 ::/0 tcp dpt:22
0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:25
0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:80
1 80 ACCEPT tcp * * ::/0 ::/0 tcp dpt:443
0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:587
774 55932 DROP all * * ::/0 ::/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2537 168K ACCEPT all * * ::/0 ::/0
UPDATE: Added a log statement to capture some logs, then went ahead and tried to SSH from a client that I know wouldn't work. It wouldn't connect and I gave up after waiting maybe 10-seconds.
Mar 29 08:57:55 cloud kernel: [170352.518576] IN=eth0 OUT= MAC=33:33:ff:e2:40:01:84:b5:9c:f9:18:30:86:dd SRC=fe80:0000:0000:0000:0000:0000:0000:0001 DST=ff02:0000:0000:0000:0000:0001:ffe2:4001 LEN=72 TC=192 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=135 CODE=0
Mar 29 08:57:56 cloud kernel: [170353.518091] IN=eth0 OUT= MAC=33:33:ff:e2:40:01:84:b5:9c:f9:18:30:86:dd SRC=fe80:0000:0000:0000:0000:0000:0000:0001 DST=ff02:0000:0000:0000:0000:0001:ffe2:4001 LEN=72 TC=192 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=135 CODE=0
Mar 29 08:57:57 cloud kernel: [170354.517936] IN=eth0 OUT= MAC=33:33:ff:e2:40:01:84:b5:9c:f9:18:30:86:dd SRC=fe80:0000:0000:0000:0000:0000:0000:0001 DST=ff02:0000:0000:0000:0000:0001:ffe2:4001 LEN=72 TC=192 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=135 CODE=0
Mar 29 08:57:59 cloud kernel: [170356.517573] IN=eth0 OUT= MAC=33:33:ff:e2:40:01:84:b5:9c:f9:18:30:86:dd SRC=fe80:0000:0000:0000:0000:0000:0000:0001 DST=ff02:0000:0000:0000:0000:0001:ffe2:4001 LEN=72 TC=192 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=135 CODE=0
Why is the SRC fe80::1
? That's definitely not the source IP from where I'm connecting from (it's abreviated prefix is 2600:1700
). Also, the DST is ff02::1:ffe2:4001
which does appear to be configured on the interface as well:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 04:01:3a:XX:XX:XX brd ff:ff:ff:ff:ff:ff
inet 104.236.XXX.XXX/18 brd 104.236.XXX.XXX scope global eth0
valid_lft forever preferred_lft forever
inet6 2604:a880:800:XXXX::YYYY:4001/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::601:3aff:fe85:dd01/64 scope link
valid_lft forever preferred_lft forever
ip -6 route
2604:a880:800:10::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev tap0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via 2604:a880:800:XXXX::1 dev eth0 metric 1024 pref medium
As requested, ip6tables-save
ip6tables-save
# Generated by ip6tables-save v1.6.0 on Thu Mar 29 09:03:33 2018
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 587 -j ACCEPT
-A INPUT -j LOG
-A INPUT -j DROP
-A OUTPUT -j ACCEPT
COMMIT
# Completed on Thu Mar 29 09:03:33 2018
Best Answer
IPv6 nodes all have link-local addresses, which are in the
fe80::/10
network. Nodes will use the link-local addressing for various things that remain on the local link (it cannot be routed), so you must allow that addressing in your rules.IPv6 doesn't have broadcast, so it makes heavy use of multicast. Nodes will have multiple unicast/anycast addresses on an interface, and a node must subscribe to the solicited-node multicast address for each of those addresses. The solicited-node multicast address is based on the last 24 bits of the unicast address, so if all your unicast/multicast addresses have the same last 24 bits, then you will only have one solicited-node multicast group for the interface (this is the ideal).
IPv6 Neighbor Discover uses the solicited-node multicast address. Since IPv6 doesn't have broadcast, ARP is not used to relate the layer-2 address to the layer-3 address. IPv6 uses ND for that, and that uses the solicited-node multicast address.