پرش به مطلب اصلی

بخش ۲: مبانی شبکه

اگر این سه موضوع را از هم جدا کنید، پیکربندی WaterWall ساده‌تر می‌شود:

  • ترافیک از کجا وارد WaterWall می‌شود؟
  • WaterWall چه کاری روی ترافیک انجام می‌دهد؟
  • WaterWall ترافیک را در ادامه به کجا می‌فرستد؟

در بیشتر مثال‌ها از پیکان‌های ساده استفاده می‌کنیم:

TcpListener -> MuxClient -> VlessClient -> TlsClient -> TcpConnector

ترافیک از سمت چپ وارد می‌شود، در جهت upstream از زنجیره می‌گذرد و پاسخ‌ها در جهت مخالف و به‌صورت downstream بازمی‌گردند.

آدرس‌های IP

آدرس IP یک Host یا Interface را در شبکه مشخص می‌کند.

چند نمونه‌ی متداول:

127.0.0.1       local machine only
0.0.0.0 bind on all IPv4 interfaces
192.168.1.10 private LAN address
203.0.113.10 public IPv4 documentation address
::1 IPv6 loopback
:: bind on all IPv6 interfaces

در Nodeهای Listener، گزینه‌ی address معمولاً همان آدرس محلی است که Node باید روی آن Bind شود.

در Nodeهای Connector، گزینه‌ی address معمولاً مقصدی راه دور است که Node باید به آن متصل شود.

پورت‌ها

پورت، یک سرویس را روی آدرس IP مشخص می‌کند. برای مثال:

22    SSH
53 DNS
80 HTTP
443 HTTPS
8080 common test HTTP port

معمولاً فقط یک پردازش می‌تواند هم‌زمان روی ترکیب یکسان آدرس، پروتکل و پورت گوش دهد. اگر WaterWall نتواند یک Listener را Bind کند، ممکن است پردازش دیگری از قبل آن پورت را در اختیار داشته باشد.

در Linux، Socketهای TCP در حال Listen را با دستور زیر بررسی کنید:

ss -ltnp

برای UDP:

ss -lunp

TCP

TCP یک پروتکل Connection-oriented است و میان دو Endpoint یک Stream می‌سازد.

در WaterWall، ترافیک TCP معمولاً با TcpListener آغاز می‌شود و به TcpConnector می‌رسد:

client -> TcpListener -> ... -> TcpConnector -> remote server

TcpListener اتصال‌های TCP ورودی را می‌پذیرد و به‌ازای هر اتصال پذیرفته‌شده یک Line در WaterWall می‌سازد. TcpConnector در سوی دیگر زنجیره، اتصال TCP خروجی را باز می‌کند.

برای پروتکل‌هایی مانند HTTP، HTTPS، SSH، SOCKS و بیشتر ترافیک تونل‌های Proxy-style از TCP استفاده کنید.

UDP

UDP یک پروتکل Message-oriented است و به‌جای Stream پیوسته، Datagram می‌فرستد.

WaterWall برای هر دو حالت Stateful و Stateless، Nodeهای UDP دارد:

UdpListener -> ... -> UdpConnector
UdpStatelessSocket -> packet-oriented chain

UDP معمولاً برای DNS، QUIC، WireGuard، ترافیک بازی‌ها و رسانه‌های Real-time به کار می‌رود. از آنجا که UDP به‌تنهایی Stream نمی‌سازد، Nodeهای پیرامون آن در WaterWall باید نحوه‌ی تشخیص Peer و مسیریابی Packetها را تعیین کنند.

Localhost، آدرس خصوصی و آدرس عمومی

آدرس 127.0.0.1 فقط اتصال‌های همان دستگاه را می‌پذیرد و برای آزمایش محلی مناسب است.

آدرس‌های خصوصی مانند 10.0.0.0/8، 172.16.0.0/12 و 192.168.0.0/16 در شبکه‌های خصوصی استفاده می‌شوند و مستقیماً از اینترنت عمومی در دسترس نیستند.

آدرس عمومی VPS زمانی از اینترنت در دسترس است که هم Firewall شرکت ارائه‌دهنده و هم Firewall سرور، پورت موردنظر را مجاز بدانند.

برای یک Listener عمومی WaterWall روی VPS، معمولاً از آدرس Bind زیر استفاده می‌شود:

{
"address": "0.0.0.0",
"port": 443
}

برای Listener آزمایشی که فقط باید محلی باشد:

{
"address": "127.0.0.1",
"port": 8080
}

DNS و نام دامنه

Nodeهای Connector می‌توانند از نام دامنه استفاده کنند:

{
"address": "example.com",
"port": 443
}

WaterWall دامنه را با DNS Resolver مشترک خود Resolve می‌کند. سیاست پیش‌فرض انتخاب آدرس در dns.domain-strategy فایل core.json تنظیم می‌شود.

اگر دامنه هم رکورد IPv4 و هم IPv6 داشته باشد، domain-strategy مشخص می‌کند WaterWall کدام‌یک را در اولویت قرار دهد.

NAT و Port Forwarding

بسیاری از دستگاه‌ها پشت NAT قرار دارند. یک دستگاه با آدرس خصوصی معمولاً می‌تواند به بیرون متصل شود، اما Clientهای بیرونی نمی‌توانند به آن اتصال ورودی برقرار کنند؛ مگر اینکه Router یا Cloud Firewall پورت را Forward کند.

یک TCP Forward ساده چنین مسیری دارد:

client -> VPS:8080 -> WaterWall -> example.com:80

زنجیره‌ی WaterWall:

TcpListener(0.0.0.0:8080) -> TcpConnector(example.com:80)

این زنجیره Streamهای TCP را Forward می‌کند، اما Header مربوط به Host در HTTP را خودکار تغییر نمی‌دهد و باعث نمی‌شود Server مقصد تصور کند Client مستقیماً به آن متصل شده است.

Streamها و Packetها

WaterWall از ترافیک مبتنی بر Stream و Packet پشتیبانی می‌کند.

ترافیک Stream-style مانند یک جریان پیوسته از Byteها رفتار می‌کند:

TcpListener -> EncryptionClient -> TcpConnector

ترافیک Packet-style شامل IP Packetها یا Datagramهای شبیه Packet است:

TunDevice -> WireGuardDevice -> UdpStatelessSocket

برخی Nodeها میان این دو مدل پل می‌زنند. برای مثال، PacketsToStream، Packetها را در قالب یک Stream بسته‌بندی می‌کند و StreamToPackets در سوی دیگر همان Stream را دوباره به Packet تبدیل می‌کند.

با زنجیره‌های Packet دقیقاً مانند زنجیره‌های TCP رفتار نکنید. یک زنجیره‌ی Packet ممکن است از Packet Lineهای سطح Worker استفاده کند که در طول پردازش تعداد زیادی Packet نامرتبط زنده می‌مانند.

خواندن پیکان‌های زنجیره

زنجیره‌ی زیر را در نظر بگیرید:

TcpListener -> MuxClient -> VlessClient -> TlsClient -> TcpConnector

مراحل آن چنین است:

  1. TcpListener اتصال یک Client مبتنی بر TCP را می‌پذیرد.
  2. MuxClient چند اتصال منطقی را روی مسیر انتقال Multiplex می‌کند.
  3. VlessClient Payload را در Framing سمت Client پروتکل VLESS قرار می‌دهد.
  4. TlsClient نتیجه را داخل یک اتصال TLS حمل می‌کند.
  5. TcpConnector به Server راه دورِ مشخص‌شده متصل می‌شود.

ترافیک برگشتی از همین Nodeها و در جهت مخالف عبور می‌کند.

هنگام طراحی زنجیره، ابتدا نمودار ساده‌ی پیکان‌ها را بنویسید. سپس هر Node روی نمودار را در فایل پیکربندی به JSON تبدیل کنید.