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

VmessServer

VmessServer درخواست‌های VMess AEAD را دریافت می‌کند، حساب کاربر را با UUID احراز هویت می‌کند و ترافیک TCP، UDP با مقصد ثابت یا packetaddr را پس از رمزگشایی به next می‌فرستد. این node مستقل از transport است. برای TLS یا WebSocket، nodeهای TlsServer یا HttpServer را پیش از آن قرار دهید.

احراز هویت​

یکی از دو روش را انتخاب کنید:

  • کاربران محلی: از uuid/id/user-id، آرایه uuids یا users/clients استفاده کنید. هر شیء کاربر یک uuid یا id/user-id و در صورت نیاز username دارد. این روش به پایگاه AuthenticationClient نیاز ندارد.
  • کاربران مدیریت‌شده: auth-client-node-name را تنظیم و تمام اعتبارنامه‌های محلی را حذف کنید. UUID کاربر در فیلد password حساب AuthenticationServer قرار می‌گیرد. این node از جدول همگام‌شده حافظه AuthenticationClient استفاده می‌کند و یک UserController داخلی پیش از outbound می‌گذارد؛ روی همین مسیر یک UserController دیگر به‌صورت دستی اضافه نکنید.

اعتبارنامه محلی UUID هگز دقیق با خط تیره یا فشرده، یا رشته UTF-8 غیرخالی با طول ۱ تا ۳۰ بایت است. شناسه کوتاه مانند Xray با UUIDv5 و namespace صفر نگاشت می‌شود: waterwall برابر 106b9dde-356b-5769-b2f6-7ea4193ec5f7 است. رشته trim، case-fold یا Unicode-normalize نمی‌شود. UUIDهای یکسان پس از نگاشت حساب تکراری‌اند و startup رد می‌شود. در روش مدیریت‌شده، password باید UUID canonical حاصل را داشته باشد؛ نمایه‌های مشترک AuthenticationClient برای VMess نام کوتاه را به‌طور خصوصی تبدیل نمی‌کنند.

روش مدیریت‌شده از پذیرش حساب، ثبت مصرف، محدودیت اتصال و IP، سهمیه و shaping تنظیم‌شده کاربر استفاده می‌کند. پس از اولین همگام‌سازی معتبر، قطع معمول شبکه کنترل باعث استفاده از آخرین جدول پذیرفته‌شده می‌شود. نبود جدول اولیه یا رد صریح اعتبارنامه AuthenticationClient پذیرش جدید را می‌بندد. تغییرات مدیر پس از refresh معتبر اعمال می‌شوند. محدودیت cache محلی تضمین reservation سراسری بین چند AuthenticationClient قطع‌شده نیست.

VMess به‌جای UUID آشکار، AuthID رمز‌شده می‌فرستد. شناسایی AuthID تازه در بدترین حالت به جستجوی O(N) بین N کلید نامزدِ دارای UUID نیاز دارد. کلید فرمان و کلید AuthID از پیش محاسبه می‌شوند و جدول آن‌ها بین workerهای همین node مشترک است. حساب‌های دارای UUID پیش از بررسی شرایط پذیرش در فهرست نامزدها قرار می‌گیرند؛ تطبیق کلید به‌تنهایی مجوز پذیرش حساب غیرفعال نیست. پس از تطبیق رمزنگاری، در روش مدیریت‌شده هویت فعلی حساب و شرایط پذیرش آن با lookup نمایه‌دار AuthenticationClient دوباره بررسی می‌شود.

کار احراز هویت در نوبت‌های محدود event loop انجام می‌شود و کارهای منتظر و cache اعتبارنامه بودجه محدود دارند. کلید cache‌شده مجوز حساب حذف‌شده یا جایگزین‌شده نیست. این محدودیت‌ها برای کار و حافظه‌اند و نرخ انتقال داده برنامه را محدود نمی‌کنند.

پشتیبانی پروتکل​

security بدنه در کلاینتTCPUDP
aes-128-gcmپشتیبانی می‌شودپشتیبانی می‌شود
chacha20-poly1305پشتیبانی می‌شودپشتیبانی می‌شود
none با chunk framingپشتیبانی می‌شودپشتیبانی می‌شود
zero یا none بدون framingپشتیبانی می‌شودرد می‌شود

در همه حالت‌ها، header درخواست و پاسخ AEAD است و alterId باید صفر باشد. حالت‌های none و zero بدنه برنامه را رمز یا احراز اصالت نمی‌کنند؛ اگر محرمانگی بدنه لازم است، transport محافظ مناسب را جداگانه انتخاب کنید. zero تنظیم کلاینت است و روی wire به none بدون chunk تبدیل می‌شود؛ stream بدون framing مرز datagramهای UDP را نگه نمی‌دارد.

در درخواست عادی، IPv4، IPv6 و دامنه غیرخالی پذیرفته می‌شود. UDP عادی یک backend برای مقصد ثابت دارد؛ رکورد خالی پایان پروتکل است و پاسخ UDP محلی خالی کنار گذاشته می‌شود. packetaddr فقط marker دقیق sp.packet-addr.v2fly.arpa را با فرمان UDP و پورت بیرونی صفر پس از احراز هویت می‌پذیرد؛ marker هرگز به DNS یا connector فرستاده نمی‌شود. هر رکورد یک envelope آدرس IP و پورت (۷ بایت IPv4، ۱۹ بایت IPv6) و یک datagram دارد. دامنه و پورت مقصد صفر در envelope رد می‌شوند. envelope بدون payload یک datagram خالی واقعی است.

هر مقصد یک backend متعلق به همین node و روی همان worker دارد. سقف آن با packetaddr-max-destinations محدود می‌شود؛ در ظرفیت کامل فقط datagram مقصد تازه drop می‌شود و مقصدهای موجود ادامه می‌دهند. Finish هر backend ورودی دقیق آن را حذف می‌کند و ورودی بعدی می‌تواند آن را دوباره بسازد. بستن carrier و shutdown همه backendهای owned را drain می‌کند. پاسخ صف‌شده بایت‌های مستقل و مقصد مبدأ immutable خود را دارد. ترافیک رمزگشایی‌شده در روش مدیریت‌شده دقیقاً یک بار از UserController می‌گذرد.

سقف payload بدنه ۶۵۵۳۵ بایت، به‌علاوه ۱۶ بایت برای authenticated-length، منهای tag رمزنگاری ۱۶ بایتی و در صورت فعال بودن global padding منهای allowance برابر ۶۳ بایت است. packetaddr دوباره اندازه دقیق envelope یعنی ۷ یا ۱۹ بایت را کم می‌کند. datagram شکسته نمی‌شود؛ پاسخ بزرگ‌تر drop می‌شود. این حدود سقف UDP/IP زیرین را افزایش نمی‌دهد.

هر جهت رمز‌شده شمارنده ۱۶ بیتی از صفر دارد. پیش‌فرض encrypted-counter-policy: "wrap" همه ordinalهای 0..65535 را برای داده می‌پذیرد و سپس بدون reset کلید، IV یا SHAKE از صفر ادامه می‌دهد. wrap باعث تکرار nonce AEAD با همان کلید session می‌شود؛ rekey نیست و یکتایی nonce را حفظ نمی‌کند. این انتخاب با ادامه اتصال در پیاده‌سازی‌های رایج سازگار است. در strict داده خروجی فقط 0..65534 را مصرف می‌کند و 65535 برای EOF رزرو است؛ داده ورودی معتبر در 65535 تحویل می‌شود و سپس اتصال پیش از استفاده مجدد بسته می‌شود. بدنه و طول احراز‌شده ordinal یکسان دارند. NONE/zero این محدودیت رمز‌شده را ندارند.

send-termination: false رکورد خالی خروجی اختیاری را حذف و مسیر full-close موجود را استفاده می‌کند. EOF معتبر ورودی همواره پذیرفته می‌شود و EOF رمز‌شده ابتدا احراز می‌شود. Finish در حالت idle درخواستی نمی‌سازد؛ zero خام EOF framed ندارد. سیاست شمارنده، allow-list و termination محلی‌اند و بیت negotiation تازه‌ای ندارند؛ endpoint strict ممکن است peer دارای wrap را در سقف خودش ببندد.

allowed-security حالت واقعی بدنه را پس از parse احراز‌شده و پیش از Init محافظت‌شده یا ساخت backend بررسی می‌کند. حالت ردشده به fallback نمی‌رود. auto انتخاب محلی کلاینت است و حالت wire در این فهرست نیست. برای پرهیز از رمزنگاری دوباره، اپراتور برای TCP داخل TLS خودش zero و برای UDP داخل TLS خودش none دارای framing را انتخاب می‌کند؛ VMess TLS را تشخیص نمی‌دهد و خودکار security را تغییر نمی‌دهد.

header قدیمی VMess و alter ID، AES-CFB، Mux.Cool، XUDP و فرمان reverse پشتیبانی نمی‌شوند. AES-CTR نیز خارج از پشتیبانی است. framing سفارشی WaterWall Mux با Mux.Cool سازگار نیست و interoperability چندجریانی VMess خارجی را فراهم نمی‌کند. TLS، WebSocket و HTTP مسئولیت nodeهای خودشان هستند؛ VmessServer تنظیمات یا تشخیص داخلی این transportها ندارد. این node splice را برای chain غیرفعال می‌کند، چون parser و رمزنگاری به buffer عادی حافظه نیاز دارند.

چیدمان و مثال​

TcpListener -> VmessServer -> TcpUdpConnector
TcpListener -> TlsServer -> VmessServer -> TcpUdpConnector
TcpListener -> HttpServer (WebSocket) -> VmessServer -> TcpUdpConnector
TcpListener -> TlsServer -> HttpServer (WebSocket) -> VmessServer -> TcpUdpConnector

کاربر محلی:

{
"name": "vmess",
"type": "VmessServer",
"settings": {
"users": [
{"username": "alice", "uuid": "5783a3e7-e373-51cd-8642-c83782b807c5"}
],
"connect": true,
"udp": true
},
"next": "outbound"
}

کاربر مدیریت‌شده:

{
"name": "vmess",
"type": "VmessServer",
"settings": {"auth-client-node-name": "auth-client"},
"next": "outbound"
}

connector خروجی معمولاً "address": "dest_context->address" و "port": "dest_context->port" دارد. برای TCP از TcpConnector، برای UDP از UdpConnector و برای هر دو از TcpUdpConnector استفاده کنید.

تنظیمات​

تنظیمپیش‌فرضکاربرد
uuid / id / user-idنداردUUID یا ID کوتاه محلی؛ فقط یک alias.
uuidsنداردآرایه رشته UUID/ID کوتاه یا شیء کاربر.
users / clientsنداردآرایه رشته UUID/ID کوتاه یا شیء کاربر؛ یکی از دو نام را انتخاب کنید.
auth-client-node-nameنداردنام AuthenticationClient؛ با تنظیمات کاربر محلی همزمان مجاز نیست.
connecttrueاجازه درخواست TCP.
udptrueاجازه UDP دارای framing؛ حداقل یکی از TCP و UDP باید فعال باشد.
handshake-timeout-ms10000مهلت قطعی handshake درخواست؛ دریافت داده آن را تمدید نمی‌کند.
auth-max-pending4096بیشترین تعداد کار احراز هویت منتظر در node.
auth-pending-max-bytes67108864بودجه مشترک بایت منطقی ورودی کارهای احراز هویت منتظر.
auth-cache-max-bytes67108864بودجه حافظه cache اعتبارنامه و احراز هویت، برحسب بایت.
replay-max-entries262144بیشترین ورودی زنده در هر یک از جدول‌های replay مربوط به AuthID و session.
fallback-node-nameنداردشاخه اختیاری برای ترافیک واجد شرایط پیش از احراز هویت.
fallback-intentional-delay-ms7تأخیر عمدی fallback؛ صفر آن را غیرفعال می‌کند.
fallback-intentional-delay-jitter-ms1jitter افزوده؛ با تأخیر صفر نادیده گرفته می‌شود.
encrypted-counter-policywrapwrap یا strict مستقل برای هر جهت رمز‌شده.
allowed-securityهر چهار حالتآرایه غیرخالی و یکتای aes-128-gcm، chacha20-poly1305، none، zero؛ UDP-only با فقط zero نامعتبر است.
send-terminationtrueارسال EOF framed اختیاری به سمت wire باز.
packetaddrtrueپذیرش packetaddr احراز‌شده؛ udp: false همه شکل‌های UDP را رد می‌کند.
packetaddr-max-destinations64عدد صحیح 1..1024 برای تعداد backend زنده هر carrier.
verbosefalsereason-code بدون اعتبارنامه یا label مقصد؛ حداکثر یک پیام در ثانیه برای هر node.

محدودیت‌های احراز هویت و timeout باید عدد صحیح در بازه 1..2147483647 باشند؛ اندازه جدول replay نیز باید در ظرفیت قابل نمایش میزبان جا شود. تنظیم نامعتبر startup را رد می‌کند. تنظیمات جدید نوع اشتباه، کلید تکراری، مقدار ناشناخته، NUL داخلی، UTF-8 خراب و حدود کسری یا خارج از بازه را رد می‌کنند. پر شدن ظرفیت درخواست تازه مربوط را رد می‌کند؛ برای باز کردن جا هیچ علامت replay منقضی‌نشده‌ای حذف نمی‌شود.

پیش از پایان احراز هویت، هر اتصال حداکثر ۶۵۵۳۶ بایت منطقی ورودی در ۲۵۶ buffer نگه می‌دارد. صف ورودی و صف پاسخ، هر کدام سقف ۲ MiB بایت منطقی، ۸ MiB هزینه تخصیص buffer و ۱۰۲۴ ورودی دارند؛ buffer فعالِ خارج‌شده از صف تا آزاد شدن همچنان حساب می‌شود. این سقف‌های ثابت مکمل بودجه مشترک احراز هویت‌اند و تضمین سقف RSS یا کل حافظه فرایند نیستند.

Fallback و جلوگیری از replay​

با fallback-node-name یک شاخه stream موجود را برای اعتبارنامه ناشناخته یا احراز هویت در دسترس‌نبودنی انتخاب کنید. prefix بررسی‌شده و بقیه بایت‌ها دقیق و به همان ترتیب بازپخش می‌شوند. هویت ردشده به شاخه fallback منتشر نمی‌شود و UserController داخلی در این مسیر نیست.

پس از شناسایی احراز هویت VMess، fallback دیگر مجاز نیست. AuthID تکراری یا منقضی، session تکراری، tag نامعتبر، header احراز‌شده خراب، فرمان پشتیبانی‌نشده پس از احراز هویت، رد منابع یا پایان مهلت handshake اتصال مربوط را می‌بندند و به fallback تبدیل نمی‌شوند.

جدول replay بین همه workerهای این node مشترک است. بازه پذیرش زمان AuthID برابر ۱۲۰ ثانیه در هر جهت با احتساب مرزهاست؛ علامت آن تا پایان تمام بازه اعتبار، حتی برای timestamp آینده، باقی می‌ماند. عقب رفتن ساعت نمی‌تواند درخواست منقضی‌شده را دوباره معتبر کند. هویت session شامل UUID، کلید بدنه درخواست و IV است و بازه replay آن سه دقیقه است. هر نمونه جداگانه VmessServer دامنه replay مستقل دارد.

آمار فقط خواندنی​

عملیات ثبت‌شده stats فقط شیء JSON خالی تا ۶۴ بایت با احتساب whitespace می‌پذیرد. مجوز عادی APIServer برای این node و operation لازم است؛ callback تاریخی به‌تنهایی آن را منتشر نمی‌کند. پاسخ JSON schema ثابت دارد. در اشغال بودن lock snapshot احراز/replay، خطای محدود busy برمی‌گردد. deadline، سقف response و هزینه واقعی تخصیص pool بررسی می‌شود؛ حداقل ۴۶۰۸ بایت working allowance به‌علاوه هزینه buffer خروجی رزرو کنید.

پاسخ تنظیمات مؤثر encrypted_counter_policy، allowed_security، send_termination، packetaddr، packetaddr_max_destinations، connect، udp، verbose و managed را دارد. approximate برابر true است. همه شمارنده‌ها رشته دهدهی با دقت کامل uint64 هستند. applications association احراز‌شده، carriers خط ورودی borrowed زنده شامل pending/fallback و backends خط مقصد UDP owned زنده را می‌شمارد. شمارنده‌های تجمعی شامل tx_records، rx_records، tx_application_bytes، rx_application_bytes، tx_wire_bytes، rx_wire_bytes، wrap_events و strict_exhaustion هستند. بایت برنامه، upload رمزگشایی‌شده ارائه‌شده به شاخه محافظت‌شده و payload پاسخ پذیرفته‌شده، بدون envelope است. بایت wire ورودی دریافتی و پاسخ framed تحویل‌شده، شامل handshake است. پاسخ UDP عادی خالی/بزرگ drop‌شده بایت پاسخ برنامه اضافه نمی‌کند. records عملیات موفق framed را می‌شمارد؛ zero خام stream بدون framing است. snapshot بین workerها و شمارنده‌ها تقریبی است.

pending_auth، pending_auth_bytes، auth_cache_bytes، authid_marks و session_marks occupancy نگه‌داشته‌شده را نشان می‌دهند؛ علامت منقضی ممکن است منتظر reclamation عادی باشد. شیء ثابت reasons شامل close عادی، mismatch/unavailable/expired AuthID، replay-or-capacity، header خراب، شکست بدنه/طول، command/security ردشده، timeout، admission، UDP بزرگ، packetaddr خراب، ظرفیت مقصد و strict exhaustion است. شکست بدنه/طول می‌تواند parser/geometry باشد و فقط خطای tag نیست. دلیل terminal یک بار در carrier و drop برای هر datagram شمرده می‌شود. UUID، password، شناسه کاربر و label مقصد منتشر نمی‌شود. خواندن از atomic و try-lock محدود است و خط یا map زنده worker دیگر پیمایش نمی‌شود. reset یا mutation وجود ندارد.

اعتبارسنجی​

peerهای pinned مستقل V2Ray 5.53.0، Xray 25.6.8 و sing-box 1.12.0 در هر دو جهت endpoint با اعلام صریح cellهای پشتیبانی‌نشده بررسی می‌شوند. stop-and-wait طولانی بیش از ۶۵۵۳۶ رکورد را روی یک اتصال transport شمارش‌شده عبور می‌دهد. native Debug/Release دو wrap واقعی، checkpoint مستقل، مالکیت/حدود packetaddr، strict، mutation parser، stats و replay را بررسی می‌کند. فرمان‌ها در tests/cases/vmess_interop/README.md و بخش ۶ راهنمای توسعه آمده‌اند.

متادیتای node​

متادیتای برگرفته از tunnels/VmessServer/instance/node.c:

ویژگیمقدار
node flagskNodeFlagBlocksSplice
can_have_prevtrue
can_have_nexttrue
layer_groupkNodeLayer4
layer_group_prev_nodekNodeLayer4
layer_group_next_nodekNodeLayer4
required_padding_left0 بایت