release: 1.4.0 — one version for stable/beta/dev
Light/dark theme and compact mobile layout, per-client speed limit, real speed tests, panel domain (Let's Encrypt), client address + cascade relay, RKN scanner guard, WARP, backup/restore, router web terminal, Android VPN client with split tunnelling and Android admin app. Updating from 1.2.x keeps keys, server.env and clients; tested 1.2.8 -> 1.4.0 on live VMs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -443,6 +443,11 @@ deploy_health_monitor() {
|
||||
chmod +x "$PHOBOS_DIR/phobos-pull.sh"
|
||||
echo "{{CLIENT_NAME}}" > "$PHOBOS_DIR/client_id"
|
||||
[ -f "pull_token" ] && cp "pull_token" "$PHOBOS_DIR/pull_token"
|
||||
[ -f "panel_tunnel_ip" ] && cp "panel_tunnel_ip" "$PHOBOS_DIR/panel_tunnel_ip"
|
||||
[ -f "panel_port" ] && cp "panel_port" "$PHOBOS_DIR/panel_port"
|
||||
[ -f "panel_scheme" ] && cp "panel_scheme" "$PHOBOS_DIR/panel_scheme"
|
||||
[ -f "panel_url" ] && cp "panel_url" "$PHOBOS_DIR/panel_url"
|
||||
[ -f "panel_urls" ] && cp "panel_urls" "$PHOBOS_DIR/panel_urls"
|
||||
log " Pull-агент установлен (client_id={{CLIENT_NAME}})"
|
||||
fi
|
||||
|
||||
|
||||
@@ -56,11 +56,11 @@ action_add() {
|
||||
for d in "$CLIENTS_DIR"/*; do
|
||||
if [[ -d "$d" ]] && [[ -f "$d/metadata.json" ]]; then
|
||||
local ip=$(jq -r '.tunnel_ip_v4 // empty' "$d/metadata.json" 2>/dev/null | cut -d/ -f1)
|
||||
[[ -n "$ip" ]] && used_ips="${used_ips}${ip}"$'\n'
|
||||
[[ -n "$ip" ]] && used_ips="${used_ips}${ip}\n"
|
||||
fi
|
||||
done
|
||||
|
||||
client_ip_v4="$(USED_IPS="$used_ips" python3 - "$server_wg_network" <<'PY'
|
||||
client_ip_v4="$(USED_IPS="$(printf "%b" "$used_ips")" python3 - "$server_wg_network" <<'PY'
|
||||
import ipaddress
|
||||
import os
|
||||
import sys
|
||||
@@ -123,7 +123,7 @@ EOF
|
||||
[instance]
|
||||
source-if = 127.0.0.1
|
||||
source-lport = ${CLIENT_WG_PORT:-13255}
|
||||
target = $SERVER_PUBLIC_IP_V4:${OBFUSCATOR_PORT:-51821}
|
||||
target = ${CLIENT_ENDPOINT:-$SERVER_PUBLIC_IP_V4}:${OBFUSCATOR_PORT:-51821}
|
||||
key = ${OBFUSCATOR_KEY:-KEY}
|
||||
masking = ${OBFUSCATOR_MASKING:-AUTO}
|
||||
verbose = INFO
|
||||
@@ -213,6 +213,7 @@ action_package() {
|
||||
local tmp=$(mktemp -d)
|
||||
local pkg_root="$tmp/phobos-$id"
|
||||
|
||||
mkdir -p "$PHOBOS_DIR/bin"
|
||||
mkdir -p "$pkg_root/bin"
|
||||
|
||||
cp "$dir/${id}.conf" "$pkg_root/${id}.conf"
|
||||
@@ -239,7 +240,7 @@ action_package() {
|
||||
|
||||
if [[ -d "$tpl_dir" ]]; then
|
||||
for required in install-router.sh.template lib-client.sh install-obfuscator.sh install-wireguard.sh; do
|
||||
[[ -f "$tpl_dir/$required" ]] || die "Обязательный шаблон $required не найден в $tpl_dir. Выполни phobos-update stable и пересоздай пакет."
|
||||
[[ -f "$tpl_dir/$required" ]] || die "Обязательный шаблон $required не найден в $tpl_dir. Выполни phobos-update и пересоздай пакет."
|
||||
done
|
||||
cp "$tpl_dir/install-router.sh.template" "$pkg_root/install-router.sh"
|
||||
sed -i "s|{{CLIENT_NAME}}|${id}|g" "$pkg_root/install-router.sh"
|
||||
@@ -273,10 +274,42 @@ action_package() {
|
||||
[[ -n "$PULL_TOKEN" ]] && echo "$PULL_TOKEN" > "$pkg_root/pull_token"
|
||||
# Generate failover.conf with current server data
|
||||
source "$PHOBOS_DIR/server/server.env"
|
||||
local panel_port="${HTTP_PORT:-}"
|
||||
if [[ -z "$panel_port" && -f /opt/phobos-panel/.port ]]; then
|
||||
panel_port=$(cat /opt/phobos-panel/.port 2>/dev/null || true)
|
||||
fi
|
||||
panel_port="${panel_port:-8443}"
|
||||
local panel_scheme="${PANEL_SCHEME:-}"
|
||||
if [[ -z "$panel_scheme" && -f /opt/phobos-panel/.scheme ]]; then
|
||||
panel_scheme=$(cat /opt/phobos-panel/.scheme 2>/dev/null || true)
|
||||
fi
|
||||
case "$panel_scheme" in http|https) ;; *) panel_scheme="http";; esac
|
||||
local panel_tunnel_ip=""
|
||||
panel_tunnel_ip="$(python3 - "${SERVER_WG_IPV4_ADDRESS:-}" "${SERVER_WG_IPV4_NETWORK:-10.25.0.0/16}" <<'PY'
|
||||
import ipaddress, sys
|
||||
iface = (sys.argv[1] or "").strip()
|
||||
network = (sys.argv[2] or "10.25.0.0/16").strip()
|
||||
if iface:
|
||||
try:
|
||||
print(ipaddress.ip_interface(iface).ip)
|
||||
raise SystemExit(0)
|
||||
except Exception:
|
||||
pass
|
||||
net = ipaddress.ip_network(network, strict=False)
|
||||
print(next(net.hosts()))
|
||||
PY
|
||||
)"
|
||||
[[ -n "$panel_tunnel_ip" ]] && echo "$panel_tunnel_ip" > "$pkg_root/panel_tunnel_ip"
|
||||
echo "$panel_port" > "$pkg_root/panel_port"
|
||||
echo "$panel_scheme" > "$pkg_root/panel_scheme"
|
||||
echo "${panel_scheme}://${SERVER_PUBLIC_IP_V4}:${panel_port}" > "$pkg_root/panel_url"
|
||||
printf 'http://%s:8444 %s://%s:%s %s://%s:%s\n' \
|
||||
"$panel_tunnel_ip" "$panel_scheme" "$panel_tunnel_ip" "$panel_port" \
|
||||
"$panel_scheme" "$SERVER_PUBLIC_IP_V4" "$panel_port" > "$pkg_root/panel_urls"
|
||||
cat > "$pkg_root/failover.conf" <<FAILEOF
|
||||
# Phobos Failover Configuration
|
||||
SERVER_1=${SERVER_PUBLIC_IP_V4}:${OBFUSCATOR_PORTS:-51821,51822,51823}
|
||||
KEY_1=${OBFUSCATOR_KEY}
|
||||
SERVER_1=${CLIENT_ENDPOINT:-$SERVER_PUBLIC_IP_V4}:${OBFUSCATOR_PORTS:-51821,51822,51823}
|
||||
KEY_1=${OBFUSCATOR_KEY:-}
|
||||
FAILEOF
|
||||
|
||||
find "$pkg_root" -type f ! -path "*/bin/*" -exec sed -i 's/\r$//' {} \;
|
||||
@@ -355,8 +388,13 @@ action_link() {
|
||||
if [[ -z "$panel_port" && -f /opt/phobos-panel/.port ]]; then
|
||||
panel_port=$(cat /opt/phobos-panel/.port 2>/dev/null || true)
|
||||
fi
|
||||
panel_port="${panel_port:-80}"
|
||||
local primary_url="http://${SERVER_PUBLIC_IP_V4}:${panel_port}/packages/$token/phobos-$id.tar.gz"
|
||||
panel_port="${panel_port:-8443}"
|
||||
local panel_scheme="${PANEL_SCHEME:-}"
|
||||
if [[ -z "$panel_scheme" && -f /opt/phobos-panel/.scheme ]]; then
|
||||
panel_scheme=$(cat /opt/phobos-panel/.scheme 2>/dev/null || true)
|
||||
fi
|
||||
case "$panel_scheme" in http|https) ;; *) panel_scheme="http";; esac
|
||||
local primary_url="${panel_scheme}://${SERVER_PUBLIC_IP_V4}:${panel_port}/packages/$token/phobos-$id.tar.gz"
|
||||
local fallback_url="http://${SERVER_PUBLIC_IP_V4}:80/packages/$token/phobos-$id.tar.gz"
|
||||
|
||||
cat > "$WWW_DIR/init/$token.sh" <<EOF
|
||||
@@ -366,12 +404,12 @@ dir="/tmp/phobos_install_\$\$"
|
||||
mkdir -p "\$dir"
|
||||
echo "Downloading..."
|
||||
ok=0
|
||||
for url in \$urls; do
|
||||
for url in \$urls; do
|
||||
rm -f "\$dir/package.tar.gz"
|
||||
if command -v curl >/dev/null; then
|
||||
curl -L -s -o "\$dir/package.tar.gz" "\$url" 2>/dev/null || continue
|
||||
curl -k -L -s -o "\$dir/package.tar.gz" "\$url" 2>/dev/null || continue
|
||||
else
|
||||
wget -q -O "\$dir/package.tar.gz" "\$url" 2>/dev/null || continue
|
||||
wget --no-check-certificate -q -O "\$dir/package.tar.gz" "\$url" 2>/dev/null || wget -q -O "\$dir/package.tar.gz" "\$url" 2>/dev/null || continue
|
||||
fi
|
||||
if grep -qi '<html' "\$dir/package.tar.gz" 2>/dev/null; then
|
||||
echo "Bad response from \$url (HTML/proxy page), trying next..."
|
||||
@@ -399,9 +437,9 @@ EOF
|
||||
chmod 755 "$PACKAGES_DIR" 2>/dev/null
|
||||
chmod 644 "$PACKAGES_DIR/phobos-$id.tar.gz" 2>/dev/null
|
||||
|
||||
local init_primary="http://${SERVER_PUBLIC_IP_V4}:${panel_port}/init/$token.sh"
|
||||
local init_primary="${panel_scheme}://${SERVER_PUBLIC_IP_V4}:${panel_port}/init/$token.sh"
|
||||
local init_fallback="http://${SERVER_PUBLIC_IP_V4}:80/init/$token.sh"
|
||||
local cmd="tmp=/tmp/phobos-init-\$\$.sh; ok=0; for u in $init_primary $init_fallback; do rm -f \$tmp; (wget -q -O \$tmp \$u || curl -fsSL -o \$tmp \$u) 2>/dev/null || continue; grep -qi '<html' \$tmp && continue; head -1 \$tmp | grep -q '^#!' || continue; sh \$tmp; ok=1; break; done; rm -f \$tmp; [ \$ok -eq 1 ] || echo 'ERROR: install script download failed (got HTML/proxy page or timeout)'"
|
||||
local cmd="p=/tmp/phobos-init-\$\$.sh; ok=0; for u in $init_primary $init_fallback; do rm -f \$p; (wget -q -O \$p \$u || wget --no-check-certificate -q -O \$p \$u || curl -kfsSL -o \$p \$u || curl -fsSL -o \$p \$u) 2>/dev/null || continue; head -c 2 \$p | grep -q \"#!\" || continue; sh \$p && ok=1 && break; done; rm -f \$p; [ \$ok -eq 1 ] || echo ERROR_install_script_download_failed"
|
||||
|
||||
echo ""
|
||||
echo "=================================================="
|
||||
|
||||
@@ -24,14 +24,18 @@ PHOBOS_DIR="/opt/etc/Phobos"
|
||||
CONF="$PHOBOS_DIR/failover.conf"
|
||||
HEALTH="$PHOBOS_DIR/phobos-health.sh"
|
||||
LOG="$PHOBOS_DIR/health.log"
|
||||
# Config sources, tried in order. TUNNEL FIRST: 10.25.0.1 is the wg0 of whatever
|
||||
# server the tunnel currently terminates on, so management rides the same
|
||||
# obfuscated channel as data — survives a public-IP ban and follows failover.
|
||||
# - 10.25.0.1:8444 -> secondary server agent (phobos-api)
|
||||
# - 10.25.0.1:10514 -> primary server panel
|
||||
# Config sources, tried in order. TUNNEL FIRST: panel_tunnel_ip is the wg0 of
|
||||
# whatever server the tunnel currently terminates on, so management rides the
|
||||
# same obfuscated channel as data — survives a public-IP ban and follows
|
||||
# failover.
|
||||
# - panel_tunnel_ip:8444 -> secondary server agent (phobos-api)
|
||||
# - panel_tunnel_ip:<panel_port> -> primary server panel
|
||||
# - public panel IP -> bootstrap / if tunnel is down
|
||||
PANEL="${PANEL:-http://212.118.52.193:10514}"
|
||||
PANEL_URLS="${PANEL_URLS:-http://10.25.0.1:8444 http://10.25.0.1:10514 $PANEL}"
|
||||
PANEL_TUNNEL_IP="${PANEL_TUNNEL_IP:-$(cat "$PHOBOS_DIR/panel_tunnel_ip" 2>/dev/null)}"
|
||||
[ -n "$PANEL_TUNNEL_IP" ] || PANEL_TUNNEL_IP="10.25.0.1"
|
||||
PANEL="${PANEL:-$(cat "$PHOBOS_DIR/panel_url" 2>/dev/null)}"
|
||||
PANEL_URLS="${PANEL_URLS:-$(cat "$PHOBOS_DIR/panel_urls" 2>/dev/null)}"
|
||||
[ -n "$PANEL_URLS" ] || PANEL_URLS="http://${PANEL_TUNNEL_IP}:8444 $PANEL"
|
||||
CLIENT_ID=$(cat "$PHOBOS_DIR/client_id" 2>/dev/null || echo "home")
|
||||
TOKEN=$(cat "$PHOBOS_DIR/pull_token" 2>/dev/null)
|
||||
TMP="/tmp/failover.conf.pull"
|
||||
@@ -50,21 +54,24 @@ trap 'rm -f "$LOCK"' EXIT
|
||||
[ -z "$TOKEN" ] && exit 0
|
||||
|
||||
detect_tunnel_iface() {
|
||||
ip -o addr show 2>/dev/null | awk '$4 ~ /^10\.25\./ {print $2; exit}'
|
||||
ip route get "$PANEL_TUNNEL_IP" 2>/dev/null | awk '{for(i=1;i<NF;i++) if($i=="dev") print $(i+1)}' | head -1
|
||||
}
|
||||
|
||||
fetch_config() {
|
||||
base="$1"
|
||||
url="${base}/api/router-config/${CLIENT_ID}?token=${TOKEN}"
|
||||
case "$base" in
|
||||
http://10.25.0.1:*|https://10.25.0.1:*)
|
||||
"http://${PANEL_TUNNEL_IP}:"*|"https://${PANEL_TUNNEL_IP}:"*)
|
||||
iface=$(detect_tunnel_iface)
|
||||
if [ -n "$iface" ] && command -v curl >/dev/null; then
|
||||
curl --interface "$iface" -s -m 8 -o "$TMP" "$url" 2>/dev/null && return 0
|
||||
curl -k --interface "$iface" -s -m 8 -o "$TMP" "$url" 2>/dev/null && return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
curl -s -m 8 -o "$TMP" "$url" 2>/dev/null
|
||||
if command -v curl >/dev/null; then
|
||||
curl -k -s -m 8 -o "$TMP" "$url" 2>/dev/null && return 0
|
||||
fi
|
||||
wget --no-check-certificate -q -O "$TMP" "$url" 2>/dev/null || wget -q -O "$TMP" "$url" 2>/dev/null
|
||||
}
|
||||
|
||||
# One fetch + compare + apply pass. Returns 0 always (best-effort).
|
||||
@@ -95,6 +102,40 @@ do_pull() {
|
||||
if [ "$old_s1" != "$new_s1" ] && [ -f "$HEALTH" ]; then
|
||||
sh "$HEALTH" apply-server 1
|
||||
fi
|
||||
|
||||
apply_obf_params
|
||||
}
|
||||
|
||||
# Apply obfuscator params (masking/max-dummy/idle) delivered in failover.conf.
|
||||
apply_obf_params() {
|
||||
M=$(grep "^OBF_MASKING=" "$CONF" 2>/dev/null | cut -d= -f2-)
|
||||
[ -z "$M" ] && return 0
|
||||
D=$(grep "^OBF_MAX_DUMMY=" "$CONF" 2>/dev/null | cut -d= -f2-)
|
||||
I=$(grep "^OBF_IDLE=" "$CONF" 2>/dev/null | cut -d= -f2-)
|
||||
changed=0
|
||||
for OBF in "$PHOBOS_DIR"/wg-obfuscator*.conf; do
|
||||
[ -f "$OBF" ] || continue
|
||||
cur=$(grep "^masking = " "$OBF" 2>/dev/null | sed 's/masking = //')
|
||||
[ "$cur" != "$M" ] && { sed -i "s/^masking = .*/masking = $M/" "$OBF"; changed=1; }
|
||||
if [ -n "$D" ]; then
|
||||
cur=$(grep "^max-dummy = " "$OBF" 2>/dev/null | sed 's/max-dummy = //')
|
||||
[ "$cur" != "$D" ] && { sed -i "s/^max-dummy = .*/max-dummy = $D/" "$OBF"; changed=1; }
|
||||
fi
|
||||
if [ -n "$I" ]; then
|
||||
cur=$(grep "^idle-timeout = " "$OBF" 2>/dev/null | sed 's/idle-timeout = //')
|
||||
[ "$cur" != "$I" ] && { sed -i "s/^idle-timeout = .*/idle-timeout = $I/" "$OBF"; changed=1; }
|
||||
fi
|
||||
done
|
||||
[ "$changed" = 0 ] && return 0
|
||||
log "PULL: obf params applied (masking=$M dummy=${D:-} idle=${I:-}), restart obfuscator"
|
||||
if ls /opt/etc/init.d/S*obfuscator* >/dev/null 2>&1; then
|
||||
for sc in /opt/etc/init.d/S*obfuscator*; do [ -x "$sc" ] && "$sc" restart >/dev/null 2>&1; done
|
||||
elif command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl restart 'wg-obfuscator*' >/dev/null 2>&1 || true
|
||||
else
|
||||
killall wg-obfuscator 2>/dev/null; sleep 1
|
||||
for OBF in "$PHOBOS_DIR"/wg-obfuscator*.conf; do [ -f "$OBF" ] && wg-obfuscator --config "$OBF" >/dev/null 2>&1 & done
|
||||
fi
|
||||
}
|
||||
|
||||
# Inner loop: cron fires this every 60s, but we poll ~4x per minute so a
|
||||
|
||||
67
overlay/phobos-ttyd.sh
Executable file
67
overlay/phobos-ttyd.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
# ============================================================
|
||||
# PCA Phobos — ttyd web-terminal на роутере Keenetic
|
||||
#
|
||||
# phobos-ttyd.sh <client_id> <token> [server_tunnel_ip]
|
||||
#
|
||||
# Ставит ttyd (web pty), открывает порт на WG-интерфейсе ТОЛЬКО для панели
|
||||
# (server tunnel IP), создаёт init-сервис (переживает перезагрузку).
|
||||
# Панель проксирует терминал к роутеру через WG-туннель (за NAT, без SSH).
|
||||
# ============================================================
|
||||
CID="${1:?usage: phobos-ttyd.sh <client_id> <token> [server_ip]}"
|
||||
TOKEN="${2:?token required}"
|
||||
SRV_IP="${3:-$(cat /opt/etc/Phobos/panel_tunnel_ip 2>/dev/null)}"
|
||||
[ -n "$SRV_IP" ] || SRV_IP="10.25.0.1"
|
||||
PORT="${TTYD_PORT:-7681}"
|
||||
SHELL_BIN="$( [ -x /opt/bin/bash ] && echo /opt/bin/bash || echo sh )"
|
||||
|
||||
# WG tunnel netdev (best effort: interface holding RFC1918 or explicit panel route)
|
||||
WGDEV=$(ip route get "$SRV_IP" 2>/dev/null | awk '{for(i=1;i<NF;i++) if($i=="dev") print $(i+1)}' | head -1)
|
||||
[ -z "$WGDEV" ] && WGDEV=nwg3
|
||||
|
||||
opkg update >/dev/null 2>&1
|
||||
opkg install ttyd >/dev/null 2>&1
|
||||
opkg install iptables >/dev/null 2>&1
|
||||
TTYD_BIN="$(command -v ttyd || echo /opt/bin/ttyd)"
|
||||
[ -x "$TTYD_BIN" ] || { echo "ERROR: ttyd not installed"; exit 1; }
|
||||
|
||||
mkdir -p /opt/etc/Phobos
|
||||
echo "$TOKEN" > /opt/etc/Phobos/ttyd_token
|
||||
chmod 600 /opt/etc/Phobos/ttyd_token
|
||||
|
||||
# init.d service: opens firewall for panel + runs ttyd (base-path + basic auth)
|
||||
cat > /opt/etc/init.d/S51phobos-ttyd <<EOF
|
||||
#!/bin/sh
|
||||
PORT=$PORT
|
||||
WGDEV=$WGDEV
|
||||
SRV_IP=$SRV_IP
|
||||
CID=$CID
|
||||
TTYD=$TTYD_BIN
|
||||
SH=$SHELL_BIN
|
||||
TOKEN=\$(cat /opt/etc/Phobos/ttyd_token 2>/dev/null)
|
||||
start() {
|
||||
# firewall: allow ONLY the panel (server tunnel IP) to reach ttyd over WG
|
||||
iptables -D INPUT -i "\$WGDEV" -s "\$SRV_IP" -p tcp --dport "\$PORT" -j ACCEPT 2>/dev/null
|
||||
iptables -I INPUT -i "\$WGDEV" -s "\$SRV_IP" -p tcp --dport "\$PORT" -j ACCEPT
|
||||
pkill -f "ttyd -p \$PORT" 2>/dev/null; sleep 1
|
||||
# busybox has no setsid/nohup; plain background detaches fine on Entware.
|
||||
# no -i flag => ttyd binds all interfaces (0.0.0.0).
|
||||
"\$TTYD" -p "\$PORT" -b "/ttyd/\$CID" -c "phobos:\$TOKEN" --writable "\$SH" >/tmp/phobos-ttyd.log 2>&1 &
|
||||
sleep 1
|
||||
echo "ttyd started on \$PORT (base /ttyd/\$CID, panel-only via \$SRV_IP)"
|
||||
}
|
||||
stop() {
|
||||
pkill -f "ttyd -p \$PORT" 2>/dev/null
|
||||
iptables -D INPUT -i "\$WGDEV" -s "\$SRV_IP" -p tcp --dport "\$PORT" -j ACCEPT 2>/dev/null
|
||||
}
|
||||
case "\$1" in
|
||||
start) start ;;
|
||||
stop) stop ;;
|
||||
restart) stop; sleep 1; start ;;
|
||||
*) echo "usage: \$0 {start|stop|restart}" ;;
|
||||
esac
|
||||
EOF
|
||||
chmod +x /opt/etc/init.d/S51phobos-ttyd
|
||||
/opt/etc/init.d/S51phobos-ttyd restart
|
||||
|
||||
echo "OK: ttyd на роутере, base-path /ttyd/$CID, порт $PORT (только для $SRV_IP по $WGDEV)."
|
||||
@@ -60,7 +60,7 @@ Options:
|
||||
Example:
|
||||
$0 --client-name Pegacomp \\
|
||||
--client-private-key "ABCD..." \\
|
||||
--client-ip 10.25.0.4 \\
|
||||
--client-ip 10.26.0.4 \\
|
||||
--client-ipv6 fd00:10:25::4 \\
|
||||
--server-public-key "EFGH..." \\
|
||||
--endpoint-port 13255 \\
|
||||
@@ -195,6 +195,7 @@ configure_wireguard_interface() {
|
||||
local description="Phobos-${CLIENT_NAME}"
|
||||
local client_ip_addr=$(echo "${CLIENT_IP}" | cut -d'/' -f1)
|
||||
local client_ipv6_block="${CLIENT_IPV6}"
|
||||
local route_target=$(echo "$client_ip_addr" | cut -d'.' -f1-2).0.0/16
|
||||
|
||||
log "Настройка интерфейса ${interface_name}..."
|
||||
|
||||
@@ -275,6 +276,31 @@ EOF
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Настраиваем статический маршрут в созданный интерфейс отдельным вызовом RCI
|
||||
local route_target_net=$(echo "$client_ip_addr" | cut -d'.' -f1-2).0.0
|
||||
log "Настройка маршрута для подсети туннеля (${route_target_net}/16) -> ${interface_name}..."
|
||||
local route_json=$(cat <<EOF
|
||||
{
|
||||
"network": "${route_target_net}",
|
||||
"mask": "255.255.0.0",
|
||||
"interface": "${interface_name}",
|
||||
"auto": true
|
||||
}
|
||||
EOF
|
||||
)
|
||||
local route_result=$(echo "${route_json}" | curl -s -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @- \
|
||||
"http://localhost:79/rci/ip/route/" 2>/dev/null)
|
||||
|
||||
if echo "${route_result}" | jq -e '.status[] | select(.status == "error")' >/dev/null 2>&1; then
|
||||
local error_msg=$(echo "${route_result}" | jq -r '.status[] | select(.status == "error") | .message // "Unknown error"' 2>/dev/null)
|
||||
error "RCI API отклонил настройку маршрута: ${error_msg}"
|
||||
log "JSON запрос:"
|
||||
log "${route_json}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Интерфейс ${interface_name} создан ✓"
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user