1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-12 17:14:46 +02:00
Commit Graph

10696 Commits

Author SHA1 Message Date
Bram Matthys 5b6c00946a Optimize set_user_modes_dont_spread(): use _cmd_uid() directly.
Only downside is that mtags would be NULL, but we don't use it in
cmd_uid() so that's okay. This saves us from generating mtags in
do_cmd() when we don't need it. And also a command handler lookup
and all that. Saves around 8% of unrealircd CPU for 100k connects.
2025-10-05 11:00:00 +02:00
Bram Matthys 80189a6ce9 Replace a HasCapability() with HasCapabilityFast()
Since mtags_to_string() is a function that is called a lot, this matters.
2025-10-05 10:34:25 +02:00
Bram Matthys fa8a0b2083 Make IsSynched() check if both the "far" server and the "near" server are
synched. Both need to be checked, because:
* The "far" server may be fully synched to "near" (and thus tagged as synced)
  but the "near" server may be introducing the "far" server, when
  we are connecting to "near"
* The "near" server may be fully synched but the "far" server is connecting
  in and may thus not be synched yet

In reality, things are even more complex, since one would have to verify
the whole chain of links. But.. yeah.

Long-story short: this fixes things like "User xyz joined #xxxxx" logging
where this showed up while the server was linking in. It is not supposed to
log that, similar to how we not log all 1000 users as newly connecting when
a 1000-user-server links in. In fact, it didn't already log that for
directly-connected-servers, but for far servers it did previously.

And... that again gave performance issues if you were connecting like a
100k-user far server.. since you suddenly had 100k * numchannels join events
being logged (which surprisingly still only took 6 seconds for 100k entries,
but still, it is wrong to do so and can be avoided).
2025-10-05 10:26:01 +02:00
Bram Matthys 9b493cfe6a Avoid a get_floodsettings_for_user() call for servers.
This didn't show up in initial profiling, but now that other areas
are faster, this one starts to show up with 15% for 100k-clone remote
server traffic. Easy change :D
2025-10-05 09:02:51 +02:00
Bram Matthys c729d18a8c Add (faster) remove_user_from_channel_withmb() and use it from various places.
We can use this when we already have the Membership struct, which is the
case for PART, (SA)JOIN 0 and QUIT. Saves a couple of iterations.
2025-10-05 09:01:08 +02:00
Bram Matthys af0a784464 Make member & membership point to each other so lookups can be much faster.
This also makes them proper list items, again to make certain fast operations
possible. Main thing is that removing an entry does not require us to walk
all of those lists. Not all code has been modified yet to benefit this,
actually only very little, the most performance-impacting ones.

This fixes SQUIT of a server with 100k users in a single channel taking
40 seconds of 100% CPU. It now takes only 1 second.
Reported by craftxbox in https://bugs.unrealircd.org/view.php?id=6484

(Can't make member & membership one entry atm, that would be too much change in U6)
2025-10-05 08:32:43 +02:00
Bram Matthys 55dd4601f2 Change some find_member_link() to find_membership_link() which is faster.
The first one iterates through all channel members (can be hundreds or thousands)
and the latter goes through the channels a user is in (typically <15).
2025-10-04 20:46:20 +02:00
Bram Matthys 68ef88c0c4 Move from HOOKTYPE_VISIBLE_IN_CHANNEL to invisible setting in member->memb_flags.
This so we can use fast(er) techniques here and there.

New functions are:
channel_has_invisible_users(client)
set_user_invisible(client, channel, 1|0)
Existing functions:
invisible_user_in_channel(client, channel)
user_can_see_member(user, target, channel)
user_can_see_member_fast()

This is work in progress, although the tests seem to pass atm.
2025-10-04 20:33:46 +02:00
Bram Matthys 1473f52603 Another sendto_channel() optimization in case of some PRIVMSGs.
When the channel is +H we broadcast to all servers, so we can simplify
that case and don't need to iterate the channel->members.
The same is true if set::broadcast-channel-messages is set to 'always',
though that is not known to be used much.
2025-10-04 08:50:42 +02:00
Bram Matthys e92b8ef3ad Fix uninitialized variable in sendto_channel() 2025-10-03 19:14:44 +02:00
Bram Matthys 2e21e7fdbf Make sendto_local_common_channels() use channel->local_members.
This too should be a significant performance improvement for multi-
server networks. Especially since this isn't just num_channel_members
of 1 channel, but about common channels, so could easily be like all
channel members of 10 channels combined.

This function is used for NICK, QUIT, and notification for CAP-
enabled clients for setname, account and away changes.
2025-10-03 19:13:39 +02:00
Bram Matthys cfe3ce38b2 testssl_profiles/*txt: TLS 1.2 -> TLSv1.2, etc... 2025-10-03 18:47:32 +02:00
Bram Matthys 569a12055f Add channel->local_members and use it in sendto_channel().
This makes things a lot faster on multi-server networks, especially for
big channels where most of the clients in the channel are remote users.

This should be non-module-API-breaking, as all code uses the
add_user_to_channel() and remove_user_from_channel() functions.

Still need to spread this to other code, more optimizations possible.
2025-10-03 18:11:03 +02:00
Bram Matthys 86e7ab307a Bump dbufs from 4k to 8k. Gives a 5% performance improvement.
That is, during my tests with 1000 TLS clients doing a couple of commands,
including one big one (WHO #channel on a 1000 user channel).

I also tested an SSL_writev() implementation (which would gather up to 16k)
but it gives very comparable speed and caries more risk of doing so in a
stable series. I think we can live with the 4 kilobyte extra per local
client in the year 2025 (and later).
2025-10-03 16:11:52 +02:00
Bram Matthys 902802a8dc I/O engine: don't request write notification if we don't need it.
In testing with 1000 TLS clients this saves around 16% of unrealircd
CPU time (so not 16% CPU, but 16% of whatever % unrealircd cpu is).
2025-10-03 16:02:51 +02:00
Val Lorentz 45ef8d1cf1 Fix multi-prefix (#320) 2025-09-30 23:57:45 +02:00
Bram Matthys d5332ca765 Fix memory leak in JSON-RPC stats.get 2025-09-30 16:50:06 +02:00
Bram Matthys ac9709531a Fix windows compile which was broken on Sep 17 by commit
0c17276039.
2025-09-29 19:41:07 +02:00
Bram Matthys 792eca7d4d Fix chathistory test fail... duh.. accidentally set a local var. 2025-09-29 18:04:41 +02:00
Bram Matthys 15c8b1aa40 Optimization: Use HasCapabilityFast() in whox.c and extended-monitor.c
The whox one saves a lookup for each channel member (so eg 500 for a
channel with 500 members). The extended-monitor saves it on delivering
watch/monitor notifications, so depends on the # of subscriptions.
And that's each time such a command is called. We now only lookup on
MOD_LOAD.
2025-09-29 18:00:14 +02:00
Bram Matthys 80a381c76a Optimization: history: use HasCapabilityFast() instead of HasCapability()
This makes it so the capability bit lookup is done only once on module load
and not on each client JOIN.
2025-09-29 17:20:06 +02:00
Bram Matthys e42610ebba Optimize MONITOR / WATCH to do ModData lookup only at MOD_LOAD()
instead for each MONITOR / WATCH command.
We use the same technique in other modules, eg for websockets.
2025-09-29 16:56:16 +02:00
Bram Matthys c0a46abd60 ModData API: add ModDataInfo .priority item and use it to speed up
things by making the keys with the most lookups first, e.g. "reputation",
"geoip", "certfp". This order is based on actual lookup counts during a
quick test with 250 clones doing some typical IRC traffic.

Key:		Lookups:	Position before:	After split:	After split+order:
"reputation"	20362		37			14		1
"geoip"		10555		44			15		2
"certfp"	9264		23			8		3
"webirc"	7407		27			10		4
"websocket"	7110		55			19		5

We could also consider going for a hash table, but this may be "good enough" for now.
2025-09-29 16:50:44 +02:00
Bram Matthys db6476e1ab ModData API (internal): split the single linked list into 7 lists, to speed
up moddata_client_get() etc -> findmoddata_byname().
Apparently we have 52 moddata registrations (that is without 3rd party modules)
so otherwise it is a loooong linked list.
2025-09-29 16:22:08 +02:00
Bram Matthys 51625592cb Get rid of a memset() of 16k in labeled response implementation.
This was done in lr_pre_command() and lr_post_command().
Nowadays we have BIGLINES stuff from servers that cause MAXLINELENGTH
to be 16k, so the LabeledResponseContext ended up being 16k+.
Although we normally have the policy to zero out complete structs
in UnrealIRCd instead of only individual members (for safety,
easy to overlook security bugs), in this case we will do zeroing
of struct members explicitly. Added some warnings about this too
in the source code. Zeroing 16k twice for each command is a bit
too much waste.
2025-09-28 18:24:23 +02:00
Bram Matthys cf2c3baca5 Whoops.. fix compile. 2025-09-28 18:02:12 +02:00
Bram Matthys 2ee12bf326 Make SHA256 30% faster when used for cloaking and other very small inputs,
simply by re-using the context.

The slowdown happened due to commit a541b8f4ad
in June 2021 when converting to OpenSSL 3+ code. Now it is basically
back to the pre-openssl-v3 speeds.
2025-09-28 17:24:11 +02:00
Bram Matthys b3fd6b9bca Optimization: use umode_letter_to_handler[] for faster has_user_mode()
and find_user_mode(). That's one array of 256 elements, instead of
iterating a linked list where - if you are unfortunate - one may
need like 26 iterations.

In sendto_channel() we did the check for user mode +T before the
sendflags & SKIP_CTCP, that makes no sense and caused useless CPU.
We now do it the other way around, and also only lookup the user
mode just once (if needed).

The umode_letter_to_handler[] code may crash, it is not well tested
yet, only had two runs so far. Seems to work ok even with REHASH tho,
but have not tested delayed module unloading for example.
2025-09-28 16:49:20 +02:00
Bram Matthys e3b92cc084 away_join() optimization: don't bother if user is not away.
Otherwise we are iterating <num channel members> all for nothing.
2025-09-28 16:20:19 +02:00
Bram Matthys 5a02d4f52c Get rid of the *@unrealircd.com mask in the example vhost as it is commented out
now anyway. And thus, get rid of the related comment as well.
2025-09-28 10:41:00 +02:00
Bram Matthys c8431b7cb8 Make client->local->caps a 64 bit unsigned int on all archs.
This was previously a "long", which could cause issues on 32 bit archs.
We ship with 28 CAPs now, and that's without 3rd party modules, so...

This is similar to the client->flags bumping in 2023
(a3ed1eabd9).
2025-09-28 10:03:04 +02:00
Bram Matthys a2e099bf47 Extbans: fix various syntax error / usage examples where old single letter
is used instead of the full name (eg ~S instead of ~certfp).
We have named extended bans since UnrealIRCd 6.0.0 (2021) already...
2025-09-25 19:27:34 +02:00
Bram Matthys ddfe7c535c Make TLINE use server_ban_parse_mask() so it uses the same logic as GLINE.
This fixes something like TLINE ~country:us not automatically converting
to ~country:US, since previously conv_param() was not called. But it also
means other code is used in the same way as GLINE (other type of rejections),
for example invalid server ext ban will print a better error with syntax
info (e.g. TLINE ~certfp:xx).

That ~country issue was reported by adamus1red in https://bugs.unrealircd.org/view.php?id=6581
2025-09-25 19:16:11 +02:00
Bram Matthys 65b69f9164 Sync away_since in S2S traffic from now on.
See also comment in f42bab778e
about away_since in JSON-RPC.
2025-09-24 13:47:53 +02:00
Bram Matthys 995b67f785 Module manager: add "last-updated" property to generated module list. 2025-09-24 09:58:21 +02:00
Bram Matthys 53707f27b9 Fix unitialized variable in link config test, due to commit from yesterday
(4c6e259681).
2025-09-22 08:25:18 +02:00
Bram Matthys 602f6c7238 URL API: add .minimum_tls_version, and use TLS1_3_VERSION for central-blocklist.
Something like:

 #ifdef TLS1_3_VERSION
        w->minimum_tls_version = TLS1_3_VERSION;
 #endif
        url_start_async(w);

Require TLSv1.3 for central-blocklist and spamreport calls, unless your
OpenSSL does not support it, which should be rare.

At some point in the future I will make this endpoint TLSv1.3+ only.
2025-09-21 14:24:06 +02:00
Bram Matthys 507061af46 Add tls-options::signature-algorithms for those who want to override the default.
We don't set it in UnrealIRCd at the moment, so this is just to override
the OpenSSL defaults at the moment. It is good to have this exposed, in
case some vulnerability is discovered or you need some flexibility in
tweaking this.
2025-09-21 13:55:24 +02:00
Bram Matthys b0b6cc81e2 This belongs to the autoconf upgrade too (see previous) 2025-09-21 13:39:12 +02:00
Bram Matthys fd5db98c88 Rebuild ./configure after upgrade of autoconf 2.71 to 2.72 2025-09-21 13:37:31 +02:00
Bram Matthys d1b1a413cf Make code that sets TLS groups also apply to client context.
(groups were previously called ecdh-curves)
2025-09-21 13:32:04 +02:00
Bram Matthys 4c6e259681 You can now use "password" multiple times in the conf (eg in allow::password).
allow {
	mask *;
	password "secret";
	password "letmein";
}

This is always an "OR" type of match, any match means you pass.

I was actually doing this for the dual-cert stuff from previous commit,
where this can come in handy:

link irc1.example.org {
...
    password "AHMYBevUxXKU/S3pdBSjXP4zi4VOetYQQVJXoNYiBR0=" { spkifp; };
    password "jNw8P4QMg9tqjEJ4/lFikXBNHdIGSeN2B4/T322VjIo=" { spkifp; };
...
}
2025-09-21 11:42:59 +02:00
Bram Matthys 877d151da4 Support multiple TLS certificates/keys, e.g. ECDSA + ML-DSA (PQC).
In the past a dual cert/key setup could have been useful for RSA + ECDSA
but nowadays all clients support ECDSA so that makes little sense.
The reason it is added now is so you can use ECDSA + ML-DSA or some
other [regular crypto] + [post quantum crypto] combination.
Actually, you could even use more than two.

To use this in the config file, simply use the certificate and key
directive multiple times. Just be sure to load the certificates and keys
in the same order. We will print a helpful error if you fail to do so.

Note that for Post Quantum Cryptography the most important step today
was/is to protect against the "Harvest now, decrypt later" scenario
https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later which is a
"passive attack". That's why in UnrealIRCd 6.2.0 we enabled
X25519MLKEM768 if it is available (OpenSSL 3.5.0 and later).
While, this commit, and this talk about dual ECDSA and ML-DSA, is about
when a quantum computer exists and actively does a man in the middle
attack. That's not a realistic scenario in 2025 and according to experts
also not in the next few years. We just make the UnrealIRCd code-
base ready to have this feature for when it is needed / will be used,
and to get this tested properly.

For testing the dual ECDSA and ML-DSA setup I used the following
command to create the 2nd cert/key (self-signed):

openssl req -x509 -nodes -newkey mldsa65 \
  -keyout ~/unrealircd/conf/tls/server.key.mdsa65.pem \
  -out ~/unrealircd/conf/tls/server.cert.mdsa65.pem \
  -days 3650

And then:

listen {
        ip *;
        port 6697;
        options { tls; }
        tls-options {
                certificate "ssl/server.cert.pem";
                key "ssl/server.key.pem";
                certificate "ssl/server.cert.mdsa65.pem";
                key "ssl/server.key.mdsa65.pem";
        }
}

When running openssl s_client -connect 127.0.0.1:6697 it shows ML-DSA is used:
...
Peer signature type: mldsa65
Negotiated TLS1.3 group: X25519MLKEM768
...

And with openssl s_client -connect 127.0.0.1:6697 -sigalgs "RSA+SHA256:RSA+SHA384:ECDSA+SHA256:ECDSA+SHA384"
it shows ECDSA is used:
..
Peer signature type: ecdsa_secp384r1_sha384
Negotiated TLS1.3 group: X25519MLKEM768
..

This is just for testing purposes (self signed cert). As of right
now (Sep 2025), you can not get a trusted certificate with ML-DSA,
as the CA/Browser Forum only allows issueing RSA and ECDSA keys.
Also, all the trusted Certificate Authorities use RSA or ECDSA.
And, again, all this is not ML-DSA specific, it should work for
other dual/multi combinations, and.. who knows they even go for
something hybrid.

A downside of dual certs is that this makes the whole spkifp thing more
complicated because if you use 2 certs/keys you now have 2 possible
fingerprints (spkifp) that could match in e.g. server linking.

While coding this, I also changed the 'STATS P' output to use the txt
numeric instead of notice, and be more verbose in its output for TLS
listeners: printing the certificate(s) and key(s).
2025-09-21 10:32:29 +02:00
Bram Matthys ccc80477ef Fix OOB read in UTF8ONLY code from today. 2025-09-20 17:40:34 +02:00
Bram Matthys b4e65b1414 Fix various "too early" cutoffs with new set::utf8-only feature 2025-09-20 15:52:31 +02:00
Bram Matthys dbb2d1a5c8 Move isupport_check_for_changes() to the 'isupport' module.
This function was added a short while ago, and well it seems to be
able to be possible in a module. Since the 'isupport' module is mandatory
and this is ISUPPORT related, it is the right place.
Can't move isupport_snapshot() because modules might not be loaded yet
or things are currently unloading, i think. Not important anyway.

Also, make things work if there are more changes than would fit
on one isupport line. Although I didn't really test this..
Ended up splitting things in 3 helper functions to avoid some
goto and/or duplicate code and stuff. The alternative was, surprisingly,
even more ugly.
2025-09-20 15:44:56 +02:00
Bram Matthys 595f56007b Add the ISUPPORT command, which simply calls the efunction.
Call the efunction from 005 introduction as well, so it uses the
batch, if needed. And yeah we opt to send the 005's always, even
if it was already sent in the handshake (or not).

Some re-indenting (spaces to tabs).

And call the efunction from VERSION as well.

For "VERSION remote.server" we don't send them in a batch as these
are not numeric 005 but 105. These are for information purposes only
and should not confuse the client (eg not to act upon).
2025-09-20 14:56:26 +02:00
Bram Matthys 5cb2428567 Some code cleanup to previous, and apparently the batch type is 'draft/isupport'
and not 'draft/extended-isupport'.
2025-09-20 14:40:16 +02:00
Bram Matthys e78a6a6dbf isupport & extended-isupport module, work in progress.
This is mostly from Valware PR https://github.com/unrealircd/unrealircd/pull/310
Will do more changes in later commits..
2025-09-20 14:34:28 +02:00
Bram Matthys 9e490196a8 set::send-isupport-updates: Valware added this, but this is now expanded
to all ISUPPORT tokens, instead of only CHANMODES, PREFIX and STATUSMSG.
E.g. changing set::min-nick-length would also broadcast the change.

Technically we will call isupport_snapshot() before the rehash (or before
delayed module unload) and then after modules were reloaded/unloaded we
call isupport_check_for_changes(). This uses the ISUPPORT system in a
general way, so works the same for all tokens.

https://www.unrealircd.org/docs/Set_block#set::send-isupport-updates

TODO: Deal with more than X changes (is currently an abort, crash)

TODO: batch for draft/extended-isupport
2025-09-20 14:05:35 +02:00