Draft: I2PTunnel: Introduces I2PTunnelHTTPBrowserClient, a class/I2PTunnel type which protects clients against colluding hidden services
@zzz here be some dragons and a not inconsiderable code-drop, but I would consider this my most important contribution and/or roadmap item from this cycle and I'd like very much to have you look at it before 2.6.0 when you have some time. I also have some supplemental materials here, since it's a rather big change.
- First, the proposal itself: https://git.idk.i2p/idk/i2p.166.host-aware-proxy/-/blob/master/PROP166.md (I have also added it to the website)
- Second, the test matrix I made for it: https://git.idk.i2p/idk/i2p.166.host-aware-proxy/-/blob/master/TESTING.md
- Lastly, the list of "colluders" that can be used to demonstrate how the attack works and how the tunnel type prevents it: https://git.idk.i2p/idk/i2p.166.host-aware-proxy/-/blob/master/README.md
This is a multi-destination HTTP proxy useful for browsing I2P Sites when the user is concerned that a network of I2P Site operators(or a single operator with multiple services) may be colluding to "profile" a user of the conventional I2P HTTP proxy. This is part of an overall effort to reduce the "Fingerprintability" of HTTP-over-I2P users on my part, and in some ways, the last piece of the puzzle. It works by managing a "multiplex" of conventional HTTP Proxies, which are short-lived and use only 1 tunnel in, 1 tunnel out for 3 hops. I sometimes use "hostname" interchangeably with destination in the proposal document. This is both because I2P hostnames map to destinations, obviously, and also because this is intended to align with the way modern, tabbed browsers are intended to work. That is, they are HTTP clients, but HTTP is no longer the application, it is merely the language the applications speak. The application, which runs in the browser and on the server it is talking to, is instead demarcated by the hostname, and therefore information should not leak across hostnames.
These proxies are created "on-demand" where the demand is contact with a new destination. A "parent" proxy operating on a single local TCP port reads the request from the browser and prepares it using a new class, HTTPRequestReader, based on code from I2PTunnelHTTPClient but moved from there to make it re-usable and provide me with some introspection/logging about the results. I then use the final "targetRequest" to look up the hash of an I2P destination, and map a new I2PTunnelHTTPClient on a random high port for that destination. The fixed-up request is then directed to the newly-created I2PTunnelHTTPClient. Any time it is encountered again, the I2PTunnelHTTPClient is re-used. Outproxies are considered a single destination, and a "global" tunnel is used for all null destinations.
In terms of UI/UX, I2PTunnelHTTPBrowserClient should be identical to the I2PTunnelHTTPClient. My test matrix above is incomplete, but includes confirming that this is the case. This includes keepalive, gzip, blinded and encrypted leaseSets. If all goes well, I volunteer to deploy it in Easy-Install Windows, since I've always described that package as "browser-centric" in advance of or instead of deploying it in i2p.i2p
.