mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
feat(installer): токен на клиента и TTL для веб-раздачи
This commit is contained in:
+17
-12
@@ -6,7 +6,7 @@
|
||||
|
||||
## Автоматическая установка (Рекомендуется)
|
||||
|
||||
Проще всего использовать официальный скрипт. Он автоматически установит зависимости, настроит **AmneziaWG (AWG 3.1)** или WireGuard, поднимет контейнеры через Docker Compose, сгенерирует ключи обфускации, создаст первого клиента и покажет **QR-код** для мгновенного импорта в приложение AmneziaWG.
|
||||
Проще всего использовать официальный скрипт. Он автоматически установит зависимости, настроит **AmneziaWG (AWG 3.1)**, поднимет контейнеры через Docker Compose, сгенерирует ключи обфускации, создаст первого клиента и выдаст **ссылки на QR-коды и конфиги** для импорта в приложение.
|
||||
|
||||
**Интерактивный мастер** (задаст вопросы в терминале):
|
||||
```bash
|
||||
@@ -27,7 +27,7 @@ freeturn client list
|
||||
freeturn client qr phone
|
||||
|
||||
# Скачивание файлов напрямую на ПК (выполняется в PowerShell / терминале ПК):
|
||||
# scp root@<vps_ip>:/opt/free-turn-proxy/clients/phone* .
|
||||
# scp -r root@<vps_ip>:/opt/free-turn-proxy/clients/phone .
|
||||
|
||||
# Удалить клиента
|
||||
freeturn client remove phone
|
||||
@@ -36,11 +36,13 @@ freeturn client remove phone
|
||||
freeturn
|
||||
```
|
||||
|
||||
> Ссылки на QR и конфиги временные: живут `--web-ttl` секунд (по умолчанию 15 минут), потом порт закрывается. У каждого клиента ссылка своя и равносильна его конфигу - делитесь осторожно; сбросить все сразу - `rm /opt/free-turn-proxy/web.token`.
|
||||
|
||||
**Неинтерактивный режим** (для автоматизации / CI):
|
||||
```bash
|
||||
# Установка через Docker с AmneziaWG бэкендом (AWG 3.1, порт 51820)
|
||||
curl -fsSL https://raw.githubusercontent.com/samosvalishe/free-turn-proxy/master/scripts/install.sh | \
|
||||
sudo bash -s -- -y --backend awg --backend-port 51820 --obf rtpopus3
|
||||
sudo bash -s -- -y --backend-port 51820 --obf rtpopus3
|
||||
|
||||
# Обновление до конкретной версии
|
||||
freeturn -y --update --version v1.2.3
|
||||
@@ -69,7 +71,7 @@ openssl rand -hex 32
|
||||
```
|
||||
2. Создайте директорию и `docker-compose.yml`:
|
||||
```bash
|
||||
mkdir -p /opt/free-turn-proxy/awg /opt/free-turn-proxy/clients && cd /opt/free-turn-proxy
|
||||
mkdir -p /opt/free-turn-proxy/awg /opt/free-turn-proxy/auth && cd /opt/free-turn-proxy
|
||||
nano docker-compose.yml
|
||||
```
|
||||
3. Вставьте конфигурацию (совместный запуск прокси и AmneziaWG бэкенда):
|
||||
@@ -86,9 +88,9 @@ openssl rand -hex 32
|
||||
- MODE=udp # udp (WG/AmneziaWG) или tcp (Xray/VLESS)
|
||||
- OBF_PROFILE=rtpopus3 # Рекомендуемая маскировка (RTP/opus + RFC 8285 + ChaCha20)
|
||||
- OBF_KEY=<ВАШ_КЛЮЧ> # 64-hex ключ (openssl rand -hex 32)
|
||||
# - CLIENTS_FILE=/opt/free-turn-proxy/clients/clients.json # Для авторизации
|
||||
# - CLIENTS_FILE=/opt/free-turn-proxy/auth/clients.json # Для авторизации
|
||||
# volumes:
|
||||
# - /opt/free-turn-proxy/clients:/opt/free-turn-proxy/clients
|
||||
# - /opt/free-turn-proxy/auth:/opt/free-turn-proxy/auth
|
||||
|
||||
# Опционально: VPN-бэкенд AmneziaWG (AWG 3.1)
|
||||
freeturn-awg:
|
||||
@@ -97,7 +99,7 @@ openssl rand -hex 32
|
||||
network_mode: "host"
|
||||
environment:
|
||||
- AWG_IFACE=ftawg0
|
||||
- AWG_LOG_LEVEL=verbose
|
||||
- AWG_LOG_LEVEL=error
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
devices:
|
||||
@@ -200,24 +202,27 @@ sudo ufw allow 56000/udp
|
||||
# Или iptables: sudo iptables -I INPUT -p udp --dport 56000 -j ACCEPT
|
||||
```
|
||||
|
||||
Для прямого AWG нужен ещё `51820/udp` - установщик открывает его при `--firewall`.
|
||||
Порт веб-раздачи открывать вручную не нужно, установщик делает это сам.
|
||||
|
||||
---
|
||||
|
||||
## Авторизация по Client ID (Опционально)
|
||||
|
||||
По умолчанию доступ открыт всем, кто знает `-obf-key`. Чтобы ограничить доступ:
|
||||
|
||||
1. Создайте пустой список: `echo '{"clients":{}}' | sudo tee /opt/free-turn-proxy/clients/clients.json`
|
||||
1. Создайте пустой список: `echo '{"clients":{}}' | sudo tee /opt/free-turn-proxy/auth/clients.json`
|
||||
2. Включите авторизацию:
|
||||
- **Docker:** раскомментируйте `CLIENTS_FILE` и `volumes` в `docker-compose.yml`, затем `docker compose up -d`.
|
||||
- **systemd:** добавьте флаг `-clients-file /opt/free-turn-proxy/clients/clients.json` в `ExecStart` и перезапустите службу.
|
||||
- **systemd:** добавьте флаг `-clients-file /opt/free-turn-proxy/auth/clients.json` в `ExecStart` и перезапустите службу.
|
||||
3. Добавляйте клиентов:
|
||||
- Через установщик:
|
||||
```bash
|
||||
sudo bash install.sh client add <имя>
|
||||
freeturn client add <имя>
|
||||
```
|
||||
- Напрямую через бинарник:
|
||||
- **Docker:** `docker exec -i free-turn-proxy env CLIENTS_FILE=/opt/free-turn-proxy/clients/clients.json /app/server clients add <id> [комментарий]`
|
||||
- **systemd:** `CLIENTS_FILE=/opt/free-turn-proxy/clients/clients.json /opt/free-turn-proxy/server clients add <id> [комментарий]`
|
||||
- **Docker:** `docker exec -i free-turn-proxy env CLIENTS_FILE=/opt/free-turn-proxy/auth/clients.json /app/server clients add <id> [комментарий]`
|
||||
- **systemd:** `CLIENTS_FILE=/opt/free-turn-proxy/auth/clients.json /opt/free-turn-proxy/server clients add <id> [комментарий]`
|
||||
|
||||
На клиенте используйте флаг `-client-id <id>` или готовую ссылку `freeturn://`.
|
||||
|
||||
|
||||
+3
-2
@@ -8,14 +8,15 @@
|
||||
|
||||
## Шаг 1: Запуск Сервера (VPS)
|
||||
|
||||
Интерактивный скрипт поднимет Docker Compose со службами `free-turn-proxy` и `freeturn-awg` (AmneziaWG 3.1), сгенерирует ключи обфускации, создаст первого клиента и выведет **QR-код прямо в терминале**:
|
||||
Интерактивный скрипт поднимет Docker Compose со службами `free-turn-proxy` и `freeturn-awg` (AmneziaWG 3.1), сгенерирует ключи обфускации, создаст первого клиента и выдаст **ссылку на его QR-код**:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/samosvalishe/free-turn-proxy/master/scripts/install.sh | sudo bash
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> **Прямое подключение (Direct AWG):** Отсканируйте выведенный терминальный QR-код в официальном приложении **AmneziaWG/AmneziaVPN** на телефоне (или импортируйте `.conf` на ПК) - туннель готов к работе сразу!
|
||||
> **Прямое подключение (Direct AWG):** Откройте выданную ссылку `-direct.png` и отсканируйте QR в официальном приложении **AmneziaWG/AmneziaVPN** на телефоне (или скачайте `.conf` из того же каталога на ПК) - туннель готов к работе сразу!
|
||||
> Ссылка равносильна конфигу - делитесь осторожно. Живёт 15 минут, показать снова: `freeturn client qr <имя>`.
|
||||
>
|
||||
> **Добавление новых клиентов:** Выполните на сервере:
|
||||
> ```bash
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ Payload - JSON-объект, закодированный `base64url` (без pa
|
||||
| `mode` | `-mode` | режим туннеля: `udp` \| `tcp`; отсутствует - `udp`. |
|
||||
| `obf` | `-obf-profile` | профиль обфускации (`rtpopus` \| `rtpopus2`); `none` опускается. |
|
||||
| `key` | `-obf-key` | ключ обфускации (hex), только при заданном `obf`. |
|
||||
| `n` | `-n` | число TURN-потоков. |
|
||||
| `spc` | `-streams-per-cred` | потоков на один кеш VK-учёток. |
|
||||
| `n` | `-n` | число TURN-потоков; отсутствует - дефолт клиента. |
|
||||
| `spc` | `-streams-per-cred` | потоков на один кеш VK-учёток; отсутствует - дефолт клиента. |
|
||||
| `cid` | `-client-id` | Client ID гостя; owner добавляет его в allowlist (`clients.json`). |
|
||||
| `listen` | `-listen` | локальный `ip:port` для WireGuard/Xray. |
|
||||
| `dns` | `-dns-mode` | резолвер клиента: `plain` \| `doh` \| `auto`. |
|
||||
|
||||
+440
-361
File diff suppressed because it is too large
Load Diff
@@ -141,7 +141,6 @@ run_script() { run bash "$SCRIPT" "$@"; }
|
||||
source '$SCRIPT'
|
||||
INSTALL_FREETURN=0
|
||||
INSTALL_AWG=0
|
||||
INSTALL_WG=0
|
||||
validate_config
|
||||
"
|
||||
[ "$status" -ne 0 ]
|
||||
@@ -154,7 +153,6 @@ run_script() { run bash "$SCRIPT" "$@"; }
|
||||
# Только FreeTurn
|
||||
INSTALL_FREETURN=1
|
||||
INSTALL_AWG=0
|
||||
INSTALL_WG=0
|
||||
INSTALL_METHOD='docker'
|
||||
PROVIDER='vk'
|
||||
PROXY_MODE='udp'
|
||||
@@ -165,7 +163,6 @@ run_script() { run bash "$SCRIPT" "$@"; }
|
||||
# Только AmneziaWG
|
||||
INSTALL_FREETURN=0
|
||||
INSTALL_AWG=1
|
||||
INSTALL_WG=0
|
||||
BACKEND_PORT='51820'
|
||||
WG_ENDPOINT='127.0.0.1:9000'
|
||||
validate_config || exit 1
|
||||
@@ -363,7 +360,6 @@ EOF
|
||||
INSTALL_METHOD='docker'
|
||||
INSTALL_FREETURN=1
|
||||
INSTALL_AWG=1
|
||||
INSTALL_WG=0
|
||||
PROXY_MODE='tcp'
|
||||
BACKEND_PORT=51821
|
||||
LISTEN_PORT=56001
|
||||
@@ -500,3 +496,290 @@ EOF
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "web_token стабилен между вызовами и ложится на диск" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
t1=\$(web_token); t2=\$(web_token)
|
||||
[ \"\$t1\" = \"\$t2\" ] || exit 1
|
||||
[ \"\${#t1}\" -eq 32 ] || exit 1
|
||||
[ -f \"\$WEB_TOKEN_FILE\" ] || exit 1
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "токен свой у каждого клиента и не равен мастер-секрету" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
a=\$(client_token phone); b=\$(client_token laptop)
|
||||
[ \"\$a\" = \"\$(client_token phone)\" ] || exit 1
|
||||
[ \"\$a\" != \"\$b\" ] || exit 1
|
||||
[ \"\$a\" != \"\$(web_token)\" ] || exit 1
|
||||
[ \"\${#a}\" -eq 32 ] || exit 1
|
||||
[ \"\$(web_base_url 1.2.3.4 phone)\" = \"http://1.2.3.4:8080/\$a\" ] || exit 1
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "docroot прячет листинг, за токеном клиента виден только его каталог" {
|
||||
ln -s "$FT_TEST_DIR" "$FT_TEST_DIR/lnprobe" 2>/dev/null
|
||||
[ -L "$FT_TEST_DIR/lnprobe" ] || skip "ФС без симлинков (не Linux)"
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
mkdir -p \"\$CLIENTS_DIR/phone\" \"\$CLIENTS_DIR/laptop\"
|
||||
printf 'phone|10.13.13.2||now\nlaptop|10.13.13.3||now\n' > \"\$CLIENTS_META\"
|
||||
_web_layout || exit 1
|
||||
[ -f \"\$WEB_ROOT/index.html\" ] || exit 1
|
||||
[ -f \"\$WEB_ROOT/\$(web_token)\$WEB_PROBE_EXT\" ] || exit 1
|
||||
[ -L \"\$WEB_ROOT/\$(client_token phone)\" ] || exit 1
|
||||
[ \"\$(readlink \"\$WEB_ROOT/\$(client_token phone)\")\" = \"\$CLIENTS_DIR/phone\" ] || exit 1
|
||||
[ -L \"\$WEB_ROOT/\$(client_token laptop)\" ] || exit 1
|
||||
# мастер-секрет каталогом не раздаётся
|
||||
[ -L \"\$WEB_ROOT/\$(web_token)\" ] && exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "_web_layout убирает симлинк удалённого клиента" {
|
||||
ln -s "$FT_TEST_DIR" "$FT_TEST_DIR/lnprobe" 2>/dev/null
|
||||
[ -L "$FT_TEST_DIR/lnprobe" ] || skip "ФС без симлинков (не Linux)"
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
mkdir -p \"\$CLIENTS_DIR/phone\" \"\$CLIENTS_DIR/laptop\"
|
||||
printf 'phone|10.13.13.2||now\nlaptop|10.13.13.3||now\n' > \"\$CLIENTS_META\"
|
||||
_web_layout || exit 1
|
||||
gone=\$(client_token laptop)
|
||||
rm -rf \"\$CLIENTS_DIR/laptop\"
|
||||
printf 'phone|10.13.13.2||now\n' > \"\$CLIENTS_META\"
|
||||
_web_layout || exit 1
|
||||
[ -L \"\$WEB_ROOT/\$gone\" ] && exit 1
|
||||
[ -L \"\$WEB_ROOT/\$(client_token phone)\" ] || exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "migrate_client_dirs раскладывает плоские артефакты по каталогам клиентов" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
mkdir -p \"\$CLIENTS_DIR\"
|
||||
printf 'phone|10.13.13.2||now\nphone-2|10.13.13.3||now\n' > \"\$CLIENTS_META\"
|
||||
: > \"\$CLIENTS_DIR/phone-direct.conf\"
|
||||
: > \"\$CLIENTS_DIR/phone-direct.png\"
|
||||
: > \"\$CLIENTS_DIR/phone-2-direct.conf\"
|
||||
migrate_client_dirs
|
||||
[ -f \"\$CLIENTS_DIR/phone/phone-direct.conf\" ] || exit 1
|
||||
[ -f \"\$CLIENTS_DIR/phone/phone-direct.png\" ] || exit 1
|
||||
# префиксы не должны перетягивать чужие файлы
|
||||
[ -f \"\$CLIENTS_DIR/phone-2/phone-2-direct.conf\" ] || exit 1
|
||||
[ -f \"\$CLIENTS_DIR/phone/phone-2-direct.conf\" ] && exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "allowlist и метаданные лежат вне раздаваемого каталога" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
case \"\$CLIENTS_FILE_CONF\" in \"\$CLIENTS_DIR\"/*) exit 1 ;; esac
|
||||
case \"\$CLIENTS_META\" in \"\$CLIENTS_DIR\"/*) exit 1 ;; esac
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "migrate_layout переносит clients.json из раздаваемого каталога" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
mkdir -p \"\$CLIENTS_DIR\"
|
||||
echo '{\"clients\":{\"a\":1}}' > \"\$CLIENTS_DIR/clients.json\"
|
||||
echo 'old|10.13.13.2||now' > \"\$CLIENTS_DIR/clients.list\"
|
||||
migrate_layout
|
||||
[ ! -f \"\$CLIENTS_DIR/clients.json\" ] || exit 1
|
||||
[ ! -f \"\$CLIENTS_DIR/clients.list\" ] || exit 1
|
||||
grep -q '\"a\":1' \"\$CLIENTSFILE\" || exit 1
|
||||
grep -q '^old|' \"\$CLIENTS_META\" || exit 1
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "valid_client_name отсекает traversal и метасимволы regex" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
valid_client_name 'phone-1' || exit 1
|
||||
valid_client_name 'a.b_c' || exit 1
|
||||
valid_client_name '../etc' && exit 1
|
||||
valid_client_name 'a/b' && exit 1
|
||||
valid_client_name 'a|b' && exit 1
|
||||
valid_client_name '.hidden' && exit 1
|
||||
valid_client_name '' && exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "alloc_client_ip упирается в границу /24" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
conf=\"\$FT_PREFIX/full.conf\"
|
||||
for i in \$(seq 2 254); do echo \"AllowedIPs = 10.13.13.\$i/32\" >> \"\$conf\"; done
|
||||
alloc_client_ip \"\$conf\" 10.13.13
|
||||
"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "write_compose_file убирает снятый сервис и удаляет файл без компонентов" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
INSTALL_FREETURN=1 INSTALL_AWG=1
|
||||
write_compose_file
|
||||
grep -q 'free-turn-proxy:' \"\$COMPOSE_FILE\" || exit 1
|
||||
grep -q 'freeturn-awg:' \"\$COMPOSE_FILE\" || exit 1
|
||||
|
||||
INSTALL_FREETURN=0
|
||||
write_compose_file
|
||||
grep -q 'free-turn-proxy:' \"\$COMPOSE_FILE\" && exit 1
|
||||
grep -q 'freeturn-awg:' \"\$COMPOSE_FILE\" || exit 1
|
||||
|
||||
INSTALL_AWG=0
|
||||
write_compose_file
|
||||
[ ! -f \"\$COMPOSE_FILE\" ] || exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "compose AWG не включает verbose-логи демона" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
INSTALL_FREETURN=0 INSTALL_AWG=1
|
||||
write_compose_file
|
||||
grep -q 'AWG_LOG_LEVEL=error' \"\$COMPOSE_FILE\" || exit 1
|
||||
grep -q 'AWG_LOG_LEVEL=verbose' \"\$COMPOSE_FILE\" && exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "get_public_ip возвращает ошибку вместо плейсхолдера" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
curl() { return 1; }
|
||||
export -f curl
|
||||
get_public_ip
|
||||
"
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "$output" != *"IP_СЕРВЕРА"* ]]
|
||||
}
|
||||
|
||||
@test "validate_config отсекает невалидный web-port" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
INSTALL_FREETURN=0 INSTALL_AWG=1
|
||||
BACKEND_PORT=51820 WG_ENDPOINT='127.0.0.1:9000' FT_WEB_PORT=99999
|
||||
validate_config
|
||||
"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "CLI-флаги не уезжают в JSON RPC диспетчер" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
for f in -y --yes --update --uninstall --reconfigure --purge --only-awg --method; do
|
||||
is_rpc_command \"\$f\" && { echo \"флаг \$f опознан как RPC\"; exit 1; }
|
||||
done
|
||||
for c in \$RPC_COMMANDS; do
|
||||
is_rpc_command \"\$c\" || { echo \"команда \$c не опознана\"; exit 1; }
|
||||
done
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "веб-раздача не оставляет постоянного systemd-юнита" {
|
||||
run grep -n 'WantedBy=multi-user.target' "$SCRIPT"
|
||||
# единственный постоянный юнит - сам сервер free-turn-proxy
|
||||
[ "$(printf '%s\n' "$output" | wc -l)" -eq 1 ]
|
||||
|
||||
run bash -c "grep -c 'RuntimeMaxSec' '$SCRIPT'"
|
||||
[ "$output" -ge 1 ]
|
||||
}
|
||||
|
||||
@test "firewall_open не держит веб-порт открытым постоянно" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
opened=()
|
||||
firewall_open_port() { opened+=(\"\$1/\$2\"); }
|
||||
INSTALL_FREETURN=1 INSTALL_AWG=1 AWG_DIRECT_PORT=1
|
||||
LISTEN_PORT=56000 BACKEND_PORT=51820 PROXY_MODE=udp FT_WEB_PORT=8080
|
||||
firewall_open
|
||||
printf '%s\n' \"\${opened[@]}\"
|
||||
"
|
||||
[[ "$output" == *"56000/udp"* ]]
|
||||
[[ "$output" == *"51820/udp"* ]]
|
||||
[[ "$output" != *"8080"* ]]
|
||||
}
|
||||
|
||||
@test "ensure_web_server открывает порт сам и закрывает при неудаче запуска" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
log=\"\$FT_PREFIX/fw.log\"
|
||||
firewall_open_port() { echo \"open \$1/\$2\" >> \"\$log\"; }
|
||||
firewall_close_port() { echo \"close \$1/\$2\" >> \"\$log\"; }
|
||||
port_owner() { echo free; }
|
||||
_web_server_argv() { printf '%s\n' fake-httpd \"\$1\"; }
|
||||
_web_start_systemd() { return 1; }
|
||||
_web_start_nohup() { return 1; }
|
||||
ensure_web_server && exit 1
|
||||
grep -q 'open 8080/tcp' \"\$log\" || exit 1
|
||||
grep -q 'close 8080/tcp' \"\$log\" || exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "_web_server_argv берёт python3, иначе busybox" {
|
||||
# подменяем 'command -v', а не PATH: иначе тест зависел бы от того, стоит ли python3 в CI
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
HAVE=''
|
||||
command() {
|
||||
if [ \"\$1\" = '-v' ]; then
|
||||
case \" \$HAVE \" in *\" \$2 \"*) echo \"/usr/bin/\$2\"; return 0 ;; esac
|
||||
return 1
|
||||
fi
|
||||
builtin command \"\$@\"
|
||||
}
|
||||
pkg_install() { return 1; }
|
||||
|
||||
_web_server_argv 8080 && exit 1
|
||||
|
||||
HAVE='busybox'
|
||||
[ \"\$(_web_server_argv 8080 | tr '\n' ' ')\" = \"busybox httpd -f -p 8080 -h \$WEB_ROOT \" ] || exit 1
|
||||
|
||||
HAVE='python3 busybox'
|
||||
[ \"\$(_web_server_argv 8080 | tr '\n' ' ')\" = \"python3 -m http.server 8080 --directory \$WEB_ROOT \" ] || exit 1
|
||||
true
|
||||
"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "validate_config отсекает слишком короткий web-ttl" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
INSTALL_FREETURN=0 INSTALL_AWG=1
|
||||
BACKEND_PORT=51820 WG_ENDPOINT='127.0.0.1:9000' FT_WEB_TTL=10
|
||||
validate_config
|
||||
"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "web_token не выдаёт нестабильный токен, если его негде сохранить" {
|
||||
run bash -c "
|
||||
source '$SCRIPT'
|
||||
WEB_TOKEN_FILE='/proc/nonexistent/web.token'
|
||||
web_token
|
||||
"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user