Set block

From UnrealIRCd documentation wiki
Jump to navigation Jump to search
Other languages:

The set block is used to tweak and configure the server settings.

Sharing settings

If you (already) run multiple IRC servers then have a look at Sharing settings between servers to ease the burden when updating settings. The set block is an ideal candidate to be shared.

Syntax used in this documentation

As described in Configuration file syntax we will refer to settings like set::options::hide-ulines or set::auto-join. You should NOT write set::options::hide-ulines in the configuration file! It's just a shorthand, an abbreviation. What we actually mean is that you should write them out like this:

set {
        options {
        auto-join "#something";

Or you could put them in separate set blocks like this:

set {
        auto-join "#something";

set {
        options {

Or even just:

set { options { hide-ulines; }; };
set { auto-join "#something"; };

If the above is unclear, then maybe have another read at the Configuration file syntax article.

It is perfectly fine to have multiple set { } blocks! In fact it's quite normal to have one block with network-wide settings, and another set block with server-specific settings. We generally don't recommend having more than 2 set blocks because then it is too easy to loose track of them ("what settings is where?"), but technically it is perfectly possible and permitted.

Available settings


Syntax: set::kline-address <email-address>

The email address that K:line questions should be sent to. This value must be specified. See also set::reject-message::kline if you want a more custom disconnect message on KLINE/ZLINE.


Syntax: set::gline-address <email-address>

The email address that G:line questions should be sent to. See also set::reject-message::gline if you want a more custom disconnect message on GLINE/GZLINE.


Syntax: set::modes-on-connect <+modes>

The modes that will be set on a user at connection.


Syntax: set::modes-on-oper <+modes>

The modes that will be set on a user when they /oper.


Syntax: set::snomask-on-oper <+modes>

The snomask that will be set on a user when they /oper.


Syntax: set::modes-on-join <+modes>

The modes that will be set on a channel when it is first created. Not all modes can be set using this command.


Syntax: set::level-on-join <none|voice|halfop|op|protect|owner>

The mode that a user will get when he's the first to join a channel. The default is 'op' (channel operator).


Syntax: set::restrict-usermodes <modes>

Restrict users to set/unset the modes listed here (don't use + or -). For example you can set +G in modes-on-connect and G in restrict-usermodes, that way you can force all users to be +G and unable to do -G.


Syntax: set::restrict-channelmodes <modes>

Restrict users to set/unset the channelmodes listed here (don't use + or -). For example you can set +G in modes-on-join and G in restrict-channelmodes, that way you can force all (new) channels to be +G and unable to do -G.

IMPORTANT: Users may evade these restrictions via the MLOCK command from Services. If you use anope, we suggest you restrict the modes there too via anope's nomlock feature, see the example below.

Example to force and restrict channel modes

This will make it so all channels are always +ntG and that users cannot set +L:

In UnrealIRCd:

set {
    modes-on-join "+ntG";
    restrict-channelmodes "ntGL";

In anope, in the module chanserv block:

    nomlock = "L"
    require = "ntG"

Remember that the channel modes on the Anope side will only be applied to newly registered channels.


Syntax: set::restrict-extendedbans <types|*>

Don't allow users to use any extended bans ("*") or disallow only certain ones (eg: "qc").


This allows you to restrict a certain command to users depending on: how long they are connected, if they are identified to Services or if they are using WebIRC_block, and their reputation score. IRCOps can always bypass any restrictions.

You can restrict any command, simply by specifying the command, and there are also 4 special types: "private-message", "private-notice", "channel-message" and "channel-notice" (that under the hood will restrict PRIVMSG and NOTICE).

Example configuration:

set {
        restrict-commands {
                /* completely disable this command: */
                somecommand {

                /* only allow this for identified users: */
                links {
                        exempt-identified yes;

                /* only allow this for webirc users: */
                join {
                        exempt-webirc yes;

                /* impose a connect-delay restriction, but with exemptions */
                list {
                        connect-delay 60;
                        exempt-webirc yes;
                        exempt-identified yes;
                        exempt-reputation-score 24;

                /* impose a connect-delay restriction with no exemptions (except ircops) */
                invite {
                        connect-delay 120;
                private-message {
                        connect-delay 10;

The option connect-delay will impose the restriction for the specified time (eg: 60 meaning 60 seconds). This can be useful against spammers since they usually spam quickly after connecting (before they are catched by opers or channel operators). If you don't set a connect-delay then the command will be disabled for all users, unless you specified any exemptions (see next).

The option exempt-identified will exempt the restrictions to users who are identified to Services, in other words: are authenticated users. These users normally went through a registration procedure that provides sufficient (but minimal) trust that they can use the command straight away, without any connect delay restrictions.

The option exempt-webirc will exempt the restrictions to users who are connecting via a WebIRC block. If you set this option, then you trust such users enough, that they can use the command straight away, without any connect delay restrictions.

The option exempt-reputation-score means that if the reputation score is equal or above this number then the user bypasses this restriction.


Syntax: set::auto-join "<channels>"

The channel(s) a user will be forced to join at connection. To specify more than one channel use a comma separated list. [Note: don't forget to add quotes, like: auto-join "#chan"]


Syntax: set::oper-auto-join "<channels>"

The channel(s) a user will be forced to join when they /oper. To specify more than one channel use a comma separated list. [Note: don't forget to add quotes, like: oper-auto-join "#chan"]


Syntax: set::anti-spam-quit-message-time <timevalue>

A time value specifying the length of time a user must be connected for before a /quit message will be displayed. Used to prevent spam. A time value is a numeric string with d meaning days, h meaning hours, m meaning minutes, and s meaning seconds, for example 1d2h3m means 1 day, 2 hours, 3 minutes.


Syntax: set::prefix-quit <text-to-prefix-quit>

Sets the text that will be used to prefix a quit message. If this value is set to 0 then the standard "Quit:" is used.


Syntax: set::static-quit <quit message>

Sets a static quit message that will be sent whenever a client logs off the network. This eliminates the need for anti-spam-quit-message-time, as well as the set::prefix-quit. It will NOT replace ERRORS with the static-quit message.


Syntax: set::static-part <no|yes|part message>

A value of 'yes' strips all part comments, a value of 'no' makes part just work as usual, anything else will be used as a part comment (eg: static-part "Bye!") but this can be quite annoying, so use with care.


Syntax: set::who-limit <limit>

Sets the limit for the maximum number of matches that will be returned for a /WHO, the default is 100.

This limit does not apply for WHO requests for a specific channel, eg WHO #channel. The limit also does not apply to IRCOps.


Syntax: set::silence-limit <limit>

Sets the limit on the maximum SILENCE list entries. If this directive is not specified, a limit of 15 is set.


Syntax: set::maxbans <limit>

Sets the limit on the maximum amount of bans (+b) allowed per channel. The default is 60. The same limit is applied to exempts (+e) and invex (+I) as well. If you change this, be sure to also take a look at maxbanlength (see next)!


Syntax: set::maxbanlength <limit>

Similar to above, but sets the maximum amount of characters for all bans added up together, so basically this puts up a limit on the (semi-)maximum amount of memory all channel bans on a channel can take. The default is 2048 (bytes). With the default set::maxbans of 60 this allows 2048:60=34 characters per ban on average. Note that if you change this, the same limit is also applied to excepts (+e) and invex (+I).


Syntax 1: set::allow-user-stats <stats-list-in-letters>
Syntax 2: set::allow-user-stats {<long-stats-flag1> <long-stats-flag2>}

Specifies a list of /STATS flags that users may also see (non-IRCOps). The default is "" (empty), which means regular users may not see any /STATS.

Be careful if you tweak this, some stats are not meant to be exposed to regular users and the information contained in them will often aid attackers / "bad guys".


Syntax: set::max-stats-matches <count>
Only available in UnrealIRCd 5.0.8 and above

If, as an IRCOp, you do STATS gline and there are thousands of glines then in the past the oper would be disconnected due to flooding ("Max SendQ exceeded"). With max-stats-matches you limit the number of *LINE entries that are outputted. The default is 1000 entries which should be sufficient protection (assuming your oper class has a sendq of 500K or more). You can set this limit higher or lower, or to zero to disable the protection (no limit).


Syntax: set::min-nick-length <length>

Specifies the minimum required length of a nick name. This defaults to 0 which means there's no minimum. The maximum is 30 (NICKLEN) but it should still be smaller than (or equal to) set::nick-length.


Syntax: set::nick-length <length>

Specifies the maximum length of a nick name. This default and maximum is 30 (NICKLEN). This setting can only be used to impose a shorter nick length than that.


Syntax: set::topic-length <length>

Specifies the maximum length of a channel topic. This default and maximum is 360, or 340 if set::topic-setter is set to 'nick-user-host'. This setting can only be used to impose a shorter length.


Syntax: set::away-length <length>

Specifies the maximum length of the away reason in /AWAY. The default is 307 and the maximum is 360.


Syntax: set::quit-length <length>

Specifies the maximum length of the quit reason in /QUIT. The default is 307 and the maximum is 395.


Syntax: set::kick-length <length>

Specifies the maximum length of the kick reason in /KICK. The default is 307 and the maximum is 360.


Syntax: set::maxchannelsperuser <amount-of-channels>

Specifies the number of channels a single user may be in at any one time. IRCOps are exempt from this restriction.


Syntax: set::maxdccallow <amount-of-entries>

Specifies the maximum number of entries a user can have on his/her DCCALLOW list.


Syntax: set::channel-command-prefix <command-prefixes>

Specifies the prefix characters for services "in channel commands". Messages starting with any of the specified characters will still be sent even if the client is +d ("deaf"). The default value is "`!." which is normally a good setting.


Syntax: set::allowed-nickchars { <list> }

Character sets / languages to allow in nick names, see Nick Character Sets.


Syntax: set::allowed-channelchars [utf8|ascii|any]

Which characters to allow in channel names. This setting must be the same on all servers.

There are 3 possible settings (utf8, ascii and any):

Setting Allowed characters Comment
utf8 All valid UTF8 characters This is the default as of UnrealIRCd 5. It should be suitable for nearly everyone since UTF8 is the de-facto standard on IRC nowadays.
ascii Only a-z/A-Z/0-9 and a few other ASCII characters This is a strict setting. It can be used if you don't want any confusion with channel names, no UTF8, etc. Technically this would be safest. Freenode uses this in their software.
any Almost all characters are permitted This is a very loose setting and was the default in UnrealIRCd 4.x. The problem is that this breaks text websocket clients. It is NOT a recommended setting.

The following characters are ALWAYS REJECTED: ASCII values below 32 (control characters), the space character, comma, colon.

Note that if you mix UnrealIRCd 4 and UnrealIRCd 5 servers on your network, then some channels which are considered illegal by this setting will be unjoinable on the UnrealIRCd 5 side. This will be especially noticeable if you use a strict setting like ascii, but may also happen for some channels if you use utf8. This problem will disappear once all of your servers are on UnrealIRCd 5. The alternative is to run with a setting of any during the transition, and then once everything is on UnrealIRCd 5, switch over to utf8. However, it is easy to forget about that last step.


Syntax: set::allow-userhost-change [never|always|not-on-channels|force-rejoin]

Specifies what happens when the user@host changes (+x/-x/chghost/chgident/setident/vhost/etc). never disables all the commands, always does always allow it even when in channels (may cause client desyncs) [default], not-on-channels means it's only allowed when the user is not on any channel, force-rejoin will force a rejoin in all channels and re-op/voice/etc if needed.


Syntax: set::topic-setter [nick|nick-user-host]

You can see who set the TOPIC by doing /TOPIC #channel. By default this only shows the nick of the person who set the topic. If you set this option to nick-user-host then it will show the nick!user@host instead.


Syntax: set::ban-setter [nick|nick-user-host]

You can see who set a ban/exempt/invex (+beI) by doing /MODE #channel b (or similar). By default this only shows the nick of the person who set the topic. If you set this option to nick-user-host then it will show the nick!user@host instead.


Syntax: set::options::hide-ulines

If this is present, Ulined servers will be hidden in /MAP and /LINKS for regular users (non-ircops). This is a very common thing to do.


Syntax: set::options::flat-map

If this is present, all servers will appear as directly linked in /map and /links, thus you can no longer see which server is linked to which. This is a little help against (D)DoS attacks because evil people now no longer can easily see the 'weak points'.


Syntax: set::options::show-opermotd

If present the opermotd will be shown to users once they successfully /oper.


Syntax: set::options::identd-check

If present the presence of an identd server will be checked and the returned value will be used for the username. If no ident request is returned or the identd server doesn't exist, the user's specified username will be prefixed with a ~. If this value is omitted no such check is made.


Syntax: set::options::show-connect-info

If present notices showing "ident request", "hostname lookup", etc. will be displayed when a user connects.


Syntax: set::options::dont-resolve

Don't do any resolving (DNS lookups) on users that connect. This can be useful if many of your users don't have a host, to speed up connecting. Note that this also means you cannot have host-based allow blocks.


Syntax: set::options::mkpasswd-for-everyone

Makes it so the /mkpasswd can be used by anyone instead of oper-only, usage of the command by non-opers is sent to the EYES snomask.


Syntax: set::options::allow-part-if-shunned

Allow shunned user to use /part.


Syntax: set::options::fail-oper-warn

If present, a user will be notified that his/her failed /oper attempt has been logged.


Syntax: set::options::allow-insane-bans

Allow insane broad bans like /GLINE *@*.xx. This makes it very easy to accidentally ban everyone on your network, so use with great care!


Syntax: set::options::disable-cap

Disable IRC Client Capabilities Extensions (CAP). Note that this makes SASL and various other features unavailable or harder for clients to use.


Syntax: set::dns::bind-ip <ip>

Specifies the IP to bind to for the resolver, rarely ever needed.


Syntax: set::network-name <name-of-network>

Specifies the name of the network on which this server is run. This value should be exactly the same on all servers on a network.


Syntax: set::default-server <server-name>

Defines the name of the default server to tell users to connect to if this server is full.


Syntax: set::default-ipv6-clone-mask

The default IPv6 clone detection mask. See allow::ipv6-clone-mask. The default value for this setting is 64.


Syntax: set::services-server <server-name>

Specifies the name of the server that the services bots are connected to. See also Services.


Syntax: set::stats-server <server-name>

Sets the name of the server on which the stats bot is located. If stats are not run this value may be left out.


Syntax: set::sasl-server <server-name>

Sets the name of the server to which SASL authenticate messages should be sent.


Syntax: set::help-channel <network-help-channel>

Sets the name of the help channel for this network.


Syntax: set::cloak-method [ip|host]

This sets the method to use when cloaking a user. The default is host which will use hostname-based cloaking (and fallback to IP-based if no host is available). The alternative is to set this to ip which will make UnrealIRCd always do IP-based cloaking. This results in a XX.YY.ZZ.IP cloaked host which provides more anonymity. IRCOps can still see the real hostname of the user and GLINEs and such still work as well.


Syntax: set::cloak-keys { "key1"; "key2"; "key3"; }

UnrealIRCd has a feature called Cloaking. The keys you specify here are used to generate such a +x host. ALL servers on the same network must use the same keys and they must be kept secret.

Each key consists of 50-100 characters, the characters should contain a mixture of: lowercase (a-z), uppercase (A-Z) and digits.

On *NIX you can use ./unrealircd gencloak to generate 3 random keys.


/* This is just an example, don't actually use these keys yourself!! */
set {
    cloak-keys {

Syntax: set::hiddenhost-prefix <prefix-value>

Defines the prefix that will be used on hiddenhosts (+x). This is usually three or four letters representing the network name. Linked servers must have the same hidden-host prefix for channel bans to function properly.


Syntax: set::tls::certificate <filename>

Specifies the filename where the server's SSL certificate is located. The default is server.cert.pem.


Syntax: set::tls::key <filename>

Specifies the filename where the server's SSL private key is located. The default is server.key.pem.


Syntax: set::tls::trusted-ca-file <filename>

Specifies the filename where the certificates of the trusted CAs are located. The default is curl-ca-bundle.crt (shipped with UnrealIRCd)


Syntax: set::tls::protocols <list-of-protocols>

Specifies which SSL/TLS protocols are permitted. Available options are: All, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3 (the latter when it becomes available). Prefix the protocol with a - (minus sign) to remove it.

Example: set { tls { protocols "All,-TLSv1,-TLSv1.1"; /* permit only TLSv1.2 and up */ }; };

See SSL Ciphers and protocols for more information and suggestions on a good setting.


Syntax: set::tls::ciphers <cipherlist>

Specifies which ciphers to be allowed for TLSv1.0, TLSv1.1 and TLSv1.2. See SSL Ciphers and protocols for more information and suggestions on a good setting.


Syntax: set::tls::ciphersuites <ciphersuitelist>

Specifies which ciphersuites to allow for TLSv1.3. See SSL Ciphers and protocols for more information.


Syntax: set::tls::ecdh-curves <curvelist>

Specifies which ECDH(E) curves to be allowed. See SSL Ciphers and protocols for more information and suggestions on a good setting.


Syntax: set::tls::renegotiate-bytes <value>

Specifies after how many bytes an SSL session should be renegotiated (eg: 20m for 20 megabytes).


Syntax: set::tls::renegotiate-timeout <timevalue>

Specifies after how much time an SSL session should be renegotiated (eg: 1h for 1 hour).


Syntax: set::tls::options::fail-if-no-clientcert

Forces clients that do not have a certificate to be denied. This would be an unusual setting to enable.

This option does not provide any security. A user can simply generate a client certificate and use it to connect, no verification is done.


Syntax: set::tls::options::no-starttls

Disable STARTTLS. STARTTLS allows clients to use SSL/TLS on regular (non-SSL) ports, which is normally a good thing.


This sets the outdated SSL/TLS protocols. It is used for set::outdated-tls-policy.

The default setting is "TLSv1.0,TLSv1.1" which marks TLSv1.0 and TLSv1.1 as outdated. In case you wonder, SSLv3 is not listed here because UnrealIRCd never allows such connections anyway.


This sets the outdated SSL/TLS ciphers. It is used for set::outdated-tls-policy.

The default setting is "AES*" which requires some explanation: This effectively marks all ciphersuites without Forward Secrecy as outdated. It stills allows AES perfectly fine, but only in combination with ECDHE/EECDH, which provides Forward Secrecy. For example AES128-SHA256 would be considered outdated and ECDHE-RSA-AES128-GCM-SHA256 is not.

If you use a weird ::ciphers setting, for example one that allows CAMELLIA, then you may have to tweak ::outdated-ciphers also. This is, however, an extremely uncommon configuration.


This configures Strict Transport Security in UnrealIRCd.

Read SSL/TLS - Strict Transport Security for information on how to deploy this.


/* Read
 * before deploying this.
set {
        tls {
                sts-policy {
                        port 6697;
                        duration 5m;

IMPORTANT: Invalid/untrusted SSL/TLS certificates or a non-working TLS port WILL LOCK YOUR USERS OUT if you use sts-policy!


The plaintext-policy block allows you to configure what UnrealIRCd should do with users/opers/server who are not connected via SSL/TLS.

set {
    plaintext-policy {
        user allow; /* must be one of: allow, warn, deny */
        oper deny; /* must be one of: allow, warn, deny */
        server deny; /* must be one of: allow, warn, deny */

An action of allow will allow the operation. The warn action will make the server send a warning notice. The deny action will reject the user/oper/server, meaning that the user cannot connect, the IRCOp cannot /OPER and the server may not link.

Optionally you can set a set::plaintext-policy::user-message and set::plaintext-policy::oper-message to change the default UnrealIRCd warn/deny text the user/ircop will receive.


The outdated-tls-policy block allows you to configure what UnrealIRCd should do with users/opers/server connecting with an outdated SSL/TLS protocol or cipher.

set {
    outdated-tls-policy {
        user warn; /* must be one of: allow, warn, deny */
        oper deny; /* must be one of: allow, warn, deny */
        server deny; /* must be one of: allow, warn, deny */

An action of allow will allow the operation. The warn action will make the server send a warning notice. The deny action will reject the user/oper/server, meaning that the user cannot connect, the IRCOp cannot /OPER and the server may not link.

To decide which protocol and ciphers are considered outdated, the set::tls::outdated-protocols and set::tls::outdated-ciphers settings are used.

Optionally you can set a set::outdated-tls-policy::user-message and set::outdated-tls-policy::oper-message to change the default UnrealIRCd warn/deny text the user/ircop will receive.


Syntax: set::ident::connect-timeout <amount>

Amount of seconds after which to give up connecting to the ident server (default: 3s).


Syntax: set::ident::read-timeout <amount>

Amount of seconds after which to give up waiting for a reply (default: 7s).


Syntax: set::handshake-timeout <amount>

Amount of seconds that a connection may be in the "handshake state", that is: the period between a TCP/IP connection accept() and the user getting online after NICK/USER have been received and DNS and ident lookups have completed (if those are enabled).

The default is 30 which is a safe value for everyone. Be careful if drastically lower this. DNS lookups, ident lookups and the handshake may take more time than you may think in some cases. You can probably set this to a value like 20 if you like. However, if you set this setting too low then you risk locking everyone out when for example your DNS server is a little slow (eg: under attack).


Syntax: set::sasl-timeout <amount>

The maximum time for SASL to take place. Time starts at the AUTHENTICATE command. The default is 15 seconds.

This protects against misbehaving or extremely laggy SASL servers (Services). Otherwise, a misbehaving server could lead to people no longer being able to connect.


Syntax: set::anti-flood::connect-flood <count>:<period>

Connection flood protection: limits the number of connection attempts from each IP to 'count' per 'period' seconds. Default is 3 per 60. This feature is also referred to as connection throttling.

UnrealIRCd also has Connthrottle which will rate limit the number of connection attempts in total (so not per-IP).

Note that connection throttling is an important security measure. It provides primary and secondary protection against DoS, flood and brute force attacks, both for handshake and fully registered connections. If you disable it or set it very permissive (eg 6 per 60 seconds) then you severely degrade these protections.


Syntax: set::anti-flood::nick-flood <count>:<period>

Nickflood protection: limits nickchanges to 'count' per 'period' seconds. For example nick-flood 4:90 means 4 per 90 seconds, the default is 3 per 60.


Syntax: set::anti-flood::join-flood <count>:<period>

Join flood protection: limits joins (to the same channel) to 'count' per 'period' seconds. For example join-flood 4:90 means 4 per 90 seconds, the default is 3 per 90. Previously this was configured through channel mode +j.


Syntax: set::anti-flood::away-flood <count>:<period>

Away flood protection: limits /away to 'count' changes per 'period' seconds. Example: away-flood 5:60s means max 5 changes per 60 seconds.


Syntax: set::anti-flood::invite-flood <count>:<period>

Invite flood protection: this limits /INVITE to a rate of 'count' per 'period' seconds. The default is 4:60 which means 4 /INVITE's per 60 seconds.


Syntax: set::anti-flood::knock-flood <count>:<period>

Knock flood protection: this limits /KNOCK to a rate of 'count' per 'period' seconds. The default is 4:120 which means 4 /KNOCK's per 120 seconds.


Syntax: set::anti-flood::unknown-flood-amount <amount>

When we receive a connection from a user and this user sends more than <amount> kilobytes of data BEFORE actually coming online (a so called "unknown connection") then the user will be killed.


Syntax: set::anti-flood::unknown-flood-bantime <timevalue>

Specifies for how long an unknown connection flooder is banned (see also previous item).


This configures the maximum number of conversations a user can have with other users at the same time. This is a protection measure against spambots who tend to mass /MSG or /INVITE many different users within a short period of time.

set {
    anti-flood {
        max-concurrent-conversations {
            users 10; /* should be between 1 and 20 */
            new-user-every 15s; /* should be between 1 and 120 */

A user may message up to set::anti-flood::max-concurrent-conversations::users different users without any problem. If he/she then messages another user this is only permitted at a rate of 1 every set::anti-flood::max-concurrent-conversations::new-user-every seconds.

For example, with a users set to 10 and new-user-every set to 15:

  • UnrealIRCd will remember up to 10 users that the user is messaging
  • The user can /MSG the first 10 users without any problem (eg: k1, k2, k3, k4, k5, k6, k7, k8, k9, k10)
  • When trying to send a message to the 11th user (eg: k11) the user will have to wait up to 15 seconds before (s)he can do.
  • Then the user can message the 11th user (k11)
  • If the user then wants to send a message to a 12th user (k12, or even user k1 again which has by now dropped of the active 10 users list) then (s)he has to wait 15 seconds again

Since most users don't actively message many different users within a short period of time, this can be used as a way to detect bots/drones that flood users. The goal is to set the limit high enough for normal users to never experience this limit, yet low enough to be meaningful as a spambot countermeasure.

Also, note that this setting only affects user to user messaging and not messages to channels. This is because it is assumed that channel flood controls can take care of channel flooding.

The default setting is as follows:

Version users new-user-every
UnrealIRCd 3.2.x - 4.2.1 20 15 seconds
UnrealIRCd 4.2.2 - now 10 15 seconds

This functionality was added in UnrealIRCd 5.0.5

This flood countermeasure works differently than all the others. It will limit floods to targets such as channels and persons at a maximum rate. This so, for example a channel, can never see more than X lines per Y seconds.

The goal is to prevent flooding at HIGH rates only. To prevent flooding at such high rates that the client may no longer be capable of handling the traffic in terms of CPU usage (such as leading to a laggy interface) or even bandwidth. This is why the maximum rates are very high. We don't want this to be triggered in normal conditions even for extreme cases, such as channels that have a quiz/trivia bot. Even with this target-flood protection enabled, some IRC clients may still have problems with some types of traffic below the set maximum rate, we only do our best to limit damage to most clients this way.

This countermeasure is NOT for low-rate or medium-rate spamming/floods. If you want more strict channel flood control (and you probably do!), then use the very powerful and customizable channel mode +f as well.

There are 2 possible target types: channels and users. For each of those 2 there are 3 possible message types in IRC: privmsg, notice and tagmsg. Below you can see the default settings:

set {
    anti-flood {
        target-flood {
            channel-privmsg 45:5;
            channel-notice 15:5;
            channel-tagmsg 15:5;
            private-privmsg 30:5;
            private-notice 10:5;
            private-tagmsg 10:5;

When the target-flood limit is hit, we will drop the message. We do not kill the user, because the user who sent the 15th/60th/etc message could be a totally innocent user who only said stop this flood!. This is also why we don't offer a configuration option for killing either, since you may very well end up killing good people.

The limits apply to everyone (including channel operators), the only exception are IRCOps which are exempt if they have the immune:target-flood privilege (all IRCOps do, by default).

This anti-flood feature is handled by the targetfloodprot module which is loaded by default. You can use blacklisting in the configuration file to completely remove this anti-flood feature: blacklist-module targetfloodprot;


Syntax: set::default-bantime

Default bantime when doing /KLINE, /GLINE, /ZLINE, GZLINE, /SHUN, etc without a time parameter (like /GLINE *@some.nasty.isp), the default is permanent (0). Example: default-bantime 90d


Syntax: set::modef-default-unsettime <value>

For channelmode +f you can specify a default unsettime, if you specify 10 for example then a /MODE #chan +f [5j]:15 will be transformed to [5j#i10]:15. The default is no default unsettime.


Syntax: set::modef-max-unsettime <value>

The maximum amount of minutes for a mode +f unsettime (in +f [5j#i


Syntax: set::modef-boot-delay

Ignore join flood controls in channel mode +f when the server has just been rebooted. This because users are likely to quickly reconnect in such a case, causing a lot of joins which normally trigger +f, causing channels to end up being +i or +R even if there was no true attack (just a server restart).

The default setting is 75 seconds. You can specify an alternative time in seconds (eg: 120), or by timespec (eg: 2m).

This feature does not take into account users reconnecting to another server in the network if a server dies or is restarted, as is frequently seen in the case of DNS RR. But at least it partially mitigates the server reboot effect.

The downside of this setting is that if a server is restarted in the middle of a drone attack, then when it is booted up again, drones would be able to bypass limits for the specified amount of time. One needs to weigh this against the false positives in channel mode +f that are otherwise caused by server restarts (eg: channels ending up +i due to +f, only because a server has been restarted during scheduled maintenance).


Syntax: set::ban-version-tkl-time <value>

If you specify an 'action' like zline/gline/etc in a Ban version block, then you can specify here how long the IP should be banned, the default is 86400 (1 day).


Syntax: set::spamfilter::ban-time <value>

Same as above but for *lines/shuns added by spamfilter


Syntax: set::spamfilter::ban-reason <reason>

Default reason to use for entries added by spamfilter


Syntax: set::spamfilter::virus-help-channel <channel>

The channel to use for the 'viruschan' action in spamfilter


Syntax: set::spamfilter::virus-help-channel-deny <yes|no>

If set to yes (or '1') it replies 'invite only' to any normal users that try to join the virus-help-channel. Only opers, people that match spamfilters and people that are /invite'd can join.


Syntax: set::spamfilter::except <target(s)>

These targets are exempt from spam filtering, that is: no action will be taken if you send a message/notice/etc to this target. This can be single target or comma separated list.. Ex: except "#help,#spamreport"


Syntax: set::spamfilter::detect-slow-warn <value>

If a spamfilter takes longer than this amount of milliseconds to execute (1000ms = 1 second), then a warning notice will be sent to all opers (default: 250). See also Spamfilter#Slow Spamfilter Detection


Syntax: set::spamfilter::detect-slow-fatal <value>

If a spamfilter takes longer than this amount of milliseconds to execute (1000ms = 1 second), then the spamfilter will be removed (default: 500). See also Spamfilter#Slow Spamfilter Detection


Syntax: set::check-target-nick-bans <yes|no>

Whenever the user changes his/her nick, check if the NEW nick would be banned. If so, do not allow the nickchange. Default is yes.


Syntax: set::ping-cookie <yes|no>

When a client connects, send a "ping cookie" consisting of a random string that the client should respond with. All clients should cope with this and do so without bothering the user. Ping cookies are a security measure. It helps in preventing blind HTTP-POST attacks and similar security issues. It also helps against TCP spoofing on very old operating systems.

The default is yes (enabled). Changing this to no is a big security risk.


Syntax: set::watch-away-notification <yes|no>

Allows you to enable/disable AWAY notification in WATCH. The default is yes (enabled).


This limits the number of targets in a command. For example for PRIVMSG it defaults to 4, which means you can address up to 4 targets via /MSG nick1,nick2,nick3,nick4 hello. These imposed protocol limits apply to everyone, including opers.

The following are the defaults:

set {
    max-targets-per-command {
        privmsg 4;
        notice 1;
        tagmsg 1;
        names 1;
        whois 1;
        whowas 1;
        kick 4;
        list max;
        join max;
        part max;
        sajoin max;
        sapart max;
        kill max;
        dccallow max;
        userhost max;
        userip max;
        ison max;
        watch max;

If you are tweaking the settings you should note that:

  • The commands NAMES and WHOWAS do not support more than 1
  • The setting for the commands USERHOST USERIP ISON WATCH can not be lowered
  • Other than the above there is no checking if the command exists or if the command itself allows multiple targets in the first place

Syntax: set::hide-ban-reason <yes|no>

This will hide the *LINE reason to anyone except the user being killed. This allows you to enter a personal message in commands like /GLINE that will not be publicly displayed.


This module can automatically kill users that seem to have "random looking nicks".

Note that you need to load this module explicitly (it is not loaded by default):

loadmodule "antirandom";

set {
        antirandom {
                /* THRESHOLD:
                 * This is pretty much the most important setting of all.
                 * For every randomly looking ident the user gets a certain amount of
                 * 'points', if this value reaches 'threshold' then the appropriate
                 * action is taken (killed, *lined, see later on).
                 *  lower = more randomly looking users will be catched (but also more
                 *          innocent users)
                 * higher = less chance of innocent users getting killed, but also less
                 *          chance on bots getting catched.
                 * <2:  DON'T!!
                 *  4:  Works good, probably a few more innocent kills but if you got
                 *      quite a bot problem then this might be a useful setting.
                 *  5:  Works well with few innocent kills, probably good to begin with.
                 *  6:  If you want to be a tad more careful
                 * >6:  For the paranoid. Module can still be quite effective, though :)
                threshold 5;

                /* BAN-ACTION:
                 * Action to take whenever the user is catched as random, options:
                 * warn, kill, gline, gzline, kline, zline, shun, tempshun
                ban-action kill;

                /* BAN-TIME:
                 * Time to ban the user (irrelevant for tempshun/kill).
                 * Something between 1 hour and 2 days is recommended.
                 * If you set it higher than 3 or 4 days then you get quite a risk
                 * of catching innocent users due to dynamic IP, not to mention
                 * your *line list gets filled up... so choose it wisely.
                ban-time 4h;

                /* BAN-REASON:
                 * The ban (or kill) reason to use.
                 * You might want to put in an entry to a FAQ or an email address
                 * where users can mail if they have been catched and don't know what to do.
                 * NOTE: One of the various reasons that ""innocent users"" are catched is
                 *       if they just randomly type in info for their nick, ident, or realname.
                ban-reason "You look like a bot. Be sure to fill in your nick/ident/realname properly.";

                /* CONVERT-TO-LOWERCASE:
                 * Convert nicks, idents, and realnames to lowercase before doing random checks?
                 * This has not been tested extensively for false positives, but might be (very)
                 * helpful to catch GnStA5FYhiTH51TUkf style random nicks as random.
                 * Enabled by default.
                convert-to-lowercase yes;

                /* FULLSTATUS-ON-LOAD:
                 * If enabled, then upon loading it will check all users that are currently
                 * connected and give a status report about who it would have killed.
                 * Note that it doesn't actually kill any currently connected users, it is for
                 * informative purposes only.
                 * This can be (very) useful if you use the module for the first time.
                 * But you probably want to disable it after a while, since once the module
                 * is actively dealing with randomly looking persons, it shouldn't report any
                 * users anymore on load and then this check only eats useless CPU on /REHASH.
                 * Enabled by default.
                fullstatus-on-load yes;

                /* SHOW-FAILEDCONNECTS:
                 * This will send out a notice whenever a randomly looking user has been catched
                 * during connecting. Obviously this can be pretty noisy.
                 * Especially recommended to enable during the first few days you use this module.
                show-failedconnects yes;

                /* EXCEPT-HOSTS:
                 * Hostmasks on this list are matched against the IP and hostname of the connecting
                 * user. If it matches then we do not check if the nick/ident/realname is random.
                 * NOTE: Use the REAL host or IP here, not any cloaked hosts!
                except-hosts {
                        mask "*.trusted.yy";
                        mask "192.168.*";

This allows you to specify which channels should be hidden from list. Right now it only supports one option: deny-channel. This will hide channels that the user cannot join due to deny channel { } restrictions:

set { hide-list { deny-channel; }; };

Note that secret channels (channel mode +s) are always hidden and IRCOps always override restrictions (if they have sufficient access).


UnrealIRCd limits the number of connections per IP that are in an "unknown" state, that is: connections that are in a handshake. This is a security setting and it defaults to 3.

Only in very rare circumstances this may need to be adjusted. For example if you have hundreds of users coming from the same IP.

Example: set { max-unknown-connections-per-ip 3; };


By default UnrealIRCd will place bans from spamfilter (and other automatic bans) on *@ip. You can change this to have bans placed on user@ip. This can be useful if you have some unusual amount of trust in idents ;). Note that this doesn't help against zlines/gzlines since ident requests and handshakes (including receiving the username) don't take place for (G)ZLINE's.

Example (this is the default setting): set { ban-include-username no; };


Syntax: set { handshake-delay 2; };

This defines the MINIMUM time it should take for a user to get connected (finish the initial handshake).

This can be useful if you have blacklist blocks so DNSBL checking can finish before allowing the user in.

The default is 2 seconds if you have any blacklist { } block. You could set it slightly higher if your DNSBL checking is slow but for most people the default should be perfectly fine. Values of 10 or more are not permitted.

If you don't have any blacklist { } blocks then the delay defaults to 0 seconds (no delay) since it would not be useful.


This allows you to change the messages that are sent to a user when their connection is rejected. This shows the defaults:

set {
   reject-message {
        password-mismatch "Password mismatch";
        too-many-connections "Too many connections from your IP";
        server-full "This server is full.";
        unauthorized "You are not authorized to connect to this server";
        kline "You are not welcome on this server. $bantype: $banreason. Email $klineaddr for more information.";
        gline "You are not welcome on this network. $bantype: $banreason. Email $glineaddr for more information.";

The set::reject-message::kline message is sent to the user when disconnecting them due to a KLINE or ZLINE. The set::reject-message::gline message is sent to the user upon GLINE or GZLINE. The message is only sent to the affected user and is not seen by other users or IRCOps. In both of these configuration items (::kline and ::gline) the following variables are available:

Variable Description Example
$bantype type of the ban (past tense) K-lined
$banreason reason of the ban (*LINE reason) Stop spamming users
$klineaddr set::kline-address
$glineaddr set::gline-address (or, if not set, then set::kline-address)
$ip IP address of the user

The antimixedutf8 module will detect and stop spam containing of characters of mixed "scripts", where (for example) some characters are in Latin script and other characters are in Cyrillic script.

Note that you need to load this module explicitly (it is not loaded by default).

loadmodule "antimixedutf8";
set {
        antimixedutf8 {
                /* Take action at this 'score'.
                 * 10 is a good and safe default.
                score 10;

                /* Action to take, see:
                ban-action block;

                /* Block/kill/ban reason (sent to user) */
                ban-reason "Possible mixed character spam";

                /* Duration of ban (does not apply to block/kill) */
                ban-time 4h; // For other types

This will ask users to type /AUTH user:pass if they need to authenticate, for example if the user matches a soft ban or require authentication { } block. Technically, it does this by simulating a SASL session to Services.

The module is loaded by default with the following default settings:

loadmodule "authprompt";
set {
        authentication-prompt {
                /* Enabled or not? */
                enabled yes;

                message "The server requires clients from this IP address to authenticate with a registered nickname and password.";
                message "Please reconnect using SASL, or authenticate now by typing: /QUOTE AUTH nick:password";
                /* As you can see you can have multiple 'message' items.
                 * It may be useful to refer to a webpage for more
                 * information and/or where users can register their nick.

                fail-message "Authentication failed";
                /* Multiple fail-message lines are also supported */
// If you use the authprompt module then you may want to raise the
// timeout in which users must complete the handshake.
// By uncommenting the following, you can raise it from 30 to 60 seconds:
// set { handshake-timeout 60s; };

The set::connthrottle settings are documented at the Connthrottle page.


Syntax: set::broadcast-channel-messages [auto|always|never]

There are 3 possible settings:

  • always: always send all channel messages to all servers, regardless of whether they have channel members or not.
  • auto (the default): don't send messages to servers if they have no channel members, except for when the channel mode +H (history) is set. In case of +H we broadcast all messages to all servers.
  • never: never broadcast channel messages to all servers, only send to servers that have channel members.

Configure settings related to Channel history.

The set::history::channel::playback-on-join block describes the behavior when a user joins a +H channel. The set::history::channel::max-storage-per-channel block sets limits on what can be set via /MODE #chan +H. Note that these are separate things: only a few lines of history are shown on-join, many more lines can be fetched via the HISTORY command (and possibly other commands in the future).

This shows the default settings:

set {
        history {
                channel {
                        /* How many lines to playback on join? */
                        playback-on-join {
                                lines 15;
                                time 1d;
                        /* How much history to keep. These are the
                         * upper maximums for channel mode +H lines:time
                        max-storage-per-channel {
                                lines 200;
                                time 1w;

Syntax: set::part-instead-of-quit-on-comment-change [yes|no]

When a QUIT message is changed due to channel restrictions, such as stripping color or censoring a word, we normally change the QUIT message. This has an effect on ALL channels, not just the one that imposed the restrictions (eg: the QUIT reason loses color or is censored for all). We feel this is the best tradeoff and this is the default setting of no.

You can also set this setting to yes. That will change the QUIT into a PART when the QUIT comment is changed. The channel(s) with the changed comment see the user PARTing, and on all other channels that do not have the restrictions (eg: are -S and -G) they will see the user QUITting with the original message.


Syntax: set::webredir::url ""

When someone (accidentally) types in their web browser then UnrealIRCd can send a HTTP redirect back to, say, Note that this is mostly a gimmick rather than something terribly useful.

For this to work, the IRC server needs to listen on ports 443 and 80 (more information about that here!). However, nowadays more and more IRC servers listen on port 443 so users can bypass firewall restrictions that they may encounter on the regular ports 6667/6697 (and also because of websockets).

Usage example (only do this after reading the above):

loadmodule "webredir";
set { webredir { url "https://..."; } }

Syntax: set::automatic-ban-target [host|userhost|..]

The IRCd may add automatic bans, for example due to a blacklist hit, a spamfilter hit, or because of antirandom or antimixedutf8. When it does, on what should the ban be placed:

  • ip: place the ban on the IP address (eg: *@
  • userip: include the ident portion in the mask (eg: user@
  • host: place the ban on the hostname (eg: *, fallback to ip.
  • userhost: include the ident portion in the mask (eg:, fallback to user@ip.
  • account: ban by services account name (eg: ~a:accountname)
  • certfp: ban by certificate fingerprint (eg: ~S:00112233etc)

The last two possibilities are only useful if you have a very special setup, it does not apply to most users. The most common choices are ip (the default), host, or userip (if you trust idents).

Note: if the ban is of type ZLINE or GZLINE then it will always resort to ip since all other options don't work. The reason for that is that UnrealIRCd closes the connection immediately in case of a (G)ZLINE. Therefore it only knows the IP information as it has not done a DNS lookup, ident lookup, TLS handshake, etc. In fact, that is what makes a ZLINE different than a KLINE (and a GZLINE from a GLINE).


Syntax: set::manual-ban-target [host|userhost|..]

Similar to automatic-ban-target, but this is used if target a nick in a *LINE, eg type /KLINE nick. When that happens, on what should the ban be placed:

  • ip: place the ban on the IP address (eg: *@
  • userip: include the ident portion in the mask (eg: user@
  • host: place the ban on the hostname (eg: *
  • userhost: include the ident portion in the mask (eg:
  • account: ban by services account name (eg: ~a:accountname)
  • certfp: ban by certificate fingerprint (eg: ~S:00112233etc)

he last two possibilities are only useful if you have a very special setup, it does not apply to most users. The most common choices are ip, host (the default), or userhost (if you trust idents).

Note: if the ban is of type ZLINE or GZLINE then it will always resort to ip since all other options don't work. The reason for that is that UnrealIRCd closes the connection immediately in case of a (G)ZLINE. Therefore it only knows the IP information as it has not done a DNS lookup, ident lookup, TLS handshake, etc. In fact, that is what makes a ZLINE different than a KLINE (and a GZLINE from a GLINE).


Note: this setting is only available in UnrealIRCd version 5.0.4 and higher. The feature is planned to be extended later.

The default setting is:

set { hide-idle-time { policy oper-usermode; } }

Syntax: set::hide-idle-time::policy [never | always | usermode | oper-usermode ];

This is a privacy setting which configures the visibility of "idle time" of users:

  • never: never hide idle time, the idle time is always shown to everyone
  • always: always hide idle time
  • usermode: show idle time, but hide idle time if user mode +I is set (uppercase letter i).
  • oper-usermode: same as previous, but only IRCOps can set the +I user mode to hide idle time.

In all cases, IRCOps can still see idle time of users.

Note that even if you are allowed to see idle time, /WHOIS Nick will never show idle time for users on another server. This is a technical limitation (the idle time is not communicated actively across servers). If you want to see the idle time of a remote user you need to double whois: /WHOIS Nick Nick. Some clients do the latter by default in popups.