Панель и подписка по домену или по IP: kit net panel, --panel-on при установке, выбор в диалоге, возврат при --restore
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@
|
||||
* Установка теперь по шагам, а все ссылки разложены по полочкам: основные и запасные. Раньше они сыпались потоком, как лента новостей.
|
||||
* Сайт-прикрытие подбирается среди соседей по подсети, а не «у всех один». Свой домен по-прежнему лучший вариант. REALITY теперь с `xtls-rprx-vision`, Hysteria2 отвечает на чужой запрос страницей сайта.
|
||||
* `kit check --deep` подключается к серверу настоящим клиентом, `--fix` лечит безопасное. Общий лимит трафика считается по всем подключениям пользователя, а в подписке Clash есть «Авто»: клиент сам выбирает быстрейший протокол. DNS в подписках теперь по DoH через прокси: запросы имён не гуляют где попало.
|
||||
* Вернулся `--restore`: чистый сервер поднимается из `kit backup`, как из резервной копии настроек телефона. Ссылки `kit user link --amnezia` и `--telegram` для AmneziaVPN и Telegram теперь одной командой, а исправление времени на Debian 13 прислал [xlok1e](https://github.com/xlok1e), спасибо.
|
||||
* Со своим доменом панель и подписку можно открывать и по домену: `--panel-on domain` при установке или `kit net panel domain` потом. Вернулся `--restore`: чистый сервер поднимается из `kit backup`, как из резервной копии настроек телефона. Ссылки `kit user link --amnezia` и `--telegram` для AmneziaVPN и Telegram теперь одной командой, а исправление времени на Debian 13 прислал [xlok1e](https://github.com/xlok1e), спасибо.
|
||||
|
||||
Сервер обновится сам этой ночью, нетерпеливым – `kit update`.
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ kit net off имя / kit net on имя # выключит
|
||||
kit net fp firefox # сменить отпечаток клиента у всех подключений
|
||||
kit net masq on # Hysteria2 отвечает на чужой запрос страницей сайта
|
||||
kit net dns on # DNS в подписке по DoH через прокси (ставится при установке)
|
||||
kit net panel domain | ip # панель и подписка по своему домену или по IP (при установке: --panel-on)
|
||||
|
||||
kit check [--deep] [--fix] # проверить сервер; --deep – ещё и подключиться клиентом, --fix – исправить безопасное
|
||||
kit update [--panel] # обновить сейчас; --panel – панель 3X-UI до проверенной версии
|
||||
|
||||
@@ -179,8 +179,12 @@ kit net off vmess-ws # выключить протокол и закры
|
||||
kit net on reality2 # создать второй REALITY на высоком порту
|
||||
kit net fp firefox # сменить отпечаток клиента у всех подключений
|
||||
kit net masq on # Hysteria2 отвечает на чужой запрос страницей сайта
|
||||
kit net panel domain # панель и подписка открываются и по домену (только со своим доменом); kit net panel ip – как раньше
|
||||
```
|
||||
|
||||
Со своим доменом панель и подписка по умолчанию открываются по IP (`https://IP/путь/`). Если нужен адрес с доменом (например, для Telegram-бота панели
|
||||
или ссылки, которая не зависит от IP), выберите «по домену» при установке (`--panel-on domain`) или позже: `kit net panel domain`. Путь у них секретный и по домену, как и по IP.
|
||||
|
||||
Лучший сайт маскировки – ваш собственный домен (`--domain` при установке): сервер изображает ваш сайт, а сертификат
|
||||
и имя совпадают. Без домена установщик ищет сайт среди соседей по подсети сервера: он естественнее, чем известный
|
||||
сайт на чужом IP. Основные протоколы – REALITY, XHTTP и Hysteria2; остальные запасные, их можно выключить командой
|
||||
|
||||
+34
-3
@@ -65,6 +65,7 @@ declare -A INNER=([reality]=10443 [xhttp]=10444 [mtproto]=10445 [web]=10446 [sel
|
||||
SNI2=""; SNI3=""
|
||||
# Свой домен (self-steal): REALITY маскируется под сайт на этом же сервере, а не под чужой.
|
||||
DOMAIN=""
|
||||
PANEL_ON=ip # где открываются панель и подписка: ip или domain (domain – только со своим доменом)
|
||||
LINK_HOST="" # адрес в ссылках: свой домен, если он выбран, иначе IP
|
||||
DOMAIN_CERT_DIR=/root/cert/domain
|
||||
SELF_IP_CERT=no # yes – сертификат на IP самоподписанный (Let's Encrypt отказал, пользователь согласился)
|
||||
@@ -210,6 +211,20 @@ ask_tty() { # приглашение; ответ – в REPLY; не 0, если
|
||||
read -r -p "$1" REPLY </dev/tty || { REPLY=""; return 1; }
|
||||
}
|
||||
|
||||
# Где открывать панель и подписку, если выбран свой домен.
|
||||
panel_on_choice() {
|
||||
[[ $PANEL_ON == domain ]] && return 0
|
||||
echo
|
||||
echo "${B}Где открывать панель и подписку?${N}"
|
||||
echo " ${B}1${N} По IP https://$HOST/… как раньше ${G}[по умолчанию]${N}"
|
||||
echo " ${B}2${N} По домену https://$DOMAIN/… сертификат домена, ссылка не зависит от IP"
|
||||
echo " ${D}Менять можно потом: kit net panel domain | ip${N}"
|
||||
ask_tty "Выбор [1]: " || return 0
|
||||
REPLY=${REPLY//[[:space:]]/}
|
||||
[[ ${REPLY%.} == 2 ]] && PANEL_ON=domain
|
||||
return 0
|
||||
}
|
||||
|
||||
# Вопрос пользователю: свой домен, сосед по подсети (по умолчанию) или свой сайт.
|
||||
choose_masking() {
|
||||
echo
|
||||
@@ -242,7 +257,7 @@ choose_masking() {
|
||||
[[ -n $d ]] || d=$prev
|
||||
[[ -n $d ]] || return 0
|
||||
if [[ ! $d =~ $re_host ]]; then warn "Это не похоже на домен (нужно только имя, без https://). Пример: vpn.example.com"; prev=""; continue; fi
|
||||
if domain_points_here "$d"; then DOMAIN=$d; return 0; fi
|
||||
if domain_points_here "$d"; then DOMAIN=$d; panel_on_choice; return 0; fi
|
||||
prev=$d
|
||||
ask_tty "Enter – проверить ещё раз (DNS обновляется не сразу), s – стандартный сайт, q – выйти: " || return 0
|
||||
REPLY=${REPLY//[[:space:]]/}
|
||||
@@ -400,7 +415,7 @@ main() {
|
||||
local PORT=443 SNI="" PANEL_SSL=auto HOST="" UFW=yes NAME="admin" yes=no protos=all ucert="" ukey="" multi=no restore=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--port | --sni | --panel-ssl | --host | --user | --protocols | --domain | --cert | --key | --restore)
|
||||
--port | --sni | --panel-ssl | --host | --user | --protocols | --domain | --cert | --key | --restore | --panel-on)
|
||||
[[ -n ${2-} ]] || die "У параметра $1 нет значения (см. --help)" ;;
|
||||
esac
|
||||
case $1 in
|
||||
@@ -415,6 +430,7 @@ main() {
|
||||
--multi-port) multi=yes; shift ;;
|
||||
--key) ukey=$2; shift 2 ;;
|
||||
--restore) restore=$2; shift 2 ;;
|
||||
--panel-on) PANEL_ON=${2,,}; shift 2 ;;
|
||||
--no-ufw) UFW=no; shift ;;
|
||||
-y|--yes) yes=yes; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
@@ -443,6 +459,8 @@ main() {
|
||||
[[ -z $DOMAIN || $DOMAIN =~ $re_host ]] || die "--domain: нужно имя вашего домена, например vpn.example.com"
|
||||
[[ -z $DOMAIN || -z $SNI ]] || die "--sni и --domain вместе не нужны: выберите либо чужой сайт (--sni), либо свой домен (--domain)."
|
||||
[[ -z $DOMAIN || $multi == no ]] || die "Свой домен работает только в режиме «всё на 443» – уберите --multi-port."
|
||||
[[ $PANEL_ON == ip || $PANEL_ON == domain ]] || die "--panel-on: ip или domain"
|
||||
[[ $PANEL_ON == ip || -n $DOMAIN || $yes == no ]] || die "--panel-on domain работает только со своим доменом (--domain vpn.example.com)."
|
||||
[[ -z $HOST || $HOST =~ $re_host || $HOST =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$ ]] || die "--host: нужен IP (например 1.2.3.4) или домен"
|
||||
[[ $NAME =~ ^[A-Za-z0-9_.-]{1,32}$ ]] || die "Имя: латиница, цифры, _ . - (до 32 символов)."
|
||||
[[ $PANEL_SSL =~ ^(auto|ip|none)$ ]] || die "--panel-ssl: auto, ip или none"
|
||||
@@ -550,6 +568,7 @@ main() {
|
||||
die "$SNI не отвечает по TLS 1.3 + HTTP/2 – REALITY с ним работать не будет. Выберите другой сайт."
|
||||
fi
|
||||
LINK_HOST=${DOMAIN:-$HOST}
|
||||
[[ $PANEL_ON == ip || -n $DOMAIN ]] || { PANEL_ON=ip; later "--panel-on domain нужен со своим доменом: панель и подписка открываются по IP."; }
|
||||
# Режим «всё на 443»: XHTTP и MTProto различаются по имени сайта, берём и им соседей по подсети.
|
||||
if [[ $TRUSTED == yes && $multi == no && ( -z $SNI2 || -z $SNI3 ) ]]; then
|
||||
local -a nb2=()
|
||||
@@ -667,6 +686,9 @@ main() {
|
||||
|
||||
step "Защита и обновления"
|
||||
install_kit_cli
|
||||
if [[ $PANEL_ON == domain ]]; then
|
||||
/usr/local/bin/kit net panel domain >/dev/null 2>&1 || { PANEL_ON=ip; later "Панель и подписку по домену включить не удалось: оставил по IP. Попробуйте позже: kit net panel domain"; }
|
||||
fi
|
||||
brand_xui_menu
|
||||
# Автообновление kit и kit-sub: только подписанные релизы, выключается kit update --manual.
|
||||
/usr/local/bin/kit update --auto >/dev/null 2>&1 || later "Автообновление не включилось – включите позже: kit update --auto"
|
||||
@@ -697,8 +719,10 @@ main() {
|
||||
|
||||
# --- итог ---
|
||||
local panel_url links
|
||||
local ph=$HOST
|
||||
if [[ $PANEL_ON == domain ]]; then ph=$DOMAIN; SUB_URL=${SUB_URL/\/\/$HOST\//\/\/$DOMAIN\/}; fi
|
||||
if [[ $SINGLE == yes ]]; then
|
||||
panel_url="https://$HOST/${XUI_WEB_BASE_PATH#/}"
|
||||
panel_url="https://$ph/${XUI_WEB_BASE_PATH#/}"
|
||||
panel_url="${panel_url%/}/"
|
||||
elif [[ $TRUSTED == yes ]]; then
|
||||
panel_url="https://$HOST:$XUI_PANEL_PORT/$XUI_WEB_BASE_PATH"
|
||||
@@ -1232,6 +1256,7 @@ install_kit_cli() {
|
||||
{
|
||||
printf 'HOST=%q\n' "$HOST"
|
||||
printf 'LINK_HOST=%q\n' "${LINK_HOST:-$HOST}"
|
||||
printf 'PANEL_ON=%q\n' "ip"
|
||||
printf 'SUB_BASE=%q\n' "${SUB_URL%$SUBID}"
|
||||
printf 'SUB_PATH=%q\n' "$SUB_PATH"
|
||||
printf 'SUB_INTERNAL=%q\n' "${SUB_INTERNAL:-$SUB_PORT}"
|
||||
@@ -1787,6 +1812,11 @@ PY
|
||||
|
||||
if [[ -f /etc/kit/kit.env ]]; then
|
||||
install_kit_file
|
||||
# Панель по домену: nginx собран заново, значит блок домена нужно вернуть (домен должен указывать на этот сервер).
|
||||
if grep -q '^PANEL_ON=domain' /etc/kit/kit.env; then
|
||||
sed -i 's/^PANEL_ON=.*/PANEL_ON=ip/' /etc/kit/kit.env
|
||||
/usr/local/bin/kit net panel domain >/dev/null 2>&1 || warn "Панель по домену не включилась (домен должен указывать на этот сервер): kit net panel domain"
|
||||
fi
|
||||
brand_xui_menu
|
||||
/usr/local/bin/kit update --auto >/dev/null 2>&1 || later "Автообновление не включилось – включите позже: kit update --auto"
|
||||
/usr/local/bin/kit __limit-timer on >/dev/null 2>&1 || later "Проверка общего лимита трафика не включилась – включите позже: kit fix"
|
||||
@@ -1843,6 +1873,7 @@ usage() {
|
||||
--user admin имя первого клиента
|
||||
--host 1.2.3.4 адрес в ссылке, если IP определился неверно
|
||||
--restore файл поднять сервер из резервной копии kit backup (на чистом VPS)
|
||||
--panel-on ip|domain панель и подписка по IP (по умолчанию) или по своему домену (нужен --domain)
|
||||
--no-ufw не трогать файрвол
|
||||
-y не задавать вопросов
|
||||
EOF
|
||||
|
||||
+186
-3
@@ -1678,6 +1678,179 @@ net_dns() { # [on|off]
|
||||
esac
|
||||
}
|
||||
|
||||
# ---------- панель и подписка: по IP или по домену ----------
|
||||
# Со своим доменом (режим «всё на 443») заход по имени домена попадает к сайту-прикрытию. Панель и подписка по
|
||||
# умолчанию открываются по IP; `kit net panel domain` добавляет их и в блок домена (сертификат Let's Encrypt домена),
|
||||
# `kit net panel ip` возвращает как было. Пути у них секретные, как и на IP.
|
||||
|
||||
PANEL_CONF=/etc/nginx/conf.d/kit.conf
|
||||
|
||||
# Разбор и пересборка блока домена в конфиге nginx. info – домен, сертификат, ключ; render – новый текст конфига.
|
||||
panel_conf_py() {
|
||||
python3 - "$@" <<'PY'
|
||||
import re, sys
|
||||
op, conf = sys.argv[1], sys.argv[2]
|
||||
text = open(conf).read()
|
||||
|
||||
def match_brace(t, start):
|
||||
depth = 0
|
||||
for j in range(start, len(t)):
|
||||
if t[j] == "{":
|
||||
depth += 1
|
||||
elif t[j] == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return j + 1
|
||||
return -1
|
||||
|
||||
def servers(t):
|
||||
out, i = [], 0
|
||||
while True:
|
||||
m = re.search(r"^server\s*\{", t[i:], re.M)
|
||||
if not m:
|
||||
return out
|
||||
a = i + m.start()
|
||||
b = match_brace(t, a)
|
||||
out.append((a, b))
|
||||
i = b
|
||||
|
||||
blocks = servers(text)
|
||||
web = next((b for b in blocks if "server_name _;" in text[b[0]:b[1]]), None)
|
||||
steal = next((b for b in blocks if "server_name _;" not in text[b[0]:b[1]] and re.search(r"server_name\s+\S+;", text[b[0]:b[1]])), None)
|
||||
if steal is None:
|
||||
sys.exit(2)
|
||||
sb = text[steal[0]:steal[1]]
|
||||
domain = re.search(r"server_name\s+(\S+);", sb).group(1)
|
||||
cert = re.search(r"ssl_certificate\s+(\S+);", sb).group(1)
|
||||
key = re.search(r"ssl_certificate_key\s+(\S+);", sb).group(1)
|
||||
port = re.search(r"listen\s+127\.0\.0\.1:(\d+)", sb).group(1)
|
||||
if op == "info":
|
||||
print(domain, cert, key)
|
||||
sys.exit(0)
|
||||
mode, sub_path, panel_path = sys.argv[3], sys.argv[4], sys.argv[5]
|
||||
def location(t, path):
|
||||
m = re.search(r"^[ \t]*location\s+" + re.escape(path) + r"\s*\{", t, re.M)
|
||||
if not m:
|
||||
return ""
|
||||
b = match_brace(t, m.end() - 1)
|
||||
return t[m.start():b]
|
||||
if mode == "domain":
|
||||
wb = text[web[0]:web[1]] if web else ""
|
||||
locs = "\n".join(x for x in (location(wb, sub_path), location(wb, panel_path)) if x)
|
||||
if not locs:
|
||||
sys.exit(3)
|
||||
new = f"""server {{
|
||||
listen 127.0.0.1:{port} ssl http2 proxy_protocol;
|
||||
server_name {domain};
|
||||
ssl_certificate {cert};
|
||||
ssl_certificate_key {key};
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
set_real_ip_from 127.0.0.1;
|
||||
real_ip_header proxy_protocol;
|
||||
server_tokens off;
|
||||
absolute_redirect off;
|
||||
access_log off;
|
||||
# kit:panel-on-domain
|
||||
{locs}
|
||||
location / {{
|
||||
root /var/www/kit;
|
||||
index index.html;
|
||||
}}
|
||||
}}"""
|
||||
else:
|
||||
new = f"""server {{
|
||||
listen 127.0.0.1:{port} ssl http2;
|
||||
server_name {domain};
|
||||
ssl_certificate {cert};
|
||||
ssl_certificate_key {key};
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
server_tokens off;
|
||||
access_log off;
|
||||
location / {{
|
||||
root /var/www/kit;
|
||||
index index.html;
|
||||
}}
|
||||
}}"""
|
||||
sys.stdout.write(text[:steal[0]] + new + text[steal[1]:])
|
||||
PY
|
||||
}
|
||||
|
||||
kit_env_set() { # ключ значение: меняет или добавляет строку в /etc/kit/kit.env
|
||||
python3 - "$KIT_ENV" "$1" "$2" <<'PY'
|
||||
import re, shlex, sys
|
||||
p, k, v = sys.argv[1:4]
|
||||
lines = open(p).read().splitlines()
|
||||
new = f"{k}={shlex.quote(v)}"
|
||||
for i, l in enumerate(lines):
|
||||
if l.startswith(k + "="):
|
||||
lines[i] = new
|
||||
break
|
||||
else:
|
||||
lines.append(new)
|
||||
open(p, "w").write("\n".join(lines) + "\n")
|
||||
PY
|
||||
}
|
||||
|
||||
net_panel() { # [domain|ip]
|
||||
local want=${1:-} info domain cert key cur new tmp bak rid panel_path old_host new_host all
|
||||
[[ ${SINGLE:-no} == yes && -f $PANEL_CONF ]] || die "Работает в режиме «всё на 443» со своим доменом (--domain при установке)."
|
||||
info=$(panel_conf_py info "$PANEL_CONF") || die "В настройках nginx нет блока своего домена: панель по домену доступна только при установке с --domain."
|
||||
read -r domain cert key <<<"$info"
|
||||
cur=${PANEL_ON:-ip}
|
||||
if [[ -z $want ]]; then
|
||||
if [[ $cur == domain ]]; then echo "Панель и подписка открываются по домену $domain (вернуть на IP: kit net panel ip)"
|
||||
else echo "Панель и подписка открываются по IP ${HOST:-?}; домен $domain – сайт-прикрытие (открывать и по домену: kit net panel domain)"; fi
|
||||
return 0
|
||||
fi
|
||||
[[ $want == domain || $want == ip ]] || die "kit net panel [domain|ip]"
|
||||
[[ $want != "$cur" ]] || { say "Уже так: панель и подписка по $([[ $want == domain ]] && echo "домену $domain" || echo "IP")."; return 0; }
|
||||
panel_path=/${XUI_WEB_BASE_PATH#/}; panel_path=${panel_path%/}/
|
||||
if [[ $want == domain ]]; then
|
||||
getent ahostsv4 "$domain" 2>/dev/null | awk '{print $1}' | grep -qx "$(host_ip)" || die "Домен $domain не указывает на этот сервер ($(host_ip)). Исправьте A-запись и повторите."
|
||||
[[ -s $cert && -s $key ]] || die "Нет сертификата домена ($cert) – не трогаю nginx."
|
||||
fi
|
||||
tmp=$(mktemp); bak=$(mktemp); cp -p "$PANEL_CONF" "$bak"
|
||||
panel_conf_py render "$PANEL_CONF" "$want" "$SUB_PATH" "$panel_path" >"$tmp" || { rm -f "$tmp" "$bak"; die "Не удалось собрать настройки nginx. Ничего не изменилось."; }
|
||||
rid=$(sni_targets | awk -F'\t' '$2 == "self" && $3 == "REALITY" {print $1; exit}')
|
||||
[[ -n $rid ]] || { rm -f "$tmp" "$bak"; die "Не нашёл REALITY со своим доменом."; }
|
||||
# Передача настоящего IP клиента сайту домена (PROXY protocol) нужна, чтобы панель видела, кто заходит.
|
||||
local xv=0; [[ $want == domain ]] && xv=1
|
||||
panel_revert() { cat "$bak" >"$PANEL_CONF"; inbound_patch "$rid" '.streamSettings |= ((if type == "string" then fromjson else . end) | .realitySettings.xver = $x)' --argjson x "$((1 - xv))" || true; nginx -t >/dev/null 2>&1 && systemctl reload nginx || true; }
|
||||
if [[ $want == domain ]]; then
|
||||
cat "$tmp" >"$PANEL_CONF"
|
||||
nginx -t >/dev/null 2>&1 || { cat "$bak" >"$PANEL_CONF"; rm -f "$tmp" "$bak"; die "nginx не принял настройки. Ничего не изменилось."; }
|
||||
inbound_patch "$rid" '.streamSettings |= ((if type == "string" then fromjson else . end) | .realitySettings.xver = $x)' --argjson x 1 || { cat "$bak" >"$PANEL_CONF"; rm -f "$tmp" "$bak"; die "Панель не приняла изменение. Ничего не изменилось."; }
|
||||
systemctl reload nginx || { panel_revert; rm -f "$tmp" "$bak"; die "nginx не перезагрузился. Всё возвращено."; }
|
||||
else
|
||||
inbound_patch "$rid" '.streamSettings |= ((if type == "string" then fromjson else . end) | .realitySettings.xver = $x)' --argjson x 0 || { rm -f "$tmp" "$bak"; die "Панель не приняла изменение. Ничего не изменилось."; }
|
||||
cat "$tmp" >"$PANEL_CONF"
|
||||
if ! nginx -t >/dev/null 2>&1 || ! systemctl reload nginx; then panel_revert; rm -f "$tmp" "$bak"; die "nginx не принял настройки. Всё возвращено."; fi
|
||||
fi
|
||||
rm -f "$tmp" "$bak"
|
||||
# Ссылки: адрес подписки в kit, панели и файле с данными входа.
|
||||
old_host=${HOST}; new_host=$domain
|
||||
if [[ $want == ip ]]; then old_host=$domain; new_host=${HOST}; fi
|
||||
kit_env_set PANEL_ON "$want"
|
||||
kit_env_set SUB_BASE "https://$([[ $want == domain ]] && echo "$domain" || echo "$HOST")${SUB_PATH}"
|
||||
all=$(api POST setting/all '{}')
|
||||
api POST setting/update "$(jq -c --arg u "https://$([[ $want == domain ]] && echo "$domain" || echo "$HOST")${SUB_PATH}" '.subURI = $u' <<<"$all")" >/dev/null || warn "Не обновил адрес подписки в панели."
|
||||
[[ -f /root/3x-ui.txt ]] && python3 - /root/3x-ui.txt "https://$old_host" "https://$new_host" <<'PY'
|
||||
import sys
|
||||
p, a, b = sys.argv[1:4]
|
||||
s = open(p).read()
|
||||
open(p, "w").write(s.replace(a + "/", b + "/").replace(a + ":", b + ":"))
|
||||
PY
|
||||
if [[ $want == domain ]]; then
|
||||
say "Панель и подписка теперь открываются и по домену $domain."
|
||||
echo "Панель: https://$domain$panel_path"
|
||||
echo "Подписка: https://$domain${SUB_PATH}ПОДПИСКА_ПОЛЬЗОВАТЕЛЯ (ссылки: kit user link имя)"
|
||||
echo "По IP они тоже работают. Вернуть как было: kit net panel ip"
|
||||
else
|
||||
say "Панель и подписка снова только по IP ${HOST}."
|
||||
echo "Панель: https://${HOST}$panel_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- kit net: протоколы, порты, сайт маскировки, отпечаток ----------
|
||||
|
||||
net_main_name() { case $1 in REALITY | XHTTP | Hysteria2) return 0 ;; *) return 1 ;; esac; }
|
||||
@@ -1731,6 +1904,9 @@ net_show() {
|
||||
[[ $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)"
|
||||
if [[ ${SINGLE:-no} == yes && -f $PANEL_CONF ]] && panel_conf_py info "$PANEL_CONF" >/dev/null 2>&1; then
|
||||
net_panel
|
||||
fi
|
||||
if jq -e 'any(.[]; .protocol == "hysteria")' <<<"$list" >/dev/null; then
|
||||
if [[ -n $(hy_masq_state) ]]; then echo "Hysteria2 отвечает на посторонний запрос страницей сайта (выключить: kit net masq off)"
|
||||
else echo "Hysteria2 без маскировки под сайт (включить: kit net masq on)"; fi
|
||||
@@ -1798,8 +1974,9 @@ cmd_net() {
|
||||
fp) net_fp "$@" ;;
|
||||
masq) hy_masq "$@" ;;
|
||||
dns) net_dns "$@" ;;
|
||||
panel) net_panel "$@" ;;
|
||||
vision) case ${1:-} in on) cmd_vision --all ;; off) cmd_vision --all off ;; *) die "kit net vision on|off" ;; esac ;;
|
||||
*) die "kit net [site | port имя порт | off имя | on имя | fp отпечаток | masq on|off | dns on|off | vision on|off]" ;;
|
||||
*) die "kit net [site | port имя порт | off имя | on имя | fp отпечаток | masq on|off | dns on|off | panel domain|ip | vision on|off]" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -1928,6 +2105,11 @@ n_toggle() {
|
||||
*) net_toggle on "$PICK" ;;
|
||||
esac
|
||||
}
|
||||
n_panel() {
|
||||
net_panel
|
||||
ask_num "1 – открывать по домену, 2 – только по IP, Enter – оставить: "
|
||||
case $REPLY in 1) net_panel domain ;; 2) net_panel ip ;; esac
|
||||
}
|
||||
n_fp() {
|
||||
local -a fps=(chrome firefox safari edge ios android qq 360 random randomized); local i
|
||||
for i in "${!fps[@]}"; do printf ' %2d %s\n' "$((i + 1))" "${fps[$i]}"; done
|
||||
@@ -1940,8 +2122,8 @@ menu_net() {
|
||||
local c
|
||||
while :; do
|
||||
echo
|
||||
box "Протоколы, порты и маскировка" "1. Показать протоколы и порты" "2. Сменить сайт маскировки" "3. Сменить порт протокола" "4. Выключить или включить протокол" "5. Сменить отпечаток клиента" "6. Второй REALITY на высоком порту" "" "0. Назад"
|
||||
ask_num "Выбор [0-6]: "; c=$REPLY
|
||||
box "Протоколы, порты и маскировка" "1. Показать протоколы и порты" "2. Сменить сайт маскировки" "3. Сменить порт протокола" "4. Выключить или включить протокол" "5. Сменить отпечаток клиента" "6. Второй REALITY на высоком порту" "7. Панель и подписка: по IP или по домену" "" "0. Назад"
|
||||
ask_num "Выбор [0-7]: "; c=$REPLY
|
||||
case $c in
|
||||
1) run_action net_show; pause ;;
|
||||
2) run_action n_site; pause ;;
|
||||
@@ -1949,6 +2131,7 @@ menu_net() {
|
||||
4) run_action n_toggle; pause ;;
|
||||
5) run_action n_fp; pause ;;
|
||||
6) run_action net_toggle on reality2; pause ;;
|
||||
7) run_action n_panel; pause ;;
|
||||
0 | "") return 0 ;;
|
||||
*) echo "Нет такого пункта." ;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user