Установщик: «рекомендуем» у своего домена, без «mihomo» в строке о проекте, без ссылок «открыть в приложении» и без деления протоколов на группы; обновление панели проверяет подключения клиентом и откатывает при сбое; README: отдельная Hysteria2 наравне с 11 протоколами

This commit is contained in:
maxdmitrov
2026-10-05 18:01:28 +03:00
parent 97718bd3e6
commit 31bc2d5480
4 changed files with 46 additions and 40 deletions
+3 -12
View File
@@ -231,7 +231,7 @@ choose_masking() {
echo "${B}Под какой сайт маскировать сервер?${N}"
echo "Со стороны он будет выглядеть как обычный сайт."
echo
echo " ${B}1${N} Свой домен самый надёжный: нужен домен и свободный порт 80"
echo " ${B}1${N} Свой домен самый надёжный: нужен домен и свободный порт 80 ${G}[рекомендуем]${N}"
echo " ${B}2${N} Сосед по подсети подберу сам, домен не нужен ${G}[рекомендуем]${N}"
echo " ${B}3${N} Свой сайт вы вводите адрес сами"
echo " ${D}Сертификат своего домена виден в публичных журналах сертификатов: связь «домен – сервер» не скрыта.${N}"
@@ -382,7 +382,7 @@ ART
printf '%s' "$N"
echo
echo "${B}3X-UI KIT $KIT_VERSION${N} · it's not Kubrick. it's just a VPN."
echo "${D}на основе панели 3X-UI (MHSanaei/3x-ui), ядра Xray и mihomo · github.com/itsnotkubrick/3X-UI_KIT${N}"
echo "${D}на основе панели 3X-UI (MHSanaei/3x-ui) и ядра Xray · github.com/itsnotkubrick/3X-UI_KIT${N}"
}
main() {
@@ -790,21 +790,12 @@ main() {
echo " Вставьте в Happ, Hiddify, Karing, v2rayN, Clash Verge или FlClash."
qrencode -t ANSIUTF8 -m 1 "$SUB_URL" || true
echo
/usr/local/bin/kit __applinks "$SUB_URL" || true
echo
KIT_NO_QR=1 /usr/local/bin/kit __links "$NAME" "$SUBID" || true
else
/usr/local/bin/kit __links "$NAME" "$SUBID" || true
fi
echo
local main_list="" spare_list="" c
for c in "${CREATED[@]}"; do
case $c in REALITY | XHTTP | Hysteria2) main_list+="$c, " ;; *) spare_list+="$c, " ;; esac
done
echo "${B}ПРОТОКОЛЫ${N}"
echo " Основные: ${main_list%, }"
echo " Запасные: ${spare_list%, }"
echo " Порты и выключение лишнего: ${B}kit net${N}"
echo "${D}Порты, выключение и включение протоколов: ${N}${B}kit net${N}"
if ((${#WARNINGS[@]})); then
echo
echo "${B}ВНИМАНИЕ${N}"
+26 -22
View File
@@ -934,6 +934,14 @@ print(json.dumps({"log": {"loglevel": "none"},
PY
}
# Подключения клиентом, только итог (для проверки до и после обновления панели): 0 – всё подключается.
deep_probe() {
CHECK_BAD=0; CHECK_WARN=0; CHECK_QUIET=yes
deep_clients >/dev/null 2>&1 || true
CHECK_QUIET=no
((CHECK_BAD == 0))
}
deep_clients() {
local xray sid link name cfg port=18080 pid ok tmp hypin
hypin=$(deep_hy_pin)
@@ -1144,6 +1152,9 @@ panel_update() {
tar xzf "$tmp/x-ui.tar.gz" -C "$tmp"
[[ -s $tmp/x-ui/x-ui ]] || die "В архиве панели нет x-ui. Сервер не тронут."
# Подключения клиентом до обновления: если они работали, после обновления должны работать так же, иначе вернём прежнюю панель.
local pre=no
deep_probe && pre=ok
# 2. Копия на случай отката (база снимается средствами SQLite).
ts=$(date +%Y%m%d-%H%M); bak=/root/x-ui-before-update-$ts
install -d -m 700 "$bak/etc-x-ui"
@@ -1186,14 +1197,15 @@ PY
systemctl start x-ui
# 4. Проверка и откат при провале.
if panel_healthy && [[ $(/usr/local/x-ui/x-ui -v 2>/dev/null | head -1) == "$target" ]]; then
if panel_healthy && [[ $(/usr/local/x-ui/x-ui -v 2>/dev/null | head -1) == "$target" ]] && { [[ $pre != ok ]] || { sleep 5; deep_probe; }; }; then
systemctl is-active -q x-ui || true
say "Панель обновлена до $target, ядро Xray ${XRAY_PIN#v} осталось."
[[ $pre == ok ]] && say "Подключения клиентом после обновления работают (REALITY, XHTTP, Hysteria2)."
echo "Копию прежней панели можно удалить, когда убедитесь, что всё работает: rm -rf $bak"
echo "Проверить сервер: ${B}kit check${N}"
return 0
fi
warn "Панель после обновления не отвечает – возвращаю прежнюю."
warn "Панель после обновления не отвечает или подключения клиентом не работают – возвращаю прежнюю."
systemctl stop x-ui || true
rm -rf /usr/local/x-ui && cp -a "$bak/usr-local-x-ui" /usr/local/x-ui
cp -a "$bak/etc-x-ui/." /etc/x-ui/
@@ -1640,22 +1652,16 @@ def sch_net_ok(label, net):
return label not in ("Shadowsocks",)
print("ПОДКЛЮЧЕНИЕ · %s" % name)
print()
main = [i for m in MAIN for i in items if i[0] == m]
ORDER = ["REALITY-2", "VLESS-WS", "Trojan-gRPC", "VMess-WS", "Shadowsocks", "TUIC", "AmneziaWG", "AmneziaWG 3.1", "MTProto"]
spare = [i for i in items if i[0] not in MAIN]
spare.sort(key=lambda i: ORDER.index(i[0]) if i[0] in ORDER else len(ORDER))
ORDER = ["REALITY", "XHTTP", "Hysteria2", "REALITY-2", "VLESS-WS", "Trojan-gRPC", "VMess-WS", "Shadowsocks", "TUIC", "AmneziaWG", "AmneziaWG 3.1", "MTProto"]
items.sort(key=lambda i: ORDER.index(i[0]) if i[0] in ORDER else len(ORDER))
qr_done = False
for title, group in (("Основные", main), ("Запасные", spare)):
if not group:
continue
print(title)
for it in group:
show(*it)
if not qr_done and it[0] == "REALITY" and shutil.which("qrencode") and not os.environ.get("KIT_NO_QR"):
sys.stdout.flush()
subprocess.run(["qrencode", "-t", "ANSIUTF8", "-m", "1", it[4]])
print()
qr_done = True
for it in items:
show(*it)
if not qr_done and it[0] == "REALITY" and shutil.which("qrencode") and not os.environ.get("KIT_NO_QR"):
sys.stdout.flush()
subprocess.run(["qrencode", "-t", "ANSIUTF8", "-m", "1", it[4]])
print()
qr_done = True
PY
python3 -c "$script" "$name" <<<"$raw"
}
@@ -1967,14 +1973,12 @@ inbound_patch() { # id фильтр-jq [аргументы jq...]: меняет
}
net_show() {
local list name port proto listen en sni fp shown_reality2=no mark note group fpl=""
local list name port proto listen en sni fp shown_reality2=no mark note fpl=""
list=$(api GET inbounds/list)
printf '%s %s %s %s\n' "$(padr Протоколы 22)" "$(padr Порт 12)" "$(padr Статус 8)" "Заметка"
for group in main spare; do
if [[ $group == main ]]; then echo "Основные"; else echo "Запасные"; fi
{
while IFS='|' read -r name port proto listen en sni fp; do
[[ -n $name ]] || continue
if net_main_name "$name"; then [[ $group == main ]] || continue; else [[ $group == spare ]] || continue; fi
[[ $name == REALITY-2 ]] && shown_reality2=yes
if [[ $listen == 127.0.0.1 ]]; then mark="443/tcp"; else mark="$port/$(port_net "$proto")"; fi
[[ $(port_net "$proto") == both ]] && mark=$port
@@ -1985,7 +1989,7 @@ net_show() {
done < <(jq -r '.[] | (.streamSettings | if type == "string" then fromjson else . end) as $s
| [.remark, .port, .protocol, .listen, .enable, ($s.realitySettings.serverNames[0] // ""),
($s.realitySettings.settings.fingerprint // $s.tlsSettings.settings.fingerprint // "")] | map(tostring) | join("|")' <<<"$list")
done
}
[[ $shown_reality2 == yes ]] || printf ' %s %s %s %s\n' "$(padr REALITY-2 20)" "$(padr – 12)" "$(padr выкл 8)" "включить: kit net on reality2"
echo
echo "Отпечаток клиента: ${fpl:-?} (сменить: kit net fp firefox)"