English · Türkçe
A masked WireGuard for networks that fingerprint and block plain WireGuard via DPI (Deep Packet Inspection): a client for iOS, macOS, Linux, and Windows (CLI), and a self-hostable masked WireGuard server.
StealthWG does not reimplement WireGuard. It builds on the official,
MIT-licensed WireGuard engine (wireguard-go) and inserts a masking layer at the
UDP socket boundary, so the bytes on the wire no longer match WireGuard's
fingerprint — while WireGuard itself provides all the real cryptography.
Plain WireGuard: WG engine ─────────────────────────► server:51820
StealthWG: WG engine ─► mask ─► noise on wire ─► unmask ─► WG
In Turkey, some ISPs and mobile carriers block or throttle WireGuard — the tunnel won't connect, or slows to a crawl, on every port, while ordinary web traffic keeps flowing. This is Deep Packet Inspection (DPI): the network fingerprints WireGuard on the wire and drops it, so switching ports or endpoints doesn't help. Turkey is where StealthWG was built and validated, but this isn't a Turkey-only problem — DPI-based VPN blocking is used by censoring networks and carriers in many countries, and the same masking helps anywhere WireGuard is fingerprinted.
The fingerprint is easy to match. Standard WireGuard's handshake packets have a fixed shape — a message-type byte followed by reserved zero bytes, plus fixed 148/92-byte sizes. DPI keys on exactly this signature to recognize and block the protocol regardless of how you configure it.
StealthWG reshapes every packet into high-entropy, variable-length noise, so the operator sees no recognizable WireGuard pattern to match — yet WireGuard still provides all the security. Validated in practice: masked WireGuard completed a handshake and carried live traffic (internet and LAN) over a Turkish mobile carrier that blocks plain WireGuard on every port.
- Cross-platform client — native iOS and macOS apps sharing one code base (masking, connection, stats, profiles).
- Traffic masking — the UdpMask codec turns WireGuard packets into high-entropy noise.
- Two transports — the UDP mask (high-entropy noise on UDP) or QUIC
(WireGuard carried as QUIC DATAGRAM on UDP 443, blending with HTTP/3). Both run
client- and server-side; the profile picks one with
[Stealth] Transport. - Multiple endpoints with automatic fallback — the client tries several server
endpoints (e.g.
:51819then:443) until one completes a handshake, and can even fall back across transports (quic://host:443then a mask endpoint). - Multiple profiles + editing — hold several servers, switch between them, edit in a structured form; generate a client keypair on device or paste your own.
- Kill switch + on-demand — per profile: always-on auto-connect, route all traffic (no leaks), and keep the LAN reachable.
- Easy import/export — paste, scan a QR, import a
.conf, or build from scratch; export any profile as a QR. - Self-hostable server, two engines — all-in-one (WireGuard + masking in one binary; for a fresh host) or relay (masks in front of an existing WireGuard). Three installs by situation: fresh host, no Docker → native all-in-one package; fresh host, with Docker → standalone bundle; already run WireGuard → relay image (RouterOS / Kubernetes). See INSTALL.md for “which one?”.
- Privacy by design — no logging of user traffic; keys never leave the device; masking is fingerprint-breaking only, not a second crypto layer.
The masking lives in one small piece, reused on both ends — exactly the symmetry that makes the design simple:
- Client (iOS / macOS / Linux / Windows) — the app (or the
stealthwg-clientCLI on Linux/Windows) runswireguard-go; aMaskBind(inwgbind) wraps its UDPconn.Bindand applies themaskcodec — sealing outbound, opening inbound — at the socket. The masking is pluggable behind a GoObfuscatorinterface (Seal/Open). - Server — either the all-in-one
stealthwgserver (embeds the samewireguard-go+MaskBind, so it terminates the masked tunnel directly), or the relaystealthwg-gateway(unmasks and forwards plain WireGuard to an unmodified upstream WireGuard).
The mask codec is symmetric: the client seals what the server opens, and vice versa. All cryptographic security remains WireGuard's.
The QUIC transport is a sibling of the mask: instead of masking each UDP
datagram, QUICBind (client) and QUICServerBind (server) carry each WireGuard
packet as a QUIC DATAGRAM frame over a real quic-go connection on UDP 443 (ALPN
h3, self-signed TLS used only for blending). WireGuard is still the only
authenticated crypto.
See INSTALL.md for step-by-step instructions — building the iOS/macOS app, and standing up a server (all-in-one native package or relay). Deep server reference: docs/deploy-gateway.md.
One question first: is WireGuard already running on your server? If no, pick A or B; if yes, pick C.
| A — Native package | B — Standalone bundle | C — Relay image | |
|---|---|---|---|
| When? | Empty Linux, no Docker | Empty Linux, you like Docker | You already run WireGuard |
| What installs? | one program (stealthwg) |
one all-in-one container | 1 box: masker only |
| WireGuard inside? | ✅ Yes | ✅ Yes (same container) | ❌ No (uses yours) |
| Engine | All-in-one | All-in-one | Relay |
| How? | apt install + stealthwg init |
docker compose up -d |
docker run … stealthwg-gateway |
- A — "Just give me one box with everything inside, no Docker." Install one
program, run
stealthwg init, done. WireGuard and the masking live inside it. - B — "Empty server, but I like Docker."
docker compose upbrings up one all-in-one container (WireGuard + masking, userspace). Same result as A, in Docker. - C — "I already run WireGuard and don't want to touch it." Install only the masker box and point it at your WireGuard. It masks in front — it does not start a second WireGuard.
Golden rule: no WireGuard yet → A or B (same job, one without Docker, one with). Already have WireGuard → C only (A/B would stand up a second WireGuard you don't need). All three support UDP mask (51819) and QUIC (443).
The app imports a standard wg-quick config with a StealthWG [Stealth] section
(MaskKey, and optional fallback Endpoints):
[Interface]
PrivateKey = <client private key>
Address = 10.0.0.2/32
[Peer]
PublicKey = <server public key>
Endpoint = <server public IP>:51819
AllowedIPs = 0.0.0.0/0
[Stealth]
MaskKey = <base64 PSK>
Endpoints = <host>:51819, <host>:443Working masked WireGuard: validated end-to-end (handshake + live traffic) from a physical iPhone over a carrier that blocks plain WireGuard, through a self-hosted gateway. Clients (iOS/macOS apps + a Linux/Windows CLI) and both server shapes are built; hardening and distribution are ongoing.
MIT. Built on the MIT-licensed WireGuard projects.
English · Türkçe
DPI (Derin Paket İncelemesi) ile düz WireGuard'ı parmak izinden tanıyıp engelleyen ağlar için maskeli WireGuard: iOS, macOS, Linux ve Windows (CLI) için bir istemci ve kendi sunucunda barındırabileceğin bir maskeli WireGuard sunucusu.
StealthWG, WireGuard'ı yeniden yazmaz. Resmi, MIT lisanslı WireGuard motorunun
(wireguard-go) üzerine kurulur ve UDP soket sınırına bir maskeleme katmanı
yerleştirir; böylece teldeki baytlar WireGuard'ın parmak iziyle eşleşmez — ama tüm
gerçek kriptografiyi yine WireGuard sağlar.
Düz WireGuard: WG motoru ────────────────────────────► sunucu:51820
StealthWG: WG motoru ─► maske ─► telde gürültü ──► maskeyi kaldır ─► WG
Türkiye'de bazı internet servis sağlayıcıları (ISP) ve GSM operatörleri WireGuard trafiğini engelliyor ya da kısıtlıyor (throttling) — tünel hiçbir portta kurulmuyor ya da sürünüyor; oysa sıradan web trafiği akmaya devam ediyor. Sebep Derin Paket İncelemesi (DPI): operatör WireGuard'ı hat üzerindeki parmak izinden tanıyıp düşürüyor, bu yüzden port ya da endpoint değiştirmek işe yaramıyor. StealthWG Türkiye'de geliştirilip doğrulandı, ama bu yalnızca Türkiye'ye özgü bir sorun değil — DPI ile VPN engellemesi birçok ülkedeki sansürcü ağlar ve operatörler tarafından kullanılıyor; aynı maskeleme, WireGuard'ın parmak izinden tanındığı her yerde işe yarar.
Bu parmak izini eşleştirmek kolaydır. Standart WireGuard'ın el sıkışma paketleri sabit bir desene sahiptir — bir mesaj-tipi baytı, ardından ayrılmış sıfır baytlar ve sabit 148/92 baytlık boyutlar. DPI, protokolü nasıl yapılandırırsan yapılandır tanıyıp engellemek için tam olarak bu imzaya bakar.
StealthWG her paketi yüksek entropili, değişken uzunlukta gürültüye dönüştürür; böylece operatör eşleştirebileceği tanıdık bir WireGuard deseni göremez — ama güvenliği yine WireGuard sağlar. Pratikte doğrulandı: maskeli WireGuard, düz WireGuard'ı her portta engelleyen bir Türk GSM operatörünün mobil verisi üzerinden el sıkışmayı tamamladı ve canlı trafik (internet ve LAN) taşıdı.
- Çok platformlu istemci — tek kod tabanını paylaşan native iOS ve macOS uygulamaları (maskeleme, bağlantı, istatistik, profiller).
- Trafik maskeleme — UdpMask codec'i WireGuard paketlerini yüksek entropili gürültüye çevirir.
- İki taşıma — UDP mask (UDP üzerinde yüksek entropili gürültü) veya
QUIC (WireGuard, UDP 443'te QUIC DATAGRAM olarak taşınır, HTTP/3 ile karışır).
İkisi de hem istemci hem sunucu tarafında çalışır; profil
[Stealth] Transportile birini seçer. - Çoklu endpoint + otomatik yedekleme — istemci birden çok sunucu endpoint'ini
(ör. önce
:51819, sonra:443) el sıkışma olana kadar sırayla dener; hatta taşımalar arası da yedekleyebilir (quic://host:443, sonra bir mask endpoint'i). - Çoklu profil + düzenleme — birden çok sunucu tut, aralarında geç, yapısal formda düzenle; cihazda anahtar üret ya da kendininkini yapıştır.
- Kill switch + on-demand — profil başına: her zaman-açık otomatik bağlan, tüm trafiği tünelden geçir (sızıntısız), yerel ağ erişimini koru.
- Kolay içe/dışa aktarma — yapıştır, QR tara,
.confiçe aktar veya sıfırdan oluştur; herhangi bir profili QR olarak dışa aktar. - Kendi sunucun, iki motor — all-in-one (WireGuard + maskeleme tek binary'de; temiz bir sunucu için) ya da relay (mevcut bir WireGuard'ın önünde maskeler). Duruma göre üç kurulum: temiz sunucu, Docker yok → native all-in-one paket; temiz sunucu, Docker var → standalone bundle; zaten WireGuard çalıştırıyorsun → relay image (RouterOS / Kubernetes). "Hangisi?" için INSTALL.md.
- Tasarımdan gizlilik — kullanıcı trafiği loglanmaz; anahtarlar cihazdan çıkmaz; maskeleme yalnızca parmak izini bozar, ikinci bir şifreleme katmanı değildir.
Maskeleme, iki uçta da tekrar kullanılan tek bir küçük parçada yaşar — tasarımı basit kılan simetri budur:
- İstemci (iOS / macOS / Linux / Windows) — uygulama (ya da Linux/Windows'ta
stealthwg-clientCLI'si)wireguard-goçalıştırır; birMaskBind(wgbindiçinde) onun UDPconn.Bind'ını sarar vemaskcodec'ini uygular — gideni sealler, geleni açar — soket sınırında. Maskeleme, GoObfuscatorarayüzünün (Seal/Open) arkasında takılabilirdir. - Sunucu — ya all-in-one
stealthwgsunucusu (aynıwireguard-go+MaskBind'i gömer, maskeli tüneli doğrudan sonlandırır), ya da relaystealthwg-gateway(maskeyi açıp değiştirilmemiş bir WireGuard'a düz WireGuard olarak iletir).
Mask codec'i simetriktir: istemcinin seallediğini sunucu açar, tersi de geçerli. Tüm kriptografik güvenlik WireGuard'da kalır.
Adım adım talimatlar için INSTALL.md — iOS/macOS uygulamasının derlenmesi ve bir sunucunun (all-in-one native paket ya da relay) ayağa kaldırılması. Derin sunucu referansı: docs/deploy-gateway.md.
Önce tek soru: Sunucunda şu an WireGuard çalışıyor mu? Hayırsa A veya B, evetse C.
| A — Native paket | B — Standalone bundle | C — Relay image | |
|---|---|---|---|
| Ne zaman? | Boş Linux, Docker istemiyorsun | Boş Linux, Docker seviyorsun | Zaten WireGuard'ın var |
| Ne kurulur? | Tek program (stealthwg) |
Tek all-in-one container | 1 kutu: sadece maskeleyici |
| İçinde WG var mı? | ✅ Var | ✅ Var (aynı container) | ❌ Yok (seninkini kullanır) |
| Motor | All-in-one | All-in-one | Relay |
| Nasıl? | apt install + stealthwg init |
docker compose up -d |
docker run … stealthwg-gateway |
- A — "Tek kutu ver, her şey içinde olsun, Docker'la uğraşmayayım." Tek program
kurarsın,
stealthwg initdersin, biter. WireGuard ve maskeleme o programın içinde. - B — "Boş sunucu ama Docker'ı severim."
docker compose updersin; sana tek all-in-one container açar (WireGuard + maskeleme, userspace). Sonuç A ile aynı, Docker'da. - C — "Zaten WireGuard'ım var, ona dokunmayayım." Sadece maskeleyici kutuyu kurarsın, "benim WG'm şurada" dersin; önüne geçip maskeler. Yeni WireGuard kurmaz.
Altın kural: WireGuard'ın yoksa → A ya da B (aynı iş, biri Docker'sız biri Docker'lı). Varsa → sadece C (A/B kurarsan boşuna ikinci bir WireGuard kurarsın). Üçünde de hem UDP mask (51819) hem QUIC (443) var.
Uygulama, StealthWG [Stealth] bölümü (MaskKey ve opsiyonel yedek Endpoints)
olan standart bir wg-quick config'i içe aktarır:
[Interface]
PrivateKey = <istemci özel anahtarı>
Address = 10.0.0.2/32
[Peer]
PublicKey = <sunucu açık anahtarı>
Endpoint = <sunucu public IP>:51819
AllowedIPs = 0.0.0.0/0
[Stealth]
MaskKey = <base64 PSK>
Endpoints = <host>:51819, <host>:443Çalışan maskeli WireGuard: fiziksel bir iPhone'dan, düz WireGuard'ı engelleyen bir operatör üzerinden, kendi barındırdığımız bir gateway ile uçtan uca (el sıkışma + canlı trafik) doğrulandı. İstemciler (iOS/macOS uygulamaları + bir Linux/Windows CLI) ve her iki sunucu biçimi inşa edildi; sertleştirme ve dağıtım sürüyor.
MIT. MIT lisanslı WireGuard projeleri üzerine kuruludur.