این پروژه پنل رسمی 3X-UI (پنل مدیریت Xray-core) رو داخل یک کانتینر روی Orbit، پلتفرم دیپلوی Flux، اجرا میکنه.
Flux/Orbit بهصورت پیشفرض فقط یک پورت عمومی با TLS رو از یک کانتینر به بیرون باز میکنه (همون "App Port"). چون پنل مدیریت، اینباند(های) پروکسی Xray، و سرور Subscription پنل هر سه باید از بیرون در دسترس باشن، این پروژه یه ریورسپروکسی کوچیک به زبان Go جلوی همهشون اجرا میکنه که همهچی رو روی همون یک پورت عمومی، با روتینگ بر اساس مسیر (Path) درخواست HTTP، مالتیپلکس (تفکیک) میکنه.
-
موقع اولین اجرا،
main.goباینری رسمی و ازپیشبیلدشدهی 3X-UI (x-ui-linux-amd64.tar.gz) رو دانلود میکنه، بهجای اینکه خودِ 3X-UI رو از سورس کامپایل کنه (چون این محیط نمیتونه فرانتاند Vue پروژه رو بیلد کنه که یه مرحلهیnpm run buildقبل ازgo buildلازم داره). -
باینری واقعی
x-uiرو روی یک پورت فقط-داخلی (از طریق env varXUI_PORT) بالا میاره — پورتی که مستقیماً از اینترنت در دسترس نیست. -
سرور HTTP سبک خودش رو روی پورت عمومی بالا میاره. این سرور مسیر (Path) درخواست ورودی رو چک میکنه و اونو (reverse proxy) به سرویس داخلی درست هدایت میکنه:
پیشوند مسیر (Path) به کجا فوروارد میشه (پورت داخلی) کاربرد /xvpnws/اینباند VLESS+WebSocket ایکسری ترافیک پروکسی /sub/سرور Subscription پنل لینکهای Subscription (هر چیز دیگه) پنل مدیریت 3X-UI پنل وب ادمین
چون net/http/httputil.ReverseProxy توی Go بهصورت بومی از هدر
Upgrade: websocket پشتیبانی میکنه (بعد از تکمیل هندشیک ۱۰۱، خودِ کانکشن رو
Hijack و بایتها رو دوطرفه رد و بدل میکنه)، این روش بهصورت شفاف از ترابرهای
مبتنی بر WebSocket ایکسری هم پشتیبانی میکنه، بدون نیاز به کد اضافه.
- مقدار App Port باید دقیقاً با
publicPortتویmain.goیکی باشه (الان:2053). - کانتینر باید به
github.comدسترسی خروجی داشته باشه تا موقع اولین اجرا بتونه ریلیز 3X-UI رو دانلود کنه.
برای هر اینباندی که میسازی، فیلد Port باید دقیقاً با یکی از پورتهای
داخلی تعریفشده توی main.go یکی باشه، و Path (زیر تنظیمات Stream) باید
دقیقاً همون پیشوند رو داشته باشه (با اسلش اول و آخر). Security روی هر
اینباند باید none باشه، چون TLS از قبل توسط edge خودِ Flux باز شده و به این
کانتینر نمیرسه.
برای سرویس Subscription، فیلد Settings → Subscription → Reverse Proxy
URI رو روی https://<دامنهی-تو>.app.runonflux.io/sub/ بذار تا لینکهای
Subscription که پنل میسازه، به مسیر عمومی اشاره کنن، نه به پورت فقط-داخلی.
برای باز کردن یک اینباند دیگهی ایکسری روی همون پورت عمومی:
- یه پورت داخلی خالی و یه پیشوند مسیر یکتا انتخاب کن.
- هر دو رو به slice به اسم
routesتویmain.goاضافه کن. - Commit و Push کن، بعد توی Orbit دکمهی Pull & Build رو بزن (نه فقط Redeploy — چون باینری Go باید دوباره کامپایل بشه).
- توی پنل، یک اینباند جدید با دقیقاً همون پورت و همون مسیر بساز.
- فقط ترابرهای مبتنی بر HTTP (WebSocket، و تئوریاً XHTTP) رو میشه با این روش مالتیپلکس کرد، چون روتینگ بر اساس بررسی مسیر (Path) درخواست HTTP انجام میشه.
- اینباندهای TCP خام و REALITY با این معماری روی پورت عمومی اصلی سازگار
نیستن، چون TLS از قبل توسط edge خودِ Flux قبل از رسیدن درخواست سادهی
HTTP به این پروکسی باز شده — REALITY به ClientHello اصلی و دستنخوردهی
TLS نیاز داره، و TCP خام هم اصلاً مسیر HTTPای برای روتینگ نداره. اگه
دیپلویت یک پورت خام دوم هم باز کرده باشه (توی تب Specifications داخل
FluxCloud، بخش
Container Portsرو چک کن)، میشه یک اینباند TCP خام یا REALITY رو مستقیماً به همون پورت وصل کرد و کاملاً از این پروکسی رد نشد.
این یک دیپلوی شخصی برای استفادهی خودمیزبانیه. اطلاعات ورود پنل، UUID کلاینتها، و لینکهای Subscription رو خصوصی نگه دار.