WireGuard with obfuscation support
Jason A. Donenfeld
Jason at zx2c4.com
Mon Sep 27 16:21:03 UTC 2021
There are some neat aspects of the approach here. Encrypting using the
pubkey has the nice effect of making packets look like noise while
also being sufficiently peer-linked that it might not be super
feasible to detect (though still possible I suppose).
I don't think we'd merge something like this into wireguard-itself,
unfortunately. Obfuscation is a bit of a cat and mouse game, and were
we to bake a handful of methods into wireguard, much focus would be
spent on detecting those, and then the whole thing would be moot.
>From my own obfuscation projects, I've found the most effective
techniques involve mimicry of other explicitly-allowed protocols,
rather than just turning packets into noise, and mimicking the related
packet timing and length relations of those protocols too. It's
possible to do this in part using Markov chains, but also for your
likely use case, you may be able to just code logic for fake tcp +
http -looking sessions, or perhaps quic in the future.
But your likely use case is also not likely to be the same as others'
use cases for obfuscation. For example, while much obfuscation focuses
on censorship resistance, there's another corner that focuses on IDS
evasion, like hiding inside of Kerberos or RDP or even resembling
SIGTRAN packets. And even in the censorship resistance space, there
are often important tradeoffs to be made between performance and
detection: do you want your connection to be as speedy as possible, or
do you want to ensure that you won't be detected? What are the
repercussions of failure for each case? And moreover, what about when
targeted traffic shaping is used in connection with DPI or related
heuristics? In that case, a popular technique appears to be adding FEC
to packets. And so on and so forth.
This all is to say that the obfuscation game is a big rabbit hole of
sorts, and there's unlikely to be one solution for the many
applications of it.
For that reason, as I've written on this list before, I think
obfuscation ought to be in a layer above wireguard, not within it. You
can do this by setting the endpoint to be a localhost udp port, or
better, by writing a netfilter module or using something like NFQUEUE
to do it in userspace. While there's a lot of enthusiasm for
"pluggable transports" and such, I actually don't think it's a bad
idea to violate the layering distinction and borrow things like peer
public keys when that makes for a potentially slicker system.
For example, I could imagine a netfilter plugin that specifically
attaches to a wireguard interface, and uses config information from it
to do per-peer obfuscation, so that additional identities don't need
to be configured. An admin would run `iptables -t mangle -A OUTPUT -m
evgeny_wg_thing --out-iface wg0 -j EVGENYS_COOL_OBFS_THING_OUT &&
iptables -t mangle -A INPUT -m evgeny_wg_thing --in-iface wg0 -j
EVGENYS_COOL_OBFS_THING_IN` and then presto, everything would work
with no additional configuration.
Splitting out your ideas into something that runs adjacent to
wireguard but works intimately with it might require a little bit more
work in the short term, but I think long term that will lead to a more
sound design, and it could grow and morph all sorts of interesting
More information about the WireGuard