Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add draft relaymsg spec #417

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Add draft relaymsg spec #417

wants to merge 2 commits into from

Conversation

jlu5
Copy link

@jlu5 jlu5 commented Jun 7, 2020

This PR submits the relaymsg extension that I developed for my network as a draft. It allows relay bots to spoof usernames in a stateless fashion, similarly to webhooks in Discord and Slack. I originally posted this idea in ircv3/ircv3-ideas#63 - but ultimately, I wanted to try implementing it anyways, after seeing plenty of stability/scalability concerns with my previous services-based relayer.

(dan- helped me edit this initial draft, so I've added him as a co-author)

Co-authored-by: Daniel Oaks <daniel@danieloaks.net>
@jwheare
Copy link
Member

jwheare commented Jun 7, 2020

Why not just use a tag for the relaynick and normal PRIVMSGs?

@jlu5
Copy link
Author

jlu5 commented Jun 7, 2020

This is something I did consider early on, ie. using @+relaymsg with a client-supplied value. However, it seemed like that would be more work for a bot to check whether the feature is supported: it would depend on message-tags being available, as well as some other signal that relaymsg is supported by the server (ISUPPORT key or a separate tag?). The fallback if the relaymsg context simply gets dropped would be quite confusing IMO.

@progval
Copy link
Contributor

progval commented Jun 7, 2020

I really like the idea, but I have a few questions/concerns:

  1. What is the meaning of nickname separators? Where should a separator be in the spoofed nickname?
  2. It should mention there should be a fallback for receiving clients which don't support relaymsg.
  3. It's a security issue for bots receiving these relayed messages if the relay bot has any kind of privilege over them (it's a bad idea to do that, but it happens, eg. if the relay bot has the same hostmask or NickServ account as a real user).
  4. It's also a security issue for bots receiving these relayed messages; if they use only nicks for authenticating senders, then the relay bot can impersonate them (again, it's a bad idea, but it happens too)

@jwheare
Copy link
Member

jwheare commented Jun 7, 2020

@jlu5 even if the server is involved and there’s a CAP you can still have the client send a normal privmsg with the relay nick as a tag and it can then only send the tagged message to clients that support it, adding the fallback in for other clients.

I don’t see the need for a separate RELAYMSG verb or for the spoofed nick to appear in the source.

@jlu5
Copy link
Author

jlu5 commented Jun 7, 2020

I think I confused the @relaymsg sender tag with a potential spoofed nick tag - my bad. (This is what happens when I comment at 2am I guess..)

The spoofed nick trick is really to ensure backwards compatibility, and not having to patch every single client to support virtual senders. Given the breadth of clients and platforms IRC supports, having this be handled client side just wasn't feasible for my network.

But, I suppose server side translation could still be possible using a client side tag? e.g. client sends @+relaynick=me/net2 PRIVMSG #channel :abcd, which gets translated on supported servers as me/net2 PRIVMSG #channel :abcd. This could also add room for specifying an ident & host to send from, though the allowed hosts should use some sort of whitelist for security reasons. (e.g. @+relaynick=me/net2 @+relayhost=relay.example.com/net2-1234 PRIVMSG #channel :abcd)

As for fallback, I'm not quite sure what's needed? relaymsg source spoofing makes the sender look like any client that happens to be sending an external message. If relaymsg isn't supported, the command fails and nothing is forwarded. I have seen some bots not working well with nicks that contain invalid nick characters, but current relay implementations already use some of these (e.g. / and ~), and I haven't heard any user complaints about broken clients. Though, full UTF-8 support is another question, so that's why I've left that as optional for consideration.

Having this as a tag on PRIVMSG would look a bit different. If the relaynick context gets dropped and the message gets sent as PRIVMSG #channel :abcd, that would be no good. It'd look like the bot was speaking to itself without any other context. I can imagine something like @+relaynick=me/net2 @+relaymsg-strip=10 PRIVMSG #channel :<me/net2> abcd to chop off the first X characters if relaymsg is supported? But this seems quite like a hack to me..

@jlu5
Copy link
Author

jlu5 commented Jun 7, 2020

Replying more specifically to #417 (comment):

I really like the idea, but I have a few questions/concerns:

1. What is the meaning of nickname separators? Where should a separator be in the spoofed nickname?

Spoofed nicks look something like jlu5/mynet or jlu5~d - in these cases the / or ~ would be the separator. In terms of implementations, PyLink uses the first format (though the separator char is configurable) and go-discord-irc uses the latter by default.

2. It should mention there should be a fallback for receiving clients which don't support `relaymsg`.

See above.

3. It's a security issue for bots receiving these relayed messages if the relay bot has any kind of privilege over them (it's a bad idea to do that, but it happens, eg. if the relay bot has the same hostmask or NickServ account as a real user).

4. It's also a security issue for bots receiving these relayed messages; if they use only nicks for authenticating senders, then the relay bot can impersonate them (again, it's a bad idea, but it happens too)

I suppose an ideal implementation of this would have to allow relaying from a bot-specified hostmask. I agree that verifying by nick only is useless, especially considering that other platforms (eg Discord) don't necessarily guarantee that nicks are unique.

@jwheare
Copy link
Member

jwheare commented Jun 7, 2020

I’m not comfortable at all with the relay nick being fully spoofed into the source. Clients seeing messages from nicks that aren’t actually on the network would be an issue, not to mention that you can’t even express many relayed nicks in the irc protocol (spaces, special characters).

Putting it in angle brackets at the start of the message is preferable as a fallback.

You’re saying relying on clients to add support for this isn’t feasible, but they will need to add support for the CAP you’re proposing anyway.

@jlu5
Copy link
Author

jlu5 commented Jun 7, 2020

I’m not comfortable at all with the relay nick being fully spoofed into the source. Clients seeing messages from nicks that aren’t actually on the network would be an issue, not to mention that you can’t even express many relayed nicks in the irc protocol (spaces, special characters).

I feel this is fundamentally a limitation of IRC in that we don't have widespread support for display names (yet). These issues have to be worked around by any implementation that wants spoofed sources, regardless of which method they use to do it. In my matterbridge fork I replace disallowed characters with a - before sending the message, for example.

There was some talk when I first drafted this about giving the option for bots to register a relayed-nick namespace as a target for commands; this could open up the possibility of things like cross-network PMs for example, and alleviate the confusion of nicks that appear but don't exist. But, it still faces the same issues of other platforms allowing more liberal display names than IRC or duplicate nicks. Nick rewriting is the best I can do in the first case, but the second is way more ambiguous.

Putting it in angle brackets at the start of the message is preferable as a fallback.

This is just what regular relay bots do, but my experience is that a lot of people dislike this syntax precisely because it doesn't integrate well with the rest of IRC.

You’re saying relying on clients to add support for this isn’t feasible, but they will need to add support for the CAP you’re proposing anyway.

Only the relay bot needs to handle the relaymsg capability to use the feature - everyone else just sees it as a regular PRIVMSG. They could request the relaymsg cap to verify that spoofed messages are in fact spoofed, but it's not a requirement for the basic design to work.

@jwheare
Copy link
Member

jwheare commented Jun 7, 2020

Oh so regular clients don’t even have to opt in to seeing spoofed nicks? That sounds even worse.

I get that you’re trying to improve the landscape but just punting on getting clients to implement this properly isn’t really the way forward. Doing stuff like this might work for niche networks where people are on board with the idea. But I don’t see it getting traction as a sanctioned ircv3 extension.

I’ll let others comment if they think this has legs though.

@slingamn
Copy link
Contributor

slingamn commented Jun 7, 2020

I'm very sympathetic to this proposal. Here's how I see it: if you want to do protocol bridging using the IRC client-to-server protocol, with separate nicknames for each identity on the other side of the bridge, the network operator currently needs to set up IP limit whitelisting and the bridge needs to create a separate TCP connection for each bridged client. I see this proposal as a way of streamlining and optimizing that. What's salient is that RELAYMSG will typically be restricted to a privileged user of some kind; in many cases, the privileges will be comparable to those associated with a server-to-server connection. So I'm not that concerned about the potential security or user rights issues here. (I'm not saying this as an unqualified endorsement of the proposal in its current form: in particular, I would be interested in having a better story about direct messages.)

Philosophically, I want to object to the characterization of small networks as "niche networks"; they may be niche individually but the use case is not niche. I think a lot of the future of IRCv3 is in the long tail of small networks.

@jwheare
Copy link
Member

jwheare commented Jun 7, 2020

No shade intended whatsoever. It just seems much better suited to a vendor prefix.

@slingamn
Copy link
Contributor

slingamn commented Jun 7, 2020

I think the implication of leaving this as a vendor prefix is that mainstream software projects --- clients, servers, and bridges --- shouldn't need to implement this, or shouldn't prioritize implementing it. But that doesn't follow from the claim (which I accept) that this will primarily be useful on small networks, or private networks.

Just at a concrete level, I imagine it would be considerably easier to get this into upstream Matterbridge if it were an official IRCv3 draft. So the question is, is this useful enough to the IRCv3 ecosystem as a whole (even if not to any large networks within it) to warrant being an IRCv3 draft? I think it is.

@jlu5
Copy link
Author

jlu5 commented Jun 7, 2020

I know that spoofed nicks aren't standards compliant, but I'd just like to point out that reserved nick characters are something I've used in production for 5+ years now, and I've never seen a single client actually explode when parsing them. (The only issues I've seen are from other bots ironically, such as matrix-appservice-irc iirc). This similarly never was opt in because those virtual clients just show up in the user list, and clients just had to adapt to it. In fact, my implementation wasn't even the first to use the nick separator trick; the predecessor that inspired it (Janus) had been around for years before that.

From all I've seen, client parsers are more liberal than the original IRC spec when it comes to parsing nicks. I don't know if this is because of all the server-side relayers using this, or if it just happened naturally.

As for whether the idea is niche, I've heard that sentiment a dozen times by now. I get that large networks don't have much demand for relayers because they already have a large established community. But for smaller / hobbyist networks, it's very much an uphill battle to get any traction these days...


For a bit more context: PyLink's goal was really to give small to mid size networks the option of forming larger communities without losing their autonomy. It does this by doing server-side relays between channels on an opt-in basis. For the most part, the UX for IRC<->IRC relays work well and you could easily say, kickban a user connected on another network.

Later on, we added Discord support based on this bridging framework and it sort of became a PoC gone wild... Some of the core concepts that originally worked well on IRC starting breaking down: kicks/bans for example could not be synced in any non-hacky way. Duplicate nicks also did weird things and never really got resolved in a consistent manner. Similarly, I had to run unidecode to flatten UTF-8 nicks into IRC compatible ASCII - a lossy process that really is a bandaid fix for a lack of UTF-8 support. But more broadly there were design concerns: IRC bridges require prepopulating a list of all users to work properly, but this would never scale well onto platforms with giant servers. User lists are paginated on platforms like Discord and Slack - and even if you could get past API limits, the amount of join/quit spam on a cycle would be awful UX on most IRC clients.

So all in all, this is the story of what really made me want to approach stateless bridging.

@jwheare
Copy link
Member

jwheare commented Jun 7, 2020

To be clear, I don't think this idea is niche, just this implementation of it. I think for something that's after all largely a display issue, clients should be involved in a proper implementation. I'd be more than happy to support an IRCv3 spec that allows for this, but the proposal here feels like a workaround/bypass rather than a solution.

@slingamn
Copy link
Contributor

slingamn commented Jun 8, 2020

Is "clients should be involved" an objection to any specification that would relay spoofed nicks to legacy clients without an opt-in? Because I think that's exactly what I'm hoping for: something that achieves parity with the multiple-clients-over-C2S implementation of bridging, but without actually requiring multiple clients.

@jwheare
Copy link
Member

jwheare commented Jun 8, 2020

If I'm understanding your comment properly, no, that's not my objection. I'd be very happy for a solution that uses a single bridging bot client and "spoofing" using a message tag, rather than directly replacing the nick/user/host source prefix.

@jwheare
Copy link
Member

jwheare commented Jun 8, 2020

"Clients should be involved" means that clients should have to implement support for displaying the "spoofed" nick somehow, and not just be fooled into thinking a message is coming from a different user that doesn't exist on the network.

@slingamn
Copy link
Contributor

slingamn commented Jun 8, 2020

Right --- "fooling" the clients, i.e., transmitting the spoofed nickmask directly as the message source, without an opt-in, is exactly what I want to do. (Again, I want parity with the multiple-clients-over-C2S implementation. It seems academic to me whether the clients "really exist" on the network on the network or not; in the multiple-clients-over-C2S case, they're still special-cased by the server (for rate limiting purposes) and not able to participate in DMs.)

"Clients should be involved" means that clients should have to implement support for displaying the "spoofed" nick somehow, and not just be fooled into thinking a message is coming from a different user that doesn't exist on the network.

What's the motivation for this? Is this a user rights issue? Is core functionality being broken?

@jwheare
Copy link
Member

jwheare commented Jun 8, 2020

It's not academic at all. Non-existent users can't be interacted with in the same way. kicks, bans, dms, whois, etc. It breaks fundamental expectations of IRC presence. This may be something you want to do, but I wouldn't describe it as mainstream IRC functionality (hence niche).

Clients should be involved because this is about how clients display messages. Asking the server to pretend for a bot just seems to be the wrong approach. I want to spend effort on specifying a robust proposal for clients to display these messages in a more user friendly way. I don't want to spend effort on ratifying a workaround.

@slingamn
Copy link
Contributor

slingamn commented Jun 8, 2020

That makes sense. DMs and WHOIS are broken anyway, but I hadn't considered the impact on moderation (kicks and bans).

@jwheare
Copy link
Member

jwheare commented Jun 8, 2020

The point isn't whether they're broken already, it's that with source spoofing they look like they aren't broken.

@progval
Copy link
Contributor

progval commented Jun 8, 2020

We have two competing views here, but I think we can unify them both:

  1. we could add a tag for PRIVMSG that contains the spoofed nick (@jwheare 's proposal), and senders use it
  2. recommend that server implementations pass it to other clients (still @jwheare 's proposal), but they are allowed to rewrite messages however they want (covers @jlu5 's use case)
  3. have the separator thing as an official (but optional) or vendored tag?

@slingamn
Copy link
Contributor

slingamn commented Jun 9, 2020

@jwheare: leaving aside the issue of sanctioning bad behavior by servers, would this proposal be feature-complete from your perspective?

@jwheare
Copy link
Member

jwheare commented Jun 9, 2020

I’d be happy with a “display name” or “relay name” client tag spec.

Whether servers use this as a hint to rewrite the source nick would be out of scope and left up to the implementation I think.

I don’t fully get the separators thing or why it has to be specified.

@slingamn
Copy link
Contributor

I thought about it and I don't see much possibility of a viable compromise specification. The objective of this specification is to enable nick spoofing. If spoofing becomes an unspecified or implementation-defined behavior, it largely defeats the purpose and also makes the specification confusing on its own terms. (An example is the question of separators: the purpose of separators is to establish a disjoint namespace for spoofed nicks. If nick spoofing is optional or peripheral to the specification, then it is indeed unclear why they should be specified.)

I'm OK with what seems to be the status quo: leaving this open as draft/relaymsg, and then keeping the bridging use case in mind for any future display name proposals.

For consistency, and to prevent conflicts with any ratified specs using the same name
Thanks @SadieCat for noticing this
@Mikaela
Copy link
Contributor

Mikaela commented Jan 11, 2021

I think there should also be a RELAYNOTICE or RELAYBOT or similar command for the usecase of bridging NOTICE use by automatons. Two scenarios where this could be encountered:

  • Bridging multiple IRC networks where bots are using NOTICEs together.
  • Bridging Matrix to IRC as they have m.notice that is used for bots.

I have been using Matterbridge's relaymsg since it was released with Oragono and loving it, so I hope it will become an officially approved spec. My favourite thing is that receiving it just works with any client and thus will reduce complaints of relaying looking ugly.

@DanielOaks
Copy link
Member

DanielOaks commented Apr 24, 2021

This spec will probably live here as an open PR forever.

If we really wanted to @jlu5 we could make it a finalised vendor spec under either overdrivenetworks.com or oragono.io... but I'm also totally okay (probably more okay) just leaving this as a PR and using /draft forever (or until some grand c2ctag future where we replace this with a displayname c2c tag or something).

@progval
Copy link
Contributor

progval commented Apr 24, 2021

I don't think draft/ should be used forever, it's supposed to be only temporary, and for somewhat experimental implementations. Vendoring is perfect for this.

@DanielOaks
Copy link
Member

DanielOaks commented Apr 24, 2021

We'll see what @jlu5 thinks about vendoring, because there's no way the spec is fundamentally changing going forward.

@slingamn
Copy link
Contributor

I support maintaining the status quo.

@SadieCat
Copy link
Contributor

Is there any reason it could not be merged as-is? Blocking things because of a display names spec that may never come doesn't seem good tbh.

@jwheare
Copy link
Member

jwheare commented Apr 25, 2021

My objections from #417 (comment) still stand.

@jlu5
Copy link
Author

jlu5 commented Apr 26, 2021

I'm fine with the status quo but I don't mind using my network as a vendor tag either. Just hoping to stick to something, as it's a fair bit of busywork to keep renaming the tag in all the known implementations.

@jlu5
Copy link
Author

jlu5 commented Apr 26, 2021

I also don't see display name support becoming mainstream any time soon so it's not really workable for me right now.
(And honestly, I don't have either the time nor the motivation to hack it into half a dozen clients.)

@jwheare
Copy link
Member

jwheare commented Apr 30, 2021

Display name client tag proposal is now here: #452

Servers could use the tag proposed there as a hint for the behaviour described here instead of defining a new RELAYMSG command and tag.

agusdallalba added a commit to agusdallalba/telepathy-idle that referenced this pull request May 10, 2021
This character is used by IRC bridges that follow the proposed IRCv3 spec at <ircv3/ircv3-specifications#417>, such as Matterbridge and PyLink.

Not accepting the character leads to messages being dropped silently.
@jaggzh
Copy link

jaggzh commented May 20, 2021

Need a "bridge" keyword in here. :)

I was thinking of the relay/bridging issue. My reasoning was to account for the multitude of chat networks; many communities have people using multiple locations because of familiarity, comfort, features, etc.
I was thinking it would be a channel setting, where the user is authorized to allow it. My goal was, initially, to require the relay to have an indicator, settable by the channel admin; for example, jaggz@dc for when jaggz is talking on discord, relayed to irc.
(We could have a fallback for clients not supporting ircv3).

The spoofed nicks allows greater capabilities however; for example, one bot could handle relaying multiple networks, etc.
Or, the spec could allow an additional field for the network/source identifier, and supporting clients could then choose how to display it (again, with some compatibility fallback).

Or, it could be made more dynamic so some channel flags/settings could let the community (chanops) specify how to handle the source identifier, like in the case of your role-playing system where, perhaps, just the spoofed nick might be visible. In all cases I think a supporting client should receive the information and be able to distinguish, whether it's merely an indicator, or a new type of message (probably not?) Preventing name conflicts (ex. with a character not allowed in normal nicks), and allowing the potential to privmsg the original user, through the relay, are important to account for (and some of that can be part of the workload of compliant relay bots).

@Mikaela
Copy link
Contributor

Mikaela commented Jun 15, 2021

This was discussed in #Limnoria due to progval/Supybot-plugins#338 and kind of continuing from #417 (comment) I would like to add from there:

for what it's worth I love it [RELAYMSG], it may not be absolutely perfect, but then again nothing is and I think it can help a lot now and if there will later be better solutions then there will and they can be implemented. Isn't that how things are working in general?

@luke-jr
Copy link

luke-jr commented Jun 29, 2021

Just a thought: if spoofed nicks were limited to /, the server could know to route any PMs for the target to . Multiple relay targets could be handled by allowing the / inside as well, so you would have Joe@Discord@relaybot.

Downside of this approach is that it may make the full spoofed nick longer than necessary.

(Reversing the order (/) might be more intuitive.)

@DanielOaks
Copy link
Member

Aha bitbot revealed that the last comment meant to say 'if spoofed nicks were limited to <spoofed>/<botnick>. (github markdown interprets those as html tags and removes them)

In our use we don't include botnick at all in the spoofed nick, we tend to do just do something like <spoofed>/<originalservice> like e.g. dan/libera or dan/discord or that kind of thing, makes sense since you can have multiple services being relay'd and still be able to differentiate the original service they're coming from.

Not including <botnick> as part of the spoofed nickname is sort of the point of this spec -- with the restrictions in place (requiring oper capab or +o/+h in the channel or whatever) having to include the original bot nick reduces readability in such a way that means the typical non-relaymsg relaying looks about as clunky as with relaymsg.

@jlu5
Copy link
Author

jlu5 commented Oct 23, 2021

Just for completeness we discussed a few months back how to potentially integrate this with display-name support:

11:08 <jlu5> I think jwheare suggested something like @display-name=display_n;display-name-prefix=<display_n>\s;message-user=display_n!display_u@display_h PRIVMSG #channel :hello
11:09 <jlu5> where iirc: @display-name is used for clients that support it, otherwise the server can optionally rewrite to @message-user being the sender, or prefixing the message with @display-name-prefix
11:20 <jlu5> either as :display_n!display_u@display_h PRIVMSG #channel :hello OR :relaybot!relaybot_u@relaybot_h PRIVMSG #channel :<display_n> hello

Basically:

  • Clients supporting display-name would just see that (possibly by declaring support for it ahead of time to the server?). This is probably the most future-proof / transparent solution as it doesn't mask the relay bot source completely
  • Everyone else will either see the fallback message (originating from the relay bot) or the message rewritten to use the display n!u@h as the source
  • The rewrite mechanism should be opt-in or opt-out, probably based on the server admin's preference. (I don't think we discussed a specific way of doing this - maybe a tag for each client to CAP REQ, or a user mode?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants