VlessServer
VlessServer پیادهسازی سمت server پروتکل plain VLESS v0 در WaterWall است. request header را از نود stream-facing قبلی
میخواند، UUID خام ۱۶ بایتی را بررسی میکند، مقصد TCP یا UDP درخواستی را بیرون میکشد و ترافیک پذیرفتهشده را به next
میفرستد.
این نود فقط بخش پایه پروتکل VLESS را پیادهسازی میکند؛ TLS، REALITY، XTLS Vision، mux، reverse، XUDP و wrapperهای transport باید با نودهای دیگری ساخته شوند.
جایگاه رایج
VLESS server عادی:
TcpListener -> TlsServer -> VlessServer -> TcpUdpConnector
خروجی فقط TCP:
TcpListener -> TlsServer -> VlessServer -> TcpConnector
خروجی با پشتیبانی UDP:
TcpListener -> TlsServer -> VlessServer -> TcpUdpConnector
VlessServer خودش TLS را terminate نمیکند. در deployment عمومی VLESS، TlsServer را پیش از آن قرار دهید؛ در غیر این
صورت UUID و metadata مقصد روی wire دیده میشوند.
نمونه Minimal
[
{
"name": "tls-in",
"type": "TlsServer",
"settings": {
"cert-file": "/etc/waterwall/fullchain.pem",
"key-file": "/etc/waterwall/privkey.pem"
},
"next": "vless-server"
},
{
"name": "vless-server",
"type": "VlessServer",
"settings": {
"uuid": "5783a3e7-e373-51cd-8642-c83782b807c5",
"connect": true,
"udp": true,
"verbose": false
},
"next": "outbound"
},
{
"name": "outbound",
"type": "TcpUdpConnector",
"settings": {
"address": "dest_context->address",
"port": "dest_context->port"
}
}
]
چند User محلی
{
"name": "vless-server",
"type": "VlessServer",
"settings": {
"users": [
"5783a3e7-e373-51cd-8642-c83782b807c5",
{
"username": "alice",
"id": "11111111-2222-3333-4444-555555555555"
}
],
"connect": true,
"udp": true
},
"next": "outbound"
}
در حالت allowlist محلی، اگر object فیلد username داشته باشد همان نام روی line ثبت میشود. UUID canonical با حروف کوچک هم
بهعنوان password مربوط به line ذخیره میشود تا ruleهای Router حتی بدون database کاربران بتوانند credential را بررسی کنند.
حالت AuthenticationClient
{
"name": "vless-server",
"type": "VlessServer",
"settings": {
"auth-client-node-name": "auth-client",
"connect": true,
"udp": true
},
"next": "outbound"
}
در این حالت، UUID روی wire به فرمت canonical، dashed و با حروف کوچک تبدیل میشود و سپس بهعنوان password کاربر از طریق
AuthenticationClient بررسی میشود.
نمونه user در database:
{
"id": 2001,
"name": "vless-user",
"password": "5783a3e7-e373-51cd-8642-c83782b807c5",
"enabled": true
}
با تنظیم auth-client-node-name دیگر نمیتوانید UUID محلی تعریف کنید. VlessServer خودش یک UserController داخلی پیش از
outbound قرار میدهد تا accounting و مسیریابی مبتنی بر user درست کار کنند.
نمونه Fallback
{
"name": "vless-server",
"type": "VlessServer",
"settings": {
"uuid": "5783a3e7-e373-51cd-8642-c83782b807c5",
"fallback-node-name": "fallback-service",
"fallback-intentional-delay-ms": 7,
"fallback-intentional-delay-jitter-ms": 1,
"connect": true,
"udp": true
},
"next": "outbound"
}
Fallback برای مقاومت در برابر active probing است. بهجای بستن فوری ترافیک نامعتبر یا احراز هویتنشده، میتوان آن را به نود دیگری سپرد.
فیلدهای لازم
| فیلد | نوع | توضیح |
|---|---|---|
name | string | نام یکتای نود داخل config. |
type | string | باید دقیقاً "VlessServer" باشد. |
settings | object | تنظیمات غیرخالی VLESS server. |
next | string | لازم است؛ ترافیک پذیرفتهشده VLESS به این نود فرستاده میشود. |
باید دقیقاً یکی از دو روش authentication را انتخاب کنید.
تنظیمات Authentication محلی
برای authentication محلی، auth-client-node-name را حذف کنید و حداقل یک UUID تنظیم کنید.
| فیلد | نوع | توضیح |
|---|---|---|
uuid | string | یک UUID. |
id | string | alias برای uuid. همزمان uuid و id را استفاده نکنید. |
uuids | array of strings | چند UUID. |
users | array | UUID string یا object با یکی از uuid، id یا user-id. object میتواند username داشته باشد. |
clients | array | alias برای users. همزمان users و clients را استفاده نکنید. |
UUID میتواند به فرمت dashed در RFC4122 یا hex فشرده ۳۲ کاراکتری باشد. UUID تکراری خطایی fatal در config است، حتی اگر usernameهای متفاوتی داشته باشد.
تنظیمات Database Authentication
| فیلد | نوع | توضیح |
|---|---|---|
auth-client-node-name | string | نام یک نود AuthenticationClient موجود در همان config. |
در database mode، uuid، id، uuids، users و clients را تنظیم نکنید.
تنظیمات اختیاری
| فیلد | پیشفرض | توضیح |
|---|---|---|
connect | true | VLESS TCP command 0x01 را فعال میکند. |
udp | true | VLESS UDP command 0x02 را فعال میکند. |
verbose | false | جزئیات بیشتری از رد اتصال و diagnostics را log میکند. |
fallback-node-name | تنظیم نشده | branch جایگزین برای probeهای نامعتبر و احراز هویتنشده. نامهای fallback-node و fallback هم پذیرفته میشوند. |
fallback-intentional-delay-ms | 7 | تأخیر payloadهای upstream که به fallback میروند؛ مقدار 0 آن را غیرفعال میکند. |
fallback-intentional-delay-jitter-ms | 1 | jitter تصادفی برای زمانبندی payloadهای تأخیردار fallback؛ با delay صفر نادیده گرفته میشود. |
حداقل یکی از connect یا udp باید فعال باشد.
قالب Request و Response
request پذیرفتهشده:
version: 1 byte, must be 00
user id: 16 raw UUID bytes
addons len: 1 byte, must be 00
command: 01 TCP or 02 UDP
destination: port first, then address
body: TCP raw stream or UDP length-prefixed packets
destination format:
port: 2 bytes big-endian
address type: 01 IPv4, 02 domain, 03 IPv6
address body: IPv4 4 bytes, domain length + bytes, or IPv6 16 bytes
response header:
00 00
response header تنها پس از برقرار شدن مسیر upstream انتخابشده فرستاده میشود. در TCP یعنی مسیر outbound برقرار شده و در UDP یعنی backend UDP line داخلی از طریق نود بعدی مقداردهی شده است.
رفتار Runtime در TCP
برای command 0x01، server:
- UUID را بررسی میکند
- destination درخواستی را میخواند
- destination را داخل
line->routing_context.dest_ctxمینویسد - نود
nextرا مقداردهی اولیه میکند - byteهای TCP body را که همراه request header رسیدهاند میفرستد
- بعد از established شدن upstream path، VLESS response header را میفرستد
نود next معمولاً TcpConnector، TcpUdpConnector، Router یا نودی است که destination context را میشناسد.
رفتار Runtime در UDP
برای command 0x02، destination داخل VLESS request اولیه برای همان VLESS line ثابت میماند. frameهای UDP جداگانه آدرس
per-packet ندارند.
UDP frameها:
length: 2 bytes big-endian
payload: length bytes
VlessServer برای destination مورد نظر یک backend UDP line داخلی میسازد. frameهای ورودی VLESS UDP پس از خواندن length
prefix به آن line میروند. پاسخ backend نیز با همان prefix دو بایتی length بستهبندی میشود و در جهت downstream به client
VLESS برمیگردد.
UDP frame با length 0 نامعتبر است. buffering ورودی UDP تا 1 MiB محدود است.
رفتار Fallback
Fallback فقط پیش از پذیرفته شدن UUID کاربرد دارد. پس از authentication موفق، addon نامعتبر، command پشتیبانینشده، مقصد خراب یا UDP frame نادرست باعث بسته شدن VLESS line میشود و byteهای احراز هویتشده دوباره به fallback داده نمیشوند.
Fallback ممکن است در این حالتها انتخاب شود:
- version byte نامعتبر
- UUID که در اولین upstream payload split شده باشد
- UUID lookup ناموفق
- آماده نبودن
AuthenticationClient
وقتی fallback تنظیم شده باشد:
- fallback branch بلافاصله
Initمیگیرد - byteهای ابتدایی ذخیرهشده و payloadهای بعدی upstream به fallback فرستاده میشوند
- payloadهای upstream در fallback میتوانند بهاندازه
fallback-intentional-delay-msبهعلاوه jitter تأخیر داشته باشند - upstream
Finishتا تحویل payloadهای delayed fallback منتظر میماند - پاسخهای downstream در fallback عمداً به تأخیر نمیافتند
کیفیت fallback بخشی از fingerprint عمومی سرویس است. fallback خراب، خطای generic، بسته شدن فوری یا تفاوت در محتوا و timing میتواند deployment را لو بدهد. delay و jitter را با رفتار سرویس عمومی خود تنظیم کنید؛ اینها فقط ریسک را کم میکنند و تضمینی برای پنهان ماندن نیستند.
قانون First Payload برای Authentication
credential کامل VLESS، یعنی byte نسخه بهعلاوه UUID خام ۱۶ بایتی، باید در نخستین callback مربوط به upstream payload حاضر باشد.
اگر نخستین payload credential کامل را نداشته باشد، line مانند یک probe نامعتبر و احراز هویتنشده در نظر گرفته میشود. در صورت وجود fallback، byteها به آن میروند وگرنه line بسته میشود. پس از دریافت کامل UUID، فیلدهای باقیمانده میتوانند در callbackهای بعدی برسند.
رفتار Finish
VlessServer پیش از فرستادن Finish واقعی، line state خود را از بین میبرد.
برای TCP و fallback، Finish در صورت نیاز به branch انتخابشده فرستاده میشود. در UDP، نود مالک backend UDP line داخلیای است که
خودش ساخته و با بسته شدن هر یک از دو سمت، آن را بهشکل امن میبندد.
Padding
VlessServer ممکن است prefix دو بایتی length در VLESS UDP را به ابتدای reply packet اضافه کند، بنابراین مقدار زیر را اعلام میکند:
required_padding_left = 2
متادیتای نود
| ویژگی | مقدار |
|---|---|
| Node flag | kNodeFlagChainHead |
| previous node | مجاز، و در استفاده عادی لازم |
| next node | لازم |
| layer group | kNodeLayerAnything |
required_padding_left | 2 |
| line state | auth state، phase، read stream، pending queues، backend UDP line |
قابلیتهای پشتیبانینشده
پیادهسازی فعلی موارد زیر را نمیپذیرد:
- request addons length غیرصفر
- XTLS Vision flow addons
- mux command
0x03 - reverse command
0x04 - commandهای ناشناخته
- XUDP و رفتار پیشرفته UDP/mux
- VLESS روی transportهای non-stream
probeهای invalid و unauthenticated ممکن است به fallback بروند. protocol data بد بعد از authentication بدون نوشتن response header دیگر close میشود.
اشتباههای رایج
VlessServerرا بدونTlsServerمستقیماً روی listener عمومی قرار ندهید، مگر اینکه عمداً plain VLESS را روی wire بخواهید.- local UUIDها را همراه
auth-client-node-nameتنظیم نکنید. - نود بعدی را دستی
UserControllerنگذارید؛ database mode خودش یکUserControllerداخلی اضافه میکند. - انتظار نداشته باشید UDP frameها برای هر packet مقصد جدید انتخاب کنند؛ VLESS request اولیه UDP target را ثابت میکند.
- به featureهای پشتیبانینشده مثل Vision، flow، mux، reverse یا XUDP تکیه نکنید.