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?

  • Why not just bind to any address? – Michael Hampton Oct 20 '14 at 22:13
  • I need to be specific as there are other alias interfaces configured and it shouldn't bind to those. – noaru Oct 21 '14 at 17:44
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.

| improve this answer | |
  • 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. – kasperd Oct 21 '14 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. – noaru Oct 21 '14 at 17:52
  • If you get the address via dhcpv6 binding to "[::]:80" sounds like the better solution :) – Stefan Oct 22 '14 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. – Sander Steffann Oct 22 '14 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). – noaru Oct 24 '14 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.