- sing-box 单进程 bind 数据网卡 - mixed HTTP+SOCKS + 中文静态面板 - install.sh 支持 curl | sudo bash - 512MB 友好 MemoryMax 默认 96MB
160 lines
4.3 KiB
Bash
Executable File
160 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 公共库
|
||
set -euo pipefail
|
||
|
||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
CONFIG_FILE="${CONFIG_FILE:-$ROOT_DIR/config/settings.conf}"
|
||
|
||
log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*" >&2; }
|
||
info() { log "INFO $*"; }
|
||
warn() { log "WARN $*"; }
|
||
err() { log "ERROR $*"; }
|
||
die() { err "$*"; exit 1; }
|
||
|
||
need_root() {
|
||
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
||
die "请用 root 运行(sudo)"
|
||
fi
|
||
}
|
||
|
||
load_config() {
|
||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||
die "缺少配置: $CONFIG_FILE
|
||
请先: cp $ROOT_DIR/config/settings.conf.example $ROOT_DIR/config/settings.conf"
|
||
fi
|
||
set -a
|
||
# shellcheck disable=SC1090
|
||
source "$CONFIG_FILE"
|
||
set +a
|
||
|
||
INSTALL_DIR="${INSTALL_DIR:-/opt/cellular-proxy}"
|
||
LOG_DIR="${LOG_DIR:-/var/log/cellular-proxy}"
|
||
CELLULAR_IFACE="${CELLULAR_IFACE:-}"
|
||
CELLULAR_SOURCE_IP="${CELLULAR_SOURCE_IP:-}"
|
||
REQUIRE_CELLULAR_IFACE="${REQUIRE_CELLULAR_IFACE:-true}"
|
||
CELLULAR_IFACE_PATTERNS="${CELLULAR_IFACE_PATTERNS:-wwan,wwp,usb,enx,ppp,cdc}"
|
||
PROXY_LISTEN_HOST="${PROXY_LISTEN_HOST:-0.0.0.0}"
|
||
PROXY_MIXED_PORT="${PROXY_MIXED_PORT:-7890}"
|
||
PROXY_USER="${PROXY_USER:-}"
|
||
PROXY_PASS="${PROXY_PASS:-}"
|
||
PANEL_LISTEN_HOST="${PANEL_LISTEN_HOST:-0.0.0.0}"
|
||
PANEL_PORT="${PANEL_PORT:-9090}"
|
||
PANEL_SECRET="${PANEL_SECRET:-please-change-me}"
|
||
ENABLE_DNS="${ENABLE_DNS:-true}"
|
||
LOG_LEVEL="${LOG_LEVEL:-warn}"
|
||
SING_BOX_SOURCE="${SING_BOX_SOURCE:-release}"
|
||
SING_BOX_VERSION="${SING_BOX_VERSION:-1.11.7}"
|
||
SING_BOX_BIN="${SING_BOX_BIN:-}"
|
||
MEMORY_MAX_MB="${MEMORY_MAX_MB:-96}"
|
||
EGRESS_CHECK_URL="${EGRESS_CHECK_URL:-https://ifconfig.me}"
|
||
EXPECTED_CELLULAR_PUBLIC_IP="${EXPECTED_CELLULAR_PUBLIC_IP:-}"
|
||
|
||
for v in REQUIRE_CELLULAR_IFACE ENABLE_DNS; do
|
||
val="${!v}"
|
||
case "${val,,}" in
|
||
1|true|yes|on) printf -v "$v" '%s' true ;;
|
||
*) printf -v "$v" '%s' false ;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
iface_exists() {
|
||
local ifc="$1"
|
||
[[ -n "$ifc" ]] && [[ -d "/sys/class/net/$ifc" ]]
|
||
}
|
||
|
||
is_virtual_or_skip_iface() {
|
||
local name="$1"
|
||
case "$name" in
|
||
lo|docker*|br-*|veth*|virbr*|cni*|flannel*|tun*|tap*|wg*|zt*|tailscale*|easy*|et*)
|
||
return 0
|
||
;;
|
||
esac
|
||
return 1
|
||
}
|
||
|
||
list_ifaces() {
|
||
local name state ip
|
||
for name in $(ls /sys/class/net 2>/dev/null | sort); do
|
||
[[ "$name" == "lo" ]] && continue
|
||
state="$(cat "/sys/class/net/$name/operstate" 2>/dev/null || echo unknown)"
|
||
ip="$(ip -4 -o addr show dev "$name" 2>/dev/null | awk '{print $4}' | head -1)"
|
||
printf '%s|%s|%s\n' "$name" "$state" "${ip:-}"
|
||
done
|
||
}
|
||
|
||
detect_default_iface() {
|
||
ip route show default 2>/dev/null | awk '/default/ {print $5; exit}'
|
||
}
|
||
|
||
detect_cellular_iface() {
|
||
local configured="$1"
|
||
if [[ -n "$configured" ]]; then
|
||
if [[ "$configured" == "lo" ]]; then
|
||
warn "CELLULAR_IFACE=lo 无效,将尝试自动探测"
|
||
elif iface_exists "$configured"; then
|
||
echo "$configured"
|
||
return 0
|
||
else
|
||
warn "配置的 CELLULAR_IFACE=$configured 不存在"
|
||
if [[ "$REQUIRE_CELLULAR_IFACE" == "true" ]]; then
|
||
return 1
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
local patterns name state ip p cand=""
|
||
IFS=',' read -r -a patterns <<< "$CELLULAR_IFACE_PATTERNS"
|
||
while IFS='|' read -r name state ip; do
|
||
[[ -z "$name" ]] && continue
|
||
is_virtual_or_skip_iface "$name" && continue
|
||
for p in "${patterns[@]}"; do
|
||
p="${p// /}"
|
||
[[ -z "$p" ]] && continue
|
||
if [[ "$name" == *"$p"* ]]; then
|
||
if [[ "$state" == "up" || "$state" == "unknown" ]] && [[ -n "$ip" ]]; then
|
||
echo "$name"
|
||
return 0
|
||
fi
|
||
cand="${cand:-$name}"
|
||
fi
|
||
done
|
||
done < <(list_ifaces)
|
||
|
||
if [[ -n "$cand" ]]; then
|
||
echo "$cand"
|
||
return 0
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
detect_source_ip() {
|
||
local ifc="$1"
|
||
ip -4 -o addr show dev "$ifc" 2>/dev/null | awk '{print $4}' | head -1 | cut -d/ -f1
|
||
}
|
||
|
||
arch_go() {
|
||
case "$(uname -m)" in
|
||
x86_64|amd64) echo amd64 ;;
|
||
aarch64|arm64) echo arm64 ;;
|
||
armv7l|armhf) echo armv7 ;;
|
||
*) die "不支持的架构: $(uname -m)" ;;
|
||
esac
|
||
}
|
||
|
||
ensure_dirs() {
|
||
mkdir -p "$INSTALL_DIR"/{bin,etc,ui,generated} "$LOG_DIR"
|
||
}
|
||
|
||
resolve_cellular() {
|
||
local cell
|
||
if ! cell="$(detect_cellular_iface "$CELLULAR_IFACE")"; then
|
||
if [[ "$REQUIRE_CELLULAR_IFACE" == "true" ]]; then
|
||
die "无法确定数据网卡。请设置 CELLULAR_IFACE= 或运行 scripts/detect.sh"
|
||
fi
|
||
warn "未找到数据网卡"
|
||
cell=""
|
||
fi
|
||
echo "$cell"
|
||
}
|