0

A few days ago I configured lighttpd to listen on my VPS IPv6 address as well. It runs on a Debian 7 Xen VPS (Linode) with a 3.15.4-x86_64-linode45 kernel. The version of lighttpd is 1.4.31-4+deb7u3.

My lighttpd.conf used this configuration to listen to IPv4:

server.bind = "10.0.0.1" server.port = 80 

I added the following to enable IPv6 as per http://redmine.lighttpd.net/projects/lighttpd/wiki/IPv6-Config

$SERVER["socket"] == "[2001:DB8::1]:80" { } 

Now, when I restarted lighttpd, everything was alright - it ended up listening to both as planned.

The problem appeared after I had to reboot my VPS. Turns out at boot time, starting lighttpd fails with the following message to the console:

[....] Starting web server: lighttpd2014-10-20 21:00:19: (network.c.405) can't bind to port: 2001:DB8::1 80 Cannot assign requested address 

If I login and run service lighttpd start it starts without a problem, listening on both IPv4 and IPv6.

I thought that maybe it didn't have the IPv6 address at boot time, so I made it output ifconfig to a file before attempting to start (in the init script) and it has both IPs assigned to the interface.

Any ideas what might be the problem or how to troubleshoot this further?

2
  • Why not just bind to any address? Commented Oct 20, 2014 at 22:13
  • I need to be specific as there are other alias interfaces configured and it shouldn't bind to those. Commented Oct 21, 2014 at 17:44

1 Answer 1

3

When IPv6 addresses are configured they aren't available immediately. The system first performs DAD (Duplicate Address Detection) to make sure that its new address doesn't conflict with an existing address on another system. Applications cannot bind (at least not with default settings) to addresses that are still tentative.

Recent versions of the Debian ifupdown package contains a script called settle-dad.sh that will pause until the interface has left the tentative state. You might want to add such a script to your boot process between configuring the network interface and starting your servers.

It's not that big/complex:

#!/bin/sh # 6 seconds maximum wait time attempts=${IF_DAD_ATTEMPTS:-60} delay=${IF_DAD_INTERVAL:-0.1} [ $attempts -eq 0 ] && exit 0 echo -n "Waiting for DAD... " for attempt in $(seq 1 $attempts); do tentative=$(ip -o -6 address list dev "$IFACE" to "${IF_ADDRESS}/${IF_NETMASK}" tentative | wc -l) if [ $tentative -eq 0 ]; then attempt=0 # This might have been our last attempt, but succesful break fi sleep $delay done if [ $attempt -eq $attempts ]; then echo "Timed out" exit 1 fi dadfailed=$(ip -o -6 address list dev "$IFACE" to "${IF_ADDRESS}/${IF_NETMASK}" dadfailed | wc -l) if [ $dadfailed -ge 1 ]; then echo "Failed" exit 1 fi echo Done 

It is distributed under the GPLv2 license.

6
  • 1
    Alternatively one could change the accept_dad setting to disable DAD. On a server with a static IP address, DAD isn't very useful after all. Commented Oct 21, 2014 at 0:31
  • It makes sense, thanks. I'll try integrating it tonight as a dependency. Seeing as it's in sid I might spin it up in a VM to see how it's called. @kasperd Completely agree with you, but in this case the IP is assigned via DHCPv6. Commented Oct 21, 2014 at 17:52
  • If you get the address via dhcpv6 binding to "[::]:80" sounds like the better solution :) Commented Oct 22, 2014 at 4:52
  • Yeah, getting an address through a dynamic protocol and then putting it statically in some other configuration files sounds like a unnecessary complication. I would personally do everything statically in such a case. Commented Oct 22, 2014 at 8:59
  • I agree that logically it doesn't make sense. But that DHCP binding is static (it's just an IP that can't be allocated via SLAAC) and its use is mandated by the whole VPS setup (ties in with DNS and their tools). Commented Oct 24, 2014 at 17:40

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.