IRC server

Lightweight and easily operable IRC daemon with SSL and systemd socket activation support. Allows for basic chat scenarios with essential IRC functionality.

Though originating from even before the early ’90s, IRC still is viable today as well-known client-server chat protocol that enables simple group and one-on-one chats. A variety of clients is available to choose from for virtually any platform – whether mobile, desktop, or commandline.

Existing IRC daemons are often feature-driven and support legacy scenarios, such as server clustering, advanced channel and nick modes, or fine-granular kick/ban access control. This lightweight and easily operable IRC server puts emphasis on basic chat scenarios with essential IRC functionality. Its features currently include SSL encryption, NickServ registration, file transfers, UTF-8, IPv6, global operator status, persistent or temporary channels, away status, IP address cloaking, chrooting, and systemd on-demand activation.

Configuration & Usage

After installation, the IRC server only needs a configuration file:

./ircd [--systemd] config-file

Optionally, listening sockets can be inherited from systemd, see below for details. The config file can take the following options:

port
Port to listen on (required). Can be stated multiple times for supporting more than a single port.
server_name
The global IRC server/domain name (required).
server_pw
Server-wide password that clients must provide (no password required per default).
oper_pw
Global password for gaining operator privileges (disabled per default).
channel (#|@|+)name[:topic]
Create a pre-defined, persistent channel. Can be stated multiple times. If the channel name is @-prefixed (instead of the usual #), only operators may join. A + prefix requires nickserv registration (voice) before joining. The topic can be set after a colon.
oper_channels (0|1)
Enable or disable the creation of new channels for operators (default 0).
nickserv_dir
NickServ database directory. Disabled if not set. See below for details.
chroot_user
Username to drop to when starting as root (required then, none per default).
chroot_dir
Directory to chroot into when starting as root (disabled per default).
ssl (0|1)
Enable or disable SSL support for all connections (disabled per default).
ssl_key
Private key in PEM format when using SSL (read before chroot).
ssl_cert
Certificate or full certificate chain in PEM format when using SSL (read before chroot).

For example, the following configuration creates a password-protected IRC server on SSL port 6697 with two channels, one of which additionally requiring the operator password. Root privileges will be dropped, but would not be required in the first place.

port 6697
server_name hackitu.de
server_pw gimmeIrc
oper_pw p4zzw0rd
channel #hackitu.de:Welcome to IRC!
channel @techtalk:Opers only! (╯°□°)╯︵ ┻━┻
oper_channels 0
chroot_user nobody
chroot_dir /var/empty
nickserv_dir nickserv-db
ssl 1
ssl_key /etc/key.pem
ssl_cert /etc/cert.pem

Logs will be written to stderr, suitable for redirection into a file or to syslog via systemd or e.g. logger.

IRC commands

Only a minimal subset of IRC commands are supported, in particular those required for seamless operation, usability, and compatibility. The following list of well-known commands provides full functionality for basic chat usage.

PASS <password>
Provides the global server password (if required by server_pw config) before being able to register with user- and nickname.
NICK <nick>
Sets or changes the own nickname.
USER <username> <ignored> <ignored> <realname>
Set the username and realname to be displayed to other clients. The values for hostname and servername are not used and will be ignored.
CAP <LS|END>
No additional capabilities are supported. These commands are thus ignored, but will be recognized for compatibility reasons.
OPER <nick> <password>
Grants yourself operator privileges using the global operator password (if set by oper_pw). Afterwards, you can join oper-only channels, set topics, and see other client’s IP addresses. If NickServ is enabled, only already identified clients may become operators.
MODE <nick> <mode>
Setting user modes is not supported. The own mode +i is however recognized for compatibility reasons.
MODE <channel>
Returns channels modes. Currently, this is a subset of +ntOPzZ.
AWAY [message]
Sets an away message or resets the away status. Away messages will be automatically replied in private/direct conversations. The away status will also be shown by the WHO command.
LIST
Returns a list of all available channels, including topic and number of members.
JOIN <channel[,channel…]>
Joins or creates channels. Creating channels or joining oper-only ones requires operator status, if allowed by oper_pw and oper_channels.
TOPIC <channel> [topic]
Gets or sets a channel’s topic. Setting topics requires operator status, if enabled by oper_pw.
WHO <channel>
Returns a list of current channel members, if on the same channel. Includes nick-, user-, and realname, away- and oper-status, and remote IP (for operators).
PING [message] & PONG
Automatically exchanged commands for keepalive and disconnect detection.
PRIVMSG <channel|nick> <message>
Sends an actual chat message to a joined channel or a particular client only. Color- and action-codes are preserved, so pseudo-commands such as ME provided by client software should work.
PART <channel> [message]
Leaves a channel with an optional status message.
QUIT [message]
Disconnects from the server with an optional status message.
NICKSERV command […]
Builtin command as alternative to direct NickServ messages. Supported subcommands are register, identify, and drop. See below for details.

There is lots of IRC documentation with more details available online. This list is thus mere for reference and documentation purposes. In addition, there are lots of GUI-based IRC clients available for virtually any platform.

NickServ

NickServ is one of the traditional IRC services, usually implemented as bot with special capabilities. In order to protect against impersonation, it allows to register nicks such that other clients can rely on the same person being behind a particular nickname. In consequence, when using a previously reserved nick, the corresponding password must be provided.

The following subset of NickServ commands is supported:

register [nick] password [email]
Enables protection of the currently used nick.
identify [nick] password
Upcoming sessions must authenticate against a registered nick by using this command before being able to use it in conversations.
drop [nick] [password]
Removes protection from the currently used, identified nick.

The service can be reached by using the /nickserv command or via private messages to NickServ. Most IRC client software support an identify password in their settings.

When connecting using a previously registered nick, no channels can be joined and no messages can be sent at first – it’s “invisible” until a successful identify command authorizes its usage. Amongst others, using the built-in NickServ service has the following additional implications and advantages:

Per default, passwords are stored hashed using crypt() (SHA-512/$6$).

Build & Installation

The binary can be built from source with default settings by simply typing make. Some of the most relevant compile-time Makefile options can be changed in the CFLAGS:

USE_OPENSSL
Enable SSL support (set per default). Requires the -lssl and -lcrypto linker flags.
USE_NICKSERV
Enables NickServ functionality. Otherwise, all NickServ commands will be declined as if no database directory would be given. Requires the -lcrypt linker flag for hashed password storage.
NDEBUG
Disables assertions and valgrind includes.
CIPHER_LIST
Changes the SSL ciphers to something different than the standard value EECDH+HIGH:EDH+HIGH:RSA+HIGH.
NO_STRICT_CRLF
Also allows newlines as IRC message separator. Usually, only carriage return + line-feed line-endings are permissive. This flag is mainly useful for debugging or non-compliant clients.
MESSAGE_LOG
Logs all IRC messages received or sent. Due to privacy concerns, this should only be enabled for debugging purposes.
NO_NODELAY
Disables the TCP_NODELAY socket option. This might introduce additional delay as multiple small packets are buffered and combined.
SOCK_TIMEOUT, SOCK_KEEPALIVE
Socket i/o and client timeout in seconds. An IRC ping interval is chosen accordingly. When tcp_keepalive is used, timeouts can be detected more early and can be prevented if caused by firewall/NATting. (Default: 60, 1)
LOG_TIME_PREFIX
Prefixes all log messages with the current timestamp. Usable for example when logging to a plain file instead of using syslog.
USE_SYSTEMD
Enables support for inheriting listening file descriptors from systemd (set per default). See below for details. Requires the -lsystemd[-daemon] linker flag.

After build, the binary can be used locally or can be installed in /usr/local/bin/ by make install. Or use the pre-built 64bit .deb package provided below.

Systemd socket activation

While still being controversial, systemd has been adopted by many distributions, in especially as init replacement.

One of the features it provides are socket units, that – in our case – will listen at TCP ports and start the corresponding service on-demand as soon as a client wants to connect. Instead of opening own listening sockets, the service can then obtain the sockets that are already ready for accepting connections by sd_listen_fds(). Inherited sockets are left open after shutdown, thus providing the possibility for saving resources when idling and seamless re-activation.

The following /etc/systemd/system/ircd.socket file will enable socket activation for two different ports to listen on:

[Socket]
ListenStream=6667
ListenStream=6697

[Install]
WantedBy=sockets.target

It implicitly references a corresponding ircd.service unit file, that will be activated upon incoming connections:

[Unit]
Description=IRCd
#Requires=network.target
#After=network.target

[Service]
ExecStart=/usr/local/bin/ircd --systemd /etc/ircd.conf
StandardError=syslog

#[Install]
#WantedBy=multi-user.target

When using socket activation, ExecStart is the only strictly required setting. Permanent or manual activation of the unit without relying on systemd sockets can be achieved by adding the commented dependencies. Afterwards, use systemctl daemon-reload followed by systemctl enable ircd.socket or systemctl enable ircd.service, according to the preferred activation mode. The status can be checked by systemctl status 'ircd.*'.

Code & Download