ZNHOO Whatever you are, be a good one!


  1. ABCs
  2. Style
  3. Security
  4. server_default
  5. Server
  6. NickServ
  7. Identification
    1. Manually Identification
    2. SASL plain scheme
    3. SASL external scheme
      1. irc.pem
      2. Nick and Certificate Association
      3. Renew certificate
  8. Unaffilicated Cloak
  9. proxy - Tor
  10. Relay
    1. Weechat Relay
    2. Nginx Reverse Proxy

Simple Authentication and Security Layer (SASL) is a method that simplify identification to NickServ as the first step after connecting to IRC servers, before anything else happens. To connect to freenode using Tor, SASL is required. In this post, I will take Weechat and Freenode for example.


  1. Conncet through WebChat on browser.

    Just fill in nick and channel names on freenode webchat. HTTPS (ssl) establish a secure connection IRC server compared to HTTP.

    By Webchat, we cannot require other services.

  2. Connect in the clear.

    Similar to Webchat, the clear way connects directly without proxy or nick reservation (by NickServ).

    Should provide IRC hostname (chat.freenode.net) and port (6697) which are implicit in Webchat (webchat.freenode.net and 80).

    After connection, join a channel to talk.

  3. Connect through Clients (Weechat Irssi etc.).
  4. Nickserv - register/identify

    Reserve and identify your nick name.

  5. SASL authentication

    Automatic identification on connection by SASL. Weechat SASL supports different authentication mechanisms:

    • plain: plain text file password (default)
    • ecdsa-nist256p-challenge: challenge with public/private key
    • external: self-signed SSL certificate
  6. Connect with proxy (i.e. Tor).
  7. BNC (i.e. ZNC), or Weechat relay protocol.

    Weechat relay supports IRC protocol as well (to be compatibile with other IRC clients).


jim@laptop ~ $ weechat
  1. iset

    /script search iset
    Alt + i

    /save after changes. WeeChat also saves your up-to-date configuration any time you exit the program.

    From now on, manage WeeChat configurations by iset script.

  2. Some specific server commands (i.e. /ns) are not standard and cannot be recoginized by IRC client.

    irc.network.send_unknown_commands on
  3. This will close the buffer (or called tab) immediately when parting a channel.

    irc.look.part_closes_buffer on
  4. By default, server and core buffers are merged together. Use Ctrl+x to tear apart or:

    irc.look.server_buffer independent


  1. SSL

    irc.server_default.ssl on
    irc.server_default.ssl_verify on
    irc.server_default.sasl_mechanism external

    The client verify the server certificate and also the server needs to verify the client certificate - mutual authentication!

  2. Turn off ctcp to prevent others from querying IRC client information.

    *ctcp*  ""
    *ctcp* off
  3. Message

    irc.server_default.msg_part ""
    irc.server_default.msg_quit ""


Some extra optional default server arguments.

irc.server_default.nicks ""
irc.server_default.username ""
irc.server_default.realname ""


/server add freenode chat.freenode.net/6697 -ssl
/set irc.server.freenode.nicks "whoami"
/connect freenode

Check server_default section of ~.weechat/irc.conf. Common default server options can be set here (i.e. irc.server_default.ssl).


NickServ allows users to register nicks on IRC servers. Different IRC servers support different set of NickServ commands. We can check by /msg nickserv help beforehand. Make sure you are connected to IRC server with your desired nick by /nick new-nick command.

Don't execute the following commands in a channel tab, otherwise sensitive information (i.e. password) might be disposed and sniffed. All IRC commands are case-insensitive.

Take Freenode for example:

  1. /msg NickServ REGISTER password youremail@example.com

    In Weechat, the pasword youremail@example.com part will be displayed as asterisks. But don't worry as long as you put a space between password and youremail@example.com.

    After this command, Weechat will show password and youremail@example.com as plain text. IRC server uses the current nick (whoami) as the account name. So whoami is both the nick and account name registered on freenode. This special nick is called primary nick.

    In a while, you will receive an email, from which you should copy the verification command to complete the registration process:

  2. /msg NickServ VERIFY REGISTER whoami temporary-code

    This temporary-code is only for account registration confirm.

    Now, account name whoami has just one nick whoami associated on Freenode server, no one else can use nick whoami unless the correct password is identified (talked later on).

    OFTC server does need this extra confirmation step.

  3. /msg NickServ SET HIDEMAIL ON

    To keep your email address private, rather than displaying it publicly, mark it as hidden.

    For OFTC, it's /msg nickserv set private on.

  4. Group more nicks to whoami account.

    A Freenode account can reserve multiple nicks. First switch to a new nick and then group it to our account (as long as that nick is not reserved by others). Grouping nicks in this way gives you the benefit of having all your nicks covered by the same unaffiliated cloak.

    # switch to nick "whoami_"
    /nick whoami_
    /msg nickserv group

    To remove a nick from your account:

    /nick whoami
    /msg nickserv ungroup whoami_
  5. /reconnect

    It will prompt like whoami is registered… you must identify yourself…. To identify yourself as nick whoami:

    /msg NickServ identify whoami <password>


Manually Identification

If you don't configure SASL, then you have two choices:

  1. Manual identification after connection to server as above.

    /reconnect freenode
    /msg NickServ identify whoami <password> # freenode
    /msg NickServ identify <password> whoami # oftc
  2. Use freenode.command to run identify.

    irc.server.freenode.command "/msg NickServ identify whoami <password>"

    freenode.command runs a command automatically once connected to the server.

SASL plain scheme

OFTC disallow this scheme.

  1. irc.server.freenode.sasl_mechanism plain
  2. set irc.server.freenode.sasl_username whoami

    The username can be any one of your grouped nicks. But usually the primary nick (namely the account name) is used.

  3. /secure set freenode <password>

    Password will be recorded in ~/.weechat/sec.conf.

  4. irc.server.freenode.sasl_password "${sec.data.freenode}"

    Tell weechat where to get the password.

  5. irc.server.freenode.sasl_fail disconnect

    If SASL auth fail, disconnect.

SASL external scheme

  1. irc.server.freenode.sasl_mechanism external

    As long as sasl_mechanism is changed to external, sasl_username and sasl_password setting won't take effect.

  2. irc.server.freenode.ssl_cert "%h/ssl/freenode.pem"

    We should generate a self-signed X509 certificate before /reconnect.


OpenSSL is a cryptography toolkit implementing the SSL/TLS protocols and related cryptography libraries. Virtually, almost any packages using SSL/TLS require OpenSSL support, OpenSSH and Firefox (HTTPS) included.

The openssl program is a command line tool from OpenSSL, providing various cryptography functions. In this post, it will used to genrate self-signed X509 certificate.

jim@laptop ~ $ openssl req -newkey rsa:4096 -nodes -keyout irc.pem -sha256 -x509 -days 365 -out irc.pem -subj "/C=USA/ST=NewYork/L=NewYork/O=UST/OU=CS/CN=IRC"
jim@laptop ~ $ mkdir -p ~/.weechat/ssl
jim@laptop ~ $ mv irc.pem ~/.weechat/ssl/
  1. req: certificate request and certificate generating utility.
  2. nodes: no DES encryption. The RSA private key won't be encrypted by DES.
  3. keyout: the private key file.
  4. sha256: the digest to sign certificate.
  5. out: the certificate file.

    The keyout and out specify the same output file name, which means private key and certificate will be merged automatically.

  6. subj: certificate Subject field. If not provided on command line, openssl will prompt for user input.

Nick and Certificate Association

To achieve certificate authentication, we should add the certificate's SHA1 fingerprint to NickServ on freenode server

Get the SHA1 fingerpring:

jim@laptop ~ $ man x509
jim@laptop ~ $ openssl x509 -noout -text -sha256 -fingerprint -in freenode.pem

Add the fingerprint:

/whois nick
/msg nickserv cert list
/msg nickserv cert add/del [sha1]


The fingerprint value can be ommited and NickServ on the server will automatically calculate the value.

Finally reconnect to identify nick by SASL external. You can see a line:

gnutls: sending one certificate

during connection. Run /whois nick to see:

has client certificate fingerprint:

Renew certificate

Upon expiration, we need to renew the certificate. Acutally, renewing is to create a new certificate herein.

# Extract private key from certification file (PEM)
~ # openssl rsa -in irc.pem -out irc.key
# Extract public certificate from certification file (PEM)
~ # openssl x509 -in irc.pem -out irc.crt
# Converts the certificate into a certificate request (PEM)
~ # openssl x509 -x509toreq -in irc.crt -out irc.csr -signkey irc.key
# Create a new certification for one year
~ # openssl x509 -req -days 365 -in irc.csr -out irc.crt.new -signkey irc.key
# Concatenate the new certificate and original key
~ # cat irc.crt.new irc.key > irc.pem.new
# Chceck validity
~ # openssl x509 -noout -text -in irc.pem.new

Remember to add the new certificate's fingerprint to IRC server and del the old one.

Unaffilicated Cloak

  1. Unaffiliated Cloak is to hide your IP from IRC channels.
  2. To obtain a cloak, just join the official #freenode channel, ask for one there and reconnect.

    When channel staff notices your request, you might get cloaked. Unaffiliated Cloak applies to all channels on Freenode server.

  3. To get a cloak on OFTC is much easier:

    /msg nickserv SET CLOAK ON

proxy - Tor

Suppose you would like to connect to IRC server by proxy, how to set?

  1. Add proxy

    /proxy add tor socks5 9050

    This will tell Weechat that a proxy named 'tor' is added.

  2. Server copy

    Suppose we find Tor proxy is troublesome someday, updates to current server must be restored. To ease configuration, issue the following command:

    /server copy freenode freenode-tor

    Update freenode-tor configuration instead.

  3. Enable proxy for IRC server

    /set irc.server.freenode-tor.proxy tor
  4. However Freenode does not allow Tor connection to chat.freenode.net.

    The server hostname should be changed to hidden url freenodeok2gncmy.onion while keeping the original port.

    /set irc.server.freenode-tor.addresses freenodeok2gncmy.onion/6697
  5. Onion certificate.

    Cannot wait to reconnect? Yeah, me too. The server certificate cannot be verified since onion url is not certified by almost all CAs.

    gnutls: the hostname in the certificate does NOT match "freenodeok2gncmy.onion"

    Currently, only a few onion url is signed by digicert.

    The solution is maully trust fetched certificates in which though the hostname is freenode.net instead of freenodeok2gncmy.onion.

    When connected to chat.freenode.net, Weechat usually receive three certificates with their SHA-1 fingerprints listed. Collect those fingerprints and assign to:

    /set irc.server.freenode-tor.ssl_fingerprint fp1,fp2,fp3,...

    Alternatively we can turn off certificate verification:

    /set irc.server.freenode-tor.ssl_verify off

    If IRC client supports key pinning, we can choose to trust freenode's public key fingerprint instead certificate's fingerprint which benefits us in that the former keep consistent while the later varies in accord with the real freenode server you connect to. Unfortunately, Weechat does not.

    If Weechat throws errors like:

    gnutls: peer's certificate is NOT trusted

    gnutls: peer's certificate issuer is unknown

    Please check whether weechat.network.gnutls_ca_file is correctly set. On Centos, it should be /etc/pki/tls/certs/ca-bundle.crt; but on archlinux, it should be /etc/ssl/certs/ca-certificates.crt.

    Recently, freenode Tor servers do not report certificate fingerprint anymore. We can manually print fingerprint by:

    ~ $ torify gnutls-cli --tofu freenodeok2gncmy.onion:6697  --print-cert | openssl x509 -noout -text -sha256 -fingerprint -in /dev/stdin
    ~ $ sed 's/://g' <<< "fingerprint delimited by colons"


To preserve or share IRC message, we can use Bounced Network Connection (BNC) like ZNC. ZNC allows connections from different end users and relay message for each of them.

To simplify the setup, we can use the standard IRC relay and its extended version - weechat relay. Weechat supports both the weechat relay and the standard IRC relay.

If you add a standard IRC relay in Weechat, you can connect to it with any IRC client like HexChat, Irssi etc. The weechat relay runs over Websocket and only allows connections from clients that support Websocket like glowing-bear or Weechat android.

This section demonstrates the following schema:

  1. Create a weechat relay instance on a remote server, bound to loopback.
  2. Nginx as a reverse proxy.
  3. Glowing-bear or Weechat-android as the front-end client.

Weechat Relay

  1. Add relay

    /relay add ipv4.weechat 9000  # plaintext relay without SSL
    /set relay.network.bind_address ""
    /set relay.network.password MY-RELAY-PASSWORD
    /set relay.network.max_clients 3

Nginx Reverse Proxy

  1. Nginx HTTPS sample

    server {
        listen 80;
        # enforce https
        return 301 https://$server_name$request_uri;
    server  {
        ssl_certificate "/etc/letsencrypt/live/irc.example.com/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/irc.example.com/privkey.pem";
  2. Add nginx proxy

    # Set connection header based on upgrade header
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    # Protect from brute force attack
    limit_req_zone $binary_remote_addr zone=weechat:10m rate=5r/m;
    server {
        listen 80;
        server_name irc.example.com;
        return 301 https://$server_name$request_uri;
    server {
        listen 443 ssl http2;
        server_name cloud.example.com;
        ssl_certificate "/etc/letsencrypt/live/irc.example.com/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/irc.example.com/privkey.pem";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout 10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        location /weechat {
             proxy_http_version 1.1;
             proxy_set_header Upgrade $http_upgrade;
             proxy_set_header Connection $connection_header;
             proxy_set_header Host $http_host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_read_timeout 3600;
             limit_req zone=weechat burst=1 nodelay;
  3. Acutally, We can connect to the weechat relay directly as long as it is configured to have a public certificate.

    1. Create a SSL weechat relay.
    2. Configure relay.network.ssl_cert_key and sslcertkey.
    3. To make things even simpler, why not just SSH into the remote server and use Weechat there?