[GH-ISSUE #42] Document AmneziaWG Protocol #14

Closed
opened 2026-10-13 21:02:17 +00:00 by bsakaguchi · 10 comments
Owner

Originally created by @marek22k on GitHub (Aug 31, 2024).
Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-go/issues/42

Hello,

AmneziaWG introduces various new parameters in contrast to Vanilla WireGuard. What exactly do these do? How does AmneziaWG work?

Originally created by @marek22k on GitHub (Aug 31, 2024). Original GitHub issue: https://github.com/amnezia-vpn/amneziawg-go/issues/42 Hello, AmneziaWG introduces various new parameters in contrast to Vanilla WireGuard. What exactly do these do? How does AmneziaWG work?
Author
Owner

@leninalive commented on GitHub (Sep 15, 2024):

I am closing this issue as we are not interested in providing such documentation publicly. If you wish, you could obtain these docs by researching source code on your own.

<!-- gh-comment-id:2351710572 --> @leninalive commented on GitHub (Sep 15, 2024): I am closing this issue as we are not interested in providing such documentation publicly. If you wish, you could obtain these docs by researching source code on your own.
Author
Owner

@marek22k commented on GitHub (Sep 15, 2024):

Is there a particular reason for this? (Do you not want to publish documentation because the risk of AmneziaWG being blocked is then higher?)
Will there be public documentation on what the parameters (S1, H1, ...) do?

<!-- gh-comment-id:2351741737 --> @marek22k commented on GitHub (Sep 15, 2024): Is there a particular reason for this? (Do you not want to publish documentation because the risk of AmneziaWG being blocked is then higher?) Will there be public documentation on what the parameters (S1, H1, ...) do?
Author
Owner

@leninalive commented on GitHub (Sep 15, 2024):

Do you not want to publish documentation because the risk of AmneziaWG being blocked is then higher?

Exactly.

<!-- gh-comment-id:2351742762 --> @leninalive commented on GitHub (Sep 15, 2024): > Do you not want to publish documentation because the risk of AmneziaWG being blocked is then higher? Exactly.
Author
Owner

@marek22k commented on GitHub (Sep 22, 2024):

I had a look at the code and in the kernel module a netlink message WG_CMD_UNKNOWN_PEER seems to be distributed in case of failed authentication of a peer. However, I cannot find a place where such a message is received. Why does AmneziaWG send it?
Is it intended for analysis by third party programs?

Furthermore, the documentation says All parameters should be the same between Client and Server, except Jc - it can vary.. I tried the whole thing once - set Jmin and Jmax to different values for two peers and it still worked. Is the documentation wrong at this point?

<!-- gh-comment-id:2365399761 --> @marek22k commented on GitHub (Sep 22, 2024): I had a look at the code and in the kernel module a netlink message [`WG_CMD_UNKNOWN_PEER`](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/8d1b073205538673f5da4831c4d39ef8acf44f8c/src/uapi/wireguard.h#L133) seems to be distributed in case of failed authentication of a peer. However, I cannot find a place where such a message is received. Why does AmneziaWG send it? Is it intended for analysis by third party programs? Furthermore, the documentation says `All parameters should be the same between Client and Server, except Jc - it can vary.`. I tried the whole thing once - set `Jmin` and `Jmax` to different values for two peers and it still worked. Is the documentation wrong at this point?
Author
Owner

@marek22k commented on GitHub (Sep 22, 2024):

Another question: The README states that the H-values may be a maximum of 2^31-1=2147483647. However, a 32-bit integer is used. Shouldn't the maximum size then be 2^32-1=4294967295?

<!-- gh-comment-id:2366785806 --> @marek22k commented on GitHub (Sep 22, 2024): Another question: The README states that the H-values may be a maximum of 2^31-1=2147483647. However, a 32-bit integer is used. Shouldn't the maximum size then be 2^32-1=4294967295?
Author
Owner

@bobpaul commented on GitHub (Oct 22, 2024):

S1, S2, Jc, Jmin, and Jmax are somewhat described on the highlevel Working Principal. But not providing a meaningful description for these values means that someone setting up their own server can't configure smart values for these settings the way the android app "automagically" does if one gives that root access to a VPS.

At a minimum I think users need a list of these extra config values, what their range of allowed values, and how one should generate those values. Honestly, patching wg or wg-quick to randomly generate these would be really good, imho. I think it would also be good for users to know if these values should be periodically cycled or if it's fine to set them once and leave them forever so long as their server config isn't cloned by others.

What we DO NOT want is people to copy/paste a list of pre-set values for H1-H4, S1, S2, etc.

<!-- gh-comment-id:2429748278 --> @bobpaul commented on GitHub (Oct 22, 2024): S1, S2, Jc, Jmin, and Jmax are somewhat described on the highlevel [Working Principal](https://docs.amnezia.org/documentation/amnezia-wg/#working-principle). But not providing a meaningful description for these values means that someone setting up their own server can't configure smart values for these settings the way the android app "automagically" does if one gives that root access to a VPS. At a minimum I think users need a list of these extra config values, what their range of allowed values, and how one should generate those values. Honestly, patching `wg` or `wg-quick` to randomly generate these would be really good, imho. I think it would also be good for users to know if these values should be periodically cycled or if it's fine to set them once and leave them forever so long as their server config isn't cloned by others. What we DO NOT want is people to copy/paste a list of pre-set values for H1-H4, S1, S2, etc.
Author
Owner

@marek22k commented on GitHub (Oct 22, 2024):

I took a look at the source code and tried to document the new parameters in my blog entry.
However, I could not find any answers to the three questions I asked here. Perhaps someone (maybe @leninalive) else could answer them?

  • I had a look at the code and in the kernel module a netlink message WG_CMD_UNKNOWN_PEER seems to be distributed in case of failed authentication of a peer. However, I cannot find a place where such a message is received. Why does AmneziaWG send it?
    Is it intended for analysis by third party programs?
  • Furthermore, the documentation says All parameters should be the same between Client and Server, except Jc - it can vary.. I tried the whole thing once - set Jmin and Jmax to different values for two peers and it still worked. Is the documentation wrong at this point?
  • The README states that the H-values may be a maximum of 2^31-1=2147483647. However, a 32-bit integer is used. Shouldn't the maximum size then be 2^32-1=4294967295?
<!-- gh-comment-id:2429840803 --> @marek22k commented on GitHub (Oct 22, 2024): I took a look at the source code and tried to document the new parameters in my [blog entry](https://mk16.de/blog/amneziawg-en/). However, I could not find any answers to the three questions I asked here. Perhaps someone (maybe @leninalive) else could answer them? - I had a look at the code and in the kernel module a netlink message WG_CMD_UNKNOWN_PEER seems to be distributed in case of failed authentication of a peer. However, I cannot find a place where such a message is received. Why does AmneziaWG send it? Is it intended for analysis by third party programs? - Furthermore, the documentation says All parameters should be the same between Client and Server, except Jc - it can vary.. I tried the whole thing once - set Jmin and Jmax to different values for two peers and it still worked. Is the documentation wrong at this point? - The README states that the H-values may be a maximum of 2^31-1=2147483647. However, a 32-bit integer is used. Shouldn't the maximum size then be 2^32-1=4294967295?
Author
Owner

@bobpaul commented on GitHub (Oct 22, 2024):

@marek22k Which "the readme" are you looking at? I only see one README file in this repo and it doesn't describe the H1-H4 values, but I did figure them out. (They're defined in the template file that's in the android client)

H1-H4 should all be 4bytes, so 0x00000000 - 0xFFFFFFFF. H1-H4 have to exactly match on peers as these are used instead of the 4 message_type identifiers (and 3 reserved 0bytes) that are in all Wireguard packet.

S1 and S2 also have to exactly match. These are used for garbage data injected into first 2 packets (initiator to responder message_type=1 and responder to initiator message_type=2). Otherwise these two messages are always the same length. By setting S1 and S2 randomly, it ensures no two independent AmneziaWG networks have the same packet lengths for these first 2 messages.

Jc, Jmin, and Jmax relate to junk data that's sent by the initiator before the obfuscated initiator packet it sent. Jc is the count (how many junk packets), Jmin and Jmax are the sizes. I think Jc, Jmin, and Jmax can be configured uniquely on every peer. These are sent when a peer is using the endpoint= configuration to initiate a new connection. The other peer (the responder) is just ignoring the junk packets, so it should not need to know the size or number of them. And this is UDP, so it's not even guaranteed all of the junk packets will make it through; I wouldn't expect the responding peer to actually watch for Jc junk packets. The responder just needs to watch for a packet with S1 bytes of garbage data followed by the 4 bytes defined in H1.

Here's an example initiator packet. I have S1 configured to 142 (so the initiator packet has 148+142=290 bytes of payload). And I have H1 configured to 221932096 (0x0d3a6a40). You can see that the 149th byte in the payload is 0x40. This is because H1 is put into the packet little-endian.
image.

WG_CMD_UNKNOWN_PEER

This isn't sent on the network. The ENUM where this is defined has only 2 other commands, Get_Device and Set_Device.

enum wg_cmd {
	WG_CMD_GET_DEVICE,
	WG_CMD_SET_DEVICE,
	WG_CMD_UNKNOWN_PEER,
	__WG_CMD_MAX
};

This for notifing a userspace app on the same machine. You can see it used in the notification listener. of the peer-approver tool in amneziawg-tools.

<!-- gh-comment-id:2430019979 --> @bobpaul commented on GitHub (Oct 22, 2024): @marek22k Which "the readme" are you looking at? I only see one [README file in this repo](https://github.com/amnezia-vpn/amneziawg-go/blob/master/README.md) and it doesn't describe the H1-H4 values, but I did figure them out. (They're [defined in the template file](https://github.com/amnezia-vpn/amnezia-client/blob/628e22869d9cfe60591259ebeeb01f79028d84d7/client/server_scripts/awg/template.conf#L10) that's in the android client) H1-H4 should all be 4bytes, so 0x00000000 - 0xFFFFFFFF. H1-H4 have to exactly match on peers as these are used instead of the 4 [message_type identifiers (and 3 reserved 0bytes)](https://www.wireguard.com/protocol/) that are in all Wireguard packet. S1 and S2 also have to exactly match. These are used for garbage data injected into first 2 packets (initiator to responder message_type=1 and responder to initiator message_type=2). Otherwise these two messages are always the same length. By setting S1 and S2 randomly, it ensures no two independent AmneziaWG networks have the same packet lengths for these first 2 messages. Jc, Jmin, and Jmax relate to junk data that's sent by the initiator before the obfuscated initiator packet it sent. Jc is the count (how many junk packets), Jmin and Jmax are the sizes. I think Jc, Jmin, and Jmax can be configured uniquely on every peer. These are sent when a peer is using the `endpoint=` configuration to initiate a new connection. The other peer (the responder) is just ignoring the junk packets, so it should not need to know the size or number of them. And this is UDP, so it's not even guaranteed all of the junk packets will make it through; I wouldn't expect the responding peer to actually watch for `Jc` junk packets. The responder just needs to watch for a packet with `S1` bytes of garbage data followed by the 4 bytes defined in `H1`. Here's an example initiator packet. I have S1 configured to 142 (so the initiator packet has 148+142=290 bytes of payload). And I have H1 configured to 221932096 (`0x0d3a6a40`). You can see that the 149th byte in the payload is `0x40`. This is because H1 is put into the packet little-endian. ![image](https://github.com/user-attachments/assets/b16bacc9-1bcb-4aa5-9a3b-db0050c6792f). **WG_CMD_UNKNOWN_PEER** This isn't sent on the network. The [ENUM where this is defined](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module/blob/8d1b073205538673f5da4831c4d39ef8acf44f8c/src/uapi/wireguard.h#L163) has only 2 other commands, `Get_Device` and `Set_Device`. ``` enum wg_cmd { WG_CMD_GET_DEVICE, WG_CMD_SET_DEVICE, WG_CMD_UNKNOWN_PEER, __WG_CMD_MAX }; ``` This for notifing a userspace app on the same machine. You can see it used in [the notification listener.](https://github.com/amnezia-vpn/amneziawg-tools/blob/c0b400c6dfc046f5cae8f3051b14cb61686fcf55/contrib/peer-approver/notification-listener.c#L161) of the peer-approver tool in `amneziawg-tools`.
Author
Owner

@marek22k commented on GitHub (Oct 23, 2024):

I meant the README for the Kernel Module. https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#configuration
Thank you for confirming the value range of H1-H4 and that the J-values may differ on both peers. This is then apparently incorrectly specified in the README.
And thanks for explaining what the kernel notifications are sent for! I originally thought it was to detect DPI systems that were actively probing the server.

<!-- gh-comment-id:2430818037 --> @marek22k commented on GitHub (Oct 23, 2024): I meant the README for the Kernel Module. https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#configuration Thank you for confirming the value range of H1-H4 and that the J-values may differ on both peers. This is then apparently incorrectly specified in the README. And thanks for explaining what the kernel notifications are sent for! I originally thought it was to detect DPI systems that were actively probing the server.
Author
Owner

@bobpaul commented on GitHub (Oct 23, 2024):

Just to double-check, I've successfully connected with values for H1=0xFFFFFFFF, H2=0xFFFFFFFE, H3=0xFFFFFFFD, and H4=0xFFFFFFFC using both amnezia-go and the amnezia-linux kernel module on linux and wgtunnel on android.

I meant the README for the Kernel Module. https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#configuration Thank you for confirming the value range of H1-H4 and that the J-values may differ on both peers. This is then apparently incorrectly specified in the README.

I notice that says "recommended range" rather than "max range". There may be a good reason for recommending lower values even though it's possible to use the full range. But it does smell like a mistake.

<!-- gh-comment-id:2430978952 --> @bobpaul commented on GitHub (Oct 23, 2024): Just to double-check, I've successfully connected with values for `H1=0xFFFFFFFF`, `H2=0xFFFFFFFE`, `H3=0xFFFFFFFD`, and `H4=0xFFFFFFFC` using both `amnezia-go` and the `amnezia-linux` kernel module on linux and `wgtunnel` on android. > I meant the README for the Kernel Module. https://github.com/amnezia-vpn/amneziawg-linux-kernel-module?tab=readme-ov-file#configuration Thank you for confirming the value range of H1-H4 and that the J-values may differ on both peers. This is then apparently incorrectly specified in the README. I notice that says "recommended range" rather than "max range". There may be a good reason for recommending lower values even though it's possible to use the full range. But it does smell like a mistake.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amneziawg-go#14
No description provided.