Iptables WireGuard obfuscation extension

Jean-Philippe Aumasson jeanphilippe.aumasson at gmail.com
Wed Sep 28 18:17:00 UTC 2022


ChaCha6 is probably enough crypto-wise here.

On Wed 28 Sep 2022 at 18:35 Jason A. Donenfeld <Jason at zx2c4.com> wrote:
> Hey Wei,
>
> On Sat, Sep 10, 2022 at 06:34:42AM -0500, Wei Chen wrote:
> > Hi,
> >
> > Jason once suggested use a netfilter module for obfuscation[1]. Here is
> one.
> >
> > https://github.com/infinet/xt_wgobfs
> >
> > It uses SipHash 1-2 to generate pseudo-random numbers in a reproducible
> way.
> > Sender and receiver share a siphash secret key. Sender creates and
> receiver
> > re-creates identical siphash output, if input is same. These siphash
> outputs
> > are used for obfuscation.
> >
> > - The first 16 bytes of WG message is obfuscated.
> > - The mac2 field is also obfuscated if it is all zeros.
> > - Padding WG message with random bytes, which also has random length.
> They are
> >   from kernel get_random_bytes_wait() though.
> > - Drop 80% of keepalive message at random. Again randomness is from
> kernel.
> > - Change the Diffserv field to zero.
> >
> > Tested working on Alpine linux kernel 5.15 and CentOS 7 kernel 3.10.
> >
> > Performance test in two Alpine VMs running on same host. Each VM has 1
> CPU and
> > 256 MB RAM. Iperf3 results 1.1Gbits/s without,vs 860Mbits/s with
> obfuscation.
>
> This is super cool! I'm very glad to see that you've made this.
>
> A couple considerations for improvement (take them or leave them):
>
> - Instead of using siphash, if you can make use of 64 bytes of
>   randomness at a time, you might be able to get away with chacha8 (or
>   even lower). The input to chacha20 is typically a 256 bit key and a
>   nonce, but because we don't care about the cryptographic security here
>   -- wireguard handles that part -- we can play fast and lose, and make
>   our threat model, "would be too computationally complex to detect in
>   real time". Things become quite fun when you don't need real crypto.
>   To that end, we could perhaps get away with using chacha8 instead of
>   chacha20, and doing so with a 128-bit key. This then provides lots of
>   input to chacha:
>
>   * 16 bytes, where the second half of that key was
>   * 16 bytes nonce (since it doesn't look like you need more than one
> block)
>   * If you really want to play fast and loose: 32-byte constant...
>
>   Again, this is awful cryptographic advice, but from a traffic analysis
>   point of view, I doubt it makes a difference.
>
>   On the other hand, if all you need is 16 bytes output, then I guess
>   siphash gets the job done.
>
> - get_random_bytes() is slow if all you need is a byte at a time. That
>   computes 96 bytes and then throws away 88 bytes of it. Instead, you
>   can use get_random_u32(), which batches, and throw away 3 bytes. Or, I
>   think I'll add to kernel 6.1 get_random_u8(), which will waste
>   nothing.
>
>   But actually, do you really need to do that? Can't you just run chacha
>   or siphash or whatever super fast non-cryptographic thing you have,
>   and just have an incrementing nonce? Or, better, since those keepalive
>   messages already have a suitably random poly1305 tag, just run siphash
>   on that, and discard if the resultant first byte is high/low/whatever.
>
> - If this is to ever go upstream, you might want to add a `--obfs-type
>   N` parameter to the XT userspace library and the IPC struct, and make
>   it mandatory. To begin, everybody would use `--obfs-type 1`, since
>   that's all there is. But maybe overtime, you'll add a fake TCP mode or
>   a fake QUIC mode or a fake HTML mode, and then the types will grow.
>   This way, maintenance wise, you only have to send updates to the
>   netfilter module in the kernel, and don't need to update the libxt
>   part.
>
> Jason
>


More information about the WireGuard mailing list