packages icon indicating copy to clipboard operation
packages copied to clipboard

xtables-wgobfs: add an iptables extension module to obfuscate WireGuard

Open infinet opened this issue 1 year ago • 10 comments

Maintainer: @infinet Compile tested: (ramips-mt7620 19.07.9 and 22.03.2, x86_64 19.07.9) Run tested: (x86_64 19.07.9)

Port from https://github.com/infinet/xt_wgobfs, this extension obfuscates WireGuard by:

  • 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 long random bytes.

  • Drop keepalive message with 80% probability.

  • Change the Diffserv field to zero.

See https://github.com/infinet/xt_wgobfs/blob/main/README.md for usage.

Example as client:

Add two iptables rules to firewall.user:

iptables -t mangle -I INPUT -p udp -m udp --sport 6789 -j WGOBFS --key mysecretkey --unobfs

iptables -t mangle -I OUTPUT -p udp -m udp --dport 6789 -j WGOBFS --key mysecretkey --obfs

Here assuming remote server is listening on port 6789.

Signed-off-by: Wei Chen [email protected]

infinet avatar Nov 27 '22 02:11 infinet

I changed the tile. Could you please re-run the Formalities test? Thanks!

infinet avatar Nov 29 '22 13:11 infinet

You need to change commit title also

Ansuel avatar Nov 29 '22 13:11 Ansuel

No usage of AUTORELEASE found in changes

github-actions[bot] avatar Nov 29 '22 13:11 github-actions[bot]

Not sure why but only 1 of the usual 10+ checks ran, I suggest rebasing on current master and doing a force push.

jefferyto avatar Aug 22 '23 04:08 jefferyto

@infinet It seems that your ChaCha8 hash function implementation has some crypto related flaws compared to reference ChaCha20 one:

  1. Although your macro called EIGHT_ROUNDS it runs only 4 rounds, so your hash is actually ChaCha4 - https://github.com/infinet/xt_wgobfs/blob/440a2ff505fec95a393c4a316ae2811c60ae0948/src/chacha8.c#L76-L79 - you have to call DOUBLE_ROUND 4 times to get 8 rounds, see reference https://git.zx2c4.com/wireguard-linux-compat/tree/src/crypto/zinc/chacha20/chacha20.c#n71
  2. You use ChaCha state part related to key in return value, whereas ChaCha20 skips it to nonce one - https://git.zx2c4.com/wireguard-linux-compat/tree/src/crypto/zinc/chacha20/chacha20.c#n150
  3. ChaCha state after rounds gets ORed with the initial state - https://github.com/infinet/xt_wgobfs/blob/440a2ff505fec95a393c4a316ae2811c60ae0948/src/chacha8.c#L101 - considering previous point it gets ORed with 4 well known constants and first half of the key. ChaCha20 hash doesn`t do OR before return at all.

valga avatar Aug 27 '23 16:08 valga

Thank you for the insight! It will take some time to review and correct that part of code. In general, this module is trying to remove wireguard packets signature with minimal overhead, while wireguard is taking care of the communication security.

infinet avatar Aug 28 '23 12:08 infinet

I've taken another look at chacha8 implementation.

  1. You're correct; the chacha8 indeed only does 4 rounds. Need to test the performance of 8 rounds. If the overhead is similar to current 4 rounds, then revise the code to 8 rounds.

  2. Wireguard uses XChaCha variant. It uses 128 bits nonce and original 256 bits key to generate a derived key, which is used by chacha20 with 96 bits nonce to encrypt message. The derived key generation takes first 32 bits and last 32 bits(Edit: first and last 128 bits) of multiple quarter rounds output, as you mentioned in remark 2.

  3. The keystream used by wireguard to encrypt message is generated by ChaCha20 block function. Its output is different from the key derive function. It adds the original state to the quarter rounds output. This module use the same approach. https://git.zx2c4.com/wireguard-linux-compat/tree/src/crypto/zinc/chacha20/chacha20.c#n84

infinet avatar Sep 04 '23 02:09 infinet

@infinet I also reviewed everything again and found this useful piece of information - https://crypto.stackexchange.com/a/11215

In short, original state addition (feed-forward) is required when you take parts of result that is being added with key (64 bits in the middle). In other words, you can omit feed-forward if you take first and last 32 bits, because they are being added with known input, so it will improve performance a bit.

So the only concern is number of rounds.

valga avatar Sep 04 '23 06:09 valga

@infinet I also reviewed everything again and found this useful piece of information - https://crypto.stackexchange.com/a/11215

So the only concern is number of rounds.

I have made few modifications.

  • The hash function is now chacha6 instead of chacha4.
  • Input to chacha is 16 bytes instead of 8 bytes.
  • All inputs for chacha are from the 16th to 31st bytes of WG message. First byte is used as counter and incremented each time to generate a new PRN.

The performance is almost the same.

infinet avatar Sep 18 '23 12:09 infinet

I have rebased it on the latest master branch.

infinet avatar Mar 22 '24 11:03 infinet