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?
Yes, lots of firmware runs on hardware where a GC doesn't make sense. Because of limited memory and performance constraints. Sometimes having predictable timings (i.e. not a GC with pauses) is nice. I believe compiler and library support is also just better for many embedded platforms in rust.
> networking type software
Rust is a much more aggressively optimizing compiler, and thus will typically be faster, in the places where that matters. GC pauses might also be a point against golang in some places here. Rust's idioms provide slightly less opportunity for bugs in places where reliability matters (e.g. having a type system that requires you check for errors instead of just patterns that encourage it).
So there's a difference, but generally go is a good enough language for networking software and it would be rare that I wouldn't suggest that "use what you know" is more important than the differences between the languages for non-firmware network software.
Very cool. I may use this, but also curious what the best choice would be if you don't need encryption. I'm specifically wanting to enable some local container networking using apple's new container tool [1]. I know I could just use Docker...
One usecase I've always wanted is being able to combine multiple tunnels into one shared connection, for instance airVPN allows 5 simultaneous users per sub, it would be awesome if I could run 5x connections and combine their traffic, but I dunno how I would do this with wg / nmcli
VPNs are level 3 while interface bonding is level 2. You’d have to create a vxlan over wireguard. It sounds like a nightmare but it would be interesting to implement.
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)?
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:
How does this work in something like Kubernetes where you have a sidebar container configuring the network for the main container without affecting others on the same host?
I think all containers share the same netns in a pod. You restrict the pod to only the Wireguard peer IP, and have a (NET_ADMIN) sidecar container create an interface (tun/kernel wg) and update the routing tables for the netns. Then I believe the traffic from the other containers in the pod is tunneled.
Can you use user namespaces to create a network namespace with the VPN active and stick applications in that namespace?
From a quick search, https://blog.thea.codes/nordvpn-wireguard-namespaces/ sees to have at least the bones of a decent solution, though I've not had a chance to dig very far. A lot of results use root to set up the namespace, but I was pretty sure that shouldn't be needed with a new kernel and user namespaces enabled
I have no idea. I’ve never messed with it, but maybe something like eBPF to intercept network syscalls? Not sure if that’s a thing—especially without root access? Mostly I was just thinking the project page could use a disclaimer since, in Go, it is common to bypass libc. :shrug:
This seems like a very cool, useful project though!
I believe you are making use of gVisor’s userspace TCP implementation. I’m not sure if there is something similar in Rust that would be so easy to set up like this.
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.
1. https://github.com/puzed/wrapguard