P2P connections bypassing VPN are possible
Longer title: P2P connections with VPN are possible with the "Enumerate all addresses" IP handling policy.
Currently we discourage the use of Snowflake proxy extension together with a VPN:
- https://forum.torproject.org/t/discourage-vpn-usage-when-running-a-snowflake-proxy/2408?u=wofwca
- tpo/web/support#296 (closed)
- https://forum.torproject.org/t/running-a-snowflake-proxy-behind-a-vpn-consequences-for-tor-users/2047/4?u=wofwca
In short, the reasoning is that the VPN's IPs are usually blocked, and the VPN's IP is what the clients will try to connect to, so the extension just won't work, and will even do harm by advertising itself as a working proxy whereas in reality it doesn't work.
However, WebRTC can bypass a VPN, i.e. listen for connections on the real (ISP-provided) user IP.
This is possible thanks to the "Mode 1 - Enumerate all addresses" IP handling policy (see RFC 8828).
This mode is active on Chromium browsers by default, but not on Gecko (Firefox).
You can test it by going to https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/, activating your VPN (disable the "kill-switch" feature if your VPN client has it), clicking "Gather candidates" and seeing if you have more than one server-reflexive (srflx) ICE candidate (they should have different IPs). If you do, this means that your browser just bypassed the VPN.
This means that running Snowflake together with a VPN should not be discouraged, as long as Snowflake can bypass the VPN.
A thing to note is that VPN clients usually have a "kill-switch" feature which prevents apps from bypassing the VPN. For example, it exists in the WireGuard client for Windows. In that case, Snowflake is not gonna be able to bypass the VPN.
As far as I'm aware, there is not a reliable way for browser extensions to test whether a VPN is used.
However, we can tell whether we can bypass the VPN if it is being used with fair certainty. And that is, as I mentioned above, by looking at ICE candidates and seeing whether we have more than one server-reflexive candidate with a unique public IP address.
The proposal
Let's add a toggle in the extensions popup with a label "I am using a VPN". If it's on, prior to trying to serve clients, Snowflake should test whether it can bypass the VPN (by, as mentioned above, looking if we can gather more than one server-reflexive candidate). If so, then let's serve clients! If not, let's disable Snowflake and tell the user what their options are, which are:
- Choose the "enumerate all addresses" IP handling policy.
- Disable the "kill-switch" feature in their VPN client.
After implementing that, we should encourage people to run Snowflake even if they're using a VPN, and even if they're inside a censored area (Snowflake extension already checks whether it is able to connect to the Snowflake bridge / server).
Does this apply to standalone Snowflake?
This idea of bypassing VPNs can also apply to standalone Snowflake, however, I am not sure whether it's possible to do on Android (with Orbot's Kindness mode) directly: maybe the "kill-switch" thing is managed by the OS. On Desktop this is perhaps not worth the effort as the extension is more popular on Desktop than standalone Snowflake. But I created an issue in Pion about IP handling policy anyway. Another thing to note is that some VPN client apps (e.g. Orbot on Android, Amnezia on desktop and Android) have a "split tunneling" ("exclude apps") feature, but in that case there is nothing for Snowflake to do: if the proxy operator is not censored, it would just work then.
Why care
You might say "why should we do so much work just for a small fraction of users who use a VPN".
My answer: because people who are affected by censorship (and therefore use a VPN) are just more likely to want to help others circumvent it. People in, let's say, the US, generally do not care as much about helping Russians circumvent censorship as Russians themselves do.
So, for this reason this resolving this issue should have a higher impact than one would expect if that wasn't the case.
In addition, this should provide somewhat better censorship-resistance for when the Snowflake proxy operator is inside a censored country, because client-to-proxy connections can be performed domestically (inside the country), which sometimes should mean that they don't have to pass through the censorship firewall.
Effectively this would be like "sharing a VPN with your comrades", similar to how NewNode operates.