Pidgin IRC with ZNC and Freenode SASL external auth

December 12, 2019 

I use Pidgin as my instant messaging client because it is open source and because it supports almost all IM protocols directly or through plugins. In my case I need support for IRC, XMPP, Facebook, Slack and SIPE (Office 365). Apparently it would be possible to use Pidgin for Signal as well, but as official Signal client is open source and works quite well I'm fine with running it standalone. As I use Linux, I can rarely hope for a native client for the proprietary IM services. Plus even if there was one, I would not want to run 4-5 messaging applications when I can have one (or two). Or to have the same amount of IM web applications open just to get messages.

In IRC I primarily connect to channels at Freenode. I use ZNC IRC bouncer in front of Pidgin so that I get the messages that arrived to the channel(s) when I was away. There are other benefits with the IRC bouncer approach, like making the IRC client configuration slightly simpler and offering various advanced features.

Some channels in Freenode require you to authenticate to Freenode before you can join them. The modern way (and only?) way to login to Freenode is to to SASL authentication. There are two ways to do this in case of Freenode:

  • PLAIN: username and password
  • EXTERNAL: TLS certificate (other mechanism may work?)

When connection to the IRC server is protected by TLS then PLAIN authentication is ok, security-vise. But an even better way is to create a self-signed certificate, authenticate to Freenode with SASL PLAIN authentication and add the certificate fingerprint to your use account. That is, using EXTERNAL authentication. The certificate part is well-documented on the ZNC cert module wiki page. The SASL part is similarly documented quite well on the sasl module wiki page. While there is lots of good info out there, integrating ZNC with Freenode at one end, and an IRC client (e.g. pidgin) on the other ended up surprisingly challenging. For the purposes of this article I assume the following things:

  • You're able to login to Freenode with your IRC client using SASL PLAIN authentication
  • You are able to login the ZNC using your IRC client
  • You have configured ZNC according to the official documentation
  • You've added Freenode to ZNC as a Network.

The way I got the integration to work was to focus on ZNC and Freenode first. ZNC is, among other things, an IRC client. You could think of it as an IRC proxy. So, the first thing you need to do is ensure that ZNC is able to connect to and authenticate with Freenode. What I found immensely useful was the foreground debugging mode in ZNC:

$ znc -D

That will provide you with fine-grained info on what ZNC is doing. Using that I was able to determine that my ZNC server was trying to reach out to Freenode using an IPv6 address. Which would be ok, if IPv6 had worked on that server. Fortunately changing the Freenode server address to allowed me to work around the IPv6 connectivity issue.

Another issue I found was that ZNC was trying to do SASL PLAIN authentication instead of SASL EXTERNAL, even when certificate was properly installed for the ZNC user and my user account on Freenode had the correct fingerprint. The solution for this was provided on ZNC's SASL page, but running those commands requires being logged in to ZNC, which is not possible if ZNC itself fails to authenticate with Freenode. So the correct order of doing things is:

  1. Configure your IRC client to connect to Freenode with SASL PLAIN authentication
  2. Setup a server you will run ZNC on and give it a public IP
  3. Add a DNS A/AAAArecord for the public IP (optional)
  4. Do the basic configuration of ZNC (admin user + normal user)
  5. Enable "sasl" and "cert" modules ZNC
  6. Create a self-signed TLS certificate
  7. Get the certificates fingerprint
  8. Copy the certificate to the correct folder on your ZNC server (see cert module docs).
  9. Use your IRC client's direct connection to Freenode to add the correct certificate fingerprint to your Freenode account
  10. Configure your IRC client to connect to your ZNC instance. In Pidgin you can just create another account that co-exists with the "direct Freenode connection" account.
  11. Create the Freenode network in ZNC but set IRCConnectEnabled = false in the config
    • This prevents ZNC from trying to authenticate with Freenode, which in turn allows you to login to ZNC with your IRC client.
  12. Login to ZNC with your IRC client and enable the EXTERNAL mechanism as described on the sasl module docs.
  13. Set IRCConnectEnabled = true for the Freenode network

If this sounds complicated, that's because it is. At this point you should see in ZNC debug logs that ZNC is able to connect to and authenticate with Freenode. At this point you should also have a working connection from your IRC client to ZNC. So all that remains is to tweak the ZNC settings, like add channels you'd like ZNC to track (join) for you. Make sure that you use TLS for all connections, that is from the IRC client to ZNC as well as from ZNC to Freenode.

Samuli Seppänen
Samuli Seppänen
Author archive