Skip to content

Commit d1cdbed

Browse files
committed
feat: add amneziawg extension
Add AmneziaWG as a Talos Linux system extension service. AmneziaWG is a WireGuard-based VPN with DPI bypass via traffic obfuscation. Signed-off-by: masterbpro <[email protected]>
1 parent 2644125 commit d1cdbed

File tree

8 files changed

+337
-0
lines changed

8 files changed

+337
-0
lines changed

.kres.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ spec:
44
targets:
55
- amazon-ena
66
- amdgpu
7+
- amneziawg
78
- amd-ucode
89
- binfmt-misc
910
- bird2

network/amneziawg/README.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# AmneziaWG
2+
3+
Adds [AmneziaWG](https://docs.amnezia.org/documentation/amnezia-wg/) VPN interfaces as system extensions.
4+
AmneziaWG is a WireGuard-based VPN protocol with DPI bypass capabilities through traffic obfuscation (header randomization, packet padding, jitter).
5+
6+
## Installation
7+
8+
See [Installing Extensions](https://github.com/siderolabs/extensions#installing-extensions).
9+
10+
## Usage
11+
12+
Configure the extension via `ExtensionServiceConfig` document.
13+
14+
```yaml
15+
---
16+
apiVersion: v1alpha1
17+
kind: ExtensionServiceConfig
18+
name: amneziawg
19+
configFiles:
20+
- content: |
21+
[Interface]
22+
PrivateKey = <your-private-key>
23+
ListenPort = 51820
24+
Address = 10.0.0.1/24
25+
Jc = 5
26+
Jmin = 50
27+
Jmax = 1000
28+
S1 = 52
29+
S2 = 52
30+
H1 = 12345678
31+
H2 = 87654321
32+
H3 = 11223344
33+
H4 = 44332211
34+
35+
[Peer]
36+
PublicKey = <peer-public-key>
37+
Endpoint = vpn.example.com:51820
38+
AllowedIPs = 0.0.0.0/0
39+
PersistentKeepalive = 25
40+
mountPath: /etc/amneziawg/awg0.conf
41+
```
42+
43+
Then apply the patch to your node's MachineConfigs
44+
```bash
45+
talosctl patch mc -p @amneziawg-config.yaml
46+
```
47+
48+
You will then be able to verify that it is in place with the following command
49+
```bash
50+
talosctl get extensionserviceconfigs
51+
52+
NODE NAMESPACE TYPE ID VERSION
53+
mynode runtime ExtensionServiceConfig amneziawg 1
54+
```
55+
56+
## Configuration
57+
58+
The config file follows the standard WireGuard format with additional AmneziaWG-specific parameters for DPI obfuscation:
59+
60+
| Parameter | Description |
61+
|-----------|-------------|
62+
| `Jc` | Junk packet count |
63+
| `Jmin` | Minimum junk packet size |
64+
| `Jmax` | Maximum junk packet size |
65+
| `S1` | Init packet padding size |
66+
| `S2` | Response packet padding size |
67+
| `H1` | Init packet header value |
68+
| `H2` | Response packet header value |
69+
| `H3` | Cookie packet header value |
70+
| `H4` | Transport packet header value |
71+
72+
All standard WireGuard fields (`PrivateKey`, `ListenPort`, `Address`, `PublicKey`, `Endpoint`, `AllowedIPs`, `PersistentKeepalive`, `MTU`, `PostUp`, `PostDown`) are also supported.
73+
74+
### Environment overrides
75+
76+
Environment variables can be set via `ExtensionServiceConfig`:
77+
78+
```yaml
79+
---
80+
apiVersion: v1alpha1
81+
kind: ExtensionServiceConfig
82+
name: amneziawg
83+
environment:
84+
- AWG_INTERFACE=awg0
85+
- AWG_CONFIG=/etc/amneziawg/awg0.conf
86+
- AWG_LOG_LEVEL=verbose
87+
configFiles:
88+
- content: |
89+
...
90+
mountPath: /etc/amneziawg/awg0.conf
91+
```
92+
93+
| Variable | Default | Description |
94+
|----------|---------|-------------|
95+
| `AWG_INTERFACE` | `awg0` | Network interface name |
96+
| `AWG_CONFIG` | `/etc/amneziawg/awg0.conf` | Path to config file |
97+
| `AWG_LOG_LEVEL` | `info` | Log level (`info` or `verbose`) |
98+
99+
For more information see https://docs.amnezia.org/documentation/amnezia-wg/

network/amneziawg/amneziawg.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: amneziawg
2+
depends:
3+
- network:
4+
- addresses
5+
- connectivity
6+
- configuration: true
7+
container:
8+
entrypoint: /usr/local/bin/entrypoint.sh
9+
environment:
10+
- PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin
11+
- WG_SOCKET_DIR=/run/amneziawg
12+
- AWG_INTERFACE=awg0
13+
- AWG_CONFIG=/etc/amneziawg/awg0.conf
14+
- AWG_LOG_LEVEL=info
15+
security:
16+
writeableRootfs: false
17+
writeableSysfs: true
18+
mounts:
19+
- source: /dev/net/tun
20+
destination: /dev/net/tun
21+
type: bind
22+
options:
23+
- bind
24+
- rw
25+
- source: /run/amneziawg
26+
destination: /run/amneziawg
27+
type: bind
28+
options:
29+
- bind
30+
- rw
31+
restart: always

network/amneziawg/entrypoint.sh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/bin/sh
2+
set -e
3+
4+
AWG_INTERFACE="${AWG_INTERFACE:-awg0}"
5+
AWG_CONFIG="${AWG_CONFIG:-/etc/amneziawg/${AWG_INTERFACE}.conf}"
6+
AWG_LOG_LEVEL="${AWG_LOG_LEVEL:-info}"
7+
8+
export WG_SOCKET_DIR=/run/amneziawg
9+
10+
log() { echo "[amneziawg] $*"; }
11+
12+
if [ ! -f "$AWG_CONFIG" ]; then
13+
log "ERROR: config file not found: $AWG_CONFIG"
14+
log "Provide config via ExtensionServiceConfig:"
15+
log ""
16+
log " apiVersion: v1alpha1"
17+
log " kind: ExtensionServiceConfig"
18+
log " name: amneziawg"
19+
log " configFiles:"
20+
log " - content: |"
21+
log " [Interface]"
22+
log " PrivateKey = <key>"
23+
log " ListenPort = 51820"
24+
log " Address = 10.0.0.1/24"
25+
log " Jc = 5"
26+
log " Jmin = 50"
27+
log " Jmax = 1000"
28+
log " S1 = 0"
29+
log " S2 = 0"
30+
log " H1 = 1"
31+
log " H2 = 2"
32+
log " H3 = 3"
33+
log " H4 = 4"
34+
log " [Peer]"
35+
log " PublicKey = <key>"
36+
log " Endpoint = <host>:51820"
37+
log " AllowedIPs = 0.0.0.0/0"
38+
log " mountPath: /etc/amneziawg/awg0.conf"
39+
exit 1
40+
fi
41+
42+
parse_field() {
43+
grep -i "^${1} *=" "$2" | head -1 | sed "s/^[^ ]* *= *//"
44+
}
45+
46+
collect_field() {
47+
grep -i "^${1} *=" "$2" | sed "s/^[^ ]* *= *//" | tr '\n' ' '
48+
}
49+
50+
ADDRESSES=$(collect_field Address "$AWG_CONFIG")
51+
MTU=$(parse_field MTU "$AWG_CONFIG")
52+
53+
STRIPPED_CONF=$(mktemp)
54+
grep -iv "^\(Address\|DNS\|MTU\|Table\|PreUp\|PostUp\|PreDown\|PostDown\|SaveConfig\) *=" "$AWG_CONFIG" > "$STRIPPED_CONF"
55+
56+
log "Starting amneziawg-go on interface $AWG_INTERFACE"
57+
export LOG_LEVEL="$AWG_LOG_LEVEL"
58+
59+
mkdir -p /run/amneziawg
60+
amneziawg-go "$AWG_INTERFACE" &
61+
AWG_PID=$!
62+
63+
SOCK="/run/amneziawg/${AWG_INTERFACE}.sock"
64+
for i in $(seq 1 50); do
65+
[ -S "$SOCK" ] && break
66+
sleep 0.1
67+
done
68+
69+
if [ ! -S "$SOCK" ]; then
70+
log "ERROR: UAPI socket did not appear at $SOCK"
71+
kill $AWG_PID 2>/dev/null
72+
exit 1
73+
fi
74+
75+
awg setconf "$AWG_INTERFACE" "$STRIPPED_CONF"
76+
rm -f "$STRIPPED_CONF"
77+
log "Configuration applied from $AWG_CONFIG"
78+
79+
for addr in $ADDRESSES; do
80+
ip addr add "$addr" dev "$AWG_INTERFACE" 2>/dev/null || true
81+
log "Address $addr added"
82+
done
83+
84+
if [ -n "$MTU" ]; then
85+
ip link set mtu "$MTU" dev "$AWG_INTERFACE"
86+
log "MTU set to $MTU"
87+
fi
88+
89+
ip link set "$AWG_INTERFACE" up
90+
log "Interface $AWG_INTERFACE is UP"
91+
92+
POST_UP=$(grep -i "^PostUp *=" "$AWG_CONFIG" | sed "s/^[^ ]* *= *//" || true)
93+
if [ -n "$POST_UP" ]; then
94+
log "Running PostUp"
95+
eval "$POST_UP" || true
96+
fi
97+
98+
cleanup() {
99+
log "Shutting down $AWG_INTERFACE"
100+
POST_DOWN=$(grep -i "^PostDown *=" "$AWG_CONFIG" | sed "s/^[^ ]* *= *//" || true)
101+
if [ -n "$POST_DOWN" ]; then
102+
log "Running PostDown"
103+
eval "$POST_DOWN" || true
104+
fi
105+
ip link set "$AWG_INTERFACE" down 2>/dev/null || true
106+
ip link delete "$AWG_INTERFACE" 2>/dev/null || true
107+
kill $AWG_PID 2>/dev/null
108+
}
109+
trap cleanup TERM INT
110+
111+
log "AmneziaWG is running:"
112+
awg show "$AWG_INTERFACE"
113+
114+
wait $AWG_PID
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: v1alpha1
2+
metadata:
3+
name: amneziawg
4+
version: "{{ .VERSION }}"
5+
author: masterbpro
6+
description: |
7+
[{{ .TIER }}] AmneziaWG is a WireGuard-based VPN protocol with DPI bypass capabilities through traffic obfuscation.
8+
compatibility:
9+
talos:
10+
version: ">= v1.7.0"

network/amneziawg/pkg.yaml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: amneziawg
2+
variant: scratch
3+
shell: /bin/bash
4+
dependencies:
5+
- stage: base
6+
- image: "{{ .BUILD_ARG_PKGS_PREFIX }}/fhs:{{ .BUILD_ARG_PKGS }}"
7+
from: /
8+
to: /rootfs/usr/local/lib/containers/amneziawg
9+
steps:
10+
- env:
11+
GOPATH: /tmp/go
12+
CGO_ENABLED: 0
13+
- cachePaths:
14+
- /.cache/go-build
15+
- /tmp/go/pkg
16+
sources:
17+
- url: https://github.com/amnezia-vpn/amneziawg-go/archive/refs/tags/v{{ .AMNEZIAWG_GO_VERSION }}.tar.gz
18+
destination: amneziawg-go.tar.gz
19+
sha256: {{ .AMNEZIAWG_GO_SHA256 }}
20+
sha512: {{ .AMNEZIAWG_GO_SHA512 }}
21+
- url: https://github.com/amnezia-vpn/amneziawg-tools/archive/refs/tags/v{{ .AMNEZIAWG_TOOLS_VERSION }}.tar.gz
22+
destination: amneziawg-tools.tar.gz
23+
sha256: {{ .AMNEZIAWG_TOOLS_SHA256 }}
24+
sha512: {{ .AMNEZIAWG_TOOLS_SHA512 }}
25+
- network: default
26+
prepare:
27+
- |
28+
mkdir amneziawg-go amneziawg-tools
29+
tar -xzf amneziawg-go.tar.gz --strip-components=1 -C amneziawg-go
30+
tar -xzf amneziawg-tools.tar.gz --strip-components=1 -C amneziawg-tools
31+
- |
32+
cd amneziawg-go
33+
go mod download
34+
- network: none
35+
build:
36+
- |
37+
cd amneziawg-go
38+
CGO_ENABLED=0 go build -v -o ../amneziawg-go-bin .
39+
- |
40+
cd amneziawg-tools/src
41+
make CC="gcc -static" WITH_WGQUICK=yes
42+
install:
43+
- |
44+
mkdir -p /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/
45+
cp -p amneziawg-go-bin /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/amneziawg-go
46+
cp -p amneziawg-tools/src/wg /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/awg
47+
cp -p amneziawg-tools/src/wg-quick/linux.bash /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/awg-quick
48+
chmod +x /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/*
49+
- |
50+
cp -p /pkg/entrypoint.sh /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/entrypoint.sh
51+
chmod +x /rootfs/usr/local/lib/containers/amneziawg/usr/local/bin/entrypoint.sh
52+
- |
53+
mkdir -p /rootfs/usr/local/lib/containers/amneziawg/sbin
54+
cp /sbin/ip /rootfs/usr/local/lib/containers/amneziawg/sbin/ip 2>/dev/null || true
55+
- |
56+
mkdir -p /rootfs/usr/local/etc/containers
57+
cp /pkg/amneziawg.yaml /rootfs/usr/local/etc/containers/
58+
- |
59+
mkdir -p /rootfs/usr/local/bin
60+
cp -p amneziawg-go-bin /rootfs/usr/local/bin/amneziawg-go
61+
cp -p amneziawg-tools/src/wg /rootfs/usr/local/bin/awg
62+
test:
63+
- |
64+
mkdir -p /extensions-validator-rootfs
65+
cp -r /rootfs/ /extensions-validator-rootfs/rootfs
66+
cp /pkg/manifest.yaml /extensions-validator-rootfs/manifest.yaml
67+
/extensions-validator validate --rootfs=/extensions-validator-rootfs --pkg-name="${PKG_NAME}"
68+
finalize:
69+
- from: /rootfs
70+
to: /rootfs
71+
- from: /pkg/manifest.yaml
72+
to: /

network/amneziawg/vars.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
VERSION: "{{ .AMNEZIAWG_GO_VERSION }}"
2+
TIER: "contrib"

network/vars.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# renovate: datasource=github-releases extractVersion=^v(?<version>.*)$ depName=amnezia-vpn/amneziawg-go
2+
AMNEZIAWG_GO_VERSION: 0.2.16
3+
AMNEZIAWG_GO_SHA256: 8327a22c7bcf4f6b05585d4b9536759c1e11fcc1e6830e5186fd55a14255eae1
4+
AMNEZIAWG_GO_SHA512: 40f438307bbdc760c58a0a692c08a64bdbdbd4468ccaf67f687a08f6ef3a3b102b8fe2103da61475074a472758db68c2d6e73786206c6deb355da0ee6dce6409
5+
# renovate: datasource=github-releases extractVersion=^v(?<version>.*)$ depName=amnezia-vpn/amneziawg-tools
6+
AMNEZIAWG_TOOLS_VERSION: 1.0.20260223
7+
AMNEZIAWG_TOOLS_SHA256: ab09cfafe6c1e9a6260964a8ba5cb2d657cc23862eb0c29253305e532ac40a16
8+
AMNEZIAWG_TOOLS_SHA512: 591afaef659e26be16c8d883da8d8ff026f855f60c9887440b566ef18b9948ca57754673d833f27e77d8c05f7e354f37b49adc9f5467334eeb7eda7165960c54
19
# renovate: datasource=github-releases extractVersion=^v(?<version>.*)$ depName=tailscale/tailscale
210
TAILSCALE_VERSION: 1.94.2
311
TAILSCALE_SHA256: c45975beb4cb7bab8047cfba77ec8b170570d184f3c806258844f3e49c60d7aa

0 commit comments

Comments
 (0)