Skip to content

therealaleph/sni-spoofing-rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sni-spoof-rs

Release Total Downloads Latest Downloads Stars License

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.

English Guide | Persian Guide

Platforms

  • Linux -- AF_PACKET raw sockets. Requires root or CAP_NET_RAW.
  • macOS -- BPF device. Requires root.
  • Windows -- WinDivert driver. Requires Administrator.

Build

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)

Setup Guide

This tool works with VLESS/VMess configs that go through Cloudflare (CDN-based configs). Your server must be behind Cloudflare.

Step 1: Find your server's Cloudflare IP

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).

Step 2: Create config.json

{
  "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.

Step 3: Edit your v2ray/xray config

In your VLESS/VMess client config, change:

  • Address: from myserver.example.com (or its IP) to 127.0.0.1
  • Port: to the listen port 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.

Step 4: Run

# 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.

Finding a working fake_sni (scan mode)

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).

Logging

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

Building from source

To build cross-platform binaries for all supported platforms, use the included Makefile:

make all

This 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.

How it works

  1. Client connects to the listener, tool dials the upstream, kernel does the TCP 3-way handshake normally.
  2. A raw packet sniffer captures the outbound SYN (records ISN) and the 3rd-handshake ACK.
  3. 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.
  4. DPI parses the fake packet, sees an allowed SNI, and whitelists the connection.
  5. The server drops the fake packet (out-of-window).
  6. Tool waits for the server's ACK with ack == ISN + 1 confirming the fake was ignored.
  7. Bidirectional relay starts. The real TLS handshake and all subsequent traffic flow normally.

راهنمای فارسی

این ابزار با کانفیگ‌های VLESS/VMess که از Cloudflare عبور می‌کنند کار می‌کند. سرور شما باید پشت Cloudflare باشد.

مرحله ۱: پیدا کردن IP کلادفلر سرور

آدرس سرور در کانفیگ v2ray شما یک دامنه است (مثل myserver.example.com). IP آن را پیدا کنید:

nslookup myserver.example.com

باید یک IP کلادفلر بگیرید (معمولا با 104.، 172.67.، 141.101. شروع می‌شود).

مرحله ۲: ساخت config.json

{
  "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)

مرحله ۳: تغییر کانفیگ v2ray/xray

در کانفیگ 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 قابل استفاده (حالت scan)

اگر 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 دانلود کنید)

License

MIT

About

DPI bypass via fake TLS ClientHello injection with wrong TCP sequence number. Rust port of @patterniha's SNI-Spoofing. Linux, macOS, Windows. Works with v2ray/xray VLESS configs behind Cloudflare.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors