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

TunDevice

TunDevice یک packet chain در WaterWall را به TUN interface سیستم‌عامل وصل می‌کند. packetهای لایه ۳ را از device مجازی می‌خواند و وارد chain می‌کند؛ packetهایی را هم که از chain برمی‌گردند در همان TUN device می‌نویسد.

این نود adapter لایه ۳ است، نه یک tunnel اتصال‌محور. برای هر connection line جداگانه‌ای نمی‌سازد؛ packetهای زمان اجرا از packet lineهایی استفاده می‌کنند که chain برای هر worker ساخته است.

جایگاه رایج

TunDevice می‌تواند در ابتدا یا انتهای packet chain قرار بگیرد:

TunDevice -> IpManipulator -> RawSocket
TunDevice -> WireGuardDevice -> UdpStatelessSocket
TunDevice -> PacketsToStream -> TcpConnector
TcpListener -> StreamToPackets -> TunDevice

اگر TunDevice در انتهای chain نباشد، packetهای خوانده‌شده از سیستم‌عامل در جهت upstream به نود بعدی می‌روند. اگر نود در انتهای chain باشد، همان packetها در جهت downstream به نود قبلی داده می‌شوند.

هر payloadی که از chain به TunDevice برسد، یک IP packet در نظر گرفته می‌شود و در TUN interface نوشته خواهد شد.

نمونه تنظیم

{
"name": "tun0-adapter",
"type": "TunDevice",
"settings": {
"device-name": "wtun0",
"device-ip": "10.10.0.1/24",
"device-mtu": 1500
},
"next": "next-node"
}

نمونه full-route با خارج کردن شبکه‌های داخلی:

{
"name": "tun0-adapter",
"type": "TunDevice",
"settings": {
"device-name": "wtun0",
"device-ip": "10.10.0.1/24",
"device-mtu": 1500,
"route-table": "main",
"route-exclude-cidrs": [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
],
"dns": ["1.1.1.1", "8.8.8.8"]
},
"next": "next-node"
}

تنظیمات ضروری

فیلدنوعتوضیح
device-namestringنام TUN interface. این نام باید با interfaceهای دیگر سیستم‌عامل یا nodeهای دیگر واتروال تداخل نداشته باشد.
device-ipstringآدرس device به شکل CIDR، مثل 10.10.0.1/24. واتروال آن را به IP و subnet mask جدا می‌کند.

object مربوط به settings الزامی است و نباید خالی باشد.

تنظیمات اختیاری

گزینهپیش‌فرضتوضیح
device-mtuMTU سراسری واتروالمقدار MTU برای TUN device. باید بین 1 و 65535 باشد.
route-tableoffنصب routeهای native سیستم‌عامل را کنترل می‌کند. مقدارهای off، main، auto یا table name/number لینوکس.
system-routefalseمیان‌بری برای full-device routing. اگر true باشد و route-table را ننویسید، مانند route-table: "main" عمل می‌کند.
route-cidrsfull route بر اساس family آدرس deviceCIDRهایی که وقتی routing فعال است باید از TUN عبور کنند.
route-exclude-cidrsنداردCIDRهایی که از route-cidrs کم می‌شوند؛ مناسب LAN، شبکه مدیریت و endpointهای upstream.
dnsتنظیم نشدهیک یا دو DNS server از نوع IPv4 برای TUN interface.
loop-protectionوقتی system routing فعال است، فعال می‌شودنمی‌گذارد socketهای outbound خود WaterWall دوباره از TUN عبور کنند.
post-up-scriptنداردcommandی که پس از بالا آمدن interface، نصب routeها و تنظیم DNS اجرا می‌شود.
pre-down-scriptنداردcommandی که پیش از پاک شدن DNS و routeها و پایین آوردن interface اجرا می‌شود.

معنی آدرس TUN

اگر این مقدار را تنظیم کنید:

10.10.0.1/24

آدرس 10.10.0.1 متعلق به interface خود سیستم‌عامل است. ارسال packet یا ping به همین آدرس معمولاً مانند دسترسی به یک آدرس local رفتار می‌کند و مسیر مورد انتظار در WaterWall را درگیر نمی‌کند.

برای فرستادن packet به WaterWall، معمولاً باید آدرس دیگری از همان range را هدف بگیرید:

10.10.0.2

در این حالت packet وارد TUN می‌شود و WaterWall آن را می‌بیند؛ برای مثال source می‌تواند 10.10.0.1 و destination برابر 10.10.0.2 باشد. پس از TunDevice نیز می‌توانید با نودهایی مانند IpOverrider یا IpManipulator آدرس‌ها و headerهای packet را تغییر دهید.

تنظیم route

نصب route در سیستم‌عامل به‌طور پیش‌فرض غیرفعال است. برای فعال کردن آن یکی از این دو روش را به کار ببرید:

"route-table": "main"

یا:

"system-route": true

مقدارهای route-table:

مقداررفتار
offهیچ routeای نصب نمی‌شود.
mainrouteها در جدول اصلی سیستم نصب می‌شوند.
autoدر پلتفرم‌های پشتیبانی‌شده مثل main-table routing رفتار می‌کند.
نام یا شماره table در Linuxrouteها در همان جدول لینوکس نصب می‌شوند.

در Windows و macOS، مقدارهای غیر از main یا auto رد می‌شوند.

اگر routing فعال باشد و route-cidrs را ننویسید، WaterWall بر اساس family مربوط به device-ip یک full route می‌سازد. default route مانند 0.0.0.0/0 به دو route از نوع /1 تقسیم می‌شود تا default route فعلی سیستم مستقیماً جایگزین نشود.

با route-exclude-cidrs می‌توانید شبکه‌هایی را از routeها کم کنید:

{
"route-table": "main",
"route-cidrs": ["0.0.0.0/0"],
"route-exclude-cidrs": [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
]
}

شبکه داخلی، مسیر مدیریت server و endpoint اصلی upstream را حتماً از routeهای TUN مستثنا کنید.

Loop Protection

با فعال شدن system route یا full route روی TUN، ممکن است سیستم‌عامل socketهای outbound خود WaterWall را هم دوباره به TUN بفرستد. نتیجه یک self-loop است: WaterWall packet را می‌فرستد، سیستم‌عامل آن را به TUN برمی‌گرداند و WaterWall همان packet را دوباره می‌خواند.

وقتی system routing فعال باشد، loop-protection نیز به‌طور پیش‌فرض روشن است. نود پیش از نصب routeهای TUN، interface فیزیکی پیش‌فرض را پیدا می‌کند و آن را به‌عنوان egress pin سراسری process منتشر می‌سازد. adapterهایی مانند TcpConnector، UdpConnector و UdpStatelessSocket از این pin استفاده می‌کنند، مگر اینکه interface خودشان صریحاً تنظیم شده باشد.

پلتفرمرفتار
Linuxاز interface پیش‌فرض detect شده برای bind کردن socket استفاده می‌شود.
Windowsاز index interface تشخیص‌داده‌شده برای مسیر outbound socket استفاده می‌شود.
macOSegress pin خودکار فعلاً وجود ندارد؛ از interface صریح در connectorها یا route exclusion استفاده کنید.

تنظیم صریح interface در adapter بر pin خودکار اولویت دارد؛ source-ip به‌تنهایی این pin را کنار نمی‌زند. اگر IP مبدأ انتخاب‌شده روی interface فیزیکی دیگری غیر از مسیر پیش‌فرض تشخیص‌داده‌شده قرار دارد، interface را در connector صریحاً تنظیم کنید.

socketهای DNS resolver در c-ares با این قابلیت pin نمی‌شوند. اگر مسیر فیزیکی پیش‌فرض host پس از startup تغییر کرد، WaterWall را restart کنید یا interfaceها و routeها را صریح تنظیم کنید.

تنظیم DNS

dns یک یا دو IPv4 address می‌پذیرد:

"dns": ["1.1.1.1", "8.8.8.8"]

آدرس IPv6، hostname، string خالی یا بیش از دو server هنگام ساخت نود پذیرفته نمی‌شود. مقدار null نیز مانند تنظیم نکردن گزینه است.

پلتفرمرفتار
Linuxبا resolvectl dns و domain مسیر ~. تنظیم می‌شود. نیازمند systemd-resolved و resolvectl است.
Windowsبا netsh روی Wintun adapter، static IPv4 DNS تنظیم می‌شود. precedence همچنان تابع metricهای Windows است.
macOSگزینه dns در زمان ساخت node رد می‌شود؛ از post-up-script و pre-down-script استفاده کنید.

مسیر packet

هنگام راه‌اندازی، TunDevice:

  1. مشخص می‌کند packetهای خوانده‌شده باید به next بروند یا prev
  2. TUN interface را می‌سازد
  3. device-ip را روی آن قرار می‌دهد
  4. interface را بالا می‌آورد
  5. routeها را در صورت فعال بودن نصب می‌کند
  6. DNS را در صورت تنظیم بودن اعمال می‌کند
  7. post-up-script را در صورت وجود اجرا می‌کند

وقتی device سیستم‌عامل packet تولید کند:

  1. packet روی یک worker دریافت می‌شود
  2. اگر device پایین باشد یا برنامه در حال پایان یافتن باشد، packet دور ریخته می‌شود
  3. نسخه IP بررسی می‌شود
  4. packetهای IPv4 با worker packet line جلو فرستاده می‌شوند
  5. packetهای غیر IPv4 در مسیر دریافت فعلی دور ریخته می‌شوند

وقتی payload از chain به TunDevice برسد:

  1. payload به‌عنوان IP packet در نظر گرفته می‌شود
  2. اگر packet line درخواست کرده باشد، checksum دوباره محاسبه می‌شود
  3. packet داخل TUN device نوشته می‌شود
  4. اگر device پایین باشد یا write ناموفق شود، buffer بازیافت و warning در log ثبت می‌شود

Packet Line

TunDevice از packet line هر worker استفاده می‌کند، نه line معمولی per-connection. packet lineها نباید در زمان اجرای عادی از بین بروند.

در buildهای debug، نود پس از فرستادن packet ورودی بررسی می‌کند که packet line هنوز زنده باشد. اگر tunnel دیگری آن را در زمان اجرا از بین برده باشد، WaterWall این اتفاق را نقض قرارداد packet tunnel می‌داند.

callbackهای اتصال‌محور مثل Init، Est، Finish، Pause و Resume برای این adapter نادیده گرفته می‌شوند. مسیر مهم runtime همان payload است.

Checksum

بعضی packet tunnelها می‌توانند روی line علامت بگذارند که checksum باید دوباره محاسبه شود. وقتی TunDevice می‌خواهد packet را به سیستم‌عامل بنویسد و recalculate_checksum فعال باشد، checksum packet را محاسبه می‌کند و flag را پاک می‌کند.

برای IPv4 fragmentها، helper مربوطه transport checksum را که از یک fragment کامل قابل محاسبه نیست با احتیاط مدیریت می‌کند و فقط بخش‌هایی را اصلاح می‌کند که از داده موجود قابل اصلاح باشند.

نکته‌های MTU

اگر device-mtu را تنظیم نکنید، MTU سراسری WaterWall به کار می‌رود.

کم کردن MTU زمانی مفید است که nodeهای بعدی overhead اضافه می‌کنند. اما اگر کنار adapterهایی مثل RawSocket کار می‌کنید که با interface فیزیکی مستقیم سروکار دارند، MTU را با path واقعی هماهنگ نگه دارید؛ در غیر این صورت سیستم‌عامل ممکن است packetها را رد کند.

Shutdown

هنگام stop یا destroy، cleanup با ترتیب معکوس انجام می‌شود:

  1. pre-down-script را قبل از down کردن device اجرا می‌کند
  2. egress pin مربوط به loop protection را پاک می‌کند
  3. DNS را پاک می‌کند
  4. routeهای نصب‌شده را به ترتیب معکوس حذف می‌کند
  5. TUN device را پایین می‌آورد و از بین می‌برد

اگر پاک‌سازی route یا DNS ناموفق باشد، warning در log ثبت می‌شود.

مشخصات Node

ویژگیمقدار
LayerLayer 3
جایگاه chainمی‌تواند chain head یا chain end باشد
nextاختیاری، ولی در استفاده معمول وقتی انتهای chain نیست وجود دارد
prevمجاز
Required left padding0
Line statestate حداقلی؛ packet runtime از worker packet line استفاده می‌کند

خطاهای رایج

  • ping کردن خود آدرس TUN و انتظار اینکه packet وارد واتروال شود. یک آدرس دیگر در range route شده را هدف بگیرید.
  • فعال کردن full routing بدون exclude کردن endpoint سرور upstream، یا تکیه بر loop protection در پلتفرم یا topologyای که این قابلیت پوشش نمی‌دهد.
  • استفاده از dns روی macOS. برای آن از script استفاده کنید.
  • انتظار forward شدن packetهای غیر IPv4 از مسیر receive فعلی.
  • رفتار دادن به TunDevice مثل TCP/UDP adapter اتصال‌محور. این نود raw IP packet را از packet line عبور می‌دهد.
  • فراموش کردن نیاز به دسترسی administrator برای مدیریت TUN روی Windows.