Второй REALITY на высоком порту: ставится установщиком, kit reality add для существующих серверов; kit check --deep подписывает XHTTP и порт

This commit is contained in:
maxdmitrov
2026-10-04 19:57:17 +03:00
parent 4b336d7395
commit 4246031ff9
2 changed files with 72 additions and 4 deletions
+19 -3
View File
@@ -53,10 +53,10 @@ XUI_ENV=/etc/x-ui/install-result.env
# Apple, iCloud, Microsoft и домены .ru сам Xray не советует – их тут нет. # Apple, iCloud, Microsoft и домены .ru сам Xray не советует – их тут нет.
SNI_CANDIDATES=(dl.google.com www.amazon.com www.samsung.com www.yahoo.com) 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 легко распознаётся сетевым оборудованием и работает нестабильно # Обычный WireGuard легко распознаётся сетевым оборудованием и работает нестабильно
# (проверено 2026-09-27: рукопожатие доходит до сервера, ответ – нет). По умолчанию не ставим. # (проверено 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) 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=() PROTOS=(); CREATED=(); OPEN=()
# Режим «всё TCP на 443»: nginx разводит по SNI и путям, подключения слушают только localhost. # Режим «всё TCP на 443»: nginx разводит по SNI и путям, подключения слушают только localhost.
@@ -819,6 +819,22 @@ proto_reality() {
fi 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() { proto_xhttp() {
local keys stream settings local keys stream settings
keys=$(api GET server/getNewX25519Cert) keys=$(api GET server/getNewX25519Cert)
@@ -1627,7 +1643,7 @@ usage() {
3X-UI со всеми протоколами одной командой 3X-UI со всеми протоколами одной командой
--protocols all all (по умолчанию – всё, кроме WireGuard), minimal (только REALITY) --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 работает нестабильно – включайте его, только если сервер и (обычный WireGuard работает нестабильно – включайте его, только если сервер и
пользователи за границей) пользователи за границей)
--port 443 порт REALITY (TCP) и Hysteria2 (UDP), по умолчанию 443 --port 443 порт REALITY (TCP) и Hysteria2 (UDP), по умолчанию 443
+53 -1
View File
@@ -875,7 +875,8 @@ deep_clients() {
[[ -n $sid ]] || { c_info "нет включённых пользователей – проверять подключения нечем (kit user add имя)"; return 0; } [[ -n $sid ]] || { c_info "нет включённых пользователей – проверять подключения нечем (kit user add имя)"; return 0; }
tmp=$(mktemp -d) tmp=$(mktemp -d)
while IFS= read -r link; do 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 port=$((port + 1)); cfg=$tmp/$port.json
deep_client_config "$link" "$port" >"$cfg" 2>/dev/null || continue deep_client_config "$link" "$port" >"$cfg" 2>/dev/null || continue
"$xray" run -c "$cfg" >/dev/null 2>&1 & pid=$! "$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 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() { usage() {
cat <<EOF cat <<EOF
${B}kit${N} $KIT_VERSION – управление сервером 3X-UI KIT ${B}kit${N} $KIT_VERSION – управление сервером 3X-UI KIT
@@ -1428,6 +1478,7 @@ ${B}kit${N} $KIT_VERSION – управление сервером 3X-UI KIT
kit check [--deep] проверить сервер: службы, сертификат, подписка, сайт маскировки, права; --deep – ещё и подключиться клиентом kit check [--deep] проверить сервер: службы, сертификат, подписка, сайт маскировки, права; --deep – ещё и подключиться клиентом
kit fix [--dry-run] исправить безопасное: перезапустить службы, права, автообновление, сертификат kit fix [--dry-run] исправить безопасное: перезапустить службы, права, автообновление, сертификат
kit port порты подключений; kit port set имя порт – сменить (ufw и ссылки обновятся) kit port порты подключений; kit port set имя порт – сменить (ufw и ссылки обновятся)
kit reality add [порт] добавить второй REALITY на высоком порту (для сетей, где привычные порты проходят хуже)
kit sni сайты маскировки; kit sni rotate [--nearby] [сайт] – сменить (--nearby – искать в подсети сервера) kit sni сайты маскировки; kit sni rotate [--nearby] [сайт] – сменить (--nearby – искать в подсети сервера)
kit version версия kit, панели и ядра kit version версия kit, панели и ядра
EOF EOF
@@ -1448,6 +1499,7 @@ case "$cmd_key" in
"panel update") shift 2; panel_update "$@" ;; "panel update") shift 2; panel_update "$@" ;;
"__limit-timer on") limit_timer_on ;; "__limit-timer on") limit_timer_on ;;
"update "*) shift; cmd_update "$@" ;; "update "*) shift; cmd_update "$@" ;;
"reality add") shift 2; reality_add "$@" ;;
"port set") shift 2; port_set "$@" ;; "port set") shift 2; port_set "$@" ;;
"port "*) [[ -z ${2:-} ]] || die "Команда: kit port или kit port set имя порт"; port_show ;; "port "*) [[ -z ${2:-} ]] || die "Команда: kit port или kit port set имя порт"; port_show ;;
"sni rotate") shift 2; sni_rotate "$@" ;; "sni rotate") shift 2; sni_rotate "$@" ;;