Несколько дней назад я настроил lighttpd для прослушивания моего IPv6-адреса VPS. Он работает на Debian 7 Xen VPS (Linode) с 3.15.4-x86_64-linode45
ядро. Версия lighttpd - 1.4.31-4+deb7u3
.
Мой lighttpd.conf использовал эту конфигурацию для прослушивания IPv4:
server.bind = "10.0.0.1"
server.port = 80
Я добавил следующее, чтобы включить IPv6 согласно http://redmine.lighttpd.net/projects/lighttpd/wiki/IPv6-Config
$SERVER["socket"] == "[2001:DB8::1]:80" { }
Теперь, когда я перезапустил lighttpd, все было в порядке - в итоге он прослушал оба, как планировалось.
Проблема появилась после того, как мне пришлось перезагрузить свой VPS. Оказывается, во время загрузки запуск lighttpd завершается ошибкой с выводом на консоль следующего сообщения:
[....] 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
Если я войду и бегу service lighttpd start
он запускается без проблем, прослушивая как IPv4, так и IPv6.
Я подумал, что, возможно, во время загрузки у него не было адреса IPv6, поэтому я сделал вывод ifconfig
в файл перед попыткой запуска (в сценарии инициализации), и оба IP-адреса назначены интерфейсу.
Есть идеи, в чем может быть проблема или как ее устранить?
Когда IPv6-адреса настроены, они не доступны сразу. Система сначала выполняет DAD (обнаружение повторяющегося адреса), чтобы убедиться, что ее новый адрес не конфликтует с существующим адресом в другой системе. Приложения не могут связываться (по крайней мере, с настройками по умолчанию) с адресами, которые все еще являются предварительными.
Последние версии Пакет Debian ifupdown содержит сценарий под названием settle-dad.sh
это будет приостановлено, пока интерфейс не выйдет из предварительного состояния. Возможно, вы захотите добавить такой сценарий в процесс загрузки между настройкой сетевого интерфейса и запуском серверов.
Это не так уж и сложно:
#!/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
Распространяется под Лицензия GPLv2.