mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-08-02 15:39:31 +08:00
221 lines
14 KiB
Bash
221 lines
14 KiB
Bash
#!/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"
|