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

DNS66 is blocking STUN/TURN traffic #193

Closed
dbrgn opened this issue Sep 7, 2017 · 9 comments
Closed

DNS66 is blocking STUN/TURN traffic #193

dbrgn opened this issue Sep 7, 2017 · 9 comments

Comments

@dbrgn
Copy link

dbrgn commented Sep 7, 2017

DNS66 is blocking STUN/TURN lookups for the WebRTC based call feature in Threema. The STUN lookups are done through UDP via ports 3478, 443 and 53. (Yes, using port 53 is ugly, but unfortunately required to get around restrictive but dumb firewalls.)

With DNS66 enabled, no reflexive or relay ICE candidates can be gathered. Does DNS66 explicitly try to block this traffic?

@julian-klode
Copy link
Owner

Then the lookup code is wrong. We only redirect special IP addresses corresponding to the DNS servers, all traffic to the internet does not arrive in the VPN. So Threema probably force uses the VPN despite the VPN not having globally routed IP addresses.

@dbrgn
Copy link
Author

dbrgn commented Sep 18, 2017

Thanks, the issue is probably related to the IP handling mode of WebRTC:

https://tools.ietf.org/html/draft-ietf-rtcweb-ip-handling-04#section-5

Mode 2: Default route + associated local addresses: WebRTC MUST
follow the kernel routing table rules (e.g., by binding
solely to the wildcard address), which will typically cause
media packets to take the same route as the application's
HTTP traffic. In addition, any private IPv4 and IPv6
addresses associated with the kernel-chosen interface MUST
be discovered through getsockname, as mentioned above, and
provided to the application. This ensures that direct
connections can still be established in this mode.

According to the docs for VpnService.Builder.allowBypass (which you never explicitly call), by default applications are not allowed to bypass the VPN unless they explicitly bind to the underlying network, which WebRTC probably does not do due to privacy considerations.

This also seems to affect other WebRTC based applications like Signal (see #181). Whitelisting works, but since the intent is to block ads, you might or might not want to change the default behavior.

@lgrahl
Copy link

lgrahl commented Sep 18, 2017

Then the lookup code is wrong.

This is unfortunately correct but caused by Google's WebRTC library. The library gathers the default address by the following technique:

   The appropriate addresses here can be
   discovered by the common trick of binding sockets to the wildcard
   addresses, connect()ing those sockets to some well-known public
   IP address (one particular example being "8.8.8.8"), and then
   reading the bound local addresses via getsockname().

And they use exactly 8.8.8.8 which in many cases will be a configured DNS server. Thus, getsockname returns the address associated to the TUN interface of this project. Hence, all further messages to STUN/TURN servers will be directed at the TUN interface, too.

Be aware that this is an issue that will affect most applications that utilise WebRTC (including browsers) and moreover might even affect other browsers that implement WebRTC. As a workaround, it might be feasible to just allow traffic that passes through the TUN interface but doesn't look like a DNS packet. Sure, it's inefficient but at least it should work.

@julian-klode
Copy link
Owner

8.8.8.8 is not configured as an address for the TUN interface, we do address translation: The addresses are bound to 192.0.2.k, k >= 1 or 2 or something. Thus connect() to 8.8.8.8 should not bind to the local address of the TUN interface.

@julian-klode julian-klode reopened this Oct 14, 2017
@julian-klode
Copy link
Owner

At least a C binary with connect() to 8.8.8.8 and getsockname() does not report back the TUN IP.

julian-klode added a commit that referenced this issue Oct 14, 2017
@julian-klode
Copy link
Owner

0.5.6 now calls allowByPass(), maybe that helps, I don't know. Any way to test that?

@julian-klode
Copy link
Owner

According to WebRTC troubleshooter, I get Relay,Reflexive, and Host connectivity; and sharing stuff via reep.io works as well.

@lgrahl
Copy link

lgrahl commented Oct 14, 2017

At least a C binary with connect() to 8.8.8.8 and getsockname() does not report back the TUN IP.

That only happens if 8.8.8.8 is configured as a DNS server locally. Have you tried that?

@julian-klode
Copy link
Owner

So, I don't see anything for me to do here.

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

No branches or pull requests

3 participants