From 79108694f3f1a80d1da6e4004de5f6d25395636f Mon Sep 17 00:00:00 2001 From: Meow <197331664+Meo597@users.noreply.github.com> Date: Thu, 12 Jun 2025 16:51:50 +0800 Subject: [PATCH] REALITY: Add rate limiting to fallback handling via token bucket (#672) Co-authored-by: Nikita Korotaev <104270279+iambabyninja@users.noreply.github.com> --- docs/config/transport.md | 45 +++++++++++++++++++++++++- docs/ru/config/transport.md | 63 +++++++++++++++++++++++++++++++------ 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/docs/config/transport.md b/docs/config/transport.md index eece864..78eec8a 100644 --- a/docs/config/transport.md +++ b/docs/config/transport.md @@ -275,6 +275,16 @@ x25519Kyber768Draft00 "maxClientVer": "", "maxTimeDiff": 0, "shortIds": ["", "0123456789abcdef"], + "limitFallbackUpload": { + "afterBytes": 0, + "bytesPerSec": 0, + "burstBytesPerSec": 0 + }, + "limitFallbackDownload": { + "afterBytes": 0, + "bytesPerSec": 0, + "burstBytesPerSec": 0 + }, "fingerprint": "chrome", "serverName": "", "publicKey": "", @@ -310,7 +320,9 @@ Reality 只是修改了TLS,客户端的实现只需要轻度修改完全随机 ::: warning 为了伪装的效果考虑,Xray对于鉴权失败(非合法reality请求)的流量,会**直接转发**至 target. 如果 target 网站的 IP 地址特殊(如使用了 CloudFlare CDN 的网站) 则相当于你的服务器充当了 CloudFlare 的端口转发,可能造成被扫描后偷跑流量的情况。 -为了杜绝这种情况,可以考虑前置Nginx等方法过滤掉不符合要求的SNI。 + +为了杜绝这种情况,可以考虑前置 Nginx 等方法过滤掉不符合要求的 SNI。 +或者你也考虑配置 `limitFallbackUpload` 和 `limitFallbackDownload`,限制其速率。 ::: > `xver` : number @@ -349,6 +361,37 @@ Reality 只是修改了TLS,客户端的实现只需要轻度修改完全随机 若包含空值,客户端 `shortId` 可为空。 +::: warning +警告:对于 REALITY 最佳实践始终是偷同 ASN 的证书,那么你大概率用不到此功能;只有当你迫不得已偷了 Cloudflare 这种免费 CDN 的证书时,为避免你服务器成为别人加速节点时可考虑开启此功能。 + +回落限速是一种特征,不建议启用,如果您是面板/一键脚本开发者,务必让这些参数随机化。 +::: + +::: tip +`limitFallbackUpload` 和 `limitFallbackDownload` 为选填,可对未通过验证的回落连接限速,`bytesPerSec` 默认为 0 即不启用。 + +原理:针对每个未通过验证的回落连接,当传输了 afterBytes 字节后开启限速算法。 +限速采用令牌桶算法,桶的容量是 burstBytesPerSec,每传输一个字节用掉一个令牌,初始 burstBytesPerSec 是满的。 +每秒以 bytesPerSec 个令牌填充桶,直到容量满。 + +举例:`afterBytes=10485760`, `burstBytesPerSec=5242880`, `bytesPerSec=1048576` 代表传输 15MB 后开始限速为 1MB/s,如果暂停传输,5 秒后能突发到 5MB/s,然后又恢复到 1MB/s。 + +建议:过大的 `afterBytes` 和 `burstBytesPerSec` 将起不到限速效果,过小的 `bytesPerSec` 和 `burstBytesPerSec` 则十分容易被探测。 +应结合被偷网站的资源大小合理设置参数,如果不允许突发,可以把 `burstBytesPerSec` 设为 0。 +::: + +> `afterBytes` : number + +选填,对回落的 REALITY 连接限速,限制传输指定字节后开始限速,默认为 0。 + +> `bytesPerSec` : number + +选填,对回落的 REALITY 连接限速,限制基准速率(字节/秒),默认为 0 即不启用限速功能。 + +> `burstBytesPerSec` : number + +选填,对回落的 REALITY 连接限速,限制突发速率(字节/秒),大于 `bytesPerSec` 时生效。 + ::: tip 以下为**出站**(**客户端**)配置。 ::: diff --git a/docs/ru/config/transport.md b/docs/ru/config/transport.md index 3e1f5a8..5142c5e 100644 --- a/docs/ru/config/transport.md +++ b/docs/ru/config/transport.md @@ -260,11 +260,11 @@ Reality — это самое безопасное на данный момен > `curvePreferences`: \[ string \] -Массив строк, задающий предпочтительные кривые для выполнения ECDHE во время TLS-рукопожатия. Список поддерживаемых кривых приведён ниже (регистр не имеет значения): -CurveP256 -CurveP384 -CurveP521 -X25519 +Массив строк, задающий предпочтительные кривые для выполнения ECDHE во время TLS-рукопожатия. Список поддерживаемых кривых приведён ниже (регистр не имеет значения): +CurveP256 +CurveP384 +CurveP521 +X25519 x25519Kyber768Draft00 Например, установка значения `"curvePreferences":["x25519Kyber768Draft00"]` позволяет включить экспериментальный алгоритм. Поскольку этот алгоритм находится на стадии черновика, данное поле может измениться в любой момент. @@ -286,6 +286,16 @@ x25519Kyber768Draft00 "maxClientVer": "", "maxTimeDiff": 0, "shortIds": ["", "0123456789abcdef"], + "limitFallbackUpload": { + "afterBytes": 0, + "bytesPerSec": 0, + "burstBytesPerSec": 0 + }, + "limitFallbackDownload": { + "afterBytes": 0, + "bytesPerSec": 0, + "burstBytesPerSec": 0 + }, "fingerprint": "chrome", "serverName": "", "publicKey": "", @@ -319,7 +329,9 @@ Reality лишь модифицирует TLS, и для реализации н ::: warning Из соображений маскировки Xray будет **непосредственно перенаправлять** трафик с неудачной аутентификацией (недопустимый запрос REALITY) на `dest`. Если IP-адрес сайта `dest` особый (например, сайт использует CloudFlare CDN), это равносильно тому, что ваш сервер действует как port forward для CloudFlare, что может привести к злоупотреблению. + Чтобы этого избежать, можно рассмотреть возможность использования Nginx и других методов для фильтрации нежелательных SNI. +Или вы также можете рассмотреть настройку соответствующих параметров `limitFallbackUpload` и `limitFallbackDownload`, чтобы ограничить скорость. ::: > `xver` : number @@ -358,6 +370,39 @@ Reality лишь модифицирует TLS, и для реализации н Если содержит пустое значение, `shortId` клиента может быть пустым. +::: warning +Предупреждение: Лучшей практикой для REALITY всегда является использование сертификата из той же ASN, поэтому, скорее всего, вам эта функция не понадобится; только если вы вынуждены использовать сертификат CDN, можно рассмотреть включение этой функции, чтобы избежать превращения вашего сервера в узел для других. + +Включение ограничения скорости может ввести новые характеристики, обнаруживаемые GFW! Если вы разработчик GUI/панели/скрипта установки в один клик, обязательно рандомизируйте эти параметры! +::: + +::: tip +`limitFallbackUpload` и `limitFallbackDownload` являются необязательными параметрами. Они позволяют ограничить скорость передачи данных для резервных (fallback) соединений, не прошедших проверку. Параметр `bytesPerSec` по умолчанию равен 0, что означает, что ограничение скорости не включено. + +Принцип работы: Для каждого соединения алгоритм ограничения скорости включается после передачи `afterBytes` байтов. + +Ограничение скорости реализовано с помощью алгоритма "маркерная корзина" (token bucket). Вместимость корзины равна `burstBytesPerSec`. Каждый переданный байт потребляет один маркер, и изначально корзина заполнена до `burstBytesPerSec`. + +Каждую секунду корзина пополняется на `bytesPerSec` маркеров, пока не достигнет своей максимальной вместимости. + +Пример: `afterBytes=10485760`, `burstBytesPerSec=5242880`, `bytesPerSec=1048576` означают, что после передачи 10 МB скорость будет ограничена до 1 МB/с. Если передача приостановится, через 5 секунд скорость может временно вырасти до 5 МB/с (burst), а затем снова вернется к 1 МB/с. + +Рекомендации: Слишком большие значения `afterBytes` и `burstBytesPerSec` не приведут к желаемому эффекту ограничения скорости. Слишком маленькие значения `bytesPerSec` и `burstBytesPerSec` могут быть легко обнаружены. + +Следует разумно подбирать параметры в зависимости от размера ресурсов веб-сайта-источника. Если внезапные скачки скорости нежелательны, установите для `burstBytesPerSec` значение 0. ::: + +> `afterBytes` : number + +Необязательный параметр. Ограничение скорости для резервных соединений REALITY. Ограничение вступает в силу после передачи указанного количества байт. По умолчанию 0. + +> `bytesPerSec` : number + +Необязательный параметр. Ограничение скорости для резервных соединений REALITY. Задаёт базовую скорость (байт/секунду). По умолчанию 0, что означает отключение функции ограничения скорости. + +> `burstBytesPerSec` : number + +Необязательный параметр. Ограничение скорости для резервных соединений REALITY. Задаёт пиковую (burst) скорость (байт/секунду). Действует, когда значение больше `bytesPerSec`. + ::: tip Ниже приведена конфигурация для **исходящего** подключения (**клиента**). ::: @@ -599,12 +644,12 @@ Reality лишь модифицирует TLS, и для реализации н Если целевой адрес представлен доменным именем, можно настроить соответствующее значение. Поведение Freedom в зависимости от настройки следующее: - При использовании `"AsIs"` Xray будет напрямую использовать встроенную функцию `Dial` из Go для установления соединения, с фиксированным приоритетом, заданным по умолчанию в RFC6724 (игнорируя такие настройки, как `gai.conf`). _(Простыми словами: IPv6 будет использоваться с приоритетом.)_ -- При использовании другого значения будет применен [встроенный DNS-сервер](../dns.md) Xray-core для разрешения доменного имени. +- При использовании другого значения будет применен [встроенный DNS-сервер](../dns.md) Xray-core для разрешения доменного имени. Если объект `DNSObject` отсутствует, будет использоваться системный DNS. Если существует несколько подходящих IP-адресов, ядро выберет один из них случайным образом. -- `"IPv4"` означает попытку установить соединение, используя только IPv4, - `"IPv4v6"` означает попытку соединения с использованием IPv4 или IPv6, но для доменов с двойным стеком будет использоваться IPv4. +- `"IPv4"` означает попытку установить соединение, используя только IPv4, + `"IPv4v6"` означает попытку соединения с использованием IPv4 или IPv6, но для доменов с двойным стеком будет использоваться IPv4. _(Если поменять местами v4 и v6, логика остается аналогичной)_ -- Если во встроенном DNS установлен параметр `"queryStrategy"`, то фактическое поведение будет комбинацией с этим параметром, и будут разрешаться только типы IP-адресов, присутствующие в обоих параметрах. Например: +- Если во встроенном DNS установлен параметр `"queryStrategy"`, то фактическое поведение будет комбинацией с этим параметром, и будут разрешаться только типы IP-адресов, присутствующие в обоих параметрах. Например: `"queryStrategy": "UseIPv4"` и `"domainStrategy": "UseIP"` фактически эквивалентны `"domainStrategy": "UseIPv4"`. ::: tip TIP