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

DomainResolver

DomainResolver نودی پیشرفته برای استفاده داخلی است که پیش از عبور دادن Init، نام domain مقصد line را به IP تبدیل می‌کند.

در پیکربندی‌های معمول لازم نیست این نود را دستی اضافه کنید. نودهای سطح بالاتری مانند TcpConnector، UdpConnector، Router، Socks5Client، VlessClient و TrojanClient در صورت نیاز آن را داخل خودشان می‌سازند و تنظیم می‌کنند. ابتدا از تنظیمات عمومی همان نودها استفاده کنید، مگر اینکه عمداً chain سفارشی‌ای می‌سازید که خودش line->routing_context.dest_ctx را مقداردهی می‌کند.

کاری که انجام می‌دهد

DomainResolver فقط context آدرس مقصد را می‌خواند و به‌روزرسانی می‌کند:

line->routing_context.dest_ctx

اگر مقصد از ابتدا IP باشد یا قبلاً resolve شده باشد، Init بی‌درنگ عبور داده می‌شود. اگر مقصد نام domain باشد، درخواست DNS به‌صورت async روی worker فعلی انجام می‌شود؛ سپس strategy انتخاب آدرس اعمال و IP برگزیده در dest_ctx نوشته می‌شود و در پایان Init که منتظر مانده بود عبور می‌کند.

این نود:

  • socket باز نمی‌کند
  • line جدید نمی‌سازد
  • payload را تغییر نمی‌دهد
  • بایتی از پروتکل به بافر اضافه نمی‌کند
  • src_ctx را resolve نمی‌کند
  • نود packet line نیست

جایگاه رایج

استفاده دستی از این نود برای سناریوهای پیشرفته است. آن را پس از نودی قرار دهید که dest_ctx را روی یک domain تنظیم می‌کند و پیش از نودی که به IP واقعی نیاز دارد.

TcpListener -> Socks5Server -> DomainResolver -> TcpConnector

در بیشتر پیکربندی‌های عادی نیازی به این کار نیست، زیرا connector یا نود پروتکل resolver داخلی خود را می‌سازد.

نمونه تنظیمات

{
"name": "resolve-domain",
"type": "DomainResolver",
"settings": {
"strategy": "prefer-ipv4",
"verbose": false
},
"next": "outbound"
}

فیلدها

فیلدنوعاجباریتوضیح
typestringبلهباید DomainResolver باشد.
settingsobjectخیرobject تنظیمات اختیاری؛ اگر نوشته شود باید از نوع object باشد.
nextstringمعمولاًنودی که پس از resolve شدن مقصد، Init را در جهت upstream می‌گیرد.

این نود از نظر فنی می‌تواند Init را از upstream یا downstream بگیرد؛ با این حال در استفاده دستی معمولاً در مسیر upstream و میانه chain از نوع stream قرار می‌گیرد.

تنظیمات

گزینهپیش‌فرضتوضیح
strategyمقدار core در dns.domain-strategyروش انتخاب نتیجه DNS. یکی از core-settings، accept-dns-returned-order، prefer-ipv4، prefer-ipv6، only-ipv4 یا only-ipv6.
verbosefalseآغاز resolve را در لاگ debug ثبت می‌کند. آدرس resolveشده همچنان در logger عادی debug مربوط به DNS ثبت می‌شود.

strategy می‌تواند string یا یکی از مقادیر داخلی مورد قبول parser مشترک domain-strategy باشد.

جریان اجرا

هنگام دریافت Init از upstream:

  1. state مربوط به line آماده می‌شود.
  2. dest_ctx بررسی می‌شود
  3. اگر نیازی به DNS نباشد، Init در جهت upstream به next می‌رود.
  4. اگر DNS لازم باشد، نود وارد state مربوط به resolving می‌شود و callback برمی‌گردد.
  5. پس از پایان DNS، آدرس انتخاب‌شده در dest_ctx نوشته می‌شود.
  6. Init منتظرمانده در جهت upstream عبور داده می‌شود.
  7. payloadهایی که هنگام DNS در صف مانده‌اند، دوباره پخش می‌شوند.

در downstream نیز همین الگو برقرار است، با این تفاوت که Init منتظرمانده به نود قبلی فرستاده می‌شود.

Pending Payload

Payloadهایی که هنگام DNS از سمتی برسند که عملیات را آغاز کرده، در صف قرار می‌گیرند. سقف این صف برای هر line برابر 1 MiB است.

این سقف پس از قرار گرفتن payload در صف بررسی می‌شود؛ بنابراین ممکن است صف به اندازه یک بافر از حد بگذرد و سپس line بسته شود. اگر DNS شکست بخورد یا صف سرریز شود، نود state خود را از بین می‌برد و تنها همان سمتی را finish می‌کند که line حل‌نشده را آغاز کرده بود.

تا پیش از رسیدن به stateِ open، callbackهای غیر از payload نادیده گرفته می‌شوند.

رفتار در خطا

در شرایط زیر line رد می‌شود:

  • مقصد نه آدرس IP باشد و نه domain معتبر.
  • ثبت درخواست async DNS شکست بخورد.
  • DNS برای strategy تنظیم‌شده هیچ آدرس قابل استفاده‌ای برنگرداند
  • صف payloadهای pending از سقف تعیین‌شده بگذرد.

DomainResolver خودش درخواست DNS را دوباره امتحان نمی‌کند. این کار باید در نود سطح بالاتر یا در طراحی transport انجام شود.

مشخصات نود

ویژگیمقدار
مخاطبکاربران پیشرفته و ترکیب داخلی نودها
جایگاهنود پشتیبان در میانه stream
Layer groupAnything to anything
Per-line stateدارد
ایجاد lineخیر
آزاد کردن lineخیر
تغییر payloadخیر
Required left padding0