Версия 0.6.0
Заменяет tpws на utunws (форк nfqws под utun+BPF из Flowseal/zapret-mac-discord-youtube) на macOS: движок уровня пакетов вместо socks5-прокси даёт macOS те же 22 стратегии Flowseal, что у Windows и Linux, включая fake-пакеты и десинк UDP/QUIC — раньше tpws этого не умел вовсе. Обход теперь ставится как LaunchDaemon (resources/darwin-helper/), пароль администратора спрашивается при каждом включении/выключении, тот же принцип, что pkexec на Linux. Системный прокси и авто-список hostlist-auto больше не нужны и убраны. README: Windows отмечена как гарантированно рабочая, macOS и Linux — как частично.
This commit is contained in:
Executable
+133
@@ -0,0 +1,133 @@
|
||||
#!/bin/sh
|
||||
# Привилегированная установка обхода блокировок на macOS — единственное, что RKNboost
|
||||
# запускает через osascript "with administrator privileges" (см. elevate.darwin.ts) для
|
||||
# включения обхода. Не редактировать под bash-специфику: этот файл исполняется как
|
||||
# /bin/sh — на macOS это тот же путь, что и на Linux, но лучше не полагаться на bashisms.
|
||||
#
|
||||
# Зовётся из src/main/zapret/utunws.darwin.ts ровно так:
|
||||
# osascript … 'do shell script "'\''<этот файл>'\'' '\''<utunws>'\'' …" with administrator privileges'
|
||||
#
|
||||
# Аргументы (все уже подготовлены и провалидированы на стороне приложения — сюда попадают
|
||||
# только готовые пути и провалидированные строки портов, тот же принцип, что у Linux-
|
||||
# помощника resources/linux-helper/rknboost-helper.sh):
|
||||
# 1: utunws_src — путь к бинарнику utunws в resources/zapret/darwin (ещё не установлен)
|
||||
# 2: fakes_src — каталог с fake-пакетами (resources/zapret/fakes)
|
||||
# 3: config_src — уже отрендеренный strategy.cfg (маркер --comment=rknboost:<id>:<hash>
|
||||
# первой строкой, пути {LISTS}/{FAKES} уже резолвлены — см. strategies.ts)
|
||||
# 4: tcp_ports — список портов TCP для pf, формат "80,443,8443" (уже проверен регуляркой
|
||||
# в packetEngineConfig())
|
||||
# 5: udp_ports — то же для UDP
|
||||
# 6: run_at_load — 0 или 1: должен ли демон переживать перезагрузку системы без
|
||||
# запущенного приложения (настройка «Автозапуск» в интерфейсе)
|
||||
set -eu
|
||||
|
||||
HELPER_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
||||
DEST='/Library/Application Support/RKNboost/zapret'
|
||||
LABEL=com.rknboost.zapret
|
||||
PLIST=/Library/LaunchDaemons/$LABEL.plist
|
||||
ANCHOR=com.apple/rknboost
|
||||
PIDFILE=/var/run/rknboost-zapret.pid
|
||||
TOKEN_FILE=/var/run/rknboost-zapret.pf-token
|
||||
KEEPINIT_FILE=/var/db/rknboost-zapret.keepinit
|
||||
|
||||
if [ "$#" -ne 6 ]; then
|
||||
echo 'install.sh: ожидается 6 аргументов' >&2
|
||||
exit 1
|
||||
fi
|
||||
UTUNWS_SRC=$1
|
||||
FAKES_SRC=$2
|
||||
CONFIG_SRC=$3
|
||||
TCP_PORTS=$4
|
||||
UDP_PORTS=$5
|
||||
RUN_AT_LOAD=$6
|
||||
|
||||
[ -x "$UTUNWS_SRC" ] || { echo 'install.sh: не найден бинарник utunws' >&2; exit 1; }
|
||||
[ -d "$FAKES_SRC" ] || { echo 'install.sh: не найден каталог fake-пакетов' >&2; exit 1; }
|
||||
[ -f "$CONFIG_SRC" ] || { echo 'install.sh: не найден strategy.cfg' >&2; exit 1; }
|
||||
# Формат уже проверен регуляркой в packetEngineConfig()/utunwsConfig() — здесь просто не
|
||||
# доверяем слепо тому, что дошло до root, тот же приём, что в rknboost-helper.sh на Linux.
|
||||
# ':' — не опечатка: utunwsConfig() переводит диапазоны в синтаксис pf (19294-19344 →
|
||||
# 19294:19344, см. toPfPortRanges() в strategies.ts), дефисов в этих строках уже нет.
|
||||
case ",$TCP_PORTS," in *[!0-9,:]*) echo 'install.sh: странный формат tcp-портов' >&2; exit 1 ;; esac
|
||||
case ",$UDP_PORTS," in *[!0-9,:]*) echo 'install.sh: странный формат udp-портов' >&2; exit 1 ;; esac
|
||||
case "$RUN_AT_LOAD" in
|
||||
0) RUNATLOAD=false ;;
|
||||
1) RUNATLOAD=true ;;
|
||||
*) echo 'install.sh: run_at_load должен быть 0 или 1' >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Сносим прошлую установку — самолечение на случай аварийно прерванной прошлой сессии,
|
||||
# тот же приём, что cmd_stop() в rknboost-helper.sh на Linux делает первым шагом start.
|
||||
/bin/launchctl bootout system/"$LABEL" >/dev/null 2>&1 || true
|
||||
/sbin/pfctl -a "$ANCHOR" -F all >/dev/null 2>&1 || true
|
||||
# Матчим процесс по полному пути НАШЕЙ установки, а не по имени: "utunws" называется так
|
||||
# же и у независимо установленного Flowseal/zapret-mac-discord-youtube — pkill -x убил бы
|
||||
# чужой процесс, если пользователь пользуется обоими приложениями одновременно.
|
||||
/usr/bin/pkill -9 -f "$DEST/bin/utunws" >/dev/null 2>&1 || true
|
||||
if [ -s "$TOKEN_FILE" ]; then
|
||||
TOKEN=$(/bin/cat "$TOKEN_FILE" 2>/dev/null || true)
|
||||
if [ -n "$TOKEN" ]; then /sbin/pfctl -X "$TOKEN" >/dev/null 2>&1 || true; fi
|
||||
/bin/rm -f "$TOKEN_FILE"
|
||||
fi
|
||||
/bin/rm -f "$PIDFILE"
|
||||
|
||||
# Копия, а не запуск прямо из resources/zapret приложения: root не должен исполнять файл
|
||||
# из каталога, куда обычный пользователь может писать (то же рассуждение, что у
|
||||
# protectedWinwsPath() в paths.ts на Windows). daemon.sh/watchdog.sh лежат рядом с этим
|
||||
# скриптом в bundledDarwinHelperDir() — тоже часть сборки, тоже копируем в защищённое место.
|
||||
/bin/rm -rf "$DEST/bin" "$DEST/fakes"
|
||||
/bin/mkdir -p "$DEST/bin" "$DEST/fakes"
|
||||
/usr/bin/ditto "$UTUNWS_SRC" "$DEST/bin/utunws"
|
||||
/usr/bin/ditto "$FAKES_SRC" "$DEST/fakes"
|
||||
/usr/bin/ditto "$HELPER_DIR/daemon.sh" "$DEST/daemon.sh"
|
||||
/usr/bin/ditto "$HELPER_DIR/watchdog.sh" "$DEST/watchdog.sh"
|
||||
# Скачанный релиз-архив помечен com.apple.quarantine — карантин на исполняемый файл внутри
|
||||
# защищённого каталога, который запускает launchd, только мешал бы.
|
||||
/usr/bin/xattr -dr com.apple.quarantine "$DEST" >/dev/null 2>&1 || true
|
||||
|
||||
/usr/bin/install -m 0644 "$CONFIG_SRC" "$DEST/strategy.cfg"
|
||||
printf '%s\n%s\n' "$TCP_PORTS" "$UDP_PORTS" > "$DEST/ports.conf"
|
||||
|
||||
/usr/sbin/chown -R root:wheel "$DEST"
|
||||
/bin/chmod 755 "$DEST" "$DEST/bin" "$DEST/bin/utunws" "$DEST/daemon.sh" "$DEST/watchdog.sh" "$DEST/fakes"
|
||||
/bin/chmod 644 "$DEST/strategy.cfg" "$DEST/ports.conf"
|
||||
|
||||
/usr/bin/sed \
|
||||
-e "s|@LABEL@|$LABEL|g" \
|
||||
-e "s|@DEST@|$DEST|g" \
|
||||
-e "s|@RUNATLOAD@|$RUNATLOAD|g" \
|
||||
"$HELPER_DIR/com.rknboost.zapret.plist.in" > "$PLIST"
|
||||
/usr/sbin/chown root:wheel "$PLIST"
|
||||
/bin/chmod 644 "$PLIST"
|
||||
|
||||
# net.inet.tcp.keepinit=7000 удлиняет время до TCP RST на этапе установления соединения —
|
||||
# desync нужно время сработать. Сохраняем исходное значение один раз, откатываем в stop.sh.
|
||||
if [ ! -s "$KEEPINIT_FILE" ]; then
|
||||
/usr/sbin/sysctl -n net.inet.tcp.keepinit > "$KEEPINIT_FILE"
|
||||
/bin/chmod 600 "$KEEPINIT_FILE"
|
||||
fi
|
||||
/usr/sbin/sysctl -w net.inet.tcp.keepinit=7000 >/dev/null
|
||||
|
||||
/bin/launchctl enable system/"$LABEL"
|
||||
I=0
|
||||
while ! /bin/launchctl bootstrap system "$PLIST"; do
|
||||
I=$((I + 1))
|
||||
if [ "$I" -gt 10 ]; then
|
||||
/bin/sh "$HELPER_DIR/stop.sh"
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.5
|
||||
done
|
||||
/bin/launchctl kickstart -k system/"$LABEL"
|
||||
|
||||
I=0
|
||||
while ! /sbin/ifconfig utun60 >/dev/null 2>&1; do
|
||||
I=$((I + 1))
|
||||
if [ "$I" -gt 100 ]; then
|
||||
/bin/sh "$HELPER_DIR/stop.sh"
|
||||
echo 'install.sh: utunws не поднялся' >&2
|
||||
/usr/bin/tail -n 40 "$DEST/engine.log" >&2 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
Reference in New Issue
Block a user