Refactor WireGuard

This commit is contained in:
Meow
2026-09-14 09:21:42 +08:00
parent 46c680b71b
commit 7aa9bea0df
16 changed files with 432 additions and 252 deletions
+1 -1
View File
@@ -62,7 +62,7 @@ The value of `userLevel` corresponds to the value of `level` in [policy](../poli
The "Arbitrary Door" has two main uses: one is for transparent proxy (see below), and the other is for mapping a port.
Sometimes some services do not support forward proxies like Socks5, and using Tun or Tproxy is overkill. If these services only communicate with a single IP and port (e.g., iperf, Minecraft server, Wireguard endpoint), you can use `tunnel`.
Sometimes some services do not support forward proxies like Socks5, and using Tun or Tproxy is overkill. If these services only communicate with a single IP and port (e.g., iperf, Minecraft server, WireGuard endpoint), you can use `tunnel`.
For example, the following Config (assuming the default outbound is a valid proxy):
+65 -24
View File
@@ -1,6 +1,6 @@
# WireGuard
User-space WireGuard protocol implementation.
User-space WireGuard protocol implementation for establishing a WireGuard tunnel with a peer and receiving traffic through the tunnel.
::: danger
**The WireGuard protocol is not designed specifically for bypassing firewalls. If used as the outer layer to cross the firewall, its distinct characteristics may lead to the server being blocked.**
@@ -16,16 +16,20 @@ User-space WireGuard protocol implementation.
{
// ...
"protocol": "wireguard",
// [!code focus:10]
// [!code focus:14]
"settings": {
"secretKey": "PRIVATE_KEY",
"secretKey": "SERVER_PRIVATE_KEY",
"peers": [
{
"publicKey": "PUBLIC_KEY",
"allowedIPs": [""]
"publicKey": "CLIENT_PUBLIC_KEY",
"preSharedKey": "PRE_SHARED_KEY",
"keepAlive": 0,
"allowedIPs": ["0.0.0.0/0", "::/0"],
"email": "love@xray.com",
"level": 0
}
],
"mtu": 1420 // optional, default 1420
"mtu": 1420
}
}
]
@@ -34,15 +38,29 @@ User-space WireGuard protocol implementation.
> `secretKey`: string
Private key. Required.
Server private key. Required.
You can generate a server key pair with the `xray wg` command. Enter the generated `PrivateKey` here; the accompanying `Password (PublicKey)` is the server public key. When using Xray as a WireGuard client, enter the server public key in `outbounds[].settings.peers[].publicKey`.
> `peers`: \[ [PeersObject](#peersobject) \]
List of WireGuard clients, where each item is a client configuration. When multiple clients are configured, Xray matches the source address of each decrypted inner IP packet against the clients' `allowedIPs` to identify which client the traffic belongs to.
::: details Network model of an Xray WireGuard inbound
A conventional WireGuard network—including point-to-point, point-to-site, and site-to-site configurations—requires both endpoints to participate in IP routing through Layer 3 network interfaces.
In contrast, an Xray WireGuard inbound does not create a TUN interface on the system, nor does the server need an in-tunnel IP address. The built-in network stack processes the decrypted inner IP packets, converts their TCP and UDP traffic into proxy connections, and passes those connections to the Xray routing system instead of forwarding the original IP packets.
A client can send its own traffic or act as a gateway for networks behind it. The Xray server does not act as a Layer 3 node that clients can access inside the tunnel, and it does not pass the original IP packets to the system kernel for further forwarding or NAT.
`allowedIPs` participates in packet processing in both directions: when receiving packets, WireGuard verifies the source address of the decrypted inner IP packet and Xray uses that address to identify the client; when sending response packets, WireGuard selects the corresponding client based on the inner destination address.
:::
> `mtu`: int
The MTU size of the underlying WireGuard TUN.
<details>
<summary>Method to Calculate MTU</summary>
The MTU of the inner IP packets carried by the WireGuard tunnel. The default is 1420.
::: details How to calculate the MTU
The structure of a WireGuard packet is as follows:
```
@@ -55,27 +73,50 @@ The structure of a WireGuard packet is as follows:
- 16-byte authentication tag
```
`N-byte encrypted data` is the MTU value we need. Depending on whether the endpoint is IPv4 or IPv6, the specific value can be 1440 (IPv4) or 1420 (IPv6). If you are in a special network environment, you may need to subtract more (e.g., home broadband PPPoE requires an extra -8).
`N-byte encrypted data` is the MTU value. Depending on whether the endpoint uses IPv4 or IPv6, the value can be 1440 (IPv4) or 1420 (IPv6). Reduce it further for special network environments if necessary (for example, subtract an additional 8 bytes for home broadband using PPPoE).
:::
</details>
> `peers`: \[ [Peers](#peers) \]
List of peers, where each item is a peer configuration.
### Peers
### PeersObject
```json
{
"publicKey": "PUBLIC_KEY",
"allowedIPs": ["0.0.0.0/0"] // optional, default ["0.0.0.0/0", "::/0"]
"publicKey": "CLIENT_PUBLIC_KEY",
"preSharedKey": "PRE_SHARED_KEY",
"keepAlive": 0,
"allowedIPs": ["0.0.0.0/0", "::/0"],
"email": "love@xray.com",
"level": 0
}
```
> `publicKey`: string
Public key, used for verification.
Client public key used for verification. Required.
> `allowedIPs`: string array
When using Xray as a WireGuard client, enter the `Password (PublicKey)` paired with the client's `outbounds[].settings.secretKey` here.
Allowed source IPs.
> `preSharedKey`: string
Optional additional symmetric encryption key. It must match the client configuration.
> `keepAlive`: int
Interval, in seconds, at which the server sends persistent keepalive packets to this client. The default is `0`, which disables keepalive packets.
> `allowedIPs`: \[ string \]
Specifies the source IP addresses or networks that this client is allowed to send, with each item expressed in CIDR notation.
The client's outbound `address` must be included in the corresponding server peer's `allowedIPs`. For example, if the client's `outbounds[].settings.address` is `["10.0.0.2"]`, this field can be set to `["10.0.0.2/32"]`.
`allowedIPs` can contain not only the client's in-tunnel IP address, but also networks routed through that peer. For example, if a third-party WireGuard client acts as a gateway for `192.168.10.0/24`, that network can be included here; the client must also configure routing and enable IP forwarding itself.
This field can be omitted when only one client is configured; the default is `["0.0.0.0/0", "::/0"]`. When multiple clients are configured, explicitly specify non-overlapping `allowedIPs`; otherwise, Xray cannot reliably distinguish between clients.
> `email`: string
Optional user email used to distinguish traffic from different users. It appears in logs and statistics.
> `level`: number
User level. Connections use the [local policy](../policy.md#levelpolicyobject) associated with this user level. The default is 0.
+70 -51
View File
@@ -1,9 +1,9 @@
# Wireguard
# WireGuard
Standard Wireguard protocol implementation.
User-space WireGuard protocol implementation for establishing a WireGuard tunnel with a peer and sending outbound traffic through the tunnel.
::: danger
**The Wireguard protocol is not designed specifically for bypassing firewalls. If used at the outermost layer to cross the Great Firewall, distinctive characteristics may lead to the server being blocked.**
**The WireGuard protocol is not designed specifically for bypassing firewalls. If used as the outer layer to cross the firewall, its distinct characteristics may lead to the server being blocked.**
:::
## OutboundConfigurationObject
@@ -16,24 +16,23 @@ Standard Wireguard protocol implementation.
{
// ...
"protocol": "wireguard",
// [!code focus:19]
// [!code focus:18]
"settings": {
"secretKey": "PRIVATE_KEY",
"secretKey": "CLIENT_PRIVATE_KEY",
"address": [
// optional, default ["10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"]
"IPv4_CIDR",
"IPv6_CIDR",
"10.0.0.1",
"fd59:7153:2388:b5fd:0000:0000:0000:0001",
"and more..."
],
"peers": [
{
"endpoint": "ENDPOINT_ADDR",
"publicKey": "PUBLIC_KEY"
"endpoint": "SERVER_ADDR",
"publicKey": "SERVER_PUBLIC_KEY"
}
],
"noKernelTun": false,
"mtu": 1420, // optional, default 1420
"reserved": [1, 2, 3],
"mtu": 1420,
"reserved": [0, 0, 0],
"domainStrategy": "ForceIP"
}
}
@@ -41,36 +40,43 @@ Standard Wireguard protocol implementation.
}
```
::: tip
Currently, configuring `streamSettings` is not supported in the Wireguard protocol outbound.
:::
> `secretKey`: string
User private key. Required.
Client private key. Required.
> `address`: string array
You can generate a client key pair with the `xray wg` command. Enter the generated `PrivateKey` here; the accompanying `Password (PublicKey)` is the client public key. When using Xray as a WireGuard server, enter the client public key in `inbounds[].settings.peers[].publicKey`.
Wireguard will start a virtual network interface (tun) locally. Use one or more IP addresses; IPv6 is supported.
> `address`: \[ string \]
Specifies the local source addresses used in the inner IP packets generated by the WireGuard outbound—that is, the client's in-tunnel IP addresses. One or more IPv4 or IPv6 addresses can be configured.
The default is `["10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"]`.
Xray automatically selects a source address from the appropriate address family based on the destination address. If multiple addresses from the same family are configured, it selects a suitable address according to its internal rules.<br>
The WireGuard server's inbound configuration must allow these addresses, and each address must be unique in the server's WireGuard inbound configuration.
> `noKernelTun`: true | false
By default, the core detects if it is running on Linux and if the current user has `CAP_NET_ADMIN` permissions to decide whether to enable the system virtual network interface; otherwise, it uses gVisor. Using the system virtual interface offers relatively higher performance. Note that this is only for processing IP packets and has nothing to do with the wireguard kernel module.
Whether to disable TUN. The default is `false`; you may need to set it to `true` in LXC or Docker environments.
This detection may not always be accurate. For example, some LXC virtualization environments may not have TUN permissions at all, causing the outbound to fail. Therefore, you can set this option to manually disable it.
::: details Do I need to enable `noKernelTun`?
When set to `false`, Xray automatically selects how to process inner IP packets: on Linux, if the Xray process has the `CAP_NET_ADMIN` capability, it creates a TUN interface and uses the kernel network stack; on other platforms or when permissions are insufficient, it uses the in-process gVisor network stack. When set to `true`, only the gVisor network stack is used and no TUN interface is created. Using TUN generally provides better performance.
When using the system virtual interface, it occupies IPv6 routing table number `10230`. Each additional Wireguard outbound will use subsequent routing tables sequentially; for example, the second one will use routing table `10231`, and so on.
This option only selects how inner IP packets are processed. The WireGuard protocol itself is still handled by Xray's user-space implementation and is unrelated to the kernel WireGuard module.
Note that if a second Xray instance is started on the same machine, it will not assign the next routing table number but will continue trying to use routing table `10230`. Since it is already occupied by the first Xray instance, it will fail to connect. If absolutely needed, you must set this option to disable the system virtual interface.
The automatic detection described above is not always accurate. For example, some LXC environments may be unable to use TUN even when they have the `CAP_NET_ADMIN` capability, causing the outbound to fail. In this case, set this option to `true`.
When TUN is used, it occupies IPv6 routing table 10230. Each additional WireGuard outbound uses the next routing table in sequence; for example, the second one uses routing table 10231, and so on.
If a second Xray instance is started on the same machine, it does not continue allocating routing table numbers. Instead, it also tries to use routing table 10230. Because that table is already occupied by the first Xray instance, the second instance cannot connect. If multiple instances are necessary, use this option to disable TUN.
:::
> `mtu`: int
MTU size of the underlying Wireguard tun.
The MTU of the inner IP packets carried by the WireGuard tunnel. The default is 1420.
<details>
<summary>MTU Calculation Method</summary>
The structure of a Wireguard packet is as follows:
::: details How to calculate the MTU
The structure of a WireGuard packet is as follows:
```
- 20-byte IPv4 header or 40 byte IPv6 header
@@ -82,58 +88,71 @@ The structure of a Wireguard packet is as follows:
- 16-byte authentication tag
```
`N-byte encrypted data` is the MTU value we need. Depending on whether the endpoint is IPv4 or IPv6, the specific value can be 1440 (IPv4) or 1420 (IPv6). If in a special environment, subtract further (e.g., home broadband PPPoE requires an extra -8).
`N-byte encrypted data` is the MTU value. Depending on whether the endpoint uses IPv4 or IPv6, the value can be 1440 (IPv4) or 1420 (IPv6). Reduce it further for special network environments if necessary (for example, subtract an additional 8 bytes for home broadband using PPPoE).
:::
</details>
> `reserved` \[ byte \]
> `reserved` \[ number \]
The three WireGuard reserved bytes. All three default to 0; set them as needed.
Wireguard reserved bytes, fill as needed.
> `peers`: \[ [PeersObject](#peersobject) \]
> `peers`: \[ [Peers](#peers) \]
List of WireGuard servers, where each item is a server configuration. When multiple servers are configured, Xray prefix-matches the destination IP address against each server's `allowedIPs` and routes the traffic to the matching server, allowing different destination networks to be forwarded through different WireGuard servers.
List of Wireguard servers, where each item is a server configuration.
::: details Packet model of an Xray WireGuard outbound
TCP and UDP connections entering the WireGuard outbound are converted by the network stack into inner IP packets. The inner source address is selected from `address`, while the inner destination address is the destination IP of the proxied traffic.
Xray prefix-matches the inner destination address against each peer's `allowedIPs`. The matching peer encrypts and encapsulates the packet, and Xray sends the resulting outer UDP packet to that peer's `endpoint`. Therefore, `address` specifies the inner source addresses used by the client, `allowedIPs` acts as the destination routing table used to select a peer, and `endpoint` is the server address used by the outer connection.
:::
::: tip
Each WireGuard server must allow all addresses in `address` that belong to the same address family as its `allowedIPs`: if `allowedIPs` contains only IPv4 networks, allow all IPv4 addresses listed in `address`; if it contains only IPv6 networks, the same rule applies to the IPv6 addresses; if it contains both IPv4 and IPv6 networks, allow all listed addresses.
When using Xray as the WireGuard server, list these addresses in `inbounds[].settings.peers[].allowedIPs`.
:::
> `domainStrategy`: "ForceIPv6v4" | "ForceIPv6" | "ForceIPv4v6" | "ForceIPv4" | "ForceIP"
Controls the domain resolution strategy when the Wireguard server address is a domain name or the target address of the proxied traffic is a domain name.
Controls the domain resolution strategy when the WireGuard server address or the target address of the proxied traffic is a domain name.
Unlike most proxy protocols, Wireguard does not allow passing domain names as targets. Therefore, if the incoming target is a domain name, it must be resolved to an IP before transmission. The meanings of this field match the corresponding `Force` strategies in [sockopt.domainStrategy](../transports/sockopt.md#sockoptobject). The default value is `ForceIP`.
Unlike most proxy protocols, WireGuard does not allow domain names to be passed as targets. If the incoming target is a domain name, it must therefore be resolved to an IP address before transmission. The meanings of this field match the corresponding `Force` strategies in [sockopt.domainStrategy](../transports/sockopt.md#sockoptobject). The default is `ForceIP`.
`sockopt.domainStrategy` includes options like `UseIP`, which are not provided here because Wireguard must obtain a usable IP and cannot perform the behavior of falling back to a domain name after `UseIP` resolution fails.<br>
Note: When applied to proxied traffic, this option is also constrained by the `address` option. For example, if you set `ForceIPv6v4` but no IPv6 address is set in `address`, even if the target domain has AAAA records, they will not be resolved/used.
`sockopt.domainStrategy` includes options such as `UseIP`, which are not available here because WireGuard must obtain a usable IP address and cannot fall back to a domain name when `UseIP` resolution fails.<br>
Note: When applied to proxied traffic, this option is also constrained by `address`. For example, if you set `ForceIPv6v4` but do not configure an IPv6 address in `address`, AAAA records will not be resolved even if the target domain has them.
### Peers
### PeersObject
```json
{
"endpoint": "ENDPOINT_ADDR",
"publicKey": "PUBLIC_KEY",
"preSharedKey": "PRE_SHARED_KEY", // optional, default "0000000000000000000000000000000000000000000000000000000000000000"
"keepAlive": 0, // optional, default 0
"allowedIPs": ["0.0.0.0/0"] // optional, default ["0.0.0.0/0", "::/0"]
"endpoint": "SERVER_ADDR",
"publicKey": "SERVER_PUBLIC_KEY",
"preSharedKey": "PRE_SHARED_KEY",
"keepAlive": 0,
"allowedIPs": ["0.0.0.0/0", "::/0"]
}
```
> `endpoint`: address
Server address, required.
Server address. Required.
URL:Port format, e.g., `engage.cloudflareclient.com:2408`<br>
IP:Port format, e.g., `162.159.192.1:2408` or `[2606:4700:d0::a29f:c001]:2408`
URL:Port format, for example, `engage.cloudflareclient.com:2408`<br>
IP:Port format, for example, `162.159.192.1:2408` or `[2606:4700:d0::a29f:c001]:2408`
> `publicKey`: string
Server public key, used for verification, required.
Server public key used for verification. Required.
When using Xray as a WireGuard server, enter the `Password (PublicKey)` paired with the server's `inbounds[].settings.secretKey` here.
> `preSharedKey`: string
Additional symmetric encryption key.
Optional additional symmetric encryption key. It must match the server configuration.
> `keepAlive`: int
Heartbeat interval in seconds. Default is 0, meaning no heartbeat.
Interval, in seconds, at which the client sends persistent keepalive packets to this server. This maintains any NAT mappings or firewall state during idle periods. Enable it only in special situations and only on the client. The default is `0`, which disables keepalive packets.
> `allowedIPs`: string array
Wireguard only allows traffic from specific source IPs.
Specifies the destination IP networks forwarded by this server, with each item expressed in CIDR notation. This field can be omitted when only one server is configured because the default is `["0.0.0.0/0", "::/0"]`, meaning that the server forwards all IPv4 and IPv6 destination traffic. When multiple servers are configured, explicitly set `allowedIPs` for each server to assign different destination networks to the appropriate server; Xray selects the server by prefix-matching the destination IP address.