Live data from Hacker News

GotaTun – Mullvad's WireGuard Implementation in Rust

mullvad.net

91–100 of 142 posts

Re: GotaTun – Mullvad's WireGuard Implementation in Rust

#91

Earlier quoted context omitted.

Correct me if I’m wrong, but if you use LD_PRELOAD, presumably it will not work for applications that circumvent libc, such as Go binaries (at least those with CGo disabled)?

Yeah you are right. Can you think of any way we could capture that traffic too?

Tor does this the right way on Linux. You make a separate user namespace with access only to the WireGuard network adapter and run the program inside of that. You want the kernel involved if you want any sort of guarantee:

https://blog.torproject.org/introducing-oniux-tor-isolation-...

Re: GotaTun – Mullvad's WireGuard Implementation in Rust

#92
post #6

Nice, I love WireGuard. I ended up building WrapGuard [1] to run applications without root access to the host and choose Go to write it in. I don't really know Rust, but does it make more sense for firmware/networking type software? Is there even a difference? 1. https://github.com/puzed/wrapguard

I've implemented a few protocols in rust (and plenty in go and other languages).

One thing others haven't mentioned that I like rust for in this space:

The typestate pattern makes it really nice to work with protocols that have state. You encode your state machine logic into types, and your transitions into methods with move semantics, and you have a nice way to make sure your higher level code is using your protocol library correctly.

Another nice thing is that you can keep the number of copies and allocations way down if you're careful about how you use your buffers.

Re: GotaTun – Mullvad's WireGuard Implementation in Rust

#95

Fingers crossed that GotaTun will also make its way into the Tailscale Android app (since that's what I use to connect to Mullvad).

GotaTun is specific to Mullvad and the features they usually add make sense for a public VPN provider. Unlikely projects such as Tailscale adopt it.

Besides, engineers at Tailscale, I don't think, strike me as startled by any hurdle too tall to debug, improve Go-based libraries. In fact, they pushed wireguard-go past 10gbps on Linux-based platforms back in April 2023! https://tailscale.com/blog/more-throughput

Re: GotaTun – Mullvad's WireGuard Implementation in Rust

#97

Earlier quoted context omitted.

Correct me if I’m wrong, but if you use LD_PRELOAD, presumably it will not work for applications that circumvent libc, such as Go binaries (at least those with CGo disabled)?

Yeah you are right. Can you think of any way we could capture that traffic too?

ptrace: https://github.com/hmgle/graftcp

Re: GotaTun – Mullvad's WireGuard Implementation in Rust

#100

Earlier quoted context omitted.

Why 1320 and not larger?

For most any 5G network you should be safe to 1420 - 80 = 1340 bytes if using IPv6 transport or 1420 - 60 = 1360 bytes if using IPv4 transport. For testing I recommend starting from 1280 as a "does this even work" baseline and then tweaking from there. I.e. 1280 either as the "outside" MTU if you only care about IPv4 or as the "inside" MTU if you want IPv6 to work through the tunnel. This leverages that IPv6 demands…

Hah! I just ran into this recently and can confirm. The coax to my DOCSIS ISP was damaged during a storm, which was causing upstream channels to barely work at all. (Amusingly, downstream had no trouble.) While waiting for the cable person to come around later in the week, I hooked my home gateway device up to an old phone instead of the modem. I figured there would be consequences, but surprisingly, everything went pretty smoothly... But my Wireguard-encapsulated connections all hung during the TLS handshake! What gives?

The answer is MTU. The MTU on my network devices were all set to 1500, and my Wireguard devices 1420, as is customary. However, I found that 1340 ( - 80) was the maximum I could use safely.

Wait, though... Why in the heck did that only impact Wireguard? My guess is that TCP connections were discovering the correct MSS value automatically. Realistically that does make sense, but something bothers me:

1. How come my Wireguard packets seemed to get lost entirely? Shouldn't they get fragmented on one end and re-assembled on the other? UDP packets are IP packets, surely they should fragment just fine?

2. Even if they don't, if the Linux TCP stack is determining the appropriate MSS for a given connection then why doesn't that seem to work here? Shouldn't the underlying TCP connection be able to discover the safe MSS relatively easily?

I spelunked through Linux code for a while looking for answers but came up empty. Wonder if anyone here knows.

My best guess is that:

1. A stateless firewall/NAT somewhere didn't like the fragmented UDP packets because it couldn't determine the source/dest ports and just dropped them entirely

2. Maybe MSS discovery relies on ICMP packets that were not able to make it through? (edit: Yeah, on second thought, this makes sense: if the Wireguard UDP packets are not making it to their destination, then the underlying encapsulated packets won't make it out either, which means there won't be any ICMP response when the TCP stack sends a packet with Don't Fragment set.)

But I couldn't find anything to strongly support that.

Post reply on HN