2024.11 Vol.1

// Network Metadata Leakage #P2p

Who Knows Who to Who

Two parties are communicating over an un-trusted channel, but they want all their data to remain hidden from others. This is the story of the internet. Luckily, encryption came along and has made it possible to efficiently hide a lot of the data. But not all of it.

I think there are three categories of data to protect.

The first is the data content itself, whatever messages the two parties are exchanging. Once encrypted this is called the ciphertext.

The second is side-channel data. This is where the real world gets a little less contained than the perfectly encapsulated “two parties and a channel”. Side channel data can be anything that sheds even just a little bit of light on the encrypted data. A third party could analyze traffic patterns between the two parties, or even electromagnetic emissions of a party’s CPU. The idea is to combine these side-channel data vectors to triangulate some information about the parties, maybe even enough to crack the data content.

The third category is metadata about the parties themselves. The big one on the internet is a party’s IP address. There are some scenarios where two parties would like to exchange messages, but don’t even want the counter-party to know their IP address. This is a tricky requirement since in order to communicate the counter-party needs to know where to send data…generally done with an IP address! This is kinda like asking someone to mail something to you, but refusing to give them an address.

The first two categories are very interesting, but largely mitigated with modern cryptographic schemes. I am curious about the metadata, since it seems almost impossible to keep it hidden entirely. And the patterns of today leave a little to be desired.

The simplest solution is to add a proxy server in-between the two parties. This server simply reads data on one end and writes it on the other, and vice versa, but it hides the two parties from each other. Simple, but obvious downsides. It adds another hop to the network, lowering performance, and the proxy becomes a point of failure. And while privacy is maintained between the parties, the proxy now knows all the metadata.

A more complex strategy is anonymity networks (e.g. TOR). These are networks of servers which two parties can proxy requests through. The networks can use a technique called onion routing where each server in a route across the network only knows about the hop before and after it. So compared to a single proxy server, the privacy is increased since the knowledge of the request is diffused across the network of machines. But the performance issues are further exasperated since there are now multiple hops across the network. Is the complexity of a network over just a proxy worth it? The number of nodes in a network probably determines its value, but who is running all these nodes?

the network stack

Both the proxy and anonymity network strategies are built on top of today’s common network stack. Back in school, we learned about the OSI seven layer definition of the network stack. I find it a bit too granular for my thinking. The standard TCP/IP implementation combines a few of those layers into just four, from top to bottom:

  • Application
    • High level protocols like HTTP and DNS.
  • Transport
    • End to end communication with protocols like TCP.
  • Internet
    • Routing of IP (Internet Protocol) data packets.
  • Link
    • Hardware transmission of data (e.g. ethernet).

It took a long time for these layers to be standardized and used everywhere. So while they have privacy shortcomings, they are probably not going anywhere any time soon. I find the IP layer extra interesting. IP packets include source and destination IP addresses headers, so kinda terrible for privacy as they are routed across the internet. But so much infrastructure has been deployed to support IP it is probably the toughest to do anything about.

With that said, another way to try and protect user metadata is to replace parts of the existing network stack. This means higher level applications would gain the privacy benefits for “free”, but much easier said then done. Most modern operating systems these days expose a socket-like abstraction which wraps up everything at and below the transport layer. They also have optimizations built in for things in the application layer like DNS. Modern languages usually provide a standard library which wraps up more of the application layer protocols like HTTP. So while it is possible to swap out some of these layers, it is going against decades of momentum.

While ambitious, I believe that is the goal for some projects like I2P the “Invisible Internet Project”. If all parties communicating buy into an augmented network stack, a lot of privacy can be gained. The cost is generally very high. Even the I2P project recognizes this cost and is an overlay on top of the internet layer, not dropping below there. Ideally, a privacy overlay is in the network stack, but as “high” up as possible for minimal adoption friction.

store and forward and query breaking

Are there any other strategies to minimize user buy-in costs? We would like to use the existing network stack, but a straightforward proxy or anonymity network don’t quite cut it.

If we take a step back, we are trying to break the connection of who is talking to who. What if a proxy’s capabilities are extended to hold state, and not just simply forward requests in a state-less fashion, a request/response between parties could be broken up into two steps. The first request stores a message on the proxy, the second pulls it down. This pattern is called Store and Forward, kinda like a mailbox. This gives a chance for a proxy to break the connection between the two parties, and maybe not even let the proxy know they are talking.

If only two parties are using a given proxy, this doesn’t change anything, the proxy knows who is talking to who. However, if the proxy is being used by many parties, the anonymity set grows. It becomes harder for a third party to connect which requests are linked between two parties. So how do the two parties link the requests to each other? The sender might write a message with ID 123 and the receiver knows to pull down the message with ID 123. The big new requirement here is the parties need to agree on an ID in an “out of band” (e.g. a QR code in real life) channel. But an ID makes it easy for the proxy to re-link the requests.

Assuming messages data is relatively small, what if a read request just returned all the messages? The calling party would only care about one message, a needle in the haystack, but this would de-link the parties. There are a lot of performance issues with that take, but perhaps some privacy-preserving filtering patterns like the ones used in BIP157/BIP158 could help mitigate things. Another possibility could be a new homomorphic cryptography pattern which allows a server to query for data without knowing what the encrypted data contains. But these generally solve the issue by querying a lot of the data (effectively creating an anonymity set), so may not scale for all use cases.

In any case, perhaps there is a strategy to break what exact data is being queried in order to break the who-to-who metadata connection. And maybe that is cheaper than the cost of an anonymity network which breaks the link with onion routing across a bunch of machines? But what if we already have a bunch of machines…

the existing lightning network

In bitcoin land, there is an existing network of machines which is thriving, lightning network nodes. And these machines are using onion routing! Can we just…use them?

The lightning network is purpose built to privately route payments between users. The onion routing is used to let nodes communicate some information in order to forward a payment. All communication is within the network, there is no “outside the network” feature to talk to anyone on the internet. The protocol is well scoped. And even with that well defined scope, it is complex.

But there is onion routing and an existing incentive to run a node beyond altruism, it’d be great to make this work! What if these nodes were extended with some sort of state storing feature and parties could use the nodes as store and forward meeting points? There would be no requirement for a data query breaking pattern, because the onion routing takes care of breaking the who-to-who metadata. It is also nice that an outsider wouldn’t know if a message is for a payment or a store and forward data drop.

New requirements for store and forwards still makes this iffy. One node in the onion route will have to be an exit node to the outside internet. Very different from the “internal only” model of today. And this also leaks some metadata about which IPs are using this feature. But maybe some balance could be struck across the lightning network where this wouldn’t be very valuable information.

The big hindrance is that lightning nodes are already doing a lot. I believe a protocol upgrade would be required to allow the onion messages to essentially pass along arbitrary data to be stored, which has a bunch of unbounded-data openness which would need to be wrangled in. It just doesn’t seem likely.

nostr relays and onion routing

There is another set of existing machines in a bitcoin adjacent land, Nostr relays. Nostr relays are storing arbitrary data (“notes”) for clients, so could be used as meeting points in a store and forward protocol. Nostr clients use high level APIs, so shouldn’t be a large lift for implementing parties. The ecosystem is also relatively well integrated with bitcoin, so there are potential financial incentives to run relays. There are also a lot of types of messages already being stored. All in all, a ripe anonymity set.

As far as I know, the Nostr relays do not support any query-breaking patterns or onion routing. So just using a relay as is would have all the problems of a normal proxy.

Perhaps Nostr relays could be extended with some sort of query-breaking method. It is not obvious to me if this would get enough privacy since it would depend on the amount of users and data of a given relay. Nostr also prides itself on its dead simplicity and these types of queries would require size-able addition to the protocol. But seems possible.

And what about onion routing? Onion routing could be added as an extension to the protocol, but I think it could also just be a wrapper side car process. The process would simply forward onion messages or persist the data at the relay if its the end of the route. Maybe even the onion routing logic could be shared from the lightning network with LDK.

Nostr is very bitcoin and ecash friendly. Onion routing might be a great use case for ecash since the bearer tokens could be embedded in each layer to pay the node to either store the message or forward it on the next hop. Bit of trust involved there, but the sender is choosing the route so theoretically could select nodes they trust. But there are still a lot of questions here. How should each layer be encrypted for a relay? Would it be possible for a response to make it back to request or is this fire and forget? NIP-01 appears to limit a relay to only using websockets which feels a little much for this use case, can that be loosened?

There has been some chatter about a re-publish operation for Nostr which may check enough boxes. But it hasn’t been worked on in a bit.

masque and ohttp

There is some new proxy tech which makes the simple one box proxy setup a little more appealing. They bring structure to the proxy protocol which makes them easier to use and possibly more private, since a single proxy can theoretically service a bunch of clients. However, they will still have the network level metadata of the communicating parties.

MASQUE is lower level, the transport level to be exact, building on tech used in HTTP/3. As long as the client and proxy understand that tech though, it can be used to proxy all sorts of connections. Even ones that were historically tough like websockets.

OHTTP is higher level, operating above classic HTTP. It is stateless and simple, but the provided structure makes it easier to integrate. All parties however, client, proxy, and server, need to use the protocol.