From 4246031ff9bf7d71fd3738d9118a705be9d4b80b Mon Sep 17 00:00:00 2001 From: maxdmitrov <56165502+maxdmitrov@users.noreply.github.com> Date: Sun, 4 Oct 2026 19:57:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=BE=D0=B9=20REALITY?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=B2=D1=8B=D1=81=D0=BE=D0=BA=D0=BE=D0=BC=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=82=D1=83:=20=D1=81=D1=82=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=81=D1=8F=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=89=D0=B8=D0=BA=D0=BE=D0=BC,=20kit=20reality=20add=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D1=83=D1=8E=D1=89=D0=B8=D1=85=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BE=D0=B2;=20kit=20check=20--deep=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=20XHTTP=20?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=D1=80=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/3x-ui.sh | 22 +++++++++++++++++--- scripts/kit.sh | 54 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/scripts/3x-ui.sh b/scripts/3x-ui.sh index 9a9f93c..55ea836 100755 --- a/scripts/3x-ui.sh +++ b/scripts/3x-ui.sh @@ -53,10 +53,10 @@ XUI_ENV=/etc/x-ui/install-result.env # Apple, iCloud, Microsoft и домены .ru сам Xray не советует – их тут нет. SNI_CANDIDATES=(dl.google.com www.amazon.com www.samsung.com www.yahoo.com) -ALL_PROTOS=(reality hy2 xhttp ws trojan vmess ss tuic wg awg awg3 mtproto) +ALL_PROTOS=(reality reality2 hy2 xhttp ws trojan vmess ss tuic wg awg awg3 mtproto) # Обычный WireGuard легко распознаётся сетевым оборудованием и работает нестабильно # (проверено 2026-09-27: рукопожатие доходит до сервера, ответ – нет). По умолчанию не ставим. -DEFAULT_PROTOS=(reality hy2 xhttp ws trojan vmess ss tuic awg awg3 mtproto) +DEFAULT_PROTOS=(reality reality2 hy2 xhttp ws trojan vmess ss tuic awg awg3 mtproto) declare -A PORTS=([xhttp]=8443 [ws]=2053 [trojan]=2083 [vmess]=2087 [ss]=8388 [tuic]=8444 [wg]=51820 [awg]=51821 [awg3]=51822 [mtproto]=8445) PROTOS=(); CREATED=(); OPEN=() # Режим «всё TCP на 443»: nginx разводит по SNI и путям, подключения слушают только localhost. @@ -819,6 +819,22 @@ proto_reality() { fi } +# Второй REALITY на высоком свободном порту, напрямую (без nginx). Где-то 443 и привычные порты +# проходят хуже, чем высокий случайный; ключи, shortId и порт у него свои, сайт маскировки тот же. +proto_reality2() { + local keys stream settings port + keys=$(api GET server/getNewX25519Cert) + settings=$(jq -nc --arg id "$(uuid)" --argjson c "$(client_base reality2)" '{clients: [$c + {id: $id, flow: "xtls-rprx-vision"}], decryption: "none", fallbacks: []}') + stream=$(jq -nc --arg sni "$SNI" --arg target "$(reality_target "$SNI")" --argjson k "$keys" --arg sid "$(openssl rand -hex 8)" '{ + network: "tcp", security: "reality", externalProxy: [], + realitySettings: {show: false, xver: 0, target: $target, serverNames: [$sni], privateKey: $k.privateKey, + minClientVer: "", maxClientVer: "", maxTimediff: 0, shortIds: [$sid], + settings: {publicKey: $k.publicKey, fingerprint: "chrome", serverName: "", spiderX: "/"}}, + tcpSettings: {acceptProxyProtocol: false, header: {type: "none"}}}') + port=$(free_port) + add_inbound "REALITY-2" "$port" tcp vless "$settings" "$stream" +} + proto_xhttp() { local keys stream settings keys=$(api GET server/getNewX25519Cert) @@ -1627,7 +1643,7 @@ usage() { 3X-UI со всеми протоколами одной командой --protocols all all (по умолчанию – всё, кроме WireGuard), minimal (только REALITY) - или список через запятую: reality,hy2,xhttp,ws,trojan,vmess,ss,tuic,wg,awg,awg3,mtproto + или список через запятую: reality,reality2,hy2,xhttp,ws,trojan,vmess,ss,tuic,wg,awg,awg3,mtproto (обычный WireGuard работает нестабильно – включайте его, только если сервер и пользователи за границей) --port 443 порт REALITY (TCP) и Hysteria2 (UDP), по умолчанию 443 diff --git a/scripts/kit.sh b/scripts/kit.sh index 9ef462c..5eefb3b 100644 --- a/scripts/kit.sh +++ b/scripts/kit.sh @@ -875,7 +875,8 @@ deep_clients() { [[ -n $sid ]] || { c_info "нет включённых пользователей – проверять подключения нечем (kit user add имя)"; return 0; } tmp=$(mktemp -d) while IFS= read -r link; do - name=${link##*#}; name=${name%%-*} + name=${link#*@}; name=${name%%\?*}; name=${name##*:} + if [[ $link == *type=xhttp* ]]; then name="XHTTP (порт $name)"; else name="REALITY (порт $name)"; fi port=$((port + 1)); cfg=$tmp/$port.json deep_client_config "$link" "$port" >"$cfg" 2>/dev/null || continue "$xray" run -c "$cfg" >/dev/null 2>&1 & pid=$! @@ -1406,6 +1407,55 @@ port_ufw() { # allow|delete порт tcp|udp|both else ufw delete allow "$p/$n" >/dev/null 2>&1 || true; fi } +# ---------- второй REALITY на высоком порту: kit reality add ---------- + +reality_add() { # [порт] + local want=${1:-} list base id port="" keys sid settings stream body c n=0 tries bid + [[ -z $want || $want =~ ^[0-9]{1,5}$ ]] || die "kit reality add [порт], например: kit reality add 24443" + list=$(api GET inbounds/list) + jq -e 'any(.[]; .remark == "REALITY-2")' <<<"$list" >/dev/null && die "REALITY-2 уже есть. Порт: kit port, смена: kit port set REALITY-2 порт" + base=$(jq -c '[.[] | select(.remark == "REALITY")][0] // empty' <<<"$list") + [[ -n $base ]] || die "На сервере нет подключения REALITY, на которое можно опереться." + if [[ -n $want ]]; then + port=$((10#$want)); ((port >= 1024 && port <= 65535)) || die "Порт: число от 1024 до 65535." + else + for tries in $(seq 1 50); do + port=$(shuf -i 20000-60000 -n 1) + jq -e --argjson p "$port" 'any(.[]; .port == $p)' <<<"$list" >/dev/null && { port=""; continue; } + ss -Hlntu "sport = :$port" | grep -q . || break + port="" + done + [[ -n $port ]] || die "Не нашёл свободный порт." + fi + jq -e --argjson p "$port" 'any(.[]; .port == $p)' <<<"$list" >/dev/null && die "Порт $port уже занят другим подключением." + ss -Hlntu "sport = :$port" | grep -q . && die "Порт $port занят другой программой." + [[ $port != "${XUI_PANEL_PORT:-}" ]] || die "Порт $port – это панель." + + keys=$(api GET server/getNewX25519Cert) + sid=$(openssl rand -hex 8) + settings=$(jq -nc '{clients: [], decryption: "none", fallbacks: []}') + # Сайт маскировки (или свой домен) – как у основного REALITY, ключи и shortId – свои. + stream=$(jq -c --argjson k "$keys" --arg sid "$sid" '(.streamSettings | if type == "string" then fromjson else . end) + | .externalProxy = [] | .tcpSettings.acceptProxyProtocol = false | .realitySettings.xver = 0 + | .realitySettings.privateKey = $k.privateKey | .realitySettings.shortIds = [$sid] + | .realitySettings.settings.publicKey = $k.publicKey | del(.sockopt)' <<<"$base") + body=$(jq -nc --argjson port "$port" --arg s "$settings" --arg st "$stream" '{remark: "REALITY-2", enable: true, listen: "", port: $port, protocol: "vless", + settings: $s, streamSettings: $st, sniffing: "{\"enabled\":true,\"destOverride\":[\"http\",\"tls\",\"quic\"],\"metadataOnly\":false,\"routeOnly\":false}", expiryTime: 0, total: 0}') + api POST inbounds/add "$body" >/dev/null + if command -v ufw >/dev/null && ufw status 2>/dev/null | grep -q '^Status: active'; then ufw allow "$port/tcp" >/dev/null; fi + id=$(api GET inbounds/list | jq -r '[.[] | select(.remark == "REALITY-2")][0].id') + [[ $id =~ ^[0-9]+$ ]] || die "Панель не создала REALITY-2." + # Тем же пользователям, что есть на основном REALITY (двойники AmneziaWG и Telegram не подключаются к нему). + bid=$(jq -r '.id' <<<"$base") + while read -r c; do + [[ -n $c ]] || continue + api POST "clients/$c/attach" "$(jq -nc --argjson i "$id" '{inboundIds: [$i]}')" >/dev/null && n=$((n + 1)) + done < <(clients | jq -r --argjson b "$bid" '.[] | select((.inboundIds // []) | index($b)) | .email') + say "REALITY-2 создан на порту ${B}$port${N}, подключено пользователей: $n. Подписка у клиентов обновится сама." + echo "Если у хостера есть свой межсетевой экран (в личном кабинете), откройте в нём порт $port (tcp)." + echo "Проверить: ${B}kit check --deep${N}. Ссылки: ${B}kit user link имя --all${N}" +} + usage() { cat <