Update ByeTube version to 1.01 and improve output
This commit is contained in:
1 parent
4ed6940c88
commit
77979af667
1 file changed
+135
-158
+135
-158
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# ByeTube for LuCI installer
|
# ByeTube for LuCI installer
|
||||||
# Version: 1.0
|
# Version: 1.01
|
||||||
|
|
||||||
|
GREEN="\033[1;32m"; MAGENTA="\033[1;35m"; NC="\033[0m"
|
||||||
|
|
||||||
BYEDPI_REPO="DPITrickster/ByeDPI-OpenWrt"
|
BYEDPI_REPO="DPITrickster/ByeDPI-OpenWrt"
|
||||||
R="${BT_ROOT:-}"
|
R="${BT_ROOT:-}"
|
||||||
@@ -12,18 +14,16 @@ LEGACY=0
|
|||||||
MODE=install
|
MODE=install
|
||||||
NOSTART=0
|
NOSTART=0
|
||||||
|
|
||||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
|
||||||
warn() { printf '\033[1;33m!! \033[0m%s\n' "$*" >&2; }
|
|
||||||
die() { printf '\033[1;31mОшибка:\033[0m %s\n' "$*" >&2; exit 1; }
|
die() { printf '\033[1;31mОшибка:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
ByeTube — установщик для OpenWrt
|
ByeTube — установщик для OpenWrt
|
||||||
|
|
||||||
sh install.sh установить и запустить
|
sh ByeTube.sh установить и запустить
|
||||||
sh install.sh --no-start установить, но не запускать
|
sh ByeTube.sh --no-start установить, но не запускать
|
||||||
sh install.sh --uninstall удалить (пакеты byedpi и hev остаются)
|
sh ByeTube.sh --uninstall удалить (пакеты byedpi и hev остаются)
|
||||||
sh install.sh --purge удалить вместе с пакетами byedpi и hev-socks5-tunnel
|
sh ByeTube.sh --purge удалить вместе с пакетами byedpi и hev-socks5-tunnel
|
||||||
|
|
||||||
BYEDPI_URL=<ссылка на .ipk/.apk> поставить byedpi с конкретной ссылки
|
BYEDPI_URL=<ссылка на .ipk/.apk> поставить byedpi с конкретной ссылки
|
||||||
FORCE_BYEDPI=1 переустановить byedpi
|
FORCE_BYEDPI=1 переустановить byedpi
|
||||||
@@ -47,8 +47,8 @@ pkg_has() {
|
|||||||
if [ "$PM" = apk ]; then apk info -e "$1" >/dev/null 2>&1
|
if [ "$PM" = apk ]; then apk info -e "$1" >/dev/null 2>&1
|
||||||
else opkg list-installed 2>/dev/null | grep -q "^$1 - "; fi
|
else opkg list-installed 2>/dev/null | grep -q "^$1 - "; fi
|
||||||
}
|
}
|
||||||
pkg_add() { if [ "$PM" = apk ]; then apk add "$@"; else opkg install "$@"; fi; }
|
pkg_add() { if [ "$PM" = apk ]; then apk add "$@"; else opkg install "$@"; fi >/dev/null 2>&1; }
|
||||||
pkg_del() { if [ "$PM" = apk ]; then apk del "$@"; else opkg remove "$@"; fi; }
|
pkg_del() { if [ "$PM" = apk ]; then apk del "$@"; else opkg remove "$@"; fi >/dev/null 2>&1; }
|
||||||
|
|
||||||
fetch() {
|
fetch() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
@@ -149,14 +149,11 @@ BT_FILE_END_7f3a9c
|
|||||||
}
|
}
|
||||||
|
|
||||||
do_uninstall() {
|
do_uninstall() {
|
||||||
say "Останавливаю и удаляю ByeTube"
|
echo -e "\n${MAGENTA}Удаляем ByeTube${NC}"
|
||||||
[ -x "$R$BT_DIR/bin/byetube" ] && "$R$BT_DIR/bin/byetube" test stop >/dev/null 2>&1
|
[ -x "$R$BT_DIR/bin/byetube" ] && "$R$BT_DIR/bin/byetube" test stop >/dev/null 2>&1
|
||||||
run_uninstall
|
run_uninstall >/dev/null 2>&1
|
||||||
if [ "$MODE" = purge ]; then
|
[ "$MODE" = purge ] && pkg_del byedpi hev-socks5-tunnel
|
||||||
say "Удаляю пакеты byedpi и hev-socks5-tunnel"
|
echo -e "ByeTube ${GREEN}удалён!${NC}\n"
|
||||||
pkg_del byedpi hev-socks5-tunnel >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
say "Готово."
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,19 +168,14 @@ fix_resolv() {
|
|||||||
|
|
||||||
ensure_dnsmasq_full() {
|
ensure_dnsmasq_full() {
|
||||||
local p
|
local p
|
||||||
if dnsmasq --version 2>/dev/null | grep -Eq '(^| )nftset( |$)'; then
|
dnsmasq --version 2>/dev/null | grep -Eq '(^| )nftset( |$)' && return 0
|
||||||
say "dnsmasq с поддержкой nftset уже установлен"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
say "Заменяю dnsmasq на dnsmasq-full (нужен nftset)"
|
|
||||||
mkdir -p "$BT_TMP_DIR"
|
mkdir -p "$BT_TMP_DIR"
|
||||||
cp /etc/config/dhcp "$BT_TMP_DIR/dhcp.bak" 2>/dev/null
|
cp /etc/config/dhcp "$BT_TMP_DIR/dhcp.bak" 2>/dev/null
|
||||||
for p in dnsmasq dnsmasq-dhcpv6; do
|
for p in dnsmasq dnsmasq-dhcpv6; do
|
||||||
pkg_has "$p" && pkg_del "$p" >/dev/null 2>&1
|
pkg_has "$p" && pkg_del "$p"
|
||||||
done
|
done
|
||||||
fix_resolv
|
fix_resolv
|
||||||
if ! pkg_add dnsmasq-full; then
|
if ! pkg_add dnsmasq-full; then
|
||||||
warn "не удалось поставить dnsmasq-full, возвращаю обычный dnsmasq"
|
|
||||||
fix_resolv
|
fix_resolv
|
||||||
pkg_add dnsmasq
|
pkg_add dnsmasq
|
||||||
[ -f /etc/config/dhcp ] || cp "$BT_TMP_DIR/dhcp.bak" /etc/config/dhcp 2>/dev/null
|
[ -f /etc/config/dhcp ] || cp "$BT_TMP_DIR/dhcp.bak" /etc/config/dhcp 2>/dev/null
|
||||||
@@ -197,13 +189,9 @@ ensure_dnsmasq_full() {
|
|||||||
|
|
||||||
install_byedpi() {
|
install_byedpi() {
|
||||||
local url json cands f
|
local url json cands f
|
||||||
if [ -x /usr/bin/ciadpi ] && [ "${FORCE_BYEDPI:-0}" != 1 ]; then
|
[ -x /usr/bin/ciadpi ] && [ "${FORCE_BYEDPI:-0}" != 1 ] && return 0
|
||||||
say "ByeDPI уже установлен"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
url="${BYEDPI_URL:-}"
|
url="${BYEDPI_URL:-}"
|
||||||
if [ -z "$url" ]; then
|
if [ -z "$url" ]; then
|
||||||
say "Ищу пакет byedpi ($ARCH, .$EXT) в $BYEDPI_REPO"
|
|
||||||
json=$(fetch "https://api.github.com/repos/$BYEDPI_REPO/releases?per_page=40" - 2>/dev/null)
|
json=$(fetch "https://api.github.com/repos/$BYEDPI_REPO/releases?per_page=40" - 2>/dev/null)
|
||||||
cands=$(printf '%s\n' "$json" \
|
cands=$(printf '%s\n' "$json" \
|
||||||
| grep -o '"browser_download_url": *"[^"]*"' \
|
| grep -o '"browser_download_url": *"[^"]*"' \
|
||||||
@@ -213,11 +201,10 @@ install_byedpi() {
|
|||||||
[ -n "$url" ] || url=$(printf '%s\n' "$cands" | head -n 1)
|
[ -n "$url" ] || url=$(printf '%s\n' "$cands" | head -n 1)
|
||||||
fi
|
fi
|
||||||
[ -n "$url" ] || die "не нашёл пакет byedpi для $ARCH (.$EXT). Скачайте вручную с https://github.com/$BYEDPI_REPO/releases и запустите: BYEDPI_URL=<ссылка> sh install.sh"
|
[ -n "$url" ] || die "не нашёл пакет byedpi для $ARCH (.$EXT). Скачайте вручную с https://github.com/$BYEDPI_REPO/releases и запустите: BYEDPI_URL=<ссылка> sh install.sh"
|
||||||
say "Скачиваю $url"
|
|
||||||
mkdir -p "$BT_TMP_DIR/dl"
|
mkdir -p "$BT_TMP_DIR/dl"
|
||||||
f="$BT_TMP_DIR/dl/$(basename "$url")"
|
f="$BT_TMP_DIR/dl/$(basename "$url")"
|
||||||
fetch "$url" "$f" || die "не удалось скачать byedpi"
|
fetch "$url" "$f" || die "не удалось скачать byedpi"
|
||||||
if [ "$PM" = apk ]; then apk add --allow-untrusted "$f"; else opkg install "$f"; fi \
|
{ if [ "$PM" = apk ]; then apk add --allow-untrusted "$f"; else opkg install "$f"; fi; } >/dev/null 2>&1 \
|
||||||
|| die "не удалось установить byedpi"
|
|| die "не удалось установить byedpi"
|
||||||
rm -rf "$BT_TMP_DIR/dl"
|
rm -rf "$BT_TMP_DIR/dl"
|
||||||
NEW_BYEDPI=1
|
NEW_BYEDPI=1
|
||||||
@@ -1004,7 +991,7 @@ BT_TMP="${BT_TMP:-/tmp/ByeTube}"
|
|||||||
BT_FUNCTIONS="${BT_FUNCTIONS:-/lib/functions.sh}"
|
BT_FUNCTIONS="${BT_FUNCTIONS:-/lib/functions.sh}"
|
||||||
BT_DEFAULT="$BT_HOME/default"
|
BT_DEFAULT="$BT_HOME/default"
|
||||||
BT_CUSTOM="$BT_HOME/custom"
|
BT_CUSTOM="$BT_HOME/custom"
|
||||||
BT_VERSION="1.0"
|
BT_VERSION="1.01"
|
||||||
|
|
||||||
TUN=byetube0
|
TUN=byetube0
|
||||||
MARK=0x10000
|
MARK=0x10000
|
||||||
@@ -2020,39 +2007,63 @@ BT_FILE_END_7f3a9c
|
|||||||
var LIST = [
|
var LIST = [
|
||||||
{
|
{
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
label: '1 · Каскад (по умолчанию)',
|
label: 'Стратегия 1',
|
||||||
name: '1 · Каскад disorder/split + tlsrec + md5sig, авто-режим -As (по умолчанию)',
|
name: 'Стратегия 1',
|
||||||
opts: '-d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -r1+s -S -a1 -As -d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -S -a1'
|
opts: '-d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -r1+s -S -a1 -As -d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -S -a1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'p2',
|
id: 'p2',
|
||||||
label: '2 · OOB + tlsrec',
|
label: 'Стратегия 2',
|
||||||
name: '2 · Короткая: OOB + tlsrec у SNI',
|
name: 'Стратегия 2',
|
||||||
opts: '-o1 -a1 -r-5+se'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'p3',
|
|
||||||
label: '3 · Fake SNI + OOB',
|
|
||||||
name: '3 · Fake SNI google.com + disorder/OOB (TTL 4)',
|
|
||||||
opts: '-n "google.com" -Qr -d5+sm -f3+sm -o2 -t4 -a1'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'p4',
|
|
||||||
label: '4 · Каскад без tlsrec',
|
|
||||||
name: '4 · Каскад disorder/split без tlsrec и авто-режима',
|
|
||||||
opts: '-d1 -s1+s -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -a1'
|
opts: '-d1 -s1+s -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -a1'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'p3',
|
||||||
|
label: 'Стратегия 3',
|
||||||
|
name: 'Стратегия 3',
|
||||||
|
opts: '-d1 -s1+s -d1+s -s3+s -d6+s -s12+s -d14+s -s20+s -d24+s -s30+s -a1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'p4',
|
||||||
|
label: 'Стратегия 4',
|
||||||
|
name: 'Стратегия 4',
|
||||||
|
opts: '-d1 -s1+s -s3+s -s6+s -s9+s -s12+s -s15+s -s20+s -s30+s -a1'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'p5',
|
id: 'p5',
|
||||||
label: '5 · Fake + disoob',
|
label: 'Стратегия 5',
|
||||||
name: '5 · Fake + disoob + tlsrec (TTL 5 и 15)',
|
name: 'Стратегия 5',
|
||||||
opts: '-f1 -t5 -n "google.com" -q3+h -Qr -f2 -q1 -r1+s -t15 -q1 -o2 -a1'
|
opts: '-d1 -s4 -d8 -s1+s -d5+s -s10+s -d20+s -a1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'p6',
|
id: 'p6',
|
||||||
label: '6 · OOB + авто-режим',
|
label: 'Стратегия 6',
|
||||||
name: '6 · OOB + tlsrec + авто-режим -At,r,s, fake google.com',
|
name: 'Стратегия 6',
|
||||||
opts: '-o1 -r-5+se -a1 -At,r,s -d1 -n "google.com" -Qr -f-1 -a1'
|
opts: '-o1 -r-5+se -a1 -At,r,s -d1 -n "google.com" -Qr -f-1 -a1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'p7',
|
||||||
|
label: 'Стратегия 7',
|
||||||
|
name: 'Стратегия 7',
|
||||||
|
opts: '-f-1 -n "google.com" -Qr -s2+s -r3 -o20 -t4 -a1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'p8',
|
||||||
|
label: 'Стратегия 8',
|
||||||
|
name: 'Стратегия 8',
|
||||||
|
opts: '-f64+se -n "google.com" -t5 -a1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'p9',
|
||||||
|
label: 'Стратегия 9',
|
||||||
|
name: 'Стратегия 9',
|
||||||
|
opts: '-o1 -r-5+se -a1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'p10',
|
||||||
|
label: 'Стратегия 10',
|
||||||
|
name: 'Стратегия 10',
|
||||||
|
opts: '-o1 -a1 -r-5+se'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -2126,6 +2137,15 @@ function btn(label, cls, onclick) {
|
|||||||
return E('button', { 'class': 'cbi-button' + (cls ? ' ' + cls : ''), 'click': onclick }, [ label ]);
|
return E('button', { 'class': 'cbi-button' + (cls ? ' ' + cls : ''), 'click': onclick }, [ label ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cmdNodes(text) {
|
||||||
|
var out = [];
|
||||||
|
String(text).split(' ').forEach(function(tok, i) {
|
||||||
|
if (i) out.push(' ');
|
||||||
|
out.push(E('span', { 'class': 'bt-tok' }, [ tok ]));
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
function hint(text) {
|
function hint(text) {
|
||||||
return E('p', { 'class': 'zm-hint' }, [ text ]);
|
return E('p', { 'class': 'zm-hint' }, [ text ]);
|
||||||
}
|
}
|
||||||
@@ -2245,23 +2265,27 @@ return view.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderMain() {
|
function renderMain() {
|
||||||
var kids = [ E('h3', {}, [ 'Состояние' ]) ];
|
var items = [];
|
||||||
kids.push(row('Служба', isWorking()
|
items.push(row('Служба', isWorking()
|
||||||
? bt.badge(true, 'работает', '')
|
? bt.badge(true, 'работает', '')
|
||||||
: bt.badge(false, '', st.enabled ? 'запущена не полностью' : 'выключена')));
|
: bt.badge(false, '', st.enabled ? 'запущена не полностью' : 'выключена')));
|
||||||
if (st.binaries === false)
|
if (st.binaries === false)
|
||||||
kids.push(row('Пакеты', bt.badge(false, '', 'не найден byedpi или hev-socks5-tunnel')));
|
items.push(row('Пакеты', bt.badge(false, '', 'не найден byedpi или hev-socks5-tunnel')));
|
||||||
kids.push(row('ByeDPI (ciadpi)', bt.badge(st.byedpi, 'запущен', 'не запущен')));
|
items.push(row('ByeDPI (ciadpi)', bt.badge(st.byedpi, 'запущен', 'не запущен')));
|
||||||
kids.push(row('hev-socks5-tunnel', bt.badge(st.hev, 'запущен', 'не запущен')));
|
items.push(row('hev-socks5-tunnel', bt.badge(st.hev, 'запущен', 'не запущен')));
|
||||||
kids.push(row('Интерфейс byetube0', bt.badge(st.tun, 'поднят', 'нет')));
|
items.push(row('Интерфейс byetube0', bt.badge(st.tun, 'поднят', 'нет')));
|
||||||
kids.push(row('Маркировка nftables', bt.badge(st.nft, 'активна', 'нет')));
|
items.push(row('Маркировка nftables', bt.badge(st.nft, 'активна', 'нет')));
|
||||||
kids.push(row('Policy routing', bt.badge(st.rule && st.route, 'активен', 'нет')));
|
items.push(row('Policy routing', bt.badge(st.rule && st.route, 'активен', 'нет')));
|
||||||
kids.push(row('dnsmasq → nftset', st.dnsmasq_nftset === false
|
items.push(row('dnsmasq → nftset', st.dnsmasq_nftset === false
|
||||||
? bt.badge(false, '', 'нужен dnsmasq-full')
|
? bt.badge(false, '', 'нужен dnsmasq-full')
|
||||||
: bt.badge(st.dns, 'домены загружены', 'нет')));
|
: bt.badge(st.dns, 'домены загружены', 'нет')));
|
||||||
kids.push(row('Firewall forward', bt.badge(st.fw, 'разрешён', 'нет')));
|
items.push(row('Firewall forward', bt.badge(st.fw, 'разрешён', 'нет')));
|
||||||
kids.push(row('IP в наборах', E('span', {}, [ 'IPv4: ' + (st.ips4 || 0) + (st.ipv6 ? ', IPv6: ' + (st.ips6 || 0) : '') ])));
|
items.push(row('IP в наборах', E('span', {}, [ 'IPv4: ' + (st.ips4 || 0) + (st.ipv6 ? ', IPv6: ' + (st.ips6 || 0) : '') ])));
|
||||||
kids.push(row('Версия', E('span', {}, [ 'v' + (st.version || '?') ])));
|
var half = Math.ceil(items.length / 2);
|
||||||
|
var kids = [ E('div', { 'class': 'bt-cols' }, [
|
||||||
|
E('div', { 'class': 'bt-col' }, items.slice(0, half)),
|
||||||
|
E('div', { 'class': 'bt-col' }, items.slice(half))
|
||||||
|
]) ];
|
||||||
kids.push(E('div', { 'class': 'zm-actions' }, [
|
kids.push(E('div', { 'class': 'zm-actions' }, [
|
||||||
st.enabled
|
st.enabled
|
||||||
? btn('Выключить', 'cbi-button-remove', function() {
|
? btn('Выключить', 'cbi-button-remove', function() {
|
||||||
@@ -2341,15 +2365,16 @@ return view.extend({
|
|||||||
'class': 'zm-config-editor',
|
'class': 'zm-config-editor',
|
||||||
'spellcheck': 'false',
|
'spellcheck': 'false',
|
||||||
'wrap': 'soft',
|
'wrap': 'soft',
|
||||||
|
'placeholder': 'Параметры ciadpi одной строкой',
|
||||||
'style': 'min-height:130px;white-space:pre-wrap'
|
'style': 'min-height:130px;white-space:pre-wrap'
|
||||||
}, [ cfg.byedpi_opts || '' ]);
|
}, [ '' ]);
|
||||||
|
|
||||||
function renderStrategy() {
|
function renderStrategy() {
|
||||||
var cur = currentPreset();
|
var cur = currentPreset();
|
||||||
fill(bannerEl, cfg.byedpi_opts
|
fill(bannerEl, cfg.byedpi_opts
|
||||||
? [ E('span', {}, [ 'Сейчас применено: ' ]), E('b', {}, [ cur ? cur.name : 'своя стратегия' ]) ]
|
? [ E('div', { 'class': 'bt-current-label' }, [ 'Сейчас применено' ]), E('div', { 'class': 'bt-current-cmd' }, cmdNodes(cfg.byedpi_opts)) ]
|
||||||
: [ E('span', {}, [ 'Стратегия ещё не выбрана' ]) ]);
|
: [ E('span', {}, [ 'Стратегия ещё не выбрана' ]) ]);
|
||||||
bannerEl.className = 'zm-current-banner' + (cfg.byedpi_opts ? '' : ' zm-current-empty');
|
bannerEl.className = 'zm-current-banner bt-current' + (cfg.byedpi_opts ? '' : ' zm-current-empty');
|
||||||
|
|
||||||
fill(presetsCard, [
|
fill(presetsCard, [
|
||||||
E('h3', {}, [ 'Готовые стратегии' ]),
|
E('h3', {}, [ 'Готовые стратегии' ]),
|
||||||
@@ -2358,7 +2383,6 @@ return view.extend({
|
|||||||
setStrategy(p.opts, p.label);
|
setStrategy(p.opts, p.label);
|
||||||
}, p.name + '\n' + p.opts);
|
}, p.name + '\n' + p.opts);
|
||||||
})),
|
})),
|
||||||
cfg.byedpi_opts ? E('div', { 'class': 'bt-cmd-line' }, [ cfg.byedpi_opts ]) : '',
|
|
||||||
hint('Стратегия зависит от провайдера — лучшую под вашего провайдера найдёт вкладка «Тест стратегий».')
|
hint('Стратегия зависит от провайдера — лучшую под вашего провайдера найдёт вкладка «Тест стратегий».')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2534,24 +2558,13 @@ return view.extend({
|
|||||||
function renderResults(text) {
|
function renderResults(text) {
|
||||||
resultsText = text || '';
|
resultsText = text || '';
|
||||||
var res = bt.parseResults(resultsText);
|
var res = bt.parseResults(resultsText);
|
||||||
if (!res.rows.length && !res.control) {
|
if (!res.rows.length) {
|
||||||
fill(testResults, [ E('h3', {}, [ 'Результаты' ]), hint(running ? 'Тест выполняется…' : 'Пока нет результатов — запустите тест.') ]);
|
fill(testResults, [ E('h3', {}, [ 'Результаты' ]), hint(running ? 'Тест выполняется…' : 'Пока нет результатов — запустите тест.') ]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var controlOk = res.control ? res.control.ok : null;
|
var controlOk = res.control ? res.control.ok : null;
|
||||||
var curClean = presets.clean(cfg.byedpi_opts);
|
var curClean = presets.clean(cfg.byedpi_opts);
|
||||||
|
|
||||||
var legend = E('div', { 'class': 'bt-legend' }, []);
|
|
||||||
if (res.control) {
|
|
||||||
legend.appendChild(document.createTextNode('Контрольный замер (без обхода): '));
|
|
||||||
legend.appendChild(E('span', { 'class': 'bt-chip bt-chip-off' }, [ res.control.ok + '/' + res.control.total ]));
|
|
||||||
legend.appendChild(E('br'));
|
|
||||||
}
|
|
||||||
legend.appendChild(E('span', { 'class': 'bt-chip bt-chip-ok' }, [ 'все домены' ]));
|
|
||||||
legend.appendChild(E('span', { 'class': 'bt-chip bt-chip-warn' }, [ 'лучше контроля' ]));
|
|
||||||
legend.appendChild(E('span', { 'class': 'bt-chip bt-chip-bad' }, [ 'не лучше' ]));
|
|
||||||
legend.appendChild(document.createTextNode('При равенстве выше стоит стратегия, что раньше в списке.'));
|
|
||||||
|
|
||||||
var rows = res.rows.map(function(r, i) {
|
var rows = res.rows.map(function(r, i) {
|
||||||
var p = presets.find(r.opts);
|
var p = presets.find(r.opts);
|
||||||
var isCur = presets.clean(r.opts) === curClean;
|
var isCur = presets.clean(r.opts) === curClean;
|
||||||
@@ -2561,7 +2574,7 @@ return view.extend({
|
|||||||
if (isCur) nm.appendChild(bt.span('bt-c-cur', (p ? ' ' : '') + '(текущая)'));
|
if (isCur) nm.appendChild(bt.span('bt-c-cur', (p ? ' ' : '') + '(текущая)'));
|
||||||
body.push(nm);
|
body.push(nm);
|
||||||
}
|
}
|
||||||
body.push(E('div', { 'class': 'bt-cmd' }, [ r.opts ]));
|
body.push(E('div', { 'class': 'bt-cmd' }, cmdNodes(r.opts)));
|
||||||
return E('tr', {}, [
|
return E('tr', {}, [
|
||||||
E('td', { 'class': 'bt-td-n' }, [ String(i + 1) ]),
|
E('td', { 'class': 'bt-td-n' }, [ String(i + 1) ]),
|
||||||
E('td', { 'class': 'bt-td-s' }, [ E('span', { 'class': bt.chipClass(r.ok, r.total, controlOk) }, [ r.ok + '/' + r.total ]) ]),
|
E('td', { 'class': 'bt-td-s' }, [ E('span', { 'class': bt.chipClass(r.ok, r.total, controlOk) }, [ r.ok + '/' + r.total ]) ]),
|
||||||
@@ -2578,7 +2591,6 @@ return view.extend({
|
|||||||
fill(testResults, [
|
fill(testResults, [
|
||||||
E('h3', {}, [ 'Результаты' ]),
|
E('h3', {}, [ 'Результаты' ]),
|
||||||
E('div', { 'class': 'zm-log zm-show bt-panel' }, [
|
E('div', { 'class': 'zm-log zm-show bt-panel' }, [
|
||||||
legend,
|
|
||||||
E('table', { 'class': 'bt-table' }, [ E('tbody', {}, rows) ])
|
E('table', { 'class': 'bt-table' }, [ E('tbody', {}, rows) ])
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
@@ -2821,13 +2833,6 @@ html.zm-theme-dark .zm-config-editor { border-color: rgba(255,255,255,.14); }
|
|||||||
|
|
||||||
.zm-hint { font-size: 12px; opacity: .65; margin-top: 6px; line-height: 1.5; overflow-wrap: break-word; }
|
.zm-hint { font-size: 12px; opacity: .65; margin-top: 6px; line-height: 1.5; overflow-wrap: break-word; }
|
||||||
|
|
||||||
.zm-refresh-banner {
|
|
||||||
display: flex; align-items: center; justify-content: space-between; gap: 14px;
|
|
||||||
background: rgba(191,135,0,.12); border: 2px solid rgba(191,135,0,.35);
|
|
||||||
color: #9a6700; border-radius: 12px; padding: 16px 20px; font-size: 15px; font-weight: 500;
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
.zm-refresh-banner button { flex-shrink: 0; }
|
|
||||||
|
|
||||||
#zm-toast-container {
|
#zm-toast-container {
|
||||||
position: fixed; top: 20px; right: 20px; z-index: 10000;
|
position: fixed; top: 20px; right: 20px; z-index: 10000;
|
||||||
@@ -2863,6 +2868,24 @@ html.zm-theme-dark .zm-config-editor { border-color: rgba(255,255,255,.14); }
|
|||||||
background: rgba(110,118,129,.08); border-color: rgba(110,118,129,.2);
|
background: rgba(110,118,129,.08); border-color: rgba(110,118,129,.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bt-cols { display: grid; grid-template-columns: 1fr 1fr; column-gap: 44px; }
|
||||||
|
.bt-col { min-width: 0; }
|
||||||
|
.bt-col .zm-label { flex: 0 0 170px; }
|
||||||
|
@media (max-width: 860px) {
|
||||||
|
.bt-cols { grid-template-columns: 1fr; }
|
||||||
|
.bt-col .zm-row { justify-content: space-between; }
|
||||||
|
.bt-col .zm-label { flex: 0 1 auto; }
|
||||||
|
.bt-col .zm-row > :last-child { margin-left: auto; }
|
||||||
|
}
|
||||||
|
.bt-current { flex-direction: column; align-items: stretch; gap: 8px; padding: 14px 18px; }
|
||||||
|
.bt-current-label { font-size: 13px; font-weight: 700; }
|
||||||
|
.bt-current-cmd {
|
||||||
|
background: #0d1117; color: #7ee787;
|
||||||
|
font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", monospace;
|
||||||
|
font-size: 14px; line-height: 1.65;
|
||||||
|
border-radius: 8px; padding: 12px 14px;
|
||||||
|
white-space: normal; user-select: all;
|
||||||
|
}
|
||||||
.bt-panel { display: block; max-height: none; min-height: 0; margin-top: 10px; }
|
.bt-panel { display: block; max-height: none; min-height: 0; margin-top: 10px; }
|
||||||
.bt-table { width: 100%; table-layout: fixed; border-collapse: collapse; border-spacing: 0; margin: 0; background: transparent; }
|
.bt-table { width: 100%; table-layout: fixed; border-collapse: collapse; border-spacing: 0; margin: 0; background: transparent; }
|
||||||
.bt-table td { padding: 8px 8px 8px 0; border: 0; border-top: 1px solid rgba(255,255,255,.10); vertical-align: top; background: transparent; color: inherit; white-space: normal; overflow-wrap: anywhere; }
|
.bt-table td { padding: 8px 8px 8px 0; border: 0; border-top: 1px solid rgba(255,255,255,.10); vertical-align: top; background: transparent; color: inherit; white-space: normal; overflow-wrap: anywhere; }
|
||||||
@@ -2877,7 +2900,8 @@ html.zm-theme-dark .zm-config-editor { border-color: rgba(255,255,255,.14); }
|
|||||||
.bt-table td { display: block; width: auto; border: 0 !important; padding: 0 !important; }
|
.bt-table td { display: block; width: auto; border: 0 !important; padding: 0 !important; }
|
||||||
.bt-table td.bt-td-c { grid-column: 1 / -1; grid-row: 2; margin-top: 7px; }
|
.bt-table td.bt-td-c { grid-column: 1 / -1; grid-row: 2; margin-top: 7px; }
|
||||||
}
|
}
|
||||||
.bt-cmd { color: #e6edf3; white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; }
|
.bt-cmd { color: #e6edf3; white-space: normal; }
|
||||||
|
.bt-tok { white-space: nowrap; }
|
||||||
.bt-name { color: #8b949e; margin-bottom: 2px; }
|
.bt-name { color: #8b949e; margin-bottom: 2px; }
|
||||||
.bt-chip { display: inline-block; min-width: 4.4em; text-align: center; padding: 1px 8px; border-radius: 5px; font-weight: 700; color: #0d1117; }
|
.bt-chip { display: inline-block; min-width: 4.4em; text-align: center; padding: 1px 8px; border-radius: 5px; font-weight: 700; color: #0d1117; }
|
||||||
.bt-chip-ok { background: #3fb950; }
|
.bt-chip-ok { background: #3fb950; }
|
||||||
@@ -2891,10 +2915,7 @@ html.zm-theme-dark .zm-config-editor { border-color: rgba(255,255,255,.14); }
|
|||||||
.bt-c-white { color: #e6edf3; }
|
.bt-c-white { color: #e6edf3; }
|
||||||
.bt-c-key { color: #e3c04a; font-weight: 700; }
|
.bt-c-key { color: #e3c04a; font-weight: 700; }
|
||||||
.bt-c-cur { color: #56d4dd; font-weight: 700; }
|
.bt-c-cur { color: #56d4dd; font-weight: 700; }
|
||||||
.bt-legend { margin-bottom: 10px; color: #8b949e; }
|
|
||||||
.bt-legend .bt-chip { margin-right: 6px; }
|
|
||||||
.bt-input { width: 110px; box-sizing: border-box; }
|
.bt-input { width: 110px; box-sizing: border-box; }
|
||||||
.bt-cmd-line { font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", monospace; font-size: 12px; opacity: .75; overflow-wrap: anywhere; margin-top: 6px; }
|
|
||||||
.cbi-page-actions { display: none !important; }
|
.cbi-page-actions { display: none !important; }
|
||||||
BT_FILE_END_7f3a9c
|
BT_FILE_END_7f3a9c
|
||||||
chmod 644 "$R/www/luci-static/resources/view/byetube/style.css"
|
chmod 644 "$R/www/luci-static/resources/view/byetube/style.css"
|
||||||
@@ -2902,68 +2923,46 @@ BT_FILE_END_7f3a9c
|
|||||||
}
|
}
|
||||||
|
|
||||||
migrate_legacy() {
|
migrate_legacy() {
|
||||||
local f moved=""
|
local f
|
||||||
if [ ! -e "$R/etc/config/ytbypass" ] && [ ! -e "$R/etc/init.d/ytbypass" ] \
|
if [ ! -e "$R/etc/config/ytbypass" ] && [ ! -e "$R/etc/init.d/ytbypass" ] \
|
||||||
&& [ ! -d "$R/usr/libexec/ytbypass" ] && [ ! -e "$R/usr/bin/ytbypass" ]; then
|
&& [ ! -d "$R/usr/libexec/ytbypass" ] && [ ! -e "$R/usr/bin/ytbypass" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
say "Найдена прежняя установка YouTube Bypass — переношу настройки в ByeTube"
|
|
||||||
LEGACY=1
|
LEGACY=1
|
||||||
if [ -f "$R/etc/config/ytbypass" ] && [ ! -f "$R/etc/config/byetube" ]; then
|
if [ -f "$R/etc/config/ytbypass" ] && [ ! -f "$R/etc/config/byetube" ]; then
|
||||||
mkdir -p "$R/etc/config"
|
mkdir -p "$R/etc/config"
|
||||||
sed 's/^config ytbypass\([[:space:]]\)/config byetube\1/' "$R/etc/config/ytbypass" > "$R/etc/config/byetube"
|
sed 's/^config ytbypass\([[:space:]]\)/config byetube\1/' "$R/etc/config/ytbypass" > "$R/etc/config/byetube"
|
||||||
moved="настройки"
|
|
||||||
fi
|
fi
|
||||||
for f in strategies.txt test-domains.txt; do
|
for f in strategies.txt test-domains.txt; do
|
||||||
if [ -s "$R/etc/ytbypass/$f" ] && [ ! -e "$R$BT_DIR/custom/$f" ]; then
|
if [ -s "$R/etc/ytbypass/$f" ] && [ ! -e "$R$BT_DIR/custom/$f" ]; then
|
||||||
mkdir -p "$R$BT_DIR/custom"
|
mkdir -p "$R$BT_DIR/custom"
|
||||||
cp "$R/etc/ytbypass/$f" "$R$BT_DIR/custom/$f"
|
cp "$R/etc/ytbypass/$f" "$R$BT_DIR/custom/$f"
|
||||||
moved="$moved${moved:+, }$f"
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
[ -n "$moved" ] && say "Перенесено: $moved"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_legacy() {
|
finish_legacy() {
|
||||||
[ "$LEGACY" = 1 ] || return 0
|
[ "$LEGACY" = 1 ] || return 0
|
||||||
say "Удаляю прежнюю установку ytbypass"
|
run_uninstall --legacy >/dev/null 2>&1
|
||||||
run_uninstall --legacy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_default_strategy() {
|
update_default_strategy() {
|
||||||
local old1 old2 new cur
|
local old new cur
|
||||||
old1='--split 1 --disorder 3+s --mod-http=h,d --auto=torst --tlsrec 1+s'
|
old='--split 1 --disorder 3+s --mod-http=h,d --auto=torst --tlsrec 1+s'
|
||||||
old2='-o1 -r-5+se -a1 -At,r,s -d1 -n "google.com" -Qr -f-1 -a1'
|
|
||||||
new='-d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -r1+s -S -a1 -As -d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -S -a1'
|
new='-d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -r1+s -S -a1 -As -d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s -S -a1'
|
||||||
cur=$(uci -q get byetube.main.byedpi_opts)
|
cur=$(uci -q get byetube.main.byedpi_opts)
|
||||||
if [ "$cur" = "$old1" ] || [ "$cur" = "$old2" ]; then
|
if [ "$cur" = "$old" ]; then
|
||||||
uci set byetube.main.byedpi_opts="$new" && uci commit byetube
|
uci set byetube.main.byedpi_opts="$new" && uci commit byetube
|
||||||
say "Стратегия по умолчанию обновлена"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
show_state() {
|
verify_running() {
|
||||||
local ST IPS
|
local ST
|
||||||
ST=$("$BT_DIR/bin/byetube" status 2>/dev/null)
|
ST=$("$BT_DIR/bin/byetube" status 2>/dev/null)
|
||||||
show() {
|
case "$ST" in *'"enabled":true'*) ;; *) return 0 ;; esac
|
||||||
if [ "$(jsonfilter -s "$ST" -e "@.$1" 2>/dev/null)" = "true" ]; then
|
case "$ST" in *'"byedpi":true'*'"hev":true'*'"tun":true'*) return 0 ;; esac
|
||||||
printf ' \033[32m[ok]\033[0m %s\n' "$2"
|
return 1
|
||||||
else
|
|
||||||
printf ' \033[31m[--]\033[0m %s\n' "$2"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
echo
|
|
||||||
say "Состояние:"
|
|
||||||
show byedpi "ByeDPI (ciadpi)"
|
|
||||||
show hev "hev-socks5-tunnel"
|
|
||||||
show tun "интерфейс byetube0"
|
|
||||||
show nft "правила nftables"
|
|
||||||
show route "policy routing"
|
|
||||||
show dns "dnsmasq -> nftset"
|
|
||||||
show fw "firewall forward"
|
|
||||||
IPS=$(jsonfilter -s "$ST" -e '@.ips4' 2>/dev/null)
|
|
||||||
echo " IP youtube.com в наборе после тестового резолва: ${IPS:-0}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
@@ -2986,10 +2985,10 @@ main() {
|
|||||||
|
|
||||||
[ "$MODE" = install ] || do_uninstall
|
[ "$MODE" = install ] || do_uninstall
|
||||||
|
|
||||||
say "OpenWrt $DISTRIB_RELEASE, архитектура $ARCH, менеджер пакетов: $PM"
|
echo -e "\n${MAGENTA}Устанавливаем ByeTube${NC}"
|
||||||
|
|
||||||
command -v fw4 >/dev/null 2>&1 || die "нужен firewall4 (OpenWrt 22.03+); hev-socks5-tunnel в пакетах — с 24.10"
|
command -v fw4 >/dev/null 2>&1 || die "нужен firewall4 (OpenWrt 22.03+); hev-socks5-tunnel в пакетах — с 24.10"
|
||||||
command -v nft >/dev/null 2>&1 || die "не найден nft"
|
command -v nft >/dev/null 2>&1 || die "не найден nft"
|
||||||
[ -d /www/luci-static/resources ] || warn "LuCI не найден — веб-интерфейс работать не будет (установите luci)"
|
|
||||||
|
|
||||||
if ip rule add pref 8999 fwmark 0x10000/0x10000 lookup 89 2>/dev/null; then
|
if ip rule add pref 8999 fwmark 0x10000/0x10000 lookup 89 2>/dev/null; then
|
||||||
ip rule del pref 8999 2>/dev/null
|
ip rule del pref 8999 2>/dev/null
|
||||||
@@ -2997,22 +2996,19 @@ main() {
|
|||||||
die "ваш ip не поддерживает fwmark с маской. Установите ip-full: замените ip-tiny на ip-full и запустите установщик снова"
|
die "ваш ip не поддерживает fwmark с маской. Установите ip-full: замените ip-tiny на ip-full и запустите установщик снова"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
say "Обновляю списки пакетов"
|
if [ "$PM" = apk ]; then apk update >/dev/null 2>&1; else opkg update >/dev/null 2>&1; fi
|
||||||
if [ "$PM" = apk ]; then apk update >/dev/null 2>&1 || warn "apk update не удался"
|
|
||||||
else opkg update >/dev/null 2>&1 || warn "opkg update не удался"; fi
|
|
||||||
|
|
||||||
pkg_has kmod-tun || { say "Ставлю kmod-tun"; pkg_add kmod-tun || die "kmod-tun не установлен"; }
|
pkg_has kmod-tun || pkg_add kmod-tun || die "kmod-tun не установлен"
|
||||||
ensure_dnsmasq_full
|
ensure_dnsmasq_full
|
||||||
|
|
||||||
if ! pkg_has hev-socks5-tunnel; then
|
if ! pkg_has hev-socks5-tunnel; then
|
||||||
say "Ставлю hev-socks5-tunnel"
|
|
||||||
pkg_add hev-socks5-tunnel || die "hev-socks5-tunnel не найден в репозитории (есть в feeds OpenWrt 24.10+)"
|
pkg_add hev-socks5-tunnel || die "hev-socks5-tunnel не найден в репозитории (есть в feeds OpenWrt 24.10+)"
|
||||||
NEW_HEV=1
|
NEW_HEV=1
|
||||||
fi
|
fi
|
||||||
install_byedpi
|
install_byedpi
|
||||||
|
|
||||||
for p in ca-bundle curl; do
|
for p in ca-bundle curl; do
|
||||||
pkg_has "$p" || pkg_add "$p" >/dev/null 2>&1 || warn "не удалось поставить $p — тест стратегий работать не будет (остальное — да)"
|
pkg_has "$p" || pkg_add "$p"
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$NEW_BYEDPI" = 1 ] && [ -x /etc/init.d/byedpi ]; then
|
if [ "$NEW_BYEDPI" = 1 ] && [ -x /etc/init.d/byedpi ]; then
|
||||||
@@ -3023,40 +3019,21 @@ main() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
migrate_legacy
|
migrate_legacy
|
||||||
say "Устанавливаю ByeTube (сервис + LuCI) в $BT_DIR"
|
|
||||||
install_payload
|
install_payload
|
||||||
finish_legacy
|
finish_legacy
|
||||||
rm -rf /tmp/luci-indexcache* /tmp/luci-modulecache
|
rm -rf /tmp/luci-indexcache* /tmp/luci-modulecache
|
||||||
/etc/init.d/rpcd reload >/dev/null 2>&1
|
/etc/init.d/rpcd reload >/dev/null 2>&1
|
||||||
|
|
||||||
update_default_strategy
|
update_default_strategy
|
||||||
/etc/init.d/byetube enable
|
/etc/init.d/byetube enable >/dev/null 2>&1
|
||||||
|
|
||||||
if [ "$NOSTART" = 1 ]; then
|
if [ "$NOSTART" != 1 ]; then
|
||||||
say "Установлено. Запуск пропущен (--no-start): /etc/init.d/byetube start"
|
/etc/init.d/byetube restart >/dev/null 2>&1
|
||||||
exit 0
|
sleep 4
|
||||||
|
verify_running || die "ByeTube установлен, но служба не запустилась. Смотрите: logread -e byetube"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
say "Запускаю"
|
echo -e "ByeTube ${GREEN}установлен!${NC}\n"
|
||||||
/etc/init.d/byetube restart
|
|
||||||
sleep 4
|
|
||||||
nslookup youtube.com 127.0.0.1 >/dev/null 2>&1
|
|
||||||
sleep 1
|
|
||||||
show_state
|
|
||||||
|
|
||||||
cat <<MSG
|
|
||||||
|
|
||||||
Готово. Веб-интерфейс: LuCI -> Службы -> ByeTube.
|
|
||||||
Все файлы приложения — в $BT_DIR, временные — в $BT_TMP_DIR.
|
|
||||||
Проверка: откройте YouTube на устройстве в LAN (DNS — роутер), затем на роутере:
|
|
||||||
$BT_DIR/bin/byetube status состояние
|
|
||||||
$BT_DIR/bin/byetube ips IP, попавшие в наборы
|
|
||||||
$BT_DIR/bin/byetube diag диагностика клиента
|
|
||||||
logread -e byetube логи
|
|
||||||
|
|
||||||
Если клиент уже держал IP YouTube в DNS-кэше — перезапустите браузер / переподключите Wi-Fi.
|
|
||||||
Удаление: sh install.sh --uninstall
|
|
||||||
MSG
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ -n "${BT_LIB_ONLY:-}" ] || main "$@"
|
[ -n "${BT_LIB_ONLY:-}" ] || main "$@"
|
||||||
Reference in new issue
Block a user