🎁 Sync 2026-07-31 00:21:49

This commit is contained in:
github-actions[bot] committed 2026-07-31 00:21:49 +08:00
1 parent f6c3fbbbbe
commit c71b32c9fb
204 files changed
+187145 -10038

No files matched your search

+220
View File
@@ -0,0 +1,220 @@
#!/bin/sh
# Установщик Re:HomeProxy для OpenWrt (в одном скрипте: APK / opkg / 23.05 legacy)
# https://github.com/1andrevich/homeproxy-hiddify
#
# Вручную ставится только LuCI-приложение + ключ подписи, а ядро, ByeDPI и Zapret
# устанавливаются через собственный бэкенд приложения (core_mgmt.uc + rpcd-объект
# luci.homeproxy) — поэтому определение архитектуры, компактные сборки под малую
# флеш-память, проверка подписи и резерв через зеркало GitHub работают той же
# проверенной логикой, что и графический интерфейс.
#
# Установка (одной строкой — ввод читается из /dev/tty, пайп остаётся интерактивным):
# wget -qO- https://raw.githubusercontent.com/1andrevich/homeproxy-hiddify/master/install.sh | sh
# Либо в два шага:
# wget -O /tmp/install.sh https://raw.githubusercontent.com/1andrevich/homeproxy-hiddify/master/install.sh
# sh /tmp/install.sh
#
# При заблокированном/замедленном GitHub можно указать зеркало:
# GH_MIRROR=https://my.mirror sh install.sh
# (зеркало также пишется в uci, чтобы делегированные загрузки тоже его использовали).
# Внимание: `sh <(wget -O- ...)` на OpenWrt НЕ работает — в busybox ash нет
# process substitution; используйте форму с пайпом выше.
G='\033[0;32m'; R='\033[0;31m'; Y='\033[0;33m'; C='\033[0;36m'; N='\033[0m'
ok() { echo -e "${G}$1${N}"; }
info() { echo -e "${C}$1${N}"; }
warn() { echo -e "${Y}$1${N}"; }
die() { echo -e "${R}$1${N}"; exit 1; }
ask() { printf "${C}%s${N} " "$1"; read -r REPLY </dev/tty 2>/dev/null || REPLY=""; }
is_yes() { case "$1" in y|Y|yes|YES|да|Да|д|Д) return 0;; *) return 1;; esac; }
# --- Разбор JSON (на устройстве нет jq): достать строковое поле / проверить result:true
jget() { printf '%s\n' "$1" | sed -n "s/.*\"$2\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" | head -1; }
jtrue() { printf '%s' "$1" | grep -qE "\"result\"[[:space:]]*:[[:space:]]*true"; }
jerr() { printf '%s\n' "$1" | grep -qE "\"error\""; }
jfalse(){ printf '%s' "$1" | grep -qE "\"$2\"[[:space:]]*:[[:space:]]*false"; }
# --- Загрузка «сначала GitHub, при сбое — зеркало» для первого хопа (app + ключ),
# пока ещё нет собственного gh_fetch приложения. dl <url> <файл>
dl() {
wget -qO "$2" --timeout=20 "$1" 2>/dev/null && [ -s "$2" ] && return 0
if [ -n "$GH_MIRROR" ]; then
m=$(echo "$1" | sed "s#https://github.com#${GH_MIRROR}#")
wget -qO "$2" --timeout=20 "$m" 2>/dev/null && [ -s "$2" ] && return 0
fi
return 1
}
api() { wget -qO- --timeout=20 "$1" 2>/dev/null; } # GitHub API (без зеркала)
echo
ok "===== Установщик Re:HomeProxy ====="
# ---------------------------------------------------------------- 0. окружение
[ "$(id -u)" = 0 ] || die "Запустите от root."
[ -r /etc/openwrt_release ] || die "Это не OpenWrt (нет /etc/openwrt_release)."
. /etc/openwrt_release 2>/dev/null
ARCH="$DISTRIB_ARCH"; VER="$DISTRIB_RELEASE"
[ -n "$ARCH" ] || die "Не удалось определить архитектуру пакетов (DISTRIB_ARCH)."
if command -v apk >/dev/null 2>&1; then PM=apk; EXT=apk
elif command -v opkg >/dev/null 2>&1; then PM=opkg; EXT=ipk
else die "Не найден поддерживаемый менеджер пакетов (apk/opkg)."; fi
case "$VER" in
23.05*) LEGACY=1 ;;
24.10*|25.*|*SNAPSHOT*) LEGACY=0 ;;
22.*|21.*|19.*) die "OpenWrt $VER слишком старая — нужна 23.05 или новее." ;;
*) LEGACY=0; warn "Непроверенная версия OpenWrt $VER — продолжаю." ;;
esac
SUFFIX="_all"; [ "$LEGACY" = 1 ] && SUFFIX="_all-legacy"
info "Версия: OpenWrt $VER | Архитектура: $ARCH | Менеджер пакетов: $PM | legacy=$LEGACY"
# ----------------------------------------------------------- 1. LuCI-приложение + ключ
ok "[1/5] Устанавливаю LuCI-приложение Re:HomeProxy..."
if [ "$PM" = apk ]; then
if [ ! -f /etc/apk/keys/homeproxy-hiddify.pub ]; then
dl "https://github.com/1andrevich/homeproxy-hiddify/releases/latest/download/homeproxy-hiddify.pub" /tmp/hp.pub \
&& cp /tmp/hp.pub /etc/apk/keys/ && rm -f /tmp/hp.pub && ok " ключ подписи добавлен в доверенные" \
|| warn " не удалось скачать ключ подписи — поставлю без проверки подписи"
fi
fi
APPURL=$(api 'https://api.github.com/repos/1andrevich/homeproxy-hiddify/releases' \
| grep -o "https://github\.com/[^\"]*luci-app-re-homeproxy[^\"]*${SUFFIX}\.${EXT}" | head -1)
[ -n "$APPURL" ] || die "Не нашёл пакет luci-app-re-homeproxy${SUFFIX}.${EXT} (GitHub заблокирован? попробуйте GH_MIRROR=...)."
dl "$APPURL" /tmp/app.$EXT || die "Не удалось скачать приложение (попробуйте GH_MIRROR=...)."
if [ "$PM" = apk ]; then
apk add /tmp/app.$EXT 2>/dev/null || apk add --allow-untrusted /tmp/app.$EXT || die "apk add завершился ошибкой."
else
opkg update >/dev/null 2>&1; opkg install /tmp/app.$EXT || die "opkg install завершился ошибкой."
fi
rm -f /tmp/app.$EXT
ok " приложение установлено."
# Русский язык интерфейса (по умолчанию — да)
ask " Установить пакет русского языка? [Y/n] (по умолчанию Y):"
case "$REPLY" in
n|N|no|NO|нет|Нет|н|Н) ;; # отказ — пропускаем
*)
info " ставлю русский язык LuCI..."
# базовый перевод интерфейса LuCI (из фида, best-effort)
if [ "$PM" = apk ]; then apk add luci-i18n-base-ru >/dev/null 2>&1; else opkg install luci-i18n-base-ru >/dev/null 2>&1; fi
# перевод самого приложения (из релиза homeproxy)
LURL=$(api 'https://api.github.com/repos/1andrevich/homeproxy-hiddify/releases' \
| grep -o "https://github\.com/[^\"]*luci-i18n-homeproxy-ru[^\"]*\.${EXT}" | head -1)
if [ -n "$LURL" ] && dl "$LURL" /tmp/i18n.$EXT; then
if [ "$PM" = apk ]; then apk add /tmp/i18n.$EXT 2>/dev/null || apk add --allow-untrusted /tmp/i18n.$EXT; \
else opkg install /tmp/i18n.$EXT; fi
else warn " перевод приложения не найден — пропускаю"; fi
rm -f /tmp/i18n.$EXT
uci set luci.main.lang=ru; uci commit luci
ok " русский язык установлен" ;;
esac
# Прописываем зеркало в бэкенд, чтобы делегированные загрузки тоже его использовали
if [ -n "$GH_MIRROR" ]; then uci set homeproxy.config.github_mirror="$GH_MIRROR"; uci commit homeproxy; fi
# rpcd нужно перезапустить, чтобы появились ubus-методы приложения (установка ByeDPI/Zapret)
/etc/init.d/rpcd restart >/dev/null 2>&1; sleep 2
CM=/usr/share/homeproxy/scripts/core_mgmt.uc
[ -f "$CM" ] || die "core_mgmt.uc не найден после установки — прерываю."
# ------------------------------------------------------- 2. ядро прокси (обязательно)
ok "[2/5] Ядро прокси (обязательно — выберите одно)"
echo " 1) hiddify-core (по умолчанию; на малой флеш-памяти выберет компактную сборку)"
echo " 2) sing-box-extended (AmneziaWG / WARP, самый широкий набор протоколов)"
ask " Выбор [1/2] (по умолчанию 1):"
case "$REPLY" in 2) CORE=singbox ;; *) CORE=hiddify ;; esac
PREP=$(ucode "$CM" prepare_install "$CORE")
jerr "$PREP" && die " подготовка ядра не удалась: $(jget "$PREP" error)"
DLURL=$(jget "$PREP" dl_url); TMP=$(jget "$PREP" tmp_path); PMG=$(jget "$PREP" pkg_manager)
[ -n "$DLURL" ] && [ -n "$TMP" ] && [ -n "$PMG" ] || die " подготовка ядра не вернула данные для загрузки."
info " скачиваю $CORE..."
jtrue "$(ucode "$CM" download_pkg "$DLURL" "$TMP")" || die " не удалось скачать ядро (попробуйте GH_MIRROR=...)."
jtrue "$(ucode "$CM" install_pkg "$CORE" "$TMP" "$PMG")" || die " установка ядра не удалась."
jtrue "$(ucode "$CM" install_kmods "$PMG")" || warn " не удалось поставить kmod — без kmod-nft-tproxy/kmod-tun прокси не будет маршрутизировать."
ok " $CORE установлен."
# --------------------------------------------------------------- 3. Zapret (опционально)
ask "[3/5] Установить Zapret 2 (обход DPI на уровне пакетов — видео/QUIC, звонки)? [y/N]:"
if is_yes "$REPLY"; then
info " ставлю модуль ядра NFQUEUE..."
if [ "$PM" = apk ]; then apk add kmod-nft-queue >/dev/null 2>&1; else opkg install kmod-nft-queue >/dev/null 2>&1; fi
ZP=$(ubus call luci.homeproxy zapret_prepare_install 2>/dev/null)
if [ -z "$ZP" ] || jerr "$ZP"; then warn " не удалось подготовить Zapret — пропускаю. ($(jget "$ZP" error))"
else
ZURL=$(jget "$ZP" dl_url); ZTMP=$(jget "$ZP" tmp_path); ZPMG=$(jget "$ZP" pkg_manager)
if [ -n "$ZURL" ] && dl "$ZURL" "$ZTMP"; then
RES=$(ubus call luci.homeproxy zapret_install_pkg "{\"tmp_path\":\"$ZTMP\",\"pkg_manager\":\"$ZPMG\"}" 2>/dev/null)
if jtrue "$RES"; then
ok " Zapret установлен."
ZST=$(ubus call luci.homeproxy zapret_status 2>/dev/null)
if jfalse "$ZST" kmod_ok; then
warn " модуль NFQUEUE не загружен — Zapret не включаю (иначе сломается firewall). Включите вручную после kmod-nft-queue."
else
uci set homeproxy.config.zapret_enabled=1; uci commit homeproxy; ok " Zapret включён."
fi
else warn " установка Zapret не удалась."; fi
else warn " не удалось скачать Zapret — пропускаю."; fi
fi
fi
# --------------------------------------------------------------- 4. ByeDPI (опционально)
ask "[4/5] Установить ByeDPI (обход DPI на уровне SOCKS, нужен curl)? [y/N]:"
if is_yes "$REPLY"; then
info " ставлю curl (его использует тестер стратегий ByeDPI)..."
if [ "$PM" = apk ]; then apk add curl >/dev/null 2>&1; else opkg install curl >/dev/null 2>&1; fi
BP=$(ubus call luci.homeproxy byedpi_prepare_install 2>/dev/null)
if [ -z "$BP" ] || jerr "$BP"; then warn " не удалось подготовить ByeDPI — пропускаю. ($(jget "$BP" error))"
else
BURL=$(jget "$BP" dl_url); BTMP=$(jget "$BP" tmp_path); BPMG=$(jget "$BP" pkg_manager)
if [ -n "$BURL" ] && dl "$BURL" "$BTMP"; then
RES=$(ubus call luci.homeproxy byedpi_install_pkg "{\"tmp_path\":\"$BTMP\",\"pkg_manager\":\"$BPMG\"}" 2>/dev/null)
if jtrue "$RES"; then
ok " ByeDPI установлен."
uci set homeproxy.config.byedpi_enabled=1; uci commit homeproxy; ok " ByeDPI включён."
else warn " установка ByeDPI не удалась."; fi
else warn " не удалось скачать ByeDPI — пропускаю."; fi
fi
fi
# ------------------------------------------------- 5. режим маршрутизации (пресет)
ask "[5/5] Настроить режим «Россия — раздельное туннелирование» (Re:filter через основной сервер)? [Д/н] (по умолчанию да):"
case "$REPLY" in
n|N|no|NO|нет|Нет|н|Н) ;; # отказ — оставляем как есть
*)
CURMODE=$(uci -q get homeproxy.config.routing_mode)
if [ -z "$CURMODE" ]; then
uci set homeproxy.config.routing_mode=proxy_banned_ru
uci set homeproxy.config.proxy_calls=1
uci set homeproxy.config.no_proxy_torrents=1
uci set homeproxy.config.ipv6_support=0
uci commit homeproxy
CURMODE=proxy_banned_ru
fi
# Re:filter через основной пул — только если режим РФ и правил ещё нет
if [ "$CURMODE" = proxy_banned_ru ] && ! uci show homeproxy 2>/dev/null | grep -q "=proxy_ru_rule$"; then
SEC=$(uci add homeproxy proxy_ru_rule)
uci set "homeproxy.$SEC.source=refilter"
uci set "homeproxy.$SEC.node=main-out"
uci set "homeproxy.$SEC.enabled=1"
uci commit homeproxy
ok " режим настроен: Re:filter через основной сервер"
else
info " режим/правила уже заданы — не меняю"
fi ;;
esac
# ------------------------------------------------------------------- 6. финал
/etc/init.d/homeproxy enable >/dev/null 2>&1
/etc/init.d/homeproxy start >/dev/null 2>&1
# LAN-адрес роутера для прямой ссылки на страницу LuCI (обрезаем /маску на 25.12+)
LANIP=$(uci -q get network.lan.ipaddr | cut -d/ -f1)
[ -n "$LANIP" ] || LANIP=$(ip -4 addr show br-lan 2>/dev/null | sed -n 's#.*inet \([0-9.]*\).*#\1#p' | head -1)
[ -n "$LANIP" ] || LANIP="192.168.1.1"
echo
ok "===== Готово ====="
info "Откройте Re:HomeProxy в браузере:"
URL="http://$LANIP/cgi-bin/luci/admin/services/homeproxy"
# OSC 8: кликабельная ссылка в поддерживающих терминалах; в остальных просто виден URL
printf '\033[0;36m \033]8;;%s\033\\%s\033]8;;\033\\\033[0m\n' "$URL" "$URL"