<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ivan Bondarev</title>
    <description>The latest articles on DEV Community by Ivan Bondarev (@bivlked).</description>
    <link>https://dev.to/bivlked</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3816233%2F20163664-3650-4603-801a-13f5a56a32e8.png</url>
      <title>DEV Community: Ivan Bondarev</title>
      <link>https://dev.to/bivlked</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bivlked"/>
    <language>en</language>
    <item>
      <title>Self-Hosted DPI-Bypass VPN on Oracle Cloud Always Free ARM</title>
      <dc:creator>Ivan Bondarev</dc:creator>
      <pubDate>Thu, 16 Apr 2026 16:48:49 +0000</pubDate>
      <link>https://dev.to/bivlked/self-hosted-dpi-bypass-vpn-on-oracle-cloud-always-free-arm-2mek</link>
      <guid>https://dev.to/bivlked/self-hosted-dpi-bypass-vpn-on-oracle-cloud-always-free-arm-2mek</guid>
      <description>&lt;p&gt;If you're reading this from a place where stock WireGuard stopped working mid-2025, you already know the problem: ISPs fingerprint the WireGuard handshake and kill the tunnel in minutes. Iran, Russia, Turkmenistan, and a handful of other countries now DPI-filter WireGuard at carrier level.&lt;/p&gt;

&lt;p&gt;AmneziaWG is a fork that randomizes the parts of the protocol DPI uses to identify it — junk packets, randomized header hashes, CPS packets that mimic QUIC or DNS. Same crypto as WireGuard underneath, roughly 5-10% CPU overhead from the obfuscation work.&lt;/p&gt;

&lt;p&gt;I wrote &lt;a href="https://github.com/bivlked/amneziawg-installer" rel="noopener noreferrer"&gt;&lt;code&gt;amneziawg-installer&lt;/code&gt;&lt;/a&gt; to handle the server side in one bash command. v5.9.0 added prebuilt ARM kernel modules, so it now runs cleanly on Oracle Cloud's Ampere A1 — which Oracle gives away on the Always Free tier (up to 4 OCPU / 24 GB RAM at no cost). The combo is the cheapest self-hosted DPI-bypass VPN you can stand up: $0/month, about 10 minutes of work.&lt;/p&gt;

&lt;p&gt;Here's the setup, end to end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Oracle Cloud account with &lt;a href="https://www.oracle.com/cloud/free/" rel="noopener noreferrer"&gt;Always Free tier&lt;/a&gt; enabled. Card is required for ID verification; you're not charged as long as you stay within free limits.&lt;/li&gt;
&lt;li&gt;An SSH key pair. &lt;code&gt;ssh-keygen -t ed25519&lt;/code&gt; on your laptop if you don't have one.&lt;/li&gt;
&lt;li&gt;The AmneziaWG client on your phone or desktop: &lt;a href="https://apps.apple.com/app/amneziawg/id6478942365" rel="noopener noreferrer"&gt;iOS&lt;/a&gt;, &lt;a href="https://github.com/amnezia-vpn/amneziawg-android" rel="noopener noreferrer"&gt;Android&lt;/a&gt;, or the full &lt;a href="https://github.com/amnezia-vpn/amnezia-client" rel="noopener noreferrer"&gt;Amnezia VPN client&lt;/a&gt; with &lt;code&gt;vpn://&lt;/code&gt; URI import on Windows/macOS/Linux.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create the Ampere A1 instance
&lt;/h2&gt;

&lt;p&gt;In the OCI console, go to &lt;strong&gt;Compute → Instances → Create instance&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;awg-vpn&lt;/code&gt; (or whatever you want).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image:&lt;/strong&gt; Canonical Ubuntu 24.04. The installer also supports 25.10, Debian 12 and 13, but 24.04 LTS is the least surprising.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shape:&lt;/strong&gt; &lt;code&gt;VM.Standard.A1.Flex&lt;/code&gt; (Ampere ARM). Start with &lt;strong&gt;2 OCPUs and 12 GB RAM&lt;/strong&gt;. The free limit is 4/24, but Oracle has been aggressively reclaiming oversized idle instances since 2024. A 2/12 box has been stable for me for months.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking:&lt;/strong&gt; create a new VCN if you don't have one, and assign a public IPv4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH keys:&lt;/strong&gt; paste the content of your &lt;code&gt;~/.ssh/id_ed25519.pub&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Create&lt;/strong&gt;. The instance comes up in about a minute. Copy the public IP from the instance details page — that's your VPN endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open UDP/51820
&lt;/h2&gt;

&lt;p&gt;OCI's default security list blocks everything inbound except TCP/22. You need to let AmneziaWG traffic in.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;Networking → Virtual Cloud Networks → your VCN → Security Lists → Default Security List → Add Ingress Rule&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source CIDR:&lt;/strong&gt; &lt;code&gt;0.0.0.0/0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP Protocol:&lt;/strong&gt; UDP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destination Port Range:&lt;/strong&gt; &lt;code&gt;51820&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save. If you want a different VPN port, pass &lt;code&gt;--port=&amp;lt;N&amp;gt;&lt;/code&gt; to the installer and match it here. That's the only network change you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH in and run the installer
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh ubuntu@&amp;lt;your-public-ip&amp;gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
wget https://raw.githubusercontent.com/bivlked/amneziawg-installer/v5.9.0/install_amneziawg_en.sh
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x install_amneziawg_en.sh
./install_amneziawg_en.sh &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OS check, base packages, kernel sysctl tweaks. The box reboots.&lt;/li&gt;
&lt;li&gt;SSH back in and re-run the same script. On ARM it downloads a prebuilt &lt;code&gt;.deb&lt;/code&gt; of the kernel module matching your running kernel. If your kernel is newer than the latest prebuilt, it falls back to DKMS automatically (slower, still works).&lt;/li&gt;
&lt;li&gt;Second reboot. SSH back. One more re-run. Done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total time: ~5-10 minutes on a 2-OCPU Ampere instance.&lt;/p&gt;

&lt;p&gt;At the end you get a summary with the endpoint, port, and the path to the first client config.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate a client config
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/root/awg/manage_amneziawg.sh add phone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/root/awg/clients/phone/phone.conf&lt;/code&gt; — the plain &lt;code&gt;.conf&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;A QR code printed to the terminal for scanning with the AmneziaWG mobile app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/root/awg/phone.vpnuri&lt;/code&gt; — a &lt;code&gt;vpn://&lt;/code&gt; URI for one-click import into the desktop Amnezia VPN client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scan the QR with the AmneziaWG app on your phone and connect. &lt;code&gt;curl ifconfig.me&lt;/code&gt; from the phone should return your Oracle IP.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if the default still gets blocked
&lt;/h2&gt;

&lt;p&gt;On a few mobile carriers — Yota, Tele2, Megafon in Moscow, and a handful of regional ISPs — the default &lt;code&gt;Jc&lt;/code&gt; (junk packet count) is too aggressive and the handshake fails. The fix is to edit &lt;code&gt;/etc/amnezia/amneziawg/awg0.conf&lt;/code&gt; on the server, drop &lt;code&gt;Jc&lt;/code&gt; to 3 or 2, restart the service, and regenerate the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart awg-quick@awg0
/root/awg/manage_amneziawg.sh regen phone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push the new config to the phone. Operator-by-operator tuning notes (which values worked where) are in &lt;a href="https://github.com/bivlked/amneziawg-installer/blob/main/ADVANCED.en.md" rel="noopener noreferrer"&gt;ADVANCED.en.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Oracle reclaim policy.&lt;/strong&gt; If your Ampere instance idles near 0% CPU for long stretches, OCI may flag it as unused and reclaim it. Running an active VPN is usually enough activity. If you're not using it much, a cron job like &lt;code&gt;stress-ng --cpu 1 --timeout 60&lt;/code&gt; a couple of times a week keeps the instance visible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kernel updates.&lt;/strong&gt; When Ubuntu ships a new kernel, the AmneziaWG module rebuilds via DKMS on the next reboot — no manual steps, but if you had a prebuilt &lt;code&gt;.deb&lt;/code&gt; match before, you may fall back to DKMS until the installer ships a newer matching module.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't use the stock WireGuard client.&lt;/strong&gt; It silently ignores &lt;code&gt;Jc&lt;/code&gt;, &lt;code&gt;S1-S4&lt;/code&gt;, &lt;code&gt;H1-H4&lt;/code&gt;, and &lt;code&gt;I1-I5&lt;/code&gt; — you'll connect, but in plain-WG mode, which is the thing DPI blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv6.&lt;/strong&gt; The installer disables host IPv6 by default on a VPN box. Pass &lt;code&gt;--allow-ipv6&lt;/code&gt; to keep it on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection vs. blocking.&lt;/strong&gt; AmneziaWG defeats rule-based DPI in real time. Sustained statistical analysis can probably still fingerprint obfuscated traffic given enough samples — that's a per-target surveillance cost model, not an ISP-level blocking model. For getting around the ISP blocking that's actually happening in Russia and Iran right now, per-install randomization is what matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost check
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Oracle Always Free ARM: $0 for up to 4 OCPU / 24 GB RAM (or 2/12 as I recommend above)&lt;/li&gt;
&lt;li&gt;AmneziaWG server: MIT, FOSS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;amneziawg-installer&lt;/code&gt;: MIT, FOSS&lt;/li&gt;
&lt;li&gt;Egress: 10 TB/month free on OCI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total: $0. The only path to a paid setup is exceeding 10 TB egress per month, which is hard to do as a personal VPN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Installer: &lt;a href="https://github.com/bivlked/amneziawg-installer" rel="noopener noreferrer"&gt;github.com/bivlked/amneziawg-installer&lt;/a&gt; (v5.9.0 is the ARM-support release)&lt;/li&gt;
&lt;li&gt;AmneziaWG protocol: &lt;a href="https://docs.amnezia.org/documentation/amnezia-wg/" rel="noopener noreferrer"&gt;docs.amnezia.org/documentation/amnezia-wg&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Upstream reference implementation: &lt;a href="https://github.com/amnezia-vpn/amneziawg-go" rel="noopener noreferrer"&gt;github.com/amnezia-vpn/amneziawg-go&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you hit a carrier-specific issue, open an issue on the installer repo with the carrier name and region — those reports are how we got the mobile fixes in the 5.8.x branch.&lt;/p&gt;

</description>
      <category>vpn</category>
      <category>selfhosted</category>
      <category>oraclecloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>AmneziaWG 2.0 in 5 Minutes: DPI-Resistant VPN That WireGuard Can't Match</title>
      <dc:creator>Ivan Bondarev</dc:creator>
      <pubDate>Mon, 06 Apr 2026 16:56:11 +0000</pubDate>
      <link>https://dev.to/bivlked/your-wireguard-got-blocked-deploy-amneziawg-20-in-5-minutes-2k7h</link>
      <guid>https://dev.to/bivlked/your-wireguard-got-blocked-deploy-amneziawg-20-in-5-minutes-2k7h</guid>
      <description>&lt;p&gt;WireGuard is blocked or throttled in Russia, China, Iran, UAE, Turkmenistan, and a bunch of other countries. If yours stopped working — you can replace it with AmneziaWG 2.0 in about 5 minutes. Same WireGuard speed, same crypto, but the traffic looks like random noise to DPI.&lt;/p&gt;

&lt;p&gt;No Linux skills needed. Three commands and you're done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;clean VPS&lt;/strong&gt; — any $3-5/month server works (1 GB RAM is plenty)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ubuntu 24.04 / 25.10&lt;/strong&gt; or &lt;strong&gt;Debian 12 / 13&lt;/strong&gt; on that server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH access&lt;/strong&gt; — your provider gives you an IP, login, and password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't have a VPS yet? Grab one from Hetzner, DigitalOcean, Vultr, or wherever — just make sure the datacenter is outside your country. Cheapest tier is fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Install (3 commands)
&lt;/h2&gt;

&lt;p&gt;SSH into your server and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/bivlked/amneziawg-installer/main/install_amneziawg_en.sh
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x install_amneziawg_en.sh
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash ./install_amneziawg_en.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The installer asks a few questions (port, subnet, number of clients) — defaults work for most setups. Hit Enter through them or use &lt;code&gt;--yes&lt;/code&gt; for fully automatic mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;bash ./install_amneziawg_en.sh &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It reboots twice (kernel updates). Just re-run the same script after each reboot — it picks up where it left off. Whole thing takes about 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Connect Your Devices
&lt;/h2&gt;

&lt;p&gt;After installation, you'll find client config files in &lt;code&gt;/root/awg/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.conf&lt;/code&gt; files — import into any AmneziaWG client&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.png&lt;/code&gt; files — QR codes, scan from your phone&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.vpnuri&lt;/code&gt; files — one-tap import for Amnezia VPN app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Which client to use:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Client&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All platforms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Amnezia VPN&lt;/strong&gt; (recommended)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/amnezia-vpn/amnezia-client/releases" rel="noopener noreferrer"&gt;Download&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;AmneziaWG&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/amnezia-vpn/amneziawg-windows-client/releases" rel="noopener noreferrer"&gt;Download&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;AmneziaWG&lt;/td&gt;
&lt;td&gt;&lt;a href="https://play.google.com/store/apps/details?id=org.amnezia.awg" rel="noopener noreferrer"&gt;Google Play&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;AmneziaWG&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apps.apple.com/app/amneziawg/id6478942365" rel="noopener noreferrer"&gt;App Store&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android (FOSS)&lt;/td&gt;
&lt;td&gt;WG Tunnel&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/wgtunnel/android" rel="noopener noreferrer"&gt;F-Droid / GitHub&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Quickest way:&lt;/strong&gt; Install Amnezia VPN on your phone, scan the QR code. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Verify
&lt;/h2&gt;

&lt;p&gt;Open a browser and go to &lt;a href="https://ifconfig.me" rel="noopener noreferrer"&gt;ifconfig.me&lt;/a&gt;. If you see your &lt;strong&gt;server's IP&lt;/strong&gt; instead of your home IP — you're on the VPN.&lt;/p&gt;

&lt;p&gt;On the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;awg show awg0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for &lt;code&gt;latest handshake&lt;/code&gt; under your peer — if it shows a recent timestamp, you're good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing Clients
&lt;/h2&gt;

&lt;p&gt;Need to add a phone, laptop, or share access with someone?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add a new client&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh add my_laptop

&lt;span class="c"&gt;# Give someone temporary access (auto-expires)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh add guest &lt;span class="nt"&gt;--expires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7d

&lt;span class="c"&gt;# See who's connected and how much traffic they used&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh stats

&lt;span class="c"&gt;# Remove a client&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh remove guest

&lt;span class="c"&gt;# List all clients&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;add&lt;/code&gt; generates a new &lt;code&gt;.conf&lt;/code&gt; + QR code + &lt;code&gt;vpn://&lt;/code&gt; URI.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Running Under the Hood
&lt;/h2&gt;

&lt;p&gt;The installer sets up &lt;a href="https://docs.amnezia.org/documentation/amnezia-wg/" rel="noopener noreferrer"&gt;AmneziaWG 2.0&lt;/a&gt; — a WireGuard fork that randomizes packet headers, adds padding, and sends decoy packets before the handshake. DPI can't fingerprint it because every server speaks its own "dialect" of the protocol.&lt;/p&gt;

&lt;p&gt;It runs as a &lt;strong&gt;kernel module&lt;/strong&gt; (not the slower userspace Go implementation), so you get near-WireGuard speeds. The crypto is identical — Curve25519, ChaCha20-Poly1305, same as stock WireGuard.&lt;/p&gt;

&lt;p&gt;The installer also hardens the server — UFW firewall with deny-all policy, Fail2Ban, and some kernel/network tuning.&lt;/p&gt;

&lt;p&gt;I wrote a detailed breakdown of how the obfuscation works &lt;a href="https://dev.to/bivlked/amneziawg-20-self-host-an-obfuscated-wireguard-vpn-that-bypasses-dpi-4692"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⭐ &lt;a href="https://github.com/bivlked/amneziawg-installer" rel="noopener noreferrer"&gt;&lt;strong&gt;amneziawg-installer&lt;/strong&gt; on GitHub&lt;/a&gt; — star it if it helped you&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amnezia-vpn/amnezia-client/releases" rel="noopener noreferrer"&gt;Amnezia VPN Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.amnezia.org/documentation/amnezia-wg/" rel="noopener noreferrer"&gt;AmneziaWG 2.0 Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Router firmware with AWG support:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/hoaxisr/awg-manager" rel="noopener noreferrer"&gt;AWG Manager&lt;/a&gt; — Keenetic&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/r0otx/asuswrt-merlin-amneziawg" rel="noopener noreferrer"&gt;AmneziaWG for Merlin&lt;/a&gt; — ASUS&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Hit a problem? &lt;a href="https://github.com/bivlked/amneziawg-installer/issues" rel="noopener noreferrer"&gt;Open an issue&lt;/a&gt; or drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>selfhosted</category>
      <category>vpn</category>
    </item>
    <item>
      <title>AmneziaWG 2.0: Self-Host an Obfuscated WireGuard VPN That Bypasses DPI</title>
      <dc:creator>Ivan Bondarev</dc:creator>
      <pubDate>Wed, 11 Mar 2026 14:10:22 +0000</pubDate>
      <link>https://dev.to/bivlked/amneziawg-20-self-host-an-obfuscated-wireguard-vpn-that-bypasses-dpi-4692</link>
      <guid>https://dev.to/bivlked/amneziawg-20-self-host-an-obfuscated-wireguard-vpn-that-bypasses-dpi-4692</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: WireGuard Is Easy to Block
&lt;/h2&gt;

&lt;p&gt;WireGuard is a great VPN protocol — fast, lean, well-audited crypto. But it has one glaring weakness: &lt;strong&gt;predictability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every WireGuard packet starts with a 4-byte header containing a message type: &lt;code&gt;1&lt;/code&gt; for handshake initiation, &lt;code&gt;2&lt;/code&gt; for response, &lt;code&gt;3&lt;/code&gt; for cookie, &lt;code&gt;4&lt;/code&gt; for data. The handshake init is always exactly 148 bytes. These are strong, static signatures that DPI systems fingerprint without breaking a sweat.&lt;/p&gt;

&lt;p&gt;And they do. WireGuard is actively blocked in &lt;strong&gt;10+ countries&lt;/strong&gt; right now. In Russia, standard WireGuard has roughly a 12% success rate. Iran sees 98% packet loss. China's Great Firewall picks it up within seconds. Egypt, Turkmenistan, Myanmar, Pakistan, UAE, Turkey, Belarus, Uzbekistan, Kazakhstan — all confirmed blocking or throttling at the DPI level.&lt;/p&gt;

&lt;p&gt;I'm based in Russia, and I watched this unfold firsthand. Through most of 2024, my WireGuard tunnels worked fine. Then they started dropping — not all at once, but ISP by ISP, week by week. Russia's TSPU (Technical Means of Countering Threats — essentially DPI boxes installed at every major provider) learned to identify WireGuard traffic and silently kill it. Handshakes just stopped completing. No error, no timeout message — the packets simply vanished.&lt;/p&gt;

&lt;p&gt;That's what pushed me to build an open-source installer for AmneziaWG 2.0, a WireGuard fork with protocol-level obfuscation. Here's how the protocol works under the hood, and how to get it running on your own server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How DPI Catches WireGuard
&lt;/h2&gt;

&lt;p&gt;Standard WireGuard uses fixed 32-bit message types for its four packet types. A DPI system needs a trivially simple heuristic:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UDP packet&lt;/strong&gt; + &lt;strong&gt;known header value (1-4)&lt;/strong&gt; + &lt;strong&gt;predictable packet size&lt;/strong&gt; = WireGuard&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Handshake init is always 148 bytes. Response is always 92 bytes. These invariant sizes are a dead giveaway. Once the DPI box flags a WireGuard session, it can block the IP, throttle the connection, or silently drop every packet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AmneziaWG 2.0 Does About It
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.amnezia.org/documentation/amnezia-wg/" rel="noopener noreferrer"&gt;AmneziaWG&lt;/a&gt; is a WireGuard fork by the &lt;a href="https://amnezia.org/" rel="noopener noreferrer"&gt;Amnezia VPN&lt;/a&gt; team. It changes the transport layer to resist DPI while leaving the cryptographic core (Curve25519, ChaCha20-Poly1305, Noise IK) untouched.&lt;/p&gt;

&lt;p&gt;The first version (AWG 1.x) replaced standard headers with custom fixed values. Helped for a while, but a patient DPI system could learn the new static values just as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWG 2.0&lt;/strong&gt; (late 2025) took a different path: randomize everything, every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Obfuscation Actually Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dynamic Headers (H1-H4)
&lt;/h3&gt;

&lt;p&gt;Instead of fixed header values, AWG 2.0 uses &lt;strong&gt;ranges&lt;/strong&gt;. Every time a packet goes out, a random value is picked from within the configured range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;H1&lt;/span&gt; = &lt;span class="m"&gt;100000&lt;/span&gt;-&lt;span class="m"&gt;800000&lt;/span&gt;         &lt;span class="c"&gt;# Handshake init
&lt;/span&gt;&lt;span class="n"&gt;H2&lt;/span&gt; = &lt;span class="m"&gt;1000000&lt;/span&gt;-&lt;span class="m"&gt;8000000&lt;/span&gt;       &lt;span class="c"&gt;# Handshake response
&lt;/span&gt;&lt;span class="n"&gt;H3&lt;/span&gt; = &lt;span class="m"&gt;10000000&lt;/span&gt;-&lt;span class="m"&gt;80000000&lt;/span&gt;     &lt;span class="c"&gt;# Cookie
&lt;/span&gt;&lt;span class="n"&gt;H4&lt;/span&gt; = &lt;span class="m"&gt;100000000&lt;/span&gt;-&lt;span class="m"&gt;800000000&lt;/span&gt;   &lt;span class="c"&gt;# Data transport
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ranges must not overlap — the protocol still needs to tell packet types apart. But the result is that &lt;strong&gt;every packet looks different on the wire&lt;/strong&gt;. There's no single header value for DPI to latch onto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Random Padding (S1-S4)
&lt;/h3&gt;

&lt;p&gt;AWG pads packets with random bytes to break the fixed-size signatures:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Packet Type&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;S1&lt;/td&gt;
&lt;td&gt;Handshake init&lt;/td&gt;
&lt;td&gt;Init becomes 148 + S1 bytes (bye-bye fixed 148)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S2&lt;/td&gt;
&lt;td&gt;Handshake response&lt;/td&gt;
&lt;td&gt;Response becomes 92 + S2 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cookie &lt;em&gt;(new in 2.0)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Pads cookie packets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data transport &lt;em&gt;(new in 2.0)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Pads &lt;strong&gt;every&lt;/strong&gt; data packet&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;S3 and S4 are the big additions in 2.0. S4 matters most — it touches every single data packet, which makes traffic analysis across the whole session much harder.&lt;/p&gt;

&lt;p&gt;One gotcha: &lt;code&gt;S1 + 56&lt;/code&gt; must not equal &lt;code&gt;S2&lt;/code&gt;. Why? Because 148 - 92 = 56, so if the padding values differ by exactly 56, the padded init and padded response end up the same size. That's a pattern you don't want.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPS — Custom Protocol Signature (I1-I5)
&lt;/h3&gt;

&lt;p&gt;Before the real WireGuard handshake, the client sends &lt;strong&gt;decoy packets&lt;/strong&gt; that mimic another protocol's signature.&lt;/p&gt;

&lt;p&gt;Parameters I1 through I5 define the content of up to 5 decoy packets using a tag format:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;b 0xHEX&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Insert specific bytes (hex-encoded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;r N&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N cryptographically random bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;rc N&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N random alphanumeric chars [A-Za-z0-9]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;rd N&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;N random decimal digits [0-9]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;t&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Current UNIX timestamp (4 bytes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;c&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Packet counter (4 bytes)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Simple version: &lt;code&gt;&amp;lt;r 128&amp;gt;&lt;/code&gt; — blast 128 random bytes. DPI sees a random UDP packet from who-knows-what.&lt;/p&gt;

&lt;p&gt;Sneakier version: &lt;code&gt;&amp;lt;b 0xc000000001&amp;gt;&amp;lt;r 64&amp;gt;&amp;lt;t&amp;gt;&lt;/code&gt; — starts with bytes that look like a QUIC Initial packet header, then random data, then a timestamp. A DPI box might classify this as the start of a normal QUIC session.&lt;/p&gt;

&lt;p&gt;The server ignores CPS packets entirely — it just waits for the real handshake init that comes after.&lt;/p&gt;

&lt;h3&gt;
  
  
  Junk Packets (Jc, Jmin, Jmax)
&lt;/h3&gt;

&lt;p&gt;Before each handshake, the client fires off &lt;code&gt;Jc&lt;/code&gt; junk packets with random sizes between &lt;code&gt;Jmin&lt;/code&gt; and &lt;code&gt;Jmax&lt;/code&gt; bytes. Pure noise that makes the connection setup profile less recognizable.&lt;/p&gt;

&lt;h3&gt;
  
  
  What This All Adds Up To
&lt;/h3&gt;

&lt;p&gt;Each AmneziaWG 2.0 server ends up with its own &lt;strong&gt;unique parameter set&lt;/strong&gt;. There's no universal DPI signature that catches all AWG 2.0 traffic — every server is, in effect, speaking its own dialect.&lt;/p&gt;

&lt;p&gt;Here's the 1.x-to-2.0 changelog:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;AWG 1.x&lt;/th&gt;
&lt;th&gt;AWG 2.0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;H1-H4&lt;/td&gt;
&lt;td&gt;Fixed values&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ranges&lt;/strong&gt; (random per packet)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S1-S2&lt;/td&gt;
&lt;td&gt;Padding for init/response&lt;/td&gt;
&lt;td&gt;Unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S3&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;New:&lt;/strong&gt; cookie padding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S4&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;New:&lt;/strong&gt; data packet padding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I1-I5 (CPS)&lt;/td&gt;
&lt;td&gt;Late addition&lt;/td&gt;
&lt;td&gt;Fully supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jc/Jmin/Jmax&lt;/td&gt;
&lt;td&gt;Junk packets&lt;/td&gt;
&lt;td&gt;Unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crypto&lt;/td&gt;
&lt;td&gt;WireGuard (untouched)&lt;/td&gt;
&lt;td&gt;WireGuard (untouched)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What About Speed?
&lt;/h2&gt;

&lt;p&gt;People always ask this, so let's get it out of the way.&lt;/p&gt;

&lt;p&gt;You might have seen a "65% overhead" number floating around online. The AmneziaWG developers &lt;a href="https://github.com/amnezia-vpn/amnezia-client/issues/526" rel="noopener noreferrer"&gt;tracked that down&lt;/a&gt; to the &lt;strong&gt;userspace Go implementation&lt;/strong&gt; (amneziawg-go), not the protocol itself. The &lt;strong&gt;kernel module&lt;/strong&gt; (what my installer uses via DKMS) runs at near-WireGuard speeds.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;WireGuard&lt;/th&gt;
&lt;th&gt;AmneziaWG 2.0&lt;/th&gt;
&lt;th&gt;OpenVPN&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Crypto overhead&lt;/td&gt;
&lt;td&gt;~4%&lt;/td&gt;
&lt;td&gt;~4% (same crypto)&lt;/td&gt;
&lt;td&gt;~15-20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Obfuscation overhead&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;+3-7% (padding/junk)&lt;/td&gt;
&lt;td&gt;+10% (obfs4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~4%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt;12%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~25-28%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Battery drain (4h streaming)&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;td&gt;19% (+1%)&lt;/td&gt;
&lt;td&gt;~25%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Real-world benchmark on an uncensored network: WireGuard 95 Mbps, AmneziaWG 92 Mbps. That's a 3% difference — you won't notice it.&lt;/p&gt;

&lt;p&gt;And in a censored network? The comparison is "92 Mbps vs 0 Mbps." If WireGuard is blocked, raw speed numbers don't mean much.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Stacks Up Against Alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;WireGuard&lt;/th&gt;
&lt;th&gt;AmneziaWG 2.0&lt;/th&gt;
&lt;th&gt;OpenVPN+obfs4&lt;/th&gt;
&lt;th&gt;Shadowsocks&lt;/th&gt;
&lt;th&gt;VLESS+Reality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DPI resistance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low (detectable)&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fastest&lt;/td&gt;
&lt;td&gt;Near-WG (&amp;lt;12% OH)&lt;/td&gt;
&lt;td&gt;Slow (~25% OH)&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium-Fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Full VPN tunnel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No (proxy)&lt;/td&gt;
&lt;td&gt;No (proxy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runs in kernel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (DKMS)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simple&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Simple (installer)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complex&lt;/td&gt;
&lt;td&gt;Simple (Outline)&lt;/td&gt;
&lt;td&gt;Complex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transport&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UDP&lt;/td&gt;
&lt;td&gt;UDP (obfuscated)&lt;/td&gt;
&lt;td&gt;TCP/UDP + TLS&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audited crypto&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Inherits WG audit&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No DPI in your country? Plain WireGuard is simpler, just use that. Need the absolute maximum DPI resistance and OK with a proxy? VLESS+Reality is worth a look, but it's a proxy, not a VPN tunnel. AmneziaWG 2.0 fills the gap between them: WireGuard-grade performance with real obfuscation in a full tunnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  One-Command Setup
&lt;/h2&gt;

&lt;p&gt;Setting up AmneziaWG 2.0 by hand means building a kernel module, generating 10+ obfuscation parameters with the right constraints, writing server and client configs, configuring firewall rules. Lots of moving parts, lots of places to get something wrong.&lt;/p&gt;

&lt;p&gt;I automated all of it in &lt;a href="https://github.com/bivlked/amneziawg-installer" rel="noopener noreferrer"&gt;&lt;strong&gt;amneziawg-installer&lt;/strong&gt;&lt;/a&gt;. It builds the &lt;strong&gt;kernel module&lt;/strong&gt; via DKMS (not the slower Go userspace implementation), so you get the speed numbers from the table above.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You Need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;clean&lt;/strong&gt; Ubuntu 24.04 / 25.10 or Debian 12 / 13 server&lt;/li&gt;
&lt;li&gt;Root SSH access&lt;/li&gt;
&lt;li&gt;~1 GB RAM (any $2-4/month VPS is enough)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/bivlked/amneziawg-installer/main/install_amneziawg_en.sh
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x install_amneziawg_en.sh
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash ./install_amneziawg_en.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script walks through 8 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;System hardening&lt;/strong&gt; — strips bloat (snapd, modemmanager), tunes kernel params (BBR, network buffers), sets up swap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DKMS build&lt;/strong&gt; — installs the AmneziaWG kernel module from &lt;a href="https://launchpad.net/~amnezia/+archive/ubuntu/ppa" rel="noopener noreferrer"&gt;Amnezia PPA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firewall&lt;/strong&gt; — UFW with deny-all default, SSH rate-limiting, VPN port only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Config generation&lt;/strong&gt; — all AWG 2.0 parameters auto-generated with proper constraints, server + client configs + QR codes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service start&lt;/strong&gt; — Fail2Ban, awg-quick@awg0 enabled and running&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two reboots happen along the way (kernel updates + module loading). The script saves its state, so you just re-run it after each reboot and it picks up where it left off.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-Interactive Mode
&lt;/h3&gt;

&lt;p&gt;For scripted or automated deployments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;bash ./install_amneziawg_en.sh &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;51820 &lt;span class="nt"&gt;--disallow-ipv6&lt;/span&gt; &lt;span class="nt"&gt;--route-amnezia&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Managing Clients
&lt;/h2&gt;

&lt;p&gt;After installation, use the management script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add a client (generates .conf + QR code + vpn:// URI)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh add my_phone

&lt;span class="c"&gt;# List all clients&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh list

&lt;span class="c"&gt;# Remove a client&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh remove my_phone

&lt;span class="c"&gt;# Check server status&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh check

&lt;span class="c"&gt;# Temporary client — auto-removed after 7 days&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh add guest &lt;span class="nt"&gt;--expires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7d

&lt;span class="c"&gt;# Traffic stats per client&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh stats

&lt;span class="c"&gt;# Backup all configs&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;bash /root/awg/manage_amneziawg.sh backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect using any client with AWG 2.0 support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/amnezia-vpn/amnezia-client/releases" rel="noopener noreferrer"&gt;&lt;strong&gt;Amnezia VPN&lt;/strong&gt;&lt;/a&gt; — full-featured, all platforms (&amp;gt;= 4.8.12.7)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/amnezia-vpn/amneziawg-windows-client/releases" rel="noopener noreferrer"&gt;&lt;strong&gt;AmneziaWG&lt;/strong&gt;&lt;/a&gt; — lightweight tunnel manager, Windows (&amp;gt;= 2.0.0)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/artem4150/VeilBox" rel="noopener noreferrer"&gt;&lt;strong&gt;VeilBox&lt;/strong&gt;&lt;/a&gt; — open-source, Windows/macOS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Checking That It Works
&lt;/h2&gt;

&lt;p&gt;On the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;awg show awg0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for &lt;code&gt;latest handshake&lt;/code&gt; under your peer. If it's there, the AWG 2.0 handshake went through.&lt;/p&gt;

&lt;p&gt;From the client side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl ifconfig.me
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see your server's IP instead of your home IP — you're connected through the VPN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I've been running this on my own servers for several months now. From Russia, through ISPs with active TSPU filtering, AWG 2.0 connections hold where stock WireGuard has been dead since mid-2025. The crypto hasn't changed, so every WireGuard audit still applies. The overhead? Under 12% on paper, closer to 3% in my testing. And since the installer uses the kernel module, you skip the userspace performance hit entirely.&lt;/p&gt;

&lt;p&gt;If you're in a country where WireGuard stopped working, give it a shot. And if you run into issues or have suggestions, I'd genuinely like to hear about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/bivlked/amneziawg-installer" rel="noopener noreferrer"&gt;amneziawg-installer on GitHub&lt;/a&gt; — star it if it's useful to you&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.amnezia.org/documentation/amnezia-wg/" rel="noopener noreferrer"&gt;AmneziaWG 2.0 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amnezia-vpn/amnezia-client/releases" rel="noopener noreferrer"&gt;Amnezia VPN Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://spatiumstas.github.io/junker/" rel="noopener noreferrer"&gt;Junker — AmneziaWG Signature Generator&lt;/a&gt; (for manual setup)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Router firmware with AWG support:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/hoaxisr/awg-manager" rel="noopener noreferrer"&gt;AWG Manager&lt;/a&gt; — Keenetic routers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/r0otx/asuswrt-merlin-amneziawg" rel="noopener noreferrer"&gt;AmneziaWG for Merlin&lt;/a&gt; — ASUS routers with GeoIP/GeoSite routing&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Questions, bugs, feature requests? Open an issue on &lt;a href="https://github.com/bivlked/amneziawg-installer/issues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or leave a comment here.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vpn</category>
      <category>opensource</category>
      <category>linux</category>
      <category>selfhosted</category>
    </item>
  </channel>
</rss>
