# Spoof Tunnel

[English](README.md)


اسپوف تانل یک تونل پروکسی در لایه‌های ۳ و ۴ شبکه (L3/L4) است که به صورت ویژه برای دور زدن فایروال‌های پردازش عمیق بسته‌ها (DPI) و سیستم‌های مانیتورینگ stateful از طریق تکنیک **جعل آی‌پی دوطرفه (Mutual IP Spoofing)** طراحی شده است.

پروتکل‌های تونل‌زنی سنتی، یک اتصال منطقی (Stateful) بین یک آی‌پی مشخص کلاینت و یک آی‌پی مشخص سرور برقرار می‌کنند. اسپوف تانل این وابستگی منطقی را با دستکاری فیلد `Source IP` درون هدر IP در هر دو سمت ارتباط کاملاً از بین می‌برد و شناسایی ترافیک را برای فایروال‌ها بسیار دشوار می‌سازد.

> [!IMPORTANT]
> 
> هر دو سرور شما باید قابلیت ارسال پکت اسپوف شده را داشته باشند.
>
> برای تست این مورد، می‌توانید از دستور زیر بصورت موقتی روی هر یک از سرور های خود استفاده کنید:
>
> iptables -t nat -A POSTROUTING -d target-ip -j SNAT --to-source spoof-ip
>
> بعد:
>
> ping target-ip
>
> و در سرور مقابل از ابزاری مثل tcpdump استفاده کنید:
>
> tcpdump icmp
>
> اگر رسیدن پکت های اسپوف شده را مشاهده کردید، سروری که از آن پکت هارا ارسال کردید قابلیت فرستادن پکت اسپوف را دارد.
## چگونگی شکل گیری پروژه:

چگونه پروژه به وجود آمد: منشأ تونل جعلی
مفهوم تونل جعل دو طرفه در واکنش به قطعی شدید اینترنت در ایران در پی قیام خونین 8 و 9 ژانویه 2026 (18-19 دی 1404) پدیدار شد. در طول این قطع کامل از اینترنت جهانی، هدف اصلی ما مهندسی معکوس دامنه و لایه دقیق محدودیت‌های تحمیلی بود.

پس از بررسی مسیرهای BGP برای پیشوندهای IP ایران، جزئیات شگفت‌انگیزی را مشاهده کردیم: برخلاف قطع اینترنت در افغانستان که مسیرهای BGP به سادگی ناپدید شدند، محدوده IP ایران همچنان به طور فعال در سطح جهانی اعلام می‌شد. این به شدت نشان داد که زیرساخت های فیزیکی بین المللی هنوز دست نخورده است.

متعاقباً، مشخص شد که برخی از نهادهای ایرانی وابسته به دولت توانستند آدرس‌های IP خاص خود را در لیست سفید قرار دهند و اتصال بین‌المللی خود را با موفقیت بازیابی کنند. این مشاهدات منجر به این فرضیه شد که محدودیت در لایه 3 اعمال می شود، به طور خاص فیلتر بر اساس srcIP و dstIP.

این فرضیه زمانی تایید شد که متوجه شدیم چند آدرس IP خارجی منتخب (مانند محدوده‌های خاص از Hetzner) هنوز هم می‌توانند اتصالات ورودی به ایران برقرار کنند. شواهد به وضوح نشان می‌دهند که «بلاک‌ اوت» یک قطع فیزیکی نیست، بلکه یک خط‌مشی سخت‌گیرانه و مبتنی بر لیست سفید فایروال لایه ۳ است.

در این محیط بسیار محدود، ایده یک تونل جعلی مطرح شد. با دستکاری هدرهای IP، می‌توانیم ترافیک لیست سفید را شبیه‌سازی کنیم. با این حال، همانطور که ذاتی جعل IP است، اگر یک بسته جعلی به یک سرور ارسال شود، سرور ذاتاً پاسخ خود را به آدرس IP جعلی - نه میزبان اصلی اصلی - هدایت می کند.

بنابراین، یک جعل استاندارد یک طرفه کافی نبود. ما به یک مکانیسم جعل متقابل دو طرفه قوی نیاز داشتیم که در آن کلاینت و سرور هر دو هدر IP خود را جعل می‌کنند و نمونه‌های از پیش تعیین‌شده‌ای هستند که به خوبی از IPهای فیزیکی واقعی یکدیگر آگاه هستند و آنها را قادر می‌سازد تا علی‌رغم مسیریابی نامتقارن و جعلی، یک ارتباط منطقی برقرار کرده و حفظ کنند.

## ۱. معماری هسته: Mutual IP Spoofing

### ۱.۱ جریان داده نامتقارن (Asymmetric Data Flow)
در این پیاده‌سازی، کلاینت و سرور توافق می‌کنند که از چه آی‌پی‌هایی به عنوان هویت جعلی استفاده کنند:

* **کلاینت به سرور (Upload):** کلاینت پکت‌ها را با یک سورس آی‌پی جعلی (مانند `Client_Spoof_IP`) مونتاژ کرده و مستقیما به آی‌پی واقعی سرور می‌فرستد.
* **سرور به کلاینت (Download):** سرور در پاسخ، پکت‌ها را با یک آی‌پی جعلی متفاوت (مانند `Server_Spoof_IP`) به عنوان مبدا ایجاد کرده و به سمت آی‌پی واقعی کلاینت ارسال می‌کند.

نتیجه این کار ایجاد دو جریان ترافیک یک‌طرفه (Unidirectional) در شبکه است. فایروال‌های میانی قادر نخواهند بود این بسته های رفت و برگشتی را با هم مرتبط کنند، که این امر منجر به بای‌پس شدن کامل جداول conntrack و سیستم‌های تشخیص الگو (Fingerprinting) می‌شود.

### ۱.۲ پیاده‌سازی سوکت خام (Raw Socket)
برای تزریق پکت‌ها با هدرهای دلخواه کشف‌نشده در لایه ۳، اسپوف تانل از Raw Socketها (`AF_INET` و `SOCK_RAW`) استفاده می‌کند. تمامی فرآیند ساخت هدرهای IPv4/IPv6 و محاسبه چک‌سام (Checksum) مستقیماً در نرم‌افزار انجام می‌شود.

* کتابخانه‌های `gopacket` و `pcap` برای دور زدن کامل استک شبکه سیستم‌عامل کاربرد وسیعی دارند.
* **فیلترهای قدرتمند BPF:** برای جلوگیری از اینکه سیستم‌عامل میزبان پکت‌های ورودی که آی‌پی آن‌ها با کارت‌شبکه لوکال هم‌خوانی ندارد را دراپ کند (و یا خطای `ICMP Destination Unreachable/TCP RST` ارسال کند)، از فیلترهای قدرتمند Berkeley Packet Filter در سطح کرنل استفاده می‌شود تا پکت‌های متعلق به تونل مستقیما تحویل برنامه شوند و محدودیت‌های مسیریابی محلی دور زده شود.

## ۲. پروتکل‌های انتقال (Transports)

### ۲.۱ حالت ICMP (ترافیک Echo)
تونل قادر است چانک‌های داده رمزنگاری شده را به عنوان Payload درون پکت‌های `ICMP Echo Request (Type 8)` و `ICMP Echo Reply (Type 0)` پنهان کند. در تجهیزات مانیتورینگ شبکه، این ترافیک صرفاً به عنوان یک عملیات پینگ مستمر یا ترافیک عیب‌یابی شبکه تفسیر می‌شود.

### ۲.۲ حالت UDP
ارسال به فرمت دیتانگرام‌های استاندارد UDP انجام می‌گیرد. این حالت می‌تواند از پورت‌های داینامیک مبدا استفاده کند تا ترافیک را شبیه به سرویس‌های UDP معمول (مثل DNS) در اینترنت نشان دهد.

## ۳. لایه تضمین تحویل (Reliability Layer)
بدلیل اینکه متدهای ICMP و UDP هیچگونه ضمانتی برای تحویل، ترتیب یا یکپارچگی داده ندارند، اسپوف تانل یک لایه شبیه به TCP را به صورت سفارشی در Userspace پیاده‌سازی کرده است. این لایه برای جلوگیری از شکسته شدن هندشیک‌های TLS و انتقال استریم دیتا ضروری است.

* **توالی پکت‌ها و تاییدیه (ACK):** کلاینت و سرور داده‌ها را درون بلوک‌های `SeqDataPacket` قرار می‌دهند که دارای یک شماره توالی افزایشی (Sequence Number) ۴ بایتی است. گیرنده نیز دریافت کلاستری از داده‌ها را از طریق `AckPacket`ها و با استفاده از Bitmap های ۶۴ بیتی تایید می‌کند تا در مصرف پهنای باند شبکه صرفه‌جویی شود.
* **کنترل جریان داده (بافرهای Send/Receive):** ماژول `RecvBuffer` تمامی توالی‌ها را در حافظه مدیریت می‌کند. پکت‌های خارج از نوبت (Out-of-Order) موقتاً در بافر نگه داشته می‌شوند تا پکت‌های قبلی دریافت شوند و داده‌ها کاملاً به صورت In-Order به سوکت مقصد (SOCKS5/Target) تحویل داده شوند.
* **موتور ارسال مجدد (Retransmission Engine):** یک Goroutine اختصاصی در پس‌زمینه، هر ۱۰۰ میلی‌ثانیه وضعیت `SendBuffer` را بررسی می‌کند. هر پکتی که زمان `retransmit_timeout` آن منقضی شده باشد با الگوریتم Exponential Backoff مجددا تا سقف `max_retries` بازپخش می‌شود.

## ۴. مالتی‌پلکسینگ (Session Multiplexing)
ایجاد یک تونل کلاینت-سرور کاملا جدید برای هر کانکشن کوچک، تاخیر اولیه شدیدی (INIT Overhead) ایجاد می‌کرد. اسپوف تانل برای رفع این مشکل دارای یک ماژول اکوسیستم داخلی (Multiplexer) است.

در این معماری، فقط یک "Master Session" منفرد روی لینک ناپایدار برقرار می‌ماند. هر کانکشن SOCKS5 اتصال یافته در پورت محلی کلاینت، منحصراً به یک شناسه ۴‌ بایتی مجازی `StreamID` نگاشت شده و تمامی داده‌های آن در قالب همان Master Session منتقل می‌شود.

* کد `0x01 MuxStreamOpen:` به همراه `[StreamID:4][TargetLen:2][آدرس مقصد]`
* کد `0x02 MuxStreamData:` به همراه `[StreamID:4][داده خام]`
* کد `0x03 MuxStreamClose:` به همراه `[StreamID:4]`
* کد `0x04 MuxStreamAck:` پاسخ سرور مبنی بر موفقیت در ریکوئست اتصال TCP به مقصد.

## ۵. رمزنگاری (Cryptography)
امنیت و لاپوشانی اطلاعات منحصرا با الگوریتم قدرتمند **ChaCha20-Poly1305 AEAD** تضمین می‌شود. ویژگی AEAD اطمینان حاصل می‌کند که هیچ حمله‌کننده از نوع MITM نتواند حتی یک بایت از ساختمان دیتای پنهان شده را رمزگشایی کرده یا تغییری در آن ایجاد کند (در غیر اینصورت کانکشن بلافاصله دراپ می‌شود).

مدیریت Nonce‌های تصادفی در ابتدای نشست (Session) مانع از وقوع حملات Replay (بازپخش بسته‌های ضبط شده) می‌گردد، و احراز هویت تونل تنها از طریق کلید استاتیک Base64 مشترک امکان پذیر خواهد بود.

---

## راهنمای استفاده

### ۱. بیلد کردن باینری
اسپوف تانل به زبان Go نوشته شده است و توسط ابزار استاندارد این زبان کامپایل می‌شود:

```bash
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o spoof ./cmd/spoof/
```

### ۲. تولید کلید‌های رمزنگاری
پیش از راه‌اندازی، باید یک جفت کلید خصوصی/عمومی (Private/Public Keys) با فرمت Base64 برای کلاینت و سرور اختصاصیِ خود ایجاد کنید.

```bash
./spoof keygen
```
*کلید Private مشترک خود و Public Key تولید شده را در جای امنی یادداشت کنید.* کلید عمومی سرور (Server Public Key) را باید درون فیلد `peer_public_key` کانفیگ کلاینت، و کلید عمومی کلاینت را درون همان فیلد در کانفیگ سرور قرار دهید.

### ۳. اجرای سرویس
> **نکته بسیار مهم:** گوش دادن روی سوکت‌های خام (Raw Sockets) در لینوکس نیازمند سطح دسترسی سیستمی بالا است. باید باینری‌ها را قطعاً به همراه `sudo` و تحت یوزر Root ران کنید (یا دسترسی `CAP_NET_RAW` به آن بدهید).

**در سمت سرور:**
```bash
sudo ./spoof -c server-config.json
```

**در سمت کلاینت:**
```bash
sudo ./spoof -c client-config.json
```
به محض اتصال موفقیت آمیز، کلاینت یک پروکسی SOCKS5 روی پورت `127.0.0.1:1080` (به صورت پیش‌فرض) باز خواهد کرد که ترافیک آن کاملا امن و از طریق تونل اسپوف شده مسیریابی می‌شود.

---

# تنظیمات کلاینت

| بخش | کلید | نوع | توضیح |
|----|----|----|----|
| 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 کلاینت |
| crypto | peer_public_key | string | کلید عمومی Base64 سرور |
| performance | buffer_size | int | اندازه بافر اصلی پکت |
| performance | mtu | int | حداکثر اندازه payload قبل از encapsulation (مثلاً 1400) |
| performance | session_timeout | int | زمان timeout جلسه اصلی (ثانیه) |
| performance | workers | int | تعداد goroutineهای پردازش پکت |
| performance | read_buffer | int | اندازه بافر خواندن سوکت کرنل |
| performance | write_buffer | int | اندازه بافر نوشتن سوکت کرنل |
| fec | enabled | bool | فعال‌سازی Forward Error Correction (Reed-Solomon) |
| fec | data_shards | int | تعداد شاردهای داده |
| fec | parity_shards | int | تعداد شاردهای parity (قابل بازیابی تا این تعداد پکت از دست رفته) |
| logging | level | string | سطح لاگ ("info"، "debug"، "warn"، "error") |
| logging | file | string | مسیر فایل لاگ (خالی = stdout) |

# تنظیمات سرور

| بخش | کلید | نوع | توضیح |
|----|----|----|----|
| 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 | IP برای گوش دادن تونل (مثلاً 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 واقعی کلاینت (سرور پاسخ‌ها را به این IP می‌فرستد) |
| spoof | client_real_ipv6 | string | نسخه IPv6 از client_real_ip |
| crypto | private_key | string | کلید خصوصی Base64 سرور |
| crypto | peer_public_key | string | کلید عمومی Base64 کلاینت |
| performance | buffer_size | int | اندازه بافر اصلی پکت |
| performance | mtu | int | حداکثر اندازه payload قبل از encapsulation |
| performance | session_timeout | int | زمان timeout جلسه اصلی (ثانیه) |
| performance | workers | int | تعداد worker برای پردازش پکت |
| performance | read_buffer | int | اندازه بافر خواندن سوکت کرنل |
| performance | write_buffer | int | اندازه بافر نوشتن سوکت کرنل |
| reliability | enabled | bool | فعال‌سازی لایه reliability شبیه TCP |
| reliability | window_size | int | حداکثر تعداد پکت‌های تأیید نشده در حال ارسال |
| reliability | retransmit_timeout_ms | int | زمان پایه برای ارسال مجدد پکت (میلی‌ثانیه) |
| reliability | max_retries | int | حداکثر تعداد تلاش مجدد برای هر پکت |
| reliability | ack_interval_ms | int | فاصله زمانی ارسال ACK (میلی‌ثانیه) |
| fec | enabled | bool | فعال‌سازی Forward Error Correction |
| fec | data_shards | int | تعداد شاردهای داده |
| fec | parity_shards | int | تعداد شاردهای parity |
| keepalive | enabled | bool | فعال‌سازی ارسال keepalive |
| keepalive | interval_seconds | int | فاصله ارسال keepalive (ثانیه) |
| keepalive | timeout_seconds | int | زمان قطع جلسه در صورت عدم فعالیت |
| logging | level | string | سطح لاگ ("info"، "debug"، "warn"، "error") |
| logging | file | string | مسیر فایل لاگ (خالی = stdout) |

توسعه داده شده و تست شده در قطعی کامل اینترنت ایران پس از قیام خونین 18 و 19 دی
