
On Oct 20, 2009, at 6:09 AM, Michael Reynolds wrote:
One usability flaw in most hostmasking implementations then is assigning it to a usermode. This means from the perspective of the client itself, its host on IRC is not static, as the mode (and thus its host) can be changed at any time. This breaks the assumption above and affects things as basic as automatic line breaks in channel or private message text. (A client that knows its own host length can calculate the maximum length of message text it can send before one server along the chain will truncate it, and can do its own line splitting to compensate.)
Using the hostname as part of the message length really is a design flaw. The message from the client never includes their own host.
If it were done again today I'd consider the statelessness that requires sending hostnames to be a flaw, but the issue with message length is more a consequence of a series of organic choices driven by constraints at the time. IRC message length was set before hosts were added, and the client and server software ran from the same codebase where prefixes were assumed. Message length estimation isn't the only thing affected by a modern stateful client having its own host changed underneath it, though. As a random example, consider those old-school scripts that automatically remove bans placed against yourself.
It also affects other clients, as things like bot access lists and channel bans no longer apply properly, WATCH/MONITOR-generated notifications might not be correct for subscribing clients, etc. The most common workaround to this is for each server to fake quit/ reconnect the mask-changing client for the benefit of other clients, but whether they internally reevaluate channel bans or deal with WATCH etc appropriately is of course an open question. It's a rather fragile and kludgy practice.
It's rather a successfully implemented practice. As you say, they simulate rejoin/reconnect to update other clients. Ban/watch/etc lists do not need reevaluated as they're checked against the masked and unmasked entry, neither of which change, unless some fruity oper gives the user a custom vhost (which isn't really covered in the realm of hostmasks).
Note that that assumes the server is aware of what the mask will be ahead of time, which is still a problem for most registration-based masking implementations.
The proper way to handle masking is to do it on connect, and not allow the masked status to change during the session.
Proper according to who?
I admit personal bias, but it's based on several perspectives, including historical discussion by others. That is the only way I'm aware of to maintain the properties assumed by both server UI and clients of various ages. The assumption that a host does not change was embedded in IRC behavior when hosts were added. It's visible in the way server-side things like channel bans are handled, how stateful clients gather and apply information during a session, and even in relatively recent server-assisted state extensions like UHNAMES. I:line-style masking and bahamut's own oper hostmasking work this way, and as a result need no special treatment by servers or clients.
However, there remains an issue with the secondary goal of maintaining a hierarchy: a mapping attack. A fundamental property of a hierarchical host is that parts of it remain static based on ISP or region. This means that for a hierarchical mask, parts of the mask remain the same, and so obtaining only one real host in the region effectively breaks part of the mask for all hosts in the same region.
5342.8743.2357.9026 -> 10.1.2.3 5342.8743.2357.1824 -> 10.1.2.something
UnrealIRCd uses a system of 3 hashes, followed by '.IP', to make it appear as a hostname to clients. Thus, it reverses the hierarchy. A hashed IP becomes dddd.cccc.bbbb.IP. The whole thing is unique per IP. *.cccc.bbbb.IP is unique per /24, etc. Assuming the hashing algorithm doesn't suck, you'd need to trick a user in the same /24 to reveal their IP to be able to do anything about other users in the same block.
I did have that implementation in mind, but acquiring partial masks for most popular regions is not terribly difficult for someone with enough time. Certain botnet runners tend to deal in information, and this is trivial information to gather. There are also the usual suspects like open proxy lists, along with more focused attacks using host information gathered from other online services, or social engineering like an accepted DCC request or a visit to a web site where the attacker reads the access logs.
Masks based on centrally-assigned identifiers are much more effective, since they cannot reveal part of the real host if they are not based on it. The most common implementation of this is on networks that register user accounts (instead of nicknames), where the user account name becomes the identifying part of the masked hostname.
This becomes a hassle to users who just want to cover their ass. They should not have to waste time identifying on each connect, just to hide their host.
Which is one reason I harp on about usability issues with the identification mechanisms commonly used. Most clients are fully capable of supplying authentication information automatically when they connect, but there are very few server implementations that actually do something with it. So far the only viable alternative I've seen to registration hassle is the hash-based hierarchical scheme that can't actually guarantee the protection it claims to provide. Which is worse, some hassle and a masking implementation that actually hides the real host, or no hassle and a masking implementation that provides a false sense of security? These options are not mutually exclusive; DALnet caters to a significant userbase that doesn't register nicknames anyway. If long- term stability is provided by registration-based masking, it might be acceptable to weaken the hierarchical properties of anonymous hash- based masking in favor of increasing attack difficulty. At that point users would have a choice.
Perhaps this could be applied to DALnet by using a unique identifier mapped to email address instead. (*Not* a hash based on the actual address, just an identifier assigned internally.) While making the resulting hosts not as aesthetically pleasing, it sidesteps the valid character issue, and should narrow the abuse window to the same size as networks using user account registration (as they usually limit number of registrations per email address).
Not sure what you're saying here, but if I'm correct in assuming you'd like to include the local part of an email address, do take note that every character is valid in an email address, except NUL.
I was envisioning something like A5432D42F768.masked.user, where the identifier is meaningless, just constant for a particular email address. It's a rough approximation to a "user account" using the existing information on DALnet.
Another issue is that if masking is optional, then most people consider it desirable for server-side access lists (channel bans, SILENCE, etc) that contain entries based on real hosts to match even if a client is masked. However, that means those lists themselves can be used to perform mapping attacks, e.g. by CTCP PINGing a client repeatedly while modifying your own SILENCE list to see which address components block the response. Note that this works in real time regardless of the masking algorithm used.
This only works if you have enough of the hostmask to begin with. For example, network-deadbeef.hsd1.mi.comcast.net covers over 1 million IPs scattered in an accumulative block of tens of millions. The client would know something's up long before you even got the right /16.
As mentioned above, there are already ways of narrowing it ahead of time. For popular regions, it's also easy to find enough online clients to distribute a mapping attack up to the last component. The problem with the mapping attack is that time is on the attacker's side.
A logical way to avoid this is to make hostmasking non-optional and forget about real hosts entirely.
And here I would have to wholeheartedly disagree wrt needing to forget real hosts. It's a feature that has been refined over the course of a decade, with constant development and testing. Oh, and it works.
But what function do real hosts serve in an environment that encourages hiding them? -- Quension