[Swan-dev] [solved] IPv6 IPsec failure on host reboot - neighbour discovery problem

Paul Wouters paul at nohats.ca
Thu Mar 19 02:10:49 EET 2015

I was looking into a bug on an IPv6 tunnel. When the hosts started ipsec
it worked fine and the tunnel came up, but when one end rebooted it
would get stuck.

Looking into this I saw:

000 Shunt list:
000 2620:52:0:ab0:42f2:e9ff:fe09:a16c/128:136 -58-> 2620:52:0:ab0:ca1f:66ff:fef1:c74c/128:0 => %hold 0    %acquire-netlink

58 is ipv6-icmp. Turns out this was an ipv6 neighbour discovery unicast
packet that was being sent by the host that did not reboot in answer
to the host just booted. It ended up being caught in its own kernel
trap. It sends an IKE packet but it is lost because the freshly booted
host does not know how to find us before it receives this ipv6 neighbour
discovery packet. I think this is a kernel bug. This was tested with
XFRM/NETKEY but I assume KLIPS has the same issue.

A workaround conn for this problem is:

conn v6neighbour-hole

The calculation for the protoport is a little weird for ICMP, from the
source code:

          * As per RFC 4301/5996, icmp type is put in the most significant
          * 8 bits and icmp code is in the least significant 8 bits of
          * port field.
          * Although Libreswan does not have any configuration options for
          * icmp type/code values, it is possible to specify icmp type and code
          * using protoport option. For example, icmp echo request
          * (type 8/code 0) needs to be encoded as 0x0800 in the port field
          * and can be specified as left/rightprotoport=icmp/2048. Now with
          * NETKEY, icmp type and code need to be passed as source and
          * destination ports, respectively. Therefore, this code extracts
          * upper 8 bits and lower 8 bits and puts into source and destination
          * ports before passing to NETKEY.

Since ipv6-icmp Neighbour Discovery is Type 136, Code 0
(as per

protoport is 58 (ipv6-icmp)
type = 136 (0x88)
code = 0

so "port" in protoport is 0x8800 or 34816

hence protoport=58/0x8800

This connection successfully resolved the "reboot host" problem for me.

Any IPv6 experts know which other ipv6-icmp type/code's we might need to
create a hole for?

Anyone disagree with adding and enabling this to /etc/ipsec.d/v6neighbour-hole.conf ?


More information about the Swan-dev mailing list