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
andoper_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
, anddrop
. 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:
- Protection from accidental or intentional impersonation for the peers to rely on.
- Distinguished status highlighted in most client software (authenticated nicks receive the voice mode).
- Only identified clients may become operators.
- Special channels can be created that require all members to be authenticated.
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.*'
.