2026-04-20 20:19:37 +03:00
|
|
|
|
#!/bin/sh
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
# Деплой frpc на роутер OpenWRT без установки пакета.
|
|
|
|
|
|
# frpc скачивается в /tmp при каждой перезагрузке.
|
|
|
|
|
|
# SERVER_IP и FRP_TOKEN получаются автоматически с bootstrap API.
|
|
|
|
|
|
#
|
|
|
|
|
|
# Использование:
|
2026-04-21 09:34:31 +03:00
|
|
|
|
# sh -c "$(wget -qO- https://raw.githubusercontent.com/Official-VPN/Routers-FRP/main/router/setup-tmpfs.sh)"
|
2026-04-20 20:19:37 +03:00
|
|
|
|
# или:
|
2026-04-21 09:34:31 +03:00
|
|
|
|
# ./setup-tmpfs.sh
|
2026-04-20 20:19:37 +03:00
|
|
|
|
#
|
|
|
|
|
|
# Требования: wget с поддержкой HTTPS (встроен в OpenWRT 23/24)
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
2026-04-21 09:34:31 +03:00
|
|
|
|
BOOTSTRAP_DOMAIN="getconfig.tgvpnbot.com"
|
2026-04-20 20:19:37 +03:00
|
|
|
|
|
|
|
|
|
|
# --- Определяем архитектуру роутера ---
|
|
|
|
|
|
detect_arch() {
|
|
|
|
|
|
local machine
|
|
|
|
|
|
machine=$(uname -m)
|
|
|
|
|
|
case "$machine" in
|
|
|
|
|
|
mips)
|
|
|
|
|
|
if grep -q "MIPS.*EB\|Big Endian" /proc/cpuinfo 2>/dev/null; then
|
|
|
|
|
|
echo "mips"
|
|
|
|
|
|
else
|
|
|
|
|
|
echo "mipsle"
|
|
|
|
|
|
fi
|
|
|
|
|
|
;;
|
|
|
|
|
|
mipsel) echo "mipsle" ;;
|
|
|
|
|
|
mips64) echo "mips64" ;;
|
|
|
|
|
|
mips64el) echo "mips64le" ;;
|
|
|
|
|
|
armv7l|armv6l) echo "arm" ;;
|
|
|
|
|
|
aarch64) echo "arm64" ;;
|
|
|
|
|
|
x86_64) echo "amd64" ;;
|
|
|
|
|
|
i686|i386) echo "386" ;;
|
|
|
|
|
|
*) echo "unknown" ;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ARCH=$(detect_arch)
|
|
|
|
|
|
if [ "$ARCH" = "unknown" ]; then
|
|
|
|
|
|
echo "ERROR: Cannot detect CPU architecture (uname -m = $(uname -m))"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
echo "CPU architecture: $(uname -m) → frpc arch: ${ARCH}"
|
|
|
|
|
|
|
|
|
|
|
|
# --- Получаем MAC-адрес WAN-интерфейса ---
|
|
|
|
|
|
WAN_DEV=$(uci get network.wan.device 2>/dev/null)
|
|
|
|
|
|
[ -z "$WAN_DEV" ] && WAN_DEV=$(uci get network.wan.ifname 2>/dev/null)
|
|
|
|
|
|
[ -z "$WAN_DEV" ] && WAN_DEV=$(uci get network.wan6.device 2>/dev/null)
|
|
|
|
|
|
[ -z "$WAN_DEV" ] && WAN_DEV="eth0"
|
|
|
|
|
|
|
|
|
|
|
|
MAC_RAW=$(cat /sys/class/net/"${WAN_DEV}"/address 2>/dev/null)
|
|
|
|
|
|
if [ -z "$MAC_RAW" ]; then
|
|
|
|
|
|
MAC_RAW=$(ip link show "$WAN_DEV" 2>/dev/null | awk '/link\/ether/{print $2}')
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$MAC_RAW" ]; then
|
|
|
|
|
|
echo "ERROR: Cannot detect WAN MAC address (device: ${WAN_DEV})"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
MAC=$(echo "$MAC_RAW" | tr ':' '-' | tr 'a-f' 'A-F')
|
2026-04-21 09:34:31 +03:00
|
|
|
|
MAC_PLAIN=$(echo "$MAC_RAW" | tr -d ':' | tr 'a-f' 'A-F')
|
2026-04-20 20:19:37 +03:00
|
|
|
|
|
|
|
|
|
|
echo "WAN device : $WAN_DEV"
|
|
|
|
|
|
echo "WAN MAC : $MAC_RAW"
|
|
|
|
|
|
echo "Proxy names: ssh-${MAC} / luci-${MAC}"
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Получаем SERVER_IP и FRP_TOKEN с bootstrap API ---
|
|
|
|
|
|
echo "Fetching FRP config from ${BOOTSTRAP_DOMAIN} ..."
|
|
|
|
|
|
BOOTSTRAP_RESPONSE=$(wget -q --no-check-certificate \
|
2026-04-21 09:34:31 +03:00
|
|
|
|
-O - "https://${BOOTSTRAP_DOMAIN}/getfrpconfig?routermac=${MAC_PLAIN}" 2>/tmp/frpc_bootstrap.log)
|
2026-04-20 20:19:37 +03:00
|
|
|
|
|
|
|
|
|
|
if [ -z "$BOOTSTRAP_RESPONSE" ]; then
|
|
|
|
|
|
echo "ERROR: Bootstrap API unreachable or returned empty response"
|
|
|
|
|
|
echo "Check: cat /tmp/frpc_bootstrap.log"
|
|
|
|
|
|
echo "Make sure MAC ${MAC_RAW} is registered in the Router-Configs-Backend"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
SERVER_IP=$(echo "$BOOTSTRAP_RESPONSE" | sed -n 's/.*"server_ip"[^:]*:[^"]*"\([^"]*\)".*/\1/p')
|
|
|
|
|
|
FRP_TOKEN=$(echo "$BOOTSTRAP_RESPONSE" | sed -n 's/.*"frp_token"[^:]*:[^"]*"\([^"]*\)".*/\1/p')
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$SERVER_IP" ] || [ -z "$FRP_TOKEN" ]; then
|
|
|
|
|
|
echo "ERROR: Failed to parse bootstrap response:"
|
|
|
|
|
|
echo "$BOOTSTRAP_RESPONSE"
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
echo "Bootstrap OK: server=${SERVER_IP}"
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Сохраняем конфиг для бутового скрипта ---
|
|
|
|
|
|
CONFIG_PERSIST="/etc/frpc_bootstrap.conf"
|
|
|
|
|
|
|
|
|
|
|
|
cat > "$CONFIG_PERSIST" <<EOF
|
|
|
|
|
|
# frpc bootstrap config — generated by setup-tmpfs.sh $(date '+%Y-%m-%d %H:%M')
|
|
|
|
|
|
# Для обновления настроек перезагрузите роутер или запустите /etc/init.d/frpc-boot restart
|
|
|
|
|
|
BOOTSTRAP_DOMAIN="${BOOTSTRAP_DOMAIN}"
|
|
|
|
|
|
SERVER_IP="${SERVER_IP}"
|
|
|
|
|
|
FRP_TOKEN="${FRP_TOKEN}"
|
|
|
|
|
|
FRP_ARCH="${ARCH}"
|
|
|
|
|
|
MAC="${MAC}"
|
|
|
|
|
|
MAC_RAW="${MAC_RAW}"
|
2026-04-21 09:34:31 +03:00
|
|
|
|
MAC_PLAIN="${MAC_PLAIN}"
|
2026-04-20 20:19:37 +03:00
|
|
|
|
FRP_VERSION="0.61.1"
|
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
echo "Bootstrap config saved: $CONFIG_PERSIST"
|
|
|
|
|
|
|
|
|
|
|
|
# --- Настраиваем dropbear: слушать на всех интерфейсах ---
|
|
|
|
|
|
echo "Configuring dropbear to listen on all interfaces ..."
|
|
|
|
|
|
uci set dropbear.@dropbear[0].Interface=''
|
|
|
|
|
|
uci commit dropbear
|
|
|
|
|
|
/etc/init.d/dropbear restart
|
|
|
|
|
|
echo "dropbear restarted"
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# --- Создаём бутовый init-скрипт ---
|
|
|
|
|
|
INIT_SCRIPT="/etc/init.d/frpc-boot"
|
|
|
|
|
|
|
|
|
|
|
|
cat > "$INIT_SCRIPT" <<'INITEOF'
|
|
|
|
|
|
#!/bin/sh /etc/rc.common
|
|
|
|
|
|
# frpc-boot — при каждом ребуте: обновляет конфиг с bootstrap API,
|
|
|
|
|
|
# скачивает frpc в /tmp и запускает его.
|
|
|
|
|
|
|
|
|
|
|
|
START=99
|
|
|
|
|
|
STOP=10
|
|
|
|
|
|
USE_PROCD=1
|
|
|
|
|
|
|
|
|
|
|
|
CONF="/etc/frpc_bootstrap.conf"
|
|
|
|
|
|
FRPC_BIN="/tmp/frpc"
|
|
|
|
|
|
FRPC_CONF="/tmp/frpc.toml"
|
|
|
|
|
|
FRPC_LOG="/tmp/frpc.log"
|
|
|
|
|
|
|
|
|
|
|
|
DOWNLOAD_BASE="https://github.com/fatedier/frp/releases/download"
|
|
|
|
|
|
|
|
|
|
|
|
load_config() {
|
|
|
|
|
|
if [ ! -f "$CONF" ]; then
|
|
|
|
|
|
logger -t frpc-boot "ERROR: $CONF not found"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
. "$CONF"
|
|
|
|
|
|
if [ -z "$MAC" ] || [ -z "$FRP_ARCH" ]; then
|
|
|
|
|
|
logger -t frpc-boot "ERROR: incomplete config in $CONF"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
return 0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Обновляем SERVER_IP и FRP_TOKEN с bootstrap API
|
|
|
|
|
|
fetch_frp_config() {
|
|
|
|
|
|
if [ -z "$BOOTSTRAP_DOMAIN" ]; then
|
|
|
|
|
|
logger -t frpc-boot "No BOOTSTRAP_DOMAIN, using cached config"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
logger -t frpc-boot "Fetching FRP config from ${BOOTSTRAP_DOMAIN} ..."
|
|
|
|
|
|
local response
|
|
|
|
|
|
response=$(wget -q --no-check-certificate \
|
2026-04-21 09:34:31 +03:00
|
|
|
|
-O - "https://${BOOTSTRAP_DOMAIN}/getfrpconfig?routermac=${MAC_PLAIN}" \
|
2026-04-20 20:19:37 +03:00
|
|
|
|
2>/tmp/frpc_bootstrap.log) || true
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$response" ]; then
|
|
|
|
|
|
logger -t frpc-boot "Bootstrap unreachable, using cached config (${SERVER_IP})"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
local new_ip new_token
|
|
|
|
|
|
new_ip=$(echo "$response" | sed -n 's/.*"server_ip"[^:]*:[^"]*"\([^"]*\)".*/\1/p')
|
|
|
|
|
|
new_token=$(echo "$response" | sed -n 's/.*"frp_token"[^:]*:[^"]*"\([^"]*\)".*/\1/p')
|
|
|
|
|
|
|
|
|
|
|
|
if [ -n "$new_ip" ] && [ -n "$new_token" ]; then
|
|
|
|
|
|
if [ "$new_ip" != "$SERVER_IP" ] || [ "$new_token" != "$FRP_TOKEN" ]; then
|
|
|
|
|
|
sed -i "s|^SERVER_IP=.*|SERVER_IP=\"${new_ip}\"|" "$CONF"
|
|
|
|
|
|
sed -i "s|^FRP_TOKEN=.*|FRP_TOKEN=\"${new_token}\"|" "$CONF"
|
|
|
|
|
|
. "$CONF"
|
|
|
|
|
|
logger -t frpc-boot "FRP config updated: server=${new_ip}"
|
|
|
|
|
|
else
|
|
|
|
|
|
logger -t frpc-boot "FRP config unchanged: server=${SERVER_IP}"
|
|
|
|
|
|
fi
|
|
|
|
|
|
else
|
|
|
|
|
|
logger -t frpc-boot "Invalid bootstrap response, using cached config"
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
download_frpc() {
|
|
|
|
|
|
local version="${FRP_VERSION:-0.61.1}"
|
|
|
|
|
|
local arch="${FRP_ARCH}"
|
|
|
|
|
|
local url="${DOWNLOAD_BASE}/v${version}/frp_${version}_linux_${arch}.tar.gz"
|
|
|
|
|
|
local tmp_tar="/tmp/frp_download.tar.gz"
|
|
|
|
|
|
|
|
|
|
|
|
logger -t frpc-boot "Downloading frpc ${version} (${arch}) ..."
|
|
|
|
|
|
|
|
|
|
|
|
if wget -q --no-check-certificate -O "$tmp_tar" "$url" 2>/tmp/frpc_wget.log; then
|
|
|
|
|
|
local tmp_dir="/tmp/frp_extract"
|
|
|
|
|
|
rm -rf "$tmp_dir"
|
|
|
|
|
|
mkdir -p "$tmp_dir"
|
|
|
|
|
|
if tar -xzf "$tmp_tar" -C "$tmp_dir" 2>/tmp/frpc_wget.log; then
|
|
|
|
|
|
mv "$tmp_dir"/frp_*/frpc "$FRPC_BIN" 2>/dev/null \
|
|
|
|
|
|
|| mv "$tmp_dir"/frpc "$FRPC_BIN" 2>/dev/null
|
|
|
|
|
|
chmod +x "$FRPC_BIN"
|
|
|
|
|
|
rm -rf "$tmp_dir" "$tmp_tar"
|
|
|
|
|
|
logger -t frpc-boot "frpc downloaded OK"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
else
|
|
|
|
|
|
logger -t frpc-boot "ERROR: tar failed"
|
|
|
|
|
|
rm -rf "$tmp_dir" "$tmp_tar"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
else
|
|
|
|
|
|
logger -t frpc-boot "ERROR: wget failed — $(cat /tmp/frpc_wget.log)"
|
|
|
|
|
|
rm -f "$tmp_tar"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
write_config() {
|
|
|
|
|
|
cat > "$FRPC_CONF" <<EOF
|
|
|
|
|
|
# Generated by frpc-boot at $(date)
|
|
|
|
|
|
# Router MAC: ${MAC}
|
|
|
|
|
|
|
|
|
|
|
|
serverAddr = "${SERVER_IP}"
|
|
|
|
|
|
serverPort = 7000
|
|
|
|
|
|
|
|
|
|
|
|
auth.method = "token"
|
|
|
|
|
|
auth.token = "${FRP_TOKEN}"
|
|
|
|
|
|
|
|
|
|
|
|
log.to = "${FRPC_LOG}"
|
|
|
|
|
|
log.level = "warn"
|
|
|
|
|
|
log.maxDays = 1
|
|
|
|
|
|
|
|
|
|
|
|
[[proxies]]
|
|
|
|
|
|
name = "ssh-${MAC}"
|
|
|
|
|
|
type = "tcp"
|
|
|
|
|
|
localIP = "0.0.0.0"
|
|
|
|
|
|
localPort = 11041
|
|
|
|
|
|
remotePort = 0
|
|
|
|
|
|
|
|
|
|
|
|
[[proxies]]
|
|
|
|
|
|
name = "luci-${MAC}"
|
|
|
|
|
|
type = "tcp"
|
|
|
|
|
|
localIP = "127.0.0.1"
|
|
|
|
|
|
localPort = 80
|
|
|
|
|
|
remotePort = 0
|
|
|
|
|
|
EOF
|
|
|
|
|
|
logger -t frpc-boot "Config written: server=${SERVER_IP}"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
start_service() {
|
|
|
|
|
|
load_config || return 1
|
|
|
|
|
|
|
|
|
|
|
|
# Обновляем конфиг с bootstrap API (безопасно: при недоступности используем кэш)
|
|
|
|
|
|
fetch_frp_config
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$SERVER_IP" ] || [ -z "$FRP_TOKEN" ]; then
|
|
|
|
|
|
logger -t frpc-boot "ERROR: SERVER_IP or FRP_TOKEN not available"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [ ! -x "$FRPC_BIN" ]; then
|
|
|
|
|
|
download_frpc || {
|
|
|
|
|
|
logger -t frpc-boot "Cannot start: frpc binary unavailable"
|
|
|
|
|
|
return 1
|
|
|
|
|
|
}
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
write_config
|
|
|
|
|
|
|
|
|
|
|
|
logger -t frpc-boot "Starting frpc (ssh-${MAC}, luci-${MAC}) ..."
|
|
|
|
|
|
|
|
|
|
|
|
procd_open_instance
|
|
|
|
|
|
procd_set_param command "$FRPC_BIN" -c "$FRPC_CONF"
|
|
|
|
|
|
procd_set_param stdout 0
|
|
|
|
|
|
procd_set_param stderr 0
|
|
|
|
|
|
procd_set_param respawn 300 5 0
|
|
|
|
|
|
procd_close_instance
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stop_service() {
|
|
|
|
|
|
logger -t frpc-boot "Stopping frpc"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boot() {
|
|
|
|
|
|
sleep 10
|
|
|
|
|
|
start
|
|
|
|
|
|
}
|
|
|
|
|
|
INITEOF
|
|
|
|
|
|
|
|
|
|
|
|
chmod +x "$INIT_SCRIPT"
|
|
|
|
|
|
echo "Init script created: $INIT_SCRIPT"
|
|
|
|
|
|
|
|
|
|
|
|
# --- Включаем автозапуск ---
|
|
|
|
|
|
"$INIT_SCRIPT" enable
|
|
|
|
|
|
echo "Service enabled (will start on next boot)"
|
|
|
|
|
|
|
|
|
|
|
|
# --- Запускаем сейчас ---
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo "Starting frpc now ..."
|
|
|
|
|
|
"$INIT_SCRIPT" start
|
|
|
|
|
|
|
|
|
|
|
|
sleep 3
|
|
|
|
|
|
|
|
|
|
|
|
# --- Проверка ---
|
|
|
|
|
|
if pgrep frpc >/dev/null 2>&1; then
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo "OK: frpc is running"
|
|
|
|
|
|
echo " Server : ${SERVER_IP}"
|
|
|
|
|
|
echo " Binary : /tmp/frpc"
|
|
|
|
|
|
echo " Config : /tmp/frpc.toml"
|
|
|
|
|
|
echo " Proxies: ssh-${MAC} / luci-${MAC}"
|
|
|
|
|
|
else
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo "WARNING: frpc may not be running."
|
|
|
|
|
|
echo "Check:"
|
|
|
|
|
|
echo " logread | grep frpc-boot"
|
|
|
|
|
|
echo " cat /tmp/frpc.log"
|
|
|
|
|
|
fi
|