SoftIpLimiter
SoftIpLimiter یک tunnel میانی stream است که تعداد source IPهای مجاز برای
استفاده همزمان از یک identity اولیه VLESS یا Trojan را محدود میکند. این نود
به دیتابیس userهای واتروال یا فهرست کاربران VLESS/Trojan نیاز ندارد؛ کلید limit
را مستقیماً از بایتهای identity موجود در TCP connection کاربر به دست میآورد.
این نود باید بلافاصله پیش از parser مربوط به protocol خام یا پیش از raw TCP relay به سروری قرار بگیرد که آن parser را اجرا میکند:
- با
identifier: vless، پیش ازVlessServerیا TCP relay به سرور VLESS بالادستی - با
identifier: trojan، پیش ازTrojanServerیا TCP relay به سرور Trojan بالادستی
این نود فقط به اندازه لازم از بایتهای ابتدایی را برای تشخیص identity میخواند.
پس از تشخیص، source IP را در یک table داخلی بررسی میکند و همان بایتهای
bufferشده را بدون تغییر میفرستد. رفتار پیشفرض برای identity تشخیصناپذیر، عبور
دادن connection بدون اعمال limit است؛ در deploymentهای سختگیرانه میتوانید آن
را به close تغییر دهید. SoftIpLimiter کاربر را authenticate نمیکند، مقصد را
تجزیه نمیکند، header را تغییر نمیدهد و payload را بازنویسی نمیکند. احراز هویت
واقعی protocol همچنان بر عهده VlessServer یا TrojanServer بعدی است.
جایگاه رایج
VLESS روی TCP خام برای محیط local یا تست:
TcpListener -> SoftIpLimiter(identifier=vless) -> VlessServer -> TcpUdpConnector
VLESS روی TLS برای deployment عمومی:
TcpListener -> TlsServer -> SoftIpLimiter(identifier=vless) -> VlessServer -> TcpUdpConnector
Trojan روی TLS:
TcpListener -> TlsServer -> SoftIpLimiter(identifier=trojan) -> TrojanServer -> TcpUdpConnector
Relay جلوی یک سرور VLESS/Trojan موجود:
TcpListener -> TlsServer -> SoftIpLimiter(identifier=trojan) -> TcpConnector(upstream Trojan server)
SoftIpLimiter را پس از هر لایه encryption یا transportی قرار دهید که بایتهای
VLESS/Trojan را پنهان میکند و پیش از server مربوط به protocol یا raw TCP relay
بگذارید که آن بایتها را مصرف یا عبور میدهد. این نود فقط برای stream است و
نباید در packet chain به کار برود.
شکل ترافیک قابل پشتیبانی
SoftIpLimiter باید یک TCP stream ساده ببیند که نخستین بایتهای application در
آن همان identity مربوط به VLESS یا Trojan باشد. clientهای TLS تنها زمانی
پشتیبانی میشوند که واتروال پیش از این نود، معمولاً با TlsServer، TLS را
terminate کرده باشد.
WebSocket، gRPC، XHTTP، wrapperهای مبتنی بر HTTP Host/header، UDP و packet
chainها پشتیبانی نمیشوند. در این حالتها identity مربوط به VLESS/Trojan در
ابتدای TCP stream دیده نمیشود و نود قادر به شناسایی کاربر نیست.
نمونه VLESS
در این نمونه هر UUID مربوط به VLESS میتواند همزمان حداکثر از دو source IP فعال استفاده شود:
[
{
"name": "listener",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": 443
},
"next": "tls-server"
},
{
"name": "tls-server",
"type": "TlsServer",
"settings": {
"cert-file": "/etc/waterwall/fullchain.pem",
"key-file": "/etc/waterwall/privkey.pem"
},
"next": "soft-ip-limit"
},
{
"name": "soft-ip-limit",
"type": "SoftIpLimiter",
"settings": {
"identifier": "vless",
"simultaneous-user-limit": 2,
"tolerance-ms": 30000,
"on-identification-failure": "passthrough",
"verbose": false
},
"next": "vless-server"
},
{
"name": "vless-server",
"type": "VlessServer",
"settings": {
"uuid": "5783a3e7-e373-51cd-8642-c83782b807c5",
"connect": true,
"udp": true
},
"next": "outbound"
},
{
"name": "outbound",
"type": "TcpUdpConnector",
"settings": {
"address": "dest_context->address",
"port": "dest_context->port"
}
}
]
نمونه Trojan
در این نمونه هر identity مربوط به password در Trojan تنها از یک source IP فعال در هر لحظه قابل استفاده است:
[
{
"name": "listener",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": 443
},
"next": "tls-server"
},
{
"name": "tls-server",
"type": "TlsServer",
"settings": {
"cert-file": "/etc/waterwall/fullchain.pem",
"key-file": "/etc/waterwall/privkey.pem"
},
"next": "trojan-soft-ip-limit"
},
{
"name": "trojan-soft-ip-limit",
"type": "SoftIpLimiter",
"settings": {
"identifier": "trojan",
"simultaneous-user-limit": 1,
"tolerance-ms": 45000,
"on-identification-failure": "close",
"verbose": true
},
"next": "trojan-server"
},
{
"name": "trojan-server",
"type": "TrojanServer",
"settings": {
"password": "secret-password",
"connect": true,
"udp": true
},
"next": "outbound"
}
]
نمونه حداقلی برای relay، زمانی که سرور دیگری پس از واتروال ترافیک Trojan را تجزیه میکند:
{
"name": "trojan-soft-ip-limit",
"type": "SoftIpLimiter",
"settings": {
"identifier": "trojan",
"simultaneous-user-limit": 1,
"tolerance-ms": 3000,
"verbose": false
},
"next": "tcp-connector"
}
فیلدهای اجباری
فیلدهای top-level:
| Field | Type | توضیح |
|---|---|---|
name | string | نام دلخواه نود؛ باید در فایل config یکتا باشد. |
type | string | باید دقیقاً "SoftIpLimiter" باشد. |
settings | object | تنظیمات SoftIpLimiter؛ نباید خالی باشد. |
next | string | الزامی است. ترافیک پذیرفتهشده به این نود فرستاده میشود. |
تنظیمات الزامی:
| Field | Type | توضیح |
|---|---|---|
identifier | string | باید دقیقاً vless یا trojan باشد. |
simultaneous-user-limit | integer | تعداد source IPهای متفاوتی که اجازه دارند همزمان از یک identity استفاده کنند. مقدار مجاز 1 تا 6 است. |
tolerance-ms | integer | مدت بیفعالیتی بر حسب millisecond که پس از آن یک ردیف IP قدیمی محسوب میشود. باید دستکم 1 باشد. |
تنظیمات اختیاری
| Field | Default | توضیح |
|---|---|---|
on-identification-failure | passthrough | رفتار با بایتهایی که قطعاً برای identifier تنظیمشده معتبر نیستند: passthrough، line را بدون IP limit عبور میدهد و close آن را رد میکند. pass و pass-through نامهای مستعار passthrough هستند. |
verbose | false | warningهای مربوط به admission ردشده و بسته شدن payloadهای فعال را در log ثبت میکند. |
استخراج Identity
در mode vless، byteهای upstream باید با این prefix شروع شوند:
version: 1 byte, must be 00
uuid: 16 raw UUID bytes
شانزده بایت UUID با calcHashBytes(uuid, 16) به یک کلید داخلی ۶۴ بیتی تبدیل میشوند.
در mode trojan، byteهای upstream باید با hash استاندارد password شروع شوند:
password hash: 56 ASCII hex bytes, hex(SHA224(password))
SoftIpLimiter این ۵۶ نویسه hex را اعتبارسنجی و decode میکند، سپس ۲۸ بایت
SHA224 را با calcHashBytes(sha224, 28) به یک کلید داخلی ۶۴ بیتی تبدیل میکند.
بایتهای identity نه مصرف میشوند و نه بازنویسی. پس از پذیرفته شدن connection، تمام stream ذخیرهشده در buffer بدون تغییر به نود بعدی میرود.
رفتار شکست تشخیص
تا زمانی که بایتهای موجود برای تصمیمگیری کافی نباشند، SoftIpLimiter منتظر
میماند. وقتی بایتها قطعاً برای mode تنظیمشده نامعتبر باشند،
on-identification-failure رفتار بعدی را تعیین میکند.
در حالت پیشفرض passthrough، نود برای آن line کاملاً شفاف عمل میکند: هیچ ردیفی
برای identity ساخته نمیشود، simultaneous-user-limit و tolerance-ms اعمال
نمیشوند، بایتهای bufferشده بدون تغییر روی نود بعدی بازپخش میشوند و payloadها
و callbackهای بعدی lifecycle به شکل عادی عبور میکنند.
اگر VlessServer یا TrojanServer بعدی fallback خودش را دارد، یا chain عمداً
probeهای غیر VLESS/Trojan را هم میپذیرد، از passthrough استفاده کنید. اگر
early data نامعتبر نباید به نود بعدی برسد، close را انتخاب کنید.
رفتار Limit
limit برای هر identity جداگانه است، نه سراسری برای کل نود. اگر
simultaneous-user-limit برابر 2 باشد، یک UUID یا password hash مربوط به Trojan میتواند
همزمان از دو source IP متفاوت استفاده شود. source IP سوم برای همان identity
رد میشود، اما هر identity دیگر فهرست IP مستقل خودش را دارد.
چند connection با source IP و identity یکسان فقط یک IP محسوب میشوند. ردیف مربوط reference count دارد و تا آزاد شدن آخرین line زنده آن source IP یا قدیمی شدن ردیف، باقی میماند.
رفتار Tolerance
tolerance-ms تنها هنگام دسترسی به table بررسی میشود:
- هنگام admission یک connection جدید
- پیش از فرستادن upstream payload
- پیش از فرستادن downstream payload
- هنگام release شدن row توسط یک line
timer پسزمینهای وجود ندارد؛ بنابراین ممکن است یک line ساکت بیشتر از
tolerance-ms idle بماند. اگر connection یا payload دیگری همان identity را لمس
کند و ردیف IP مربوط به line ساکت حذف شود، آن line با payload بعدی خودش بسته
خواهد شد.
اگر clientها معمولاً connectionهای idle را مدت زیادی نگه میدارند، tolerance را بزرگتر بگذارید. برای آزاد شدن سریعتر slotهای IP قدیمی، مقدار کوچکتری انتخاب کنید.
با مقدارهای خیلی بزرگ مراقب باشید. با simultaneous-user-limit: 1، اگر tolerance-ms را مثلاً یک ساعت
بگذارید، وقتی کاربر از اینترنت گوشی به Wi-Fi جابهجا شود، IP قبلی ممکن است تا یک ساعت تنها slot همان identity را نگه
دارد. برای clientهای mobile یا کاربرهایی که network عوض میکنند، مقدار کوتاهی مثل 3000 تا 5000 ms معمولاً نقطه
شروع عملیتری است.
نیاز به Source IP
برای identityهای تشخیصدادهشده، SoftIpLimiter به یک source IP معتبر در source
context مربوط به line نیاز دارد. listenerهای معمول stream مانند TcpListener
این مقدار را فراهم میکنند.
اگر source context وجود نداشته باشد یا از نوع IPv4/IPv6 نباشد، connection پذیرفته نمیشود.
اگر تشخیص identity شکست بخورد و on-identification-failure برابر passthrough باشد، source-IP row ساخته نمیشود و
این نیازمندی source IP برای آن line استفاده نمیشود.
Logging
این نود بهطور پیشفرض log اضافهای نمینویسد.
وقتی verbose برابر true باشد، admissionهای ردشده و بسته شدن payloadهای فعال همراه mode
مربوط به identifier، کلید داخلی ۶۴ بیتی، source IP، worker id، دلیل، تعداد IP
فعلی و limit تنظیمشده ثبت میشوند. UUID خام VLESS و SHA224 خام Trojan هرگز در
log نوشته نمیشوند.
نکتههای عملیاتی
SoftIpLimiterنود authentication نیست.VlessServerیاTrojanServerبعدی هنوز authentication را انجام میدهد.- میتواند قبل از
VlessServer/TrojanServerمحلی قرار بگیرد، یا قبل از یکTcpConnectorکه ترافیک را به سرور VLESS/Trojan بالادستی relay میکند. - به fail2ban یا limiter خارجی نیاز ندارد؛ table مربوط به identity/IP در خود واتروال نگهداری میشود.
- early data نامعتبر یا قابل تشخیص نبودن بهصورت پیشفرض عبور داده میشود. برای reject شدن در همین node،
on-identification-failureراcloseبگذارید. - این node username را نمیشناسد. key فقط از UUID اولیه VLESS یا مقدار SHA224 اولیه Trojan ساخته میشود.
- اگر
simultaneous-user-limitبرابر1باشد، یک identity همچنان میتواند چند line همزمان از همان source IP باز کند. - اگر clientها بین networkها جابهجا میشوند، limit را آنقدر بالا بگذارید که overlap معمول را پوشش دهد.
- table در tunnel state قرار دارد، میان workerهای همان tunnel instance مشترک است و با RW lock محافظت میشود.
- وقتی میخواهید بفهمید connection بهخاطر IP limit reject یا active-close شده یا نه، موقتا
verboseرا فعال کنید.
Metadata نود
| Property | Value |
|---|---|
| Node flag | kNodeFlagNone |
| Previous node | Required |
| Next node | Required |
| Layer group | kNodeLayer4 |
| Previous node layer | kNodeLayer4 |
| Next node layer | kNodeLayer4 |
required_padding_left | 0 |
اشتباههای رایج
- قرار دادن
SoftIpLimiter(identifier=trojan)پیش ازTlsServer؛ در آن نقطه بایتهای Trojan هنوز رمز شدهاند و limiter نمیتواند connection را شناسایی کند. - انتظار پشتیبانی از WebSocket، gRPC، XHTTP، یا configهایی که HTTP
Host/header دارند. - قرار دادن
SoftIpLimiterبعد ازVlessServerیاTrojanServer. این limiter باید raw protocol identity را قبل از مصرف شدن توسط parser ببیند. - انتظار authentication از این node.
- انتظار اعمال limit روی lineهای pass-through پیشفرض؛ این lineها بدون ردیف identity عبور میکنند. برای enforcement سختگیرانه
از
"on-identification-failure": "close"استفاده کنید. - تنظیم
simultaneous-user-limitبیشتر از6. - استفاده از این node در packet chainها.