ParsaKSH/spoof-tunnel
GitHub: ParsaKSH/spoof-tunnel
一個基於 IP 模擬的雙向隧道工具,解決傳統狀態防火牆對源地址與連線狀態的過度信任問題。
Stars: 158 | Forks: 47
# Spoof Tunnel
[Persian-فارسی](README-fa.md)
Spoof Tunnel یک پروکسی لایه 3/Layer 4 طراحی شده برای گذرافزایی از Deep Packet Inspection (DPI) و firewallهای وضعیتی دقیق از طریق **spoofing دوطرفه دو طرفه IP** است.
در تفاوت با پروتکلهای تونلیng سنتی که یک ارتباط وضعیتی (stateful) بین یک IP ثابت کلاینت و یک IP ثابت سرور برقرار میکنند، Spoof Tunnel کاملاً اجازه ارتباط را از آدرسهای شبکه فیزیکی جدا میکند با تقلید فیلد `Source IP` در هدر IP در هر دو پنهان.
### چگونگی ایجاد پروژه: ریشه Spoof Tunnel
ایده یک تونل دوطرفه spoofing پس از قطع کامل اینترنت در ایران پس از اعتراض خشونتآمیز در تاریخ ۸ و ۹ ژانویه ۲۰۲۶ (۱۸-۱۹ دی ۱۴۰۴) ظاهر شد. در این قطع کامل اینترنت، هدف اصلی ما برای برگشت به ریشه بود.
پس از بررسی مسیرهای BGP برای پیشوندهای IP ایرانی، یک جزئیات شگفتانگیز را مشاهده کردیم: در تفاوت با قطع اینترنت در افغانستان که مسیرهای BGP به سادگی ناپدید میشدند، رشتههای IP ایران هنوز فعالانه در جهان اعلام میشدند. این نشان میداد که زیرساخت فیزیکی بینالمللی به طور کامل سالم بود.
بعداً مشخص شد که سازمانهای دولتی ایرانی برخی از آدرسهای IP خاص خود را به لیست سفید داده و موفق به بازیابی ارتباط بینالمللی شده بودند. این نگارش منجر به ایجاد فرضیه شد که محدودیت در لایه 3 اجرا میشود و بر اساس فیلتری srcIP و dstIP عمل میکند.
این فرضیه هنگامی به طور قطعی تایید شد که چندین آدرس IP خارجی انتخابی (مانند فراترنگاههای Hetzner) قادر به برقراری ارتباط ورودی به ایران هستند. شواهد به وضوح نشان داد که "قطع کامل" یک سیاست فیلتری با لیست سفید در لایه 3 دقیق است.
در این محیط بسیار محدود، ایده یک تونل spoofing به وجود آمد. با مدیریت هدر IP، ما میتوانستیم ترافیک را شبیه به یک لیست سفید تقلید کنیم. با این حال، به همین دلیل که در IP spoofing جای دارد، اگر یک پکت از آیپی دروغ سازی شده به یک سرور ارسال شود، سرور به طور خودکار پاسخ خود را به آدرس IP دروغ ارسال میکند—نه به ماشین منبع واقعاً.
بنابراین، یک تونل مستقی单向 spoof کافی نبود. ما نیاز به یک مکانیزم دوطرفه spoofing قوی بود که هر دو طرف (کلاینت و سرور) هدرهای IP خود را تقلید کنند و آدرسهای فیزیکی واقعی خود را پیشبینی کنند تا بتوانند ارتباطی منطقی را ایجاد و حفظ کنند، علیرغم مسیریابی غیرقابل پیشبینی و تقلید شده.
## 1. هسته ساختار: Spoofing IP دوطرفه
### ۱.۱ جریان داده غیرهمزیب
در یک سناریو معمول، کلاینت و سرور به آدرسهای IP خاصی متفق میشوند تا spoof کنند:
* **کلاینت → سرور (آپلود):** کلاینت پکتهایی با منبع IP دروغ (مثلاً `Client_Spoof_IP`) ارسال میکند که به آدرس شنوایی واقعی سرور هدیه داده میشود.
* **سرور → کلاینت (دانلود):** سرور پاسخ میدهد با ارسال پکتهایی که منبع IP دروغ آنها (مثلاً `Server_Spoof_IP`) به آدرس IP واقعی کلاینت اشاره دارد.
این وضعیت ایجاد میکند که میانگیران شبکه فیلترهای پیشرفته ترافیک UDP یا ICMP یکجهه را دیده کنند که به طور منطقی با هیچ یک از جداول ردیابی ارتباط (conntrack) تطابق ندارد، و به طور مؤثر، میزان ردیابی ترافیق (traffic fingerprinting) را نادیده گرفته و از جداول conntrack گذر میکند.
### ۱.۲ پیادهسازی رشته خام (Raw Socket)
برای ایجاد پکتهایی با هدرهای لایه 3 (IPv4/IPv6) به طور دستی تغییر داده شده، Spoof Tunnel از رشتههای خام (`AF_INET`, `SOCK_RAW`) استفاده میکند. این ابزار تمام هدر IPv4/IPv6 را به صورت دستی ساخته و چکسامهای IP مربوطه را در محاسبات نرم افزاری محاسبه میکند.
* `gopacket` و `pcap` به شدت استفاده میشوند تا از پیشگیری از لایه پروندهٔ هسته (kernel network stack) گذر کند.
* **فیلترهای BPF:** برای پیشگیری از اینکه سیستم عامل میزبان پکتهای دروغ وارد شده را رد کند یا پاسخ با `ICMP Destination Unreachable` / `TCP RST` بدهد، یک فیلتر پکتبندی برکندی (Berkeley Packet Filter) تحریکی خشونتآمیز است که محدوده گیری را به جریان تونل انتظار را محدود میکند و محدودیتهای مسیریابی محلی را گذر میدهد.
## 2. پشتیبانی از انتقالات
### ۲.۱ ICMP (حالت Echo)
تونل چنین پکتهای رمزنگاری شده را درون پکتهای معمولی `ICMP Echo Request (Type 8)` و `ICMP Echo Reply (Type 0)` جایگزینی میکند. برای میانگیران شبکه، این ترافیک شبیه به یک بارگیری یا نگارش آزمایشی بیضرر ظاهر میشود.
### ۲.۲ UDP
دیتاگرامههای UDP استاندارد با درجه آزادی منبع پورت بهکار میرود. این پروتکل الگوهایی را شبیه به DNS یا برنامههای کاربردی UDP سفارشی تقلید میکند.
## 3. لایه اعتماد (Reliability Layer)
چون ICMP و UDP هیچ گارانتی ارسال ندارند، Spoof Tunnel یک لایه اعتماد شبیه به TCP سفارشی در فضای کاربری پیادهسازی میکند. این کار الزامی برای حفظ TLS handshakeهای مستقر و ارسال جریان در ترتیب است.
* **شمارششده پکتها و ACK:** هر پکت پیام (payload) در فرمت `SeqDataPacket` پوشیده میشود که شامل یک شماره توالی (4 بایت) است. دریافتکننده اعداد را از طریق `AckPacket` تأیید میکند که از یک شماره پایه (base sequence number) همراه با یک نقشه تأیید ۶۴‑بیتی برای مدیریت بلوکهای داده در یک زمان پردازش میشود.
* **کنترل جریان و پشتیبانی از حافظه:** `RecvBuffer` یک نقشه داخلی از دنبالهها نگه میدارد. پکتهای خارج از ترتیب در حافظه پساندازی میشوند. دادهها به socket TCP داخلی SOCKS5/هدف **به ترتیب دقیق** ارسال میشوند.
* **مهندس بازتاب:** یک گوروتین پسزمینه فعال هر ۱۰۰ms `SendBuffer` را پیمایش میکند. پکتهای تأیید نشده که به زمان `retransmit_timeout` بیشتر از محدوده خود باشند، با backoff اکسپونانسی تکرار میشوند تا به حداکثر `max_retries` معیار رسید.
## 4. Multiplexing نشست
ایجاد یک نشست تونل جدید (exchange INIT / INIT_ACK) با تأخیر قابل توجهی همراه است. برای کاهش این تأخیر، Spoof Tunnel یک مولتیپلکسور داخلی (Mux) پیادهسازی میکند.
یک "نشست اصلی" (Master Session) در طول یک ارتباط غیرقابل اعتماد برقرار میشود. تمام ارتباطهای TCP SOCKS5 ورودی به یک `StreamID` چهار بایتی منحصر به فرد اختصاص داده میشود و در این نشست اصلی مولتیپلکس میشوند.
* `0x01 MuxStreamOpen:` پس از [StreamID:4][TargetLen:2][Target String]
* `0x02 MuxStreamData:` پس از [StreamID:4][Raw Payload]
* `0x03 MuxStreamClose:` پس از [StreamID:4]
* `0x04 MuxStreamAck:` تأیید سرور برای ایجاد موفق یک جریان پروکسی.
## 5. رمزنگاری
امنیت و پنهانی از طریق **ChaCha20-Poly1305 AEAD** اجباری است. AEAD این امکان را فراهم میکند که هیچ یک از بایتهای پیام یا ساختار هدر تونل توسط یک مهاجم MITM فعال مشاهده یا تغییر یابد بدون درک فوری و توقف ارتباط.
هر نشست یک nonce تصادفی ایجاد میکند تا حملات تکراری را جلوگیری کند، در حالی که کلیدهای پیشاشتراک Base64 ثابت به عنوان یک راز کلید رمزنگاری عمل میکنند.
## راهنمای استفاده
### ۱. ساخت فایل باینری
Spoof Tunnel نوشته شده به زبان Go. میتوانید آن را با استفاده از ابزارهای معمولی Go ساخت کنید:
```
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o spoof ./cmd/spoof/
```
### ۲. ایجاد کلیدهای رمزنگاری
پیش از شروع تونل، شما نیاز به یک جفت کلیدهای Base64 خصوصی/عمومی برای سرور و کلاینت دارید.
```
./spoof keygen
```
* **توجه:** کلید خصوصی و کلید عمومی را یادداشت کنید. کلید عمومی سرور باید در فیلد `peer_public_key` کلاینت قرار گیرد و کلید عمومی کلاینت باید در فیلد `peer_public_key` سرور قرار گیرد.
### ۳. اجرای خدمت
**روی سرور:**
```
sudo ./spoof -c server-config.json
```
**روی کلاینت:**
```
sudo ./spoof -c client-config.json
```
پس از اتصال کلاینت، یک پروکسی SOCKS5 روی `127.0.0.1:1080` (به طور پیشفرض) باز میشود که مسیریابی ایمن از طریق تونل spoof شده انجام میدهد.
## پیکربندی کلاینت
| بخش | کلید | نوع | توضیحات |
|------------|-------------------------|---------|-----------------------------------------------------------------------------|
| mode | mode | string | باید "client" باشد |
| transport | type | string | "udp" یا "icmp" (ترانسپورت تونل) |
| transport | icmp_mode | string | "echo" یا "reply" (فقط برای ICMP) |
| transport | protocol_number | int | 0 (پیشفرض، استفاده نشده برای ICMP/UDP) |
| listen | address | string | آدرس شنوایی SOCKS5 (127.0.0.1) |
| listen | port | int | پورت شنوایی SOCKS5 (1080) |
| server | address | string | آدرس IP واقعی سرور برای ارسال پکتهای تونل |
| server | port | int | پورت سرور (برای UDP) |
| spoof | source_ip | string | IP که این کلاینت زمان ارسال پکتهای خارجی ادعا میکند |
| spoof | peer_spoof_ip | string | IP دروغ سرور انتظار شده (استفاده شده توسط فیلتر BPF) |
| crypto | private_key | string | کلید خصوصی Base64 کلاینت (از ./spoof keygen) |
| crypto | peer_public_key | string | کلید عمومی Base64 سرور |
| performance| buffer_size | int | حجم بافر اصلی پکت |
| performance| mtu | int | حجم حداکثر پیشپردازش قبل از جلوگیری (مثلاً 1400) |
| performance| session_timeout | int | زمان انقضا نهایی نشست اصلی در ثانیه |
| performance| workers | int | تعداد گوروتینهای پردازش پکت |
| performance| read_buffer | int | اندازه پوشش خواندن سکت کلینت |
| performance| write_buffer | int | اندازه پوشش نوشتن سکت کلینت |
| fec | enabled | bool | true = فعال کردن کد اصلاح خطای رید-سولomon (Reed-Solomon) |
| fec | data_shards | int | تعداد شاردهای داده واقعی |
| fec | parity_shards | int | تعداد شاردهای پاریتی (تا این حد پکتهای از دست رفته را بازیابی میکند) |
| logging | level | string | "info", "debug", "warn", یا "error" |
| logging | file | string | مسیر فایل گزارش (خالی = استاندارد خروجی) |
## پیکربندی سرور
| بخش | کلید | نوع | توضیحات |
|------------|-------------------------|---------|-----------------------------------------------------------------------------|
| mode | mode | string | باید "server" باشد |
| transport | type | string | "udp" یا "icmp" (ترانسپورت تونل) |
| transport | icmp_mode | string | "echo" یا "reply" (فقط برای ICMP) |
| transport | protocol_number | int | 0 (پیشفرض، استفاده نشده برای ICMP/UDP) |
| listen | address | string | آدرس گوشی تونل (0.0.0.0 برای تمامی رابطها) |
| listen | port | int | پورت شنوایی UDP (به اغیاه یادگرفته برای ICMP) |
| spoof | source_ip | string | IP که این سرور زمان ارسال پکتهای خارجی ادعا میکند |
| spoof | source_ipv6 | string | نسخه IPv6 از source_ip (اگر استفاده نشود خالی بگذارید) |
| spoof | peer_spoof_ip | string | IP دروغ کلاینت انتظار شده (استفاده شده توسط فیلتر BPF) |
| spoof | peer_spoof_ipv6 | string | نسخه IPv6 از peer_spoof_ip |
| spoof | client_real_ip | string | آدرس IP واقعی کلاینت (سرور مسیریابی پاسخها به اینجا میکند) |
| spoof | client_real_ipv6 | string | نسخه IPv6 از client_real_ip |
| crypto | private_key | string | کلید خصوصی Base64 سرور (از ./spoof keygen) |
| crypto | peer_public_key | string | کلید عمومی Base64 کلاینت |
| performance| buffer_size | int | حجم بافر اصلی پکت |
| performance| mtu | int | حجم حداکثر پیشپردازش قبل از جلوگیری (مثلاً 1400) |
| performance| session_timeout | int | زمان انقضا نهایی نشست اصلی در ثانیه |
| performance| workers | int | تعداد گوروتینهای پردازش پکت |
| performance| read_buffer | int | اندازه پوشش خواندن سکت کلینت |
| performance| write_buffer | int | اندازه پوشش نوشتن سکت کلینت |
| reliability| enabled | bool | true = فعال کردن لایه اعتماد سفارشی TCP-like |
| reliability| window_size | int | حداکثر پکتهای غیر تأیید شده در پرواز |
| reliability| retransmit_timeout_ms | int | زمان انتظار اساسی قبل از تکرار (ms) |
| reliability| max_retries | int | حداکثر تلاشهای تکراری برای هر پکت |
| reliability| ack_interval_ms | int | چگونگی ارسال ACK (ms) |
| fec | enabled | bool | true = فعال کردن کد اصلاح خطای رید-سولomon (Reed-Solomon) |
| fec | data_shards | int | تعداد شاردهای داده واقعی |
| fec | parity_shards | int | تعداد شاردهای پاریتی (تا این حد پکتهای از دست رفته را بازیابی میکند) |
| keepalive | enabled | bool | true = ارسال پینگهای دورهبندی منظم |
| keepalive | interval_seconds | int | ثانیههای میان پینگهای دورهبندی |
| keepalive | timeout_seconds | int | زمان انتظار بدون فعالی قبل از قطع نشست |
| logging | level | string | "info", "debug", "warn", یا "error" |
| logging | file | string | مسیر فایل گزارش (خالی = استاندارد خروجی) |
标签:DPI绕过, EVTX分析, IP伪造, L3隧道, L4隧道, 中间人, 代理, 会话脱耦, 匿名通信, 协议混淆, 双向伪造, 反审查, 开源网络, 数据包操作, 无文件攻击, 日志审计, 流量转发, 目录遍历, 网络伪装, 网络工具, 网络规避, 防火墙穿透, 隧道