Rust implementation of patterniha's SNI-Spoofing DPI bypass technique. All credit for the original idea and method goes to @patterniha.
A TCP forwarder that injects a fake TLS ClientHello with an intentionally wrong TCP sequence number right after the 3-way handshake. Stateful DPI reads the fake SNI and whitelists the flow. The real server drops the packet (out-of-window seq). Real traffic then passes through undetected.
- Linux -- AF_PACKET raw sockets. Requires root or
CAP_NET_RAW. - macOS -- BPF device. Requires root.
- Windows -- WinDivert driver. Requires Administrator.
cargo build --release
Pre-built binaries for Linux (amd64/arm64), macOS (amd64/arm64), and Windows (amd64) are available two ways:
- GitHub Releases page
- The
releases/folder in this repository (useful if the Releases page is blocked for you -- just clone the repo or download as ZIP)
This tool works with VLESS/VMess configs that go through Cloudflare (CDN-based configs). Your server must be behind Cloudflare.
Your v2ray/xray config has a server address (a domain like myserver.example.com). Resolve it to get the IP:
nslookup myserver.example.com
You should get a Cloudflare IP (usually starts with 104., 172.67., 141.101., etc).
{
"graceful_shutdown_sec": 0,
"listeners": [
{
"listen": "0.0.0.0:40443",
"connect": "CLOUDFLARE_IP:443",
"fake_sni": "security.vercel.com"
}
]
}Replace CLOUDFLARE_IP with the IP from step 1. The fake_sni can be any domain that is allowed by your DPI (a well-known site behind Cloudflare works best).
| Field | Description |
|---|---|
listen |
Local address and port to listen on |
connect |
Cloudflare IP and port (must be an IP, not a hostname) |
fake_sni |
SNI for the fake ClientHello (max 219 bytes) |
conn_timeout_sec |
Seconds to wait for the upstream TCP connection to complete (default: 5) |
handshake_timeout_sec |
Seconds to wait for the sniffer to confirm the fake packet was sent (default: 2) |
keepalive_time_sec |
Seconds of idle before TCP keepalive probes begin (default: 11) |
keepalive_interval_sec |
Seconds between individual TCP keepalive probes (default: 2) |
| Top-level Field | Description |
|---|---|
graceful_shutdown_sec |
Seconds to wait for active connections to finish after receiving a shutdown signal. 0 exits immediately (default: 0) |
Multiple listeners are supported -- each maps to one upstream.
In your VLESS/VMess client config, change:
- Address: from
myserver.example.com(or its IP) to127.0.0.1 - Port: to the
listenport from config.json (e.g.40443) - Keep everything else the same (SNI, host, path, UUID, etc.)
Example -- if your original config has:
address: myserver.example.com
port: 443
Change it to:
address: 127.0.0.1
port: 40443
The tool sits between your v2ray client and the server. Your client connects to the tool, the tool handles the DPI bypass, and forwards traffic to Cloudflare.
# Linux/macOS
sudo ./sni-spoof-rs config.json
# Windows (run as Administrator)
sni-spoof-rs.exe config.json
Windows note: The Windows download is a zip containing sni-spoof-rs.exe and WinDivert64.sys. Keep both files in the same folder. The .sys file is the kernel driver that WinDivert needs to intercept packets.
Then connect with your v2ray/xray client as usual.
If your chosen fake_sni stops working (e.g., after a DPI update), the tool includes a scanner that probes a built-in list of ~650 Cloudflare-fronted domains and reports which ones pass through your network:
# scan using built-in list (no sudo needed -- scan mode is plain outbound TLS)
./sni-spoof-rs scan
# save working SNIs to a file
./sni-spoof-rs scan -o working.txt
# scan your own list
./sni-spoof-rs scan --list my-snis.txt
# probe against a specific Cloudflare IP
./sni-spoof-rs scan --target 172.67.139.236:443
# faster scanning
./sni-spoof-rs scan --concurrency 30 --timeout 4
Pick any SNI from the output as your fake_sni in config.json. The scanner does not need root or the raw socket -- it just opens a TCP connection and sends a ClientHello.
Caveat: this works for passive SNI-based DPI (the current common case). If your ISP does full TLS MITM (terminates and re-establishes TLS), most SNIs will appear "reachable" but the DPI bypass itself will still fail -- that problem requires a different tool (REALITY, Hysteria, ECH in xray).
The default log level is warn -- the tool runs silent unless something goes wrong. No connection metadata is logged by default.
Set RUST_LOG for verbosity when debugging:
sudo RUST_LOG=info ./sni-spoof-rs config.json
sudo RUST_LOG=debug ./sni-spoof-rs config.json
To build cross-platform binaries for all supported platforms, use the included Makefile:
make allThis will create binaries for Linux (x64/ARM64), macOS (x64/ARM64), and Windows (x64) in the bins/ directory. Individual platform targets are also available: make linux-x64, make macos-arm64, etc.
- Client connects to the listener, tool dials the upstream, kernel does the TCP 3-way handshake normally.
- A raw packet sniffer captures the outbound SYN (records ISN) and the 3rd-handshake ACK.
- After the 3rd ACK, a fake TLS ClientHello is injected with
seq = ISN + 1 - len(fake). This sequence number is before the server's receive window. - DPI parses the fake packet, sees an allowed SNI, and whitelists the connection.
- The server drops the fake packet (out-of-window).
- Tool waits for the server's ACK with
ack == ISN + 1confirming the fake was ignored. - Bidirectional relay starts. The real TLS handshake and all subsequent traffic flow normally.
این ابزار با کانفیگهای VLESS/VMess که از Cloudflare عبور میکنند کار میکند. سرور شما باید پشت Cloudflare باشد.
آدرس سرور در کانفیگ v2ray شما یک دامنه است (مثل myserver.example.com). IP آن را پیدا کنید:
nslookup myserver.example.com
باید یک IP کلادفلر بگیرید (معمولا با 104.، 172.67.، 141.101. شروع میشود).
{
"graceful_shutdown_sec": 0,
"listeners": [
{
"listen": "0.0.0.0:40443",
"connect": "IP_CLOUDFLARE:443",
"fake_sni": "security.vercel.com"
}
]
}به جای IP_CLOUDFLARE آیپی مرحله ۱ را بگذارید. مقدار fake_sni میتواند هر دامنهای باشد که فیلتر نیست (یک سایت معروف پشت کلادفلر بهتر جواب میدهد).
| فیلد | توضیح |
|---|---|
listen |
آدرس و پورت محلی برای گوش دادن |
connect |
آیپی و پورت کلادفلر (باید IP باشد، نه دامنه) |
fake_sni |
SNI برای ClientHello جعلی (حداکثر ۲۱۹ بایت) |
conn_timeout_sec |
ثانیههای انتظار برای برقراری اتصال (پیشفرض: 5) |
handshake_timeout_sec |
ثانیههای انتظار برای تأیید ارسال پکت جعلی توسط sniffer (پیشفرض: 2) |
keepalive_time_sec |
ثانیههای بیفعالیتی قبل از شروع پروبهای TCP keepalive (پیشفرض: 11) |
keepalive_interval_sec |
فاصله زمانی بین پروبهای TCP keepalive به ثانیه (پیشفرض: 2) |
| فیلد سطح بالا | توضیح |
|---|---|
graceful_shutdown_sec |
مدت انتظار (به ثانیه) برای اتمام اتصالات فعال پس از دریافت سیگنال خاموشی. مقدار 0 بلافاصله خارج میشود (پیشفرض: 0) |
در کانفیگ VLESS/VMess خود این تغییرات را بدهید:
- آدرس (address): عوض کنید به
127.0.0.1 - پورت (port): عوض کنید به پورت listen از config.json (مثلا
40443) - بقیه تنظیمات را دست نزنید (SNI، host، path، UUID و غیره)
مثال -- اگر کانفیگ اصلی شما اینطوری است:
address: myserver.example.com
port: 443
تغییر دهید به:
address: 127.0.0.1
port: 40443
# لینوکس/مک
sudo ./sni-spoof-rs config.json
# ویندوز (با دسترسی Administrator اجرا کنید)
sni-spoof-rs.exe config.json
نکته ویندوز: فایل دانلودی ویندوز یک zip است که شامل sni-spoof-rs.exe و WinDivert64.sys میباشد. هر دو فایل باید در یک پوشه باشند. فایل .sys درایور کرنل WinDivert است که برای رهگیری پکتها لازم است.
بعد از اجرا، کلاینت v2ray/xray خود را مثل همیشه وصل کنید.
اگر fake_sni فعلی شما کار نمیکند (مثلا بعد از آپدیت DPI)، ابزار یک اسکنر داخلی دارد که لیستی از حدود ۶۵۰ دامنه پشت کلادفلر را روی شبکهی شما تست میکند و SNIهای در دسترس را نشان میدهد:
# اسکن با لیست داخلی (نیاز به sudo ندارد)
./sni-spoof-rs scan
# ذخیره نتایج در فایل
./sni-spoof-rs scan -o working.txt
# استفاده از لیست سفارشی
./sni-spoof-rs scan --list my-snis.txt
# تست روی یک IP کلادفلر خاص
./sni-spoof-rs scan --target 172.67.139.236:443
# اسکن سریعتر
./sni-spoof-rs scan --concurrency 30 --timeout 4
هر SNI از خروجی را میتوانید در config.json به عنوان fake_sni بگذارید. حالت scan نیازی به root یا raw socket ندارد -- فقط یک اتصال TCP عادی باز میکند و ClientHello میفرستد.
نکته مهم: این روش برای DPI غیرفعال که SNI را چک میکند (حالت رایج فعلی) جواب میدهد. اگر ISP شما TLS MITM کامل انجام میدهد (یعنی TLS را ترمینیت و دوباره باز میکند)، اکثر SNIها "قابل دسترس" نشان داده میشوند ولی خود دور زدن DPI کار نمیکند -- این مشکل نیاز به ابزار دیگری دارد (REALITY، Hysteria، یا فعال کردن ECH در xray).
برای ساخت فایلهای اجرایی برای تمام پلتفرمها، از Makefile موجود استفاده کنید:
make allاین دستور فایلهای اجرایی برای لینوکس (x64/ARM64)، مک (x64/ARM64) و ویندوز (x64) را در پوشه bins/ میسازد. همچنین میتوانید برای هر پلتفرم جداگانه بیلد بگیرید: make linux-x64، make macos-arm64 و غیره.
فایلهای اجرایی آماده برای لینوکس، مک و ویندوز از دو جا قابل دانلودند:
- صفحه GitHub Releases
- پوشه
releases/در خود ریپازیتوری (اگر صفحه Releases برای شما فیلتر است از اینجا دانلود کنید -- کافیست ریپو را clone یا به صورت ZIP دانلود کنید)
MIT