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

Bgp4Client

Bgp4Client یک تونل stream در لایه ۴ است. Payloadهای upstream را در فریم‌هایی شبیه BGP قرار می‌دهد و فریم‌های downstream ساخته‌شده توسط Bgp4Server را باز می‌کند.

این نود باید با Bgp4Server استفاده شود:

TcpListener -> Bgp4Client -> ... -> Bgp4Server -> TcpConnector

در استقرار واقعی، ... معمولاً مسیر transport میان دو طرف است؛ مانند TCP، TLS، mux، reverse یا بخشی دیگر از chain در WaterWall.

هشدار

Bgp4Client مسیریابی واقعی BGP، برقراری BGP peering، تبادل route یا احراز هویت BGP را پیاده‌سازی نمی‌کند. شکل فریم شبیه BGP فقط برای استتار و فریم‌بندی stream به کار می‌رود.

این نود چه می‌کند؟

  • هنگام init در جهت upstream، برای هر line یک stream خواندن و state مربوط به اولین فریم را مقداردهی اولیه می‌کند.
  • در اولین payloadِ upstream، یک body ساختگی BGP OPEN را پیش از بایت‌های برنامه prepend می‌کند.
  • payloadهای upstream را در فریم‌های شبیه BGP قرار می‌دهد.
  • یک نوع BGP غیر-OPEN تصادفی برای frameهای payload upstream بعدی انتخاب می‌کند.
  • فریم‌های شبیه BGP در جهت downstream را از یک stream buffer می‌خواند.
  • اطلاعات فریم downstream را حذف و payload بازیابی‌شده را به تونل قبلی می‌فرستد.
  • در صورت دریافت فریم نامعتبر، هر دو جهت را می‌بندد.

Bgp4Client یک تونل stream معمولی است. Socket شبکه یا packet line نمی‌سازد و packet lineای را نیز آزاد نمی‌کند.

نمونه تنظیم

سمت کلاینت:

{
"name": "bgp4-client",
"type": "Bgp4Client",
"settings": {
"password": "compat-value"
},
"next": "transport-out"
}

سمت سرور متناظر:

{
"name": "bgp4-server",
"type": "Bgp4Server",
"settings": {
"password": "compat-value"
},
"next": "target"
}

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

فیلدهای اجباری

فیلدهای سطح اصلی:

فیلدنوعتوضیح
namestringنام یکتای نود در پیکربندی.
typestringباید دقیقاً "Bgp4Client" باشد.
nextstringنود stream بعدی که فریم‌های بسته‌بندی‌شده را می‌گیرد.

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

گزینهنوعپیش‌فرضتوضیح
passwordstring"passwd"فیلد سازگاری. هنگام راه‌اندازی hash می‌شود، اما منطق فعلی فریم‌بندی از این hash استفاده نمی‌کند.

در حال حاضر تنظیم دیگری خوانده نمی‌شود.

فرمت فریم

همه payloadهای upstream با این ساختار بسته‌بندی می‌شوند:

16-byte marker | 2-byte body length | 1-byte BGP type | body

جزئیات فیلد:

فیلدمقدار
markerشانزده بایت با مقدار 0xff.
body lengthیک uint16_t با ترتیب big-endian؛ شامل بایت type به‌علاوه بایت‌های body.
BGP typeمقدار 1 برای نخستین فریم OPEN؛ یکی از مقادیر تصادفی 2 تا 5 برای فریم‌های بعدی payload.
bodypayload تونل‌شده؛ در نخستین فریم upstream شامل body ساختگی OPEN و سپس payload تونل‌شده است.

مقادیر نوع پشتیبانی‌شده:

نوعنام
1OPEN
2UPDATE
3NOTIFICATION
4KEEPALIVE
5ROUTE-REFRESH

طول فریم با طول استاندارد پیام BGP یکسان نیست. قالب قدیمی شبیه BGP در WaterWall، طول را برابر بایت type به‌علاوه بایت‌های body در نظر می‌گیرد و marker شانزده‌بایتی و فیلد طول دوبایتی را حساب نمی‌کند.

اولین Upstream Payload

Bgp4Client هنگام init فریم OPEN مستقلی نمی‌فرستد. در عوض، نخستین payloadِ upstream را با BGP type برابر 1 فریم می‌کند و پیش از بایت‌های برنامه یک body ساختگی OPEN قرار می‌دهد.

فیلدهای synthetic OPEN:

فیلدرفتار
versionهمیشه 4.
AS numberیک uint16_t تصادفی که هنگام ساخت instance تونل تولید می‌شود.
hold time90 ثانیه.
router idمقدار تصادفی تولیدشده در هنگام ساخته شدن tunnel instance.
optional parameter lengthطول تصادفی بین 3 تا 10 بایت.
optional parameter bytesبایت‌های تصادفی در بازه 0 تا 199.

پس از نخستین فریم، open_sent برای line تنظیم می‌شود. Payloadهای بعدی upstream بدون پیشوند ساختگی OPEN بسته‌بندی می‌شوند و یک type تصادفی غیر از OPEN می‌گیرند.

از آنجا که Bgp4Server انتظار دارد داده تونل‌شده برنامه پس از پیشوند OPEN قرار بگیرد، نخستین فریم OPEN باید بعد از body ساختگی OPEN دارای بایت‌های payload باشد.

Downstream Parsing

بایت‌های downstream در یک buffer_stream_t جمع می‌شوند.

Bgp4Client برای هر فریم کامل downstream:

  1. بررسی می‌کند که هر ۱۶ بایت اول 0xff باشند.
  2. فیلد دوبایتی طول body را می‌خواند.
  3. فریم‌هایی را که طول body آن‌ها از فیلد یک‌بایتی type بیشتر نیست رد می‌کند.
  4. تا بافر شدن کل فریم منتظر می‌ماند.
  5. marker، length و type را حذف می‌کند.
  6. فریم‌هایی را که پس از آن payloadی ندارند نمی‌پذیرد.
  7. payload بازیابی‌شده را در جهت downstream به تونل قبلی می‌فرستد.

اگر فریم ناقص باشد، parser منتظر بایت‌های بعدی می‌ماند. اگر حجم داده بافرشده از سقف فعلی بافر بگذرد، line بسته می‌شود.

محدودیت‌ها و Padding

مقدارمقداریادداشت
حداکثر طول body65535 بایتشامل type یک‌بایتی.
حداکثر payload در body عادی65534 بایتمجموع payload و type باید در 65535 بایت جا شود.
حداکثر بایت در بافر خواندنحدود 131106 بایتمعادل دو پیام فریم‌شده با بیشترین اندازه.
required_padding_left39 بایتبرای پیشوند فریم و بزرگ‌ترین پیشوند ساختگی OPEN کافی است.

اگر payloadِ upstream در یک فریم شبیه BGP جا نشود، رد می‌شود و فریمی فرستاده نخواهد شد.

جریان داده

جهت upstream:

previous node -> Bgp4Client wraps -> next node

جهت downstream:

next node -> Bgp4Client unwraps -> previous node

Bgp4Client انتظار دارد در سمت مقابل Bgp4Server قرار گرفته باشد. هر peer ناسازگاری که فریم مورد انتظار را نسازد، خطای پروتکل ایجاد می‌کند.

رفتار Lifecycle

با دریافت init در جهت upstream، Bgp4Client state مربوط به line را مقداردهی اولیه می‌کند و init را در همان جهت به تونل بعدی می‌فرستد.

با دریافت est در جهت downstream، آن را به تونل قبلی می‌فرستد.

Payloadهای upstream را فریم‌بندی و به تونل بعدی می‌فرستد. Payloadهای downstream را بافر و تجزیه می‌کند، فریم را باز می‌کند و داده بازیابی‌شده را به تونل قبلی می‌فرستد.

با دریافت finish از هر جهت، state مربوط به line را از بین می‌برد و finish را در همان جهت منتشر می‌کند: در upstream به تونل بعدی و در downstream به تونل قبلی.

در صورت دریافت فریم نامعتبر، Bgp4Client state محلی را از بین می‌برد و هر دو جهت را با ترتیب لازم برای یک تونل میانی می‌بندد: ابتدا finish در upstream و سپس finish در downstream.

Pause و resume در همان جهت دریافت‌شده عبور داده می‌شوند:

Callbackمقصد ارسال
upstream pause/resumenext tunnel upstream
downstream pause/resumeprevious tunnel downstream

نکته‌ها

  • برای استفاده عملی از Bgp4Client باید آن را با Bgp4Server جفت کنید.
  • در پیاده‌سازی فعلی، password قابلیت امنیتی محسوب نمی‌شود.
  • فیلد طول در قالب شبیه BGP، بایت‌های marker و length را در نظر نمی‌گیرد.
  • اولین OPEN frame فقط وقتی اولین upstream payload برسد فرستاده می‌شود.
  • upstream est و downstream init غیرفعال هستند.
  • این نود یک تونل stream لایه ۴ است، نه packet tunnel.