Delan Azabani

Using IPv6 with IRCd-Hybrid

It's great to see that Hybrid has IPv6 support, but it's not quite perfect. Out of the box, while an attempt is made to listen on all interfaces over both protocols, "address already in use" errors for the listening sockets may appear in /var/log/ircd/ircd-hybrid.log — with a bit of configuration, this can be fixed though.

The following is the relevant excerpt of the initial /etc/ircd-hybrid/ircd.conf:

listen {
	port = 6665 .. 6669;
};

Messages like this appeared in the log when Hybrid was started:

binding listener socket irc.comssa.org.au[0::/6665]:Address already in use
binding listener socket irc.comssa.org.au[0::/6666]:Address already in use
binding listener socket irc.comssa.org.au[0::/6667]:Address already in use
binding listener socket irc.comssa.org.au[0::/6668]:Address already in use
binding listener socket irc.comssa.org.au[0::/6669]:Address already in use

With a bit of research, I found a forum thread with example configuration snippets to prepare services for IPv6, but it didn't quite work for two reasons. The suggested configuration was as follows:

listen {
	host = "0.0.0.0"; # Bind to all IPv4
	host = "::"; # Bind to all IPv6
	port = 6665 .. 6669;
};

The same messages were logged, and clients were still unable to connect over IPv6. As was the case earlier, netstat -l did not show any services listening on those ports. I'm not sure if it's a bug in Hybrid, but listening on a specific interface's IP address seems to be required for IPv6, although I've never had to do this for other programs like nginx.

listen {
	host = "0.0.0.0"; # Bind to all IPv4
	host = "2001:470:7c85::1";
	port = 6665 .. 6669;
};

I was then able to connect over IPv6, and I was delighted. All seemed well until a few hours later when a client notified me that they were unable to connect. They didn't have IPv6. Also broken was qwebirc, which uses IPv4. Running netstat -l again now showed that Hybrid was listening only over IPv6, as if the second host line overrode the first.

Digging into the source of Hybrid 8.1.13, the doc/reference.conf showed that host lines are essentially optional modifiers for the next port line; you need one port line for each interface or address you wish to listen on. The final configuration that listened properly on both IPv4 and IPv6 for me was:

listen {
	host = "0.0.0.0"; # Bind to all IPv4
	post = 6665 .. 6669;
	host = "2001:470:7c85::1";
	port = 6665 .. 6669;
};

As a brief note: like most daemons, sending SIGHUP to the Hybrid process or running /etc/init.d/ircd-hybrid reload allows you to use a new configuration without disconnecting any users. To my pleasant surprise, even when enabling incorrect configurations that ceased to listen over IPv4, existing IPv4 users still remained connected.