بخش ۲: مبانی شبکه
اگر این سه موضوع را از هم جدا کنید، پیکربندی 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
مراحل آن چنین است:
TcpListenerاتصال یک Client مبتنی بر TCP را میپذیرد.MuxClientچند اتصال منطقی را روی مسیر انتقال Multiplex میکند.VlessClientPayload را در Framing سمت Client پروتکل VLESS قرار میدهد.TlsClientنتیجه را داخل یک اتصال TLS حمل میکند.TcpConnectorبه Server راه دورِ مشخصشده متصل میشود.
ترافیک برگشتی از همین Nodeها و در جهت مخالف عبور میکند.
هنگام طراحی زنجیره، ابتدا نمودار سادهی پیکانها را بنویسید. سپس هر Node روی نمودار را در فایل پیکربندی به JSON تبدیل کنید.