diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cf19fc..6aec086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ * `kit` без аргументов открывает меню, как у x-ui: нажали цифру – готово. Всё про сеть собрано в `kit net`: порты, протоколы, сайт маскировки, отпечаток. Команды остались для скриптов, команд стало меньше, а умеет `kit` больше. * Установка теперь по шагам, а все ссылки разложены по полочкам: основные и запасные. Раньше они сыпались потоком, как лента новостей. * Сайт-прикрытие подбирается среди соседей по подсети, а не «у всех один». Свой домен по-прежнему лучший вариант. REALITY теперь с `xtls-rprx-vision`, Hysteria2 отвечает на чужой запрос страницей сайта. -* `kit check --deep` подключается к серверу настоящим клиентом, `--fix` лечит безопасное. Общий лимит трафика считается по всем подключениям пользователя, а в подписке Clash есть «Авто»: клиент сам выбирает быстрейший протокол. DNS в подписках теперь по DoH через прокси, чтобы имена сайтов не бегали к провайдеру на экскурсию. +* `kit check --deep` подключается к серверу настоящим клиентом, `--fix` лечит безопасное. Общий лимит трафика считается по всем подключениям пользователя, а в подписке Clash есть «Авто»: клиент сам выбирает быстрейший протокол. DNS в подписках теперь по DoH через прокси: запросы имён не гуляют где попало. * Вернулся `--restore`: чистый сервер поднимается из `kit backup`, как из резервной копии настроек телефона. Ссылки `kit user link --amnezia` и `--telegram` для AmneziaVPN и Telegram теперь одной командой, а исправление времени на Debian 13 прислал [xlok1e](https://github.com/xlok1e), спасибо. Сервер обновится сам этой ночью, нетерпеливым – `kit update`. diff --git a/README.md b/README.md index c83e43f..72f2136 100644 --- a/README.md +++ b/README.md @@ -281,8 +281,8 @@ sh -c "$(curl -sSL https://raw.githubusercontent.com/jameszeroX/XKeen/main/insta 1. `kit check --deep` – проверит сервер и подключится к нему клиентом: так видно, виноват сервер или сеть. 2. `kit net fp firefox` – другой отпечаток клиента, иногда помогает одной командой (вернуть: `kit net fp chrome`). -3. `kit net site` – новый сайт-прикрытие; `kit net on reality2` – второй REALITY на другом порту (помогает не у всех операторов). - Если в вашей сети не проходит TCP, а UDP проходит (так бывает на мобильном интернете) – пользуйтесь Hysteria2: в подписке Clash «Авто» выберет её сама, в остальных приложениях – вручную. +3. `kit net site` – новый сайт-прикрытие; `kit net on reality2` – дополнительный REALITY на другом порту. + Один протокол не подключается – попробуйте соседний: у каждого свои сильные стороны (Hysteria2 работает по UDP, остальные по TCP). В подписке Clash «Авто» выбирает сама, в остальных приложениях – вручную. 4. Не помогло – перенесите сервер на другой адрес: `kit backup`, на новом сервере `bash 3x-ui.sh --restore файл`. Если подписка выдавалась на домене, а не на IP, клиентам достаточно сменить адрес в DNS. diff --git a/manuals/3x-ui.md b/manuals/3x-ui.md index 172b414..9282490 100644 --- a/manuals/3x-ui.md +++ b/manuals/3x-ui.md @@ -159,7 +159,7 @@ kit check --fix # исправить безопасное `kit check` проверяет службы, версии, срок сертификата, что панель не торчит наружу, права на файлы с паролями и ключами, ответ подписки для Happ, Hiddify, v2rayN и Clash, а также что сайт маскировки отвечает по -TLS 1.3 и HTTP/2, и подсказывает, что сделать заметнее (известный сайт на чужом IP, лишние порты). Вывод можно просто прислать в чат, если нужна помощь. +TLS 1.3 и HTTP/2, и подсказывает, что улучшить (сайт маскировки, лишние порты). Вывод можно просто прислать в чат, если нужна помощь. `kit check --fix` лечит только безопасное: перезапускает упавшие службы, возвращает права `600`, включает автообновление, перечитывает сертификат и снимает TLS у встроенной подписки 3X-UI (его включает команда @@ -182,7 +182,7 @@ kit net masq on # Hysteria2 отвечает на чужой зап ``` Лучший сайт маскировки – ваш собственный домен (`--domain` при установке): сервер изображает ваш сайт, а сертификат -и имя совпадают. Без домена установщик ищет сайт среди соседей по подсети сервера: это незаметнее, чем известный +и имя совпадают. Без домена установщик ищет сайт среди соседей по подсети сервера: он естественнее, чем известный сайт на чужом IP. Основные протоколы – REALITY, XHTTP и Hysteria2; остальные запасные, их можно выключить командой `kit net off`. diff --git a/scripts/3x-ui.sh b/scripts/3x-ui.sh index 877c31f..62e61b2 100755 --- a/scripts/3x-ui.sh +++ b/scripts/3x-ui.sh @@ -116,12 +116,12 @@ sni_alive() { sni_ok "$1"; } SNI_RE='^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)+$' -# Бесплатные и динамические имена (sslip.io, work.gd и т. п.) любят чужие прокси-серверы: под них маскироваться не стоит. +# Бесплатные и динамические имена (sslip.io, work.gd и т. п.) часто используют чужие прокси-серверы: под них маскироваться не стоит. SNI_DYN_RE='(^|\.)(sslip\.io|nip\.io|xip\.io|traefik\.me|work\.gd|duckdns\.org|ddns\.net|hopto\.org|zapto\.org|myftp\.biz|dynu\.net|freeddns\.org|no-ip\.(org|biz|info)|nom\.za|tk|ml|ga|cf|gq)$' -# Известные сайты на чужом IP заметны: сайт-прикрытие должен быть «своим» для подсети сервера. +# Известные сайты на чужом IP не подходят: сайт-прикрытие должен быть «своим» для подсети сервера. SNI_BRAND_RE='(^|\.)(google|googleapis|gstatic|youtube|microsoft|windows|apple|icloud|amazon|amazonaws|samsung|yahoo|cloudflare|facebook|instagram|netflix|github|telegram)\.[a-z.]+$' -# Имена с «сомнительными» словами не берём: маскироваться под такой сайт неприятно и небезопасно для вас. +# Имена с «сомнительными» словами не берём: брать такой сайт для маскировки неприятно и небезопасно для вас. SNI_BAD_RE='(probiv|porn|xxx|sex|adult|casino|bet|vpn|proxy|torrent|crack|hack|warez|drug|weapon|leak|escort|gambl|poker)' # У сайта настоящий сертификат: цепочка проходит проверку, имя совпадает. @@ -1002,7 +1002,7 @@ proto_reality() { } # Второй REALITY на высоком свободном порту, напрямую (без nginx). Где-то 443 и привычные порты -# проходят хуже, чем высокий случайный; ключи, shortId и порт у него свои, сайт маскировки тот же. +# бывает удобнее высокий случайный порт; ключи, shortId и порт у него свои, сайт маскировки тот же. proto_reality2() { local keys stream settings port keys=$(api GET server/getNewX25519Cert) @@ -1080,7 +1080,7 @@ proto_ss() { proto_hy2() { local settings stream settings=$(jq -nc --arg a "$(rand_str 16)" --argjson c "$(client_base hy2)" '{version: 2, clients: [$c + {auth: $a}]}') - # На чужой HTTP/3-запрос сервер отвечает страницей сайта (masquerade), а не молчанием или ошибкой. + # На посторонний HTTP/3-запрос сервер отвечает страницей сайта (masquerade), а не молчанием или ошибкой. stream=$(jq -nc --argjson t "$(tls_json '["h3"]')" --arg page "${STUB_HTML:-}" '{network: "hysteria", security: "tls", tlsSettings: $t, hysteriaSettings: ({version: 2} + (if $page != "" then {masquerade: {type: "string", content: $page, statusCode: 200, headers: {"content-type": "text/html; charset=utf-8"}}} else {} end))}') add_inbound "Hysteria2" "$PORT" udp hysteria "$settings" "$stream" @@ -1815,7 +1815,7 @@ PY warn "IP сервера сменился: $old_ip → $HOST." echo "Старые подписки указывают на старый IP, поэтому клиентам нужно один раз добавить" echo "подписку заново: ${B}kit user list${N}, затем ${B}kit user link имя${N}." - echo "${D}Чтобы в следующий раз переезд прошёл незаметно для клиентов, ставьте сервер на домен (--cert, --key, --host).${N}" + echo "${D}Чтобы в следующий раз переезд прошёл без хлопот для клиентов, ставьте сервер на домен (--cert, --key, --host).${N}" else echo "Клиентам ничего менять не нужно: ключи, ссылки и подписки те же." fi diff --git a/scripts/kit.sh b/scripts/kit.sh index cd7fa54..75d516f 100644 --- a/scripts/kit.sh +++ b/scripts/kit.sh @@ -837,22 +837,22 @@ check_system() { if ((${used:-0} >= 95)); then c_warn "диск заполнен на ${used}%"; else c_ok "место на диске: занято ${used:-?}%"; fi } -# Заметность: известный сайт на чужом IP и запасные порты, которые на чужой заход отвечают пустой страницей. +# Маскировка: известный сайт на чужом IP и запасные порты, которые на посторонний запрос отвечают пустой страницей. check_stealth() { local id kind remark sni names list while IFS=$'\t' read -r id kind remark sni; do [[ $kind == reality && -n $sni && $sni =~ $SNI_BRAND_RE ]] || continue - same_net "$sni" || c_warn "$remark: $sni – известный сайт на чужом IP, это заметно. Надёжнее сосед по подсети: kit net site" + same_net "$sni" || c_warn "$remark: $sni – известный сайт на чужом IP не годится для маскировки. Лучше сосед по подсети: kit net site" done < <(sni_targets 2>/dev/null || true) list=$(api GET inbounds/list 2>/dev/null) || return 0 if jq -e 'any(.[]; .protocol == "hysteria" and .enable == true)' <<<"$list" >/dev/null && [[ -z $(hy_masq_state) ]]; then - c_warn "Hysteria2 на чужой HTTP/3-запрос отвечает не как сайт. Включить: kit net masq on" + c_warn "Hysteria2 на посторонний HTTP/3-запрос отвечает не как сайт. Включить: kit net masq on" fi if [[ -z $(jq -r '.subJsonDns // ""' <<<"$(api POST setting/all '{}' 2>/dev/null)" 2>/dev/null) ]]; then c_warn "DNS в подписке Xray JSON обычный (UDP 8.8.8.8). Включить DoH через прокси: kit net dns on" fi names=$(jq -r '[.[] | select(.enable == true and .listen != "127.0.0.1" and (.remark == "VLESS-WS" or .remark == "Trojan-gRPC" or .remark == "VMess-WS")) | .remark] | join(", ")' <<<"$list") - [[ -z $names ]] || c_warn "$names открыты на своих портах и на чужой заход отвечают пустой страницей. Не нужны? kit net off имя (режим «всё на 443» их прячет за сайтом)" + [[ -z $names ]] || c_warn "$names открыты на своих портах и на посторонний запрос отвечают пустой страницей. Не нужны? kit net off имя (режим «всё на 443» прячет их за сайтом)" } run_checks() { @@ -1229,12 +1229,12 @@ SNI_POOL=(dl.google.com www.amazon.com www.samsung.com www.yahoo.com www.microso SNI_RE='^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)+$' -# Бесплатные и динамические имена (sslip.io, work.gd и т. п.) любят чужие прокси-серверы: под них маскироваться не стоит. +# Бесплатные и динамические имена (sslip.io, work.gd и т. п.) часто используют чужие прокси-серверы: под них маскироваться не стоит. SNI_DYN_RE='(^|\.)(sslip\.io|nip\.io|xip\.io|traefik\.me|work\.gd|duckdns\.org|ddns\.net|hopto\.org|zapto\.org|myftp\.biz|dynu\.net|freeddns\.org|no-ip\.(org|biz|info)|nom\.za|tk|ml|ga|cf|gq)$' -# Известные сайты на чужом IP заметны: сайт-прикрытие должен быть «своим» для подсети сервера. +# Известные сайты на чужом IP не подходят: сайт-прикрытие должен быть «своим» для подсети сервера. SNI_BRAND_RE='(^|\.)(google|googleapis|gstatic|youtube|microsoft|windows|apple|icloud|amazon|amazonaws|samsung|yahoo|cloudflare|facebook|instagram|netflix|github|telegram)\.[a-z.]+$' -# Имена с «сомнительными» словами не берём: маскироваться под такой сайт неприятно и небезопасно для вас. +# Имена с «сомнительными» словами не берём: брать такой сайт для маскировки неприятно и небезопасно для вас. SNI_BAD_RE='(probiv|porn|xxx|sex|adult|casino|bet|vpn|proxy|torrent|crack|hack|warez|drug|weapon|leak|escort|gambl|poker)' # У сайта настоящий сертификат: цепочка проходит проверку, имя совпадает. @@ -1358,7 +1358,7 @@ sni_rotate() { # [--nearby] [--dry-run] [сайт] say "Ищу сайты в подсети сервера (около 250 коротких подключений к порту 443 соседних адресов)" while read -r a; do [[ -n $a ]] && pool+=("$a"); done < <(nearby_sites) if ((${#pool[@]} == 0)); then - warn "В подсети подходящего сайта не нашёл. Известный сайт на чужом IP заметнее остальных." + warn "В подсети подходящего сайта не нашёл. Известный сайт на чужом IP подходит хуже остальных." echo " Лучший выход – свой домен (установка с --domain) или свой сайт: kit net site сайт.com" if [[ -t 0 ]]; then ask_tty " Взять запасной сайт из списка? [y/N] " @@ -1386,7 +1386,7 @@ sni_rotate() { # [--nearby] [--dry-run] [сайт] done for i in "${!ids[@]}"; do if [[ ${news[$i]} =~ $SNI_BRAND_RE ]] && ! same_net "${news[$i]}"; then - warn "Для ${remarks[$i]} в подсети не хватило сайтов – взят известный сайт из общего списка, он заметнее соседа. Лучше свой сайт: kit net site сайт.com" + warn "Для ${remarks[$i]} в подсети не хватило сайтов – взят известный сайт из общего списка, он подходит хуже соседа. Лучше свой сайт: kit net site сайт.com" break fi done @@ -1645,7 +1645,7 @@ hy_masq() { # on|off [[ -n $page ]] || page='Cumulo Cloud

Cumulo Cloud

Service status: all systems operational.

' inbound_patch "$id" '.streamSettings |= ((if type == "string" then fromjson else . end) | .hysteriaSettings.masquerade = {type: "string", content: $c, statusCode: 200, headers: {"content-type": "text/html; charset=utf-8"}})' --arg c "$page" \ || die "Панель не приняла изменение. Ничего не изменилось." - say "Hysteria2 теперь отвечает на чужой HTTP/3-запрос страницей сайта." + say "Hysteria2 теперь отвечает на посторонний HTTP/3-запрос страницей сайта." else inbound_patch "$id" '.streamSettings |= ((if type == "string" then fromjson else . end) | del(.hysteriaSettings.masquerade))' || die "Панель не приняла изменение." say "Маскировка Hysteria2 выключена." @@ -1732,7 +1732,7 @@ net_show() { echo echo "Отпечаток клиента: ${fpl:-?} (сменить: kit net fp firefox)" if jq -e 'any(.[]; .protocol == "hysteria")' <<<"$list" >/dev/null; then - if [[ -n $(hy_masq_state) ]]; then echo "Hysteria2 отвечает на чужой запрос страницей сайта (выключить: kit net masq off)" + if [[ -n $(hy_masq_state) ]]; then echo "Hysteria2 отвечает на посторонний запрос страницей сайта (выключить: kit net masq off)" else echo "Hysteria2 без маскировки под сайт (включить: kit net masq on)"; fi fi }