--- /dev/null
+# ============================================================
+# AWG Proxy -- MikroTik RouterOS (protocol: v2)
+# 2026-06-29 07:35:38
+# ============================================================
+
+# 0. Check prerequisites
+:if ([:len [/system/package/find where name="container" disabled=no]] = 0) do={
+ :put "Container package is not installed or disabled. Install it and reboot."
+ :error "Usage: /system/device-mode/update container=yes"
+}
+
+# Check storage device
+{
+ :local targetDisk "sata1"
+ :local diskFree 0
+ :do { :set diskFree [/disk/get [find where mount-point=$targetDisk] free] } on-error={}
+ :if ($diskFree = 0) do={
+ :local baseDisk $targetDisk
+ :local dashPos [:find $targetDisk "-part"]
+ :if ([:typeof $dashPos] != "nil") do={ :set baseDisk [:pick $targetDisk 0 $dashPos] }
+ :if ([:len [/disk/find where slot=$baseDisk]] > 0) do={
+ :put ("Device $baseDisk found but $targetDisk is not available.")
+ :put "Format $baseDisk as ext4? ALL DATA WILL BE ERASED!"
+ :put "Press 'y' to confirm, any other key to cancel:"
+ :local key [/terminal/inkey timeout=30]
+ :if ($key = 121 || $key = 89) do={
+ :put "Formatting $baseDisk as ext4..."
+ /disk/format-drive $baseDisk file-system=ext4 label=$baseDisk
+ :delay 3s
+ :do { :set diskFree [/disk/get [find where mount-point=$targetDisk] free] } on-error={}
+ :if ($diskFree = 0) do={
+ :put ("ERROR: $targetDisk not found after formatting.")
+ :put "Check mount point: /disk/print"
+ :error ("Mount point $targetDisk not found after formatting")
+ }
+ :put ("Formatted OK. Free: " . ($diskFree / 1048576) . " MB")
+ } else={
+ :error "Formatting cancelled"
+ }
+ } else={
+ :put ("ERROR: Storage device $targetDisk not found.")
+ :put "Check available disks: /disk/print"
+ :error ("Storage not found: " . $targetDisk)
+ }
+ } else={
+ :put ("Storage OK: $targetDisk (" . ($diskFree / 1048576) . " MB free)")
+ }
+}
+
+# 1. Uninstall script
+/system/script/add name=awg-proxy-uninstall comment=awg-proxy source={
+ :put "Uninstallimg AmneziaWG..."
+ :log info "Uninstallimg AmneziaWG..."
+ :local prevDNS ""
+ :do { :set prevDNS [/container/envs/get [find where list="awg-proxy-env" key="AWG_PREV_DNS"] value] } on-error={}
+ :local prevTmpdir ""
+ :do { :set prevTmpdir [/container/envs/get [find where list="awg-proxy-env" key="AWG_PREV_TMPDIR"] value] } on-error={}
+ /ip/route/remove [find where comment=awg-proxy-tunnel]
+ /ip/route/remove [find where comment=awg-proxy-dns]
+ /container/stop [find where interface=veth-awg-proxy]
+ :delay 7s
+ /container/remove [find where interface=veth-awg-proxy]
+ /container/envs/remove [find where list="awg-proxy-env"]
+ :if ($prevDNS != "") do={
+ :do { /ip/dns/set servers="$prevDNS" } on-error={}
+ :put ("DNS restored to: $prevDNS")
+ }
+ /container/config set tmpdir=$prevTmpdir
+ :put ("Container tmpdir restored to: $prevTmpdir")
+ /ip/firewall/nat/remove [find where out-interface="wg-awg-proxy"]
+ /ip/firewall/nat/remove [find where src-address="172.18.9.104/30"]
+ /ip/address/remove [find where address="172.18.9.105/30"]
+ /interface/veth/remove [find where name="veth-awg-proxy"]
+ /interface/wireguard/peers/remove [find where interface="wg-awg-proxy"]
+ /ip/address/remove [find where interface="wg-awg-proxy"]
+ /interface/wireguard/remove [find where name="wg-awg-proxy"]
+ :do { /file/remove [find where name~"awg-proxy.+tar"] } on-error={}
+ :do { /file/remove [find where name="sata1/awg-proxy"] } on-error={}
+ :do { /file/remove [find where name="sata1/ru_ranges_timeout.rsc"] } on-error={}
+ :do { /file/remove [find where name~"sata1/pull"] } on-error={}
+ :put "Uninstall AmneziaWG Proxy complete!"
+ :log info "Uninstall AmneziaWG Proxy complete!"
+ /system/script/remove [find where name=awg-proxy-uninstall]
+}
+
+# 2. Network infrastructure
+/interface/veth/add name=veth-awg-proxy address=172.18.9.106/30 gateway=172.18.9.105
+/ip/address/add address=172.18.9.105/30 interface=veth-awg-proxy
+/ip/firewall/nat/add chain=srcnat action=masquerade src-address=172.18.9.104/30
+
+# 3. WireGuard interface (MikroTik derives the public key automatically)
+/interface/wireguard/add name=wg-awg-proxy private-key="4CHyNhbOs923/EyNDguMXJXdghL2I3UyzXPwrANVgHs=" listen-port=13241 disabled=yes
+/interface/wireguard/peers/add interface=wg-awg-proxy public-key="o5IgCl1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU=" preshared-key="RNvF7T1cg5tyXcYQnD9N5BEp6e20vVJQTv0GMjyvHU0=" endpoint-address=172.18.9.106 endpoint-port=51820 allowed-address=0.0.0.0/0 persistent-keepalive=10
+/ip/address/add address=10.9.0.3/32 interface=wg-awg-proxy
+
+# 4. Container environment variables
+/container/envs/add list=awg-proxy-env key=AWG_LISTEN value=":51820"
+/container/envs/add list=awg-proxy-env key=AWG_REMOTE value="109.107.177.79:55055"
+/container/envs/add list=awg-proxy-env key=AWG_JC value="9"
+/container/envs/add list=awg-proxy-env key=AWG_JMIN value="105"
+/container/envs/add list=awg-proxy-env key=AWG_JMAX value="920"
+/container/envs/add list=awg-proxy-env key=AWG_S1 value="90"
+/container/envs/add list=awg-proxy-env key=AWG_S2 value="136"
+/container/envs/add list=awg-proxy-env key=AWG_H1 value="472437748-472438637"
+/container/envs/add list=awg-proxy-env key=AWG_H2 value="707808381-707809250"
+/container/envs/add list=awg-proxy-env key=AWG_H3 value="1609078552-1609079495"
+/container/envs/add list=awg-proxy-env key=AWG_H4 value="1012329484-1012329741"
+/container/envs/add list=awg-proxy-env key=AWG_SERVER_PUB value="o5IgCl1/G6xbl6j7sPaP4ZNYREeYOmqZjKbm+v0b9jU="
+/container/envs/add list=awg-proxy-env key=AWG_CLIENT_PUB value=[/interface/wireguard/get [find name=wg-awg-proxy] public-key]
+/container/envs/add list=awg-proxy-env key=AWG_S3 value="45"
+/container/envs/add list=awg-proxy-env key=AWG_S4 value="27"
+/container/envs/add list=awg-proxy-env key=AWG_I1 value="<b 0x000100142112a442><r 12><b 0x80220008636f7475726e2d3480280004><r 4>"
+/container/envs/add list=awg-proxy-env key=AWG_I2 value="<r 32><t>"
+/container/envs/add list=awg-proxy-env key=AWG_I3 value="<rd 16><r 24>"
+/container/envs/add list=awg-proxy-env key=AWG_I4 value="<t><rc 20>"
+/container/envs/add list=awg-proxy-env key=AWG_I5 value="<r 38>"
+
+# 5. DNS
+{ :local rawDNS [/ip/dns/get servers]; :local prevDNS ""; :foreach s in=[:toarray $rawDNS] do={ :if ([:len $prevDNS] > 0) do={ :set prevDNS "$prevDNS,$s" } else={ :set prevDNS $s } }; /container/envs/add list=awg-proxy-env key=AWG_PREV_DNS value="$prevDNS" }
+# NOTE: replaces existing DNS configuration
+/ip/dns/set servers=109.107.177.79
+/ip/route/add dst-address=109.107.177.79/32 gateway=wg-awg-proxy distance=1 comment=awg-proxy-dns
+
+# 6. Download, create and start container
+:local prevTmpdir [/container/config/get tmpdir]
+/container/envs/add list=awg-proxy-env key=AWG_PREV_TMPDIR value=$prevTmpdir
+/container/config set tmpdir=sata1/pull memory-high=200M
+{
+ :local arch [/system/resource/get architecture-name]
+ :local ver [/system/resource/get version]
+ :local dotPos [:find $ver "."]
+ :local rest [:pick $ver ($dotPos + 1) [:len $ver]]
+ :local endPos [:find $rest "."]
+ :if ([:typeof $endPos] = "nil") do={ :set endPos [:find $rest " "] }
+ :local minor [:tonum [:pick $rest 0 $endPos]]
+ :local suffix ""
+ :if ($minor <= 20) do={ :set suffix "-7.20-Docker" }
+ :local file ""
+ :if ($arch = "arm64") do={ :set file ("awg-proxy-arm64" . $suffix . ".tar.gz") }
+ :if ($arch = "arm") do={ :set file ("awg-proxy-arm" . $suffix . ".tar.gz") }
+ :if ($arch ~ "x86") do={ :set file ("awg-proxy-amd64" . $suffix . ".tar.gz") }
+ :if ($file = "") do={ :error "Unsupported architecture: $arch" }
+ :local url "https://github.com/timbrs/amneziawg-mikrotik-c/releases/latest/download/$file"
+ :local filePath ("sata1/pull/" . $file)
+ :do { /file/make-directory sata1/pull } on-error={}
+ :if ([:len [/file/find where name=$filePath]] = 0) do={
+ :local freeStorage 0
+ :do { :set freeStorage [/disk/get [find where mount-point="sata1"] free] } on-error={}
+ :if ($freeStorage < 262144) do={
+ :put ("WARNING: Low disk space (" . ($freeStorage / 1024) . "KB free). Need at least 256KB.")
+ :put "See: https://github.com/timbrs/amneziawg-mikrotik-c#insufficient-disk-space"
+ :error "Insufficient disk space"
+ }
+ :put ("Fetching: $url -> " . $filePath)
+ /tool/fetch url=$url dst-path=$filePath http-max-redirect-count=10
+ } else={
+ :put ("File already exists: " . $filePath)
+ }
+ /container/add file=$filePath interface=veth-awg-proxy envlist=awg-proxy-env hostname=awg-proxy root-dir=sata1/awg-proxy logging=no start-on-boot=yes comment=awg-proxy
+ :if ($minor > 20) do={ [:parse "/container/set [find where interface=veth-awg-proxy] shm-size=4M"] }
+ /file/remove $filePath
+ :local freeMem [/system/resource/get free-memory]
+ :if ($freeMem < 16777216) do={
+ :put ("WARNING: Low memory (" . ($freeMem / 1048576) . "MB free). 16MB+ recommended.")
+ }
+ /container/start [find where interface=veth-awg-proxy]
+ :do { /file/remove [find where name="console-dump.txt"] } on-error={}
+ :put "Waiting for container to start..."
+ :delay 5s
+ /interface/wireguard/enable wg-awg-proxy
+ :put "WireGuard interface enabled"
+ :put "Installation complete!"
+ :put "Ping test: 109.107.177.79 via AmneziaWG tunnel. repeat 10 times"
+ /ping 109.107.177.79 count=10 interval=1
+ :put ""
+ :put "======= NEXT STEPS ======="
+ :put ""
+ :put "Route specific traffic through the AmneziaWG tunnel:"
+ :put ""
+ :put " Route a single host:"
+ :put " /ip/route/add dst-address=8.8.8.8/32 gateway=wg-awg-proxy comment=awg-proxy-tunnel"
+ :put ""
+ :put " Route a subnet:"
+ :put " /ip/route/add dst-address=100.0.0.0/8 gateway=wg-awg-proxy comment=awg-proxy-tunnel"
+ :put ""
+ :put " Remove a route:"
+ :put " /ip/route/remove [find where comment=awg-proxy-tunnel dst-address=8.8.8.8/32]"
+ :put ""
+ :put " Show all tunnel routes:"
+ :put " /ip/route/print where comment=awg-proxy-tunnel"
+ :put ""
+ :put " Uninstall:"
+ :put " /system/script/run awg-proxy-uninstall"
+ :put "========================="
+}
+
+# 7. Verification
+# /container/print
+# /interface/wireguard/print
+# /interface/wireguard/peers/print