#!/usr/bin/env bash set -e # ───────────────────────────────────────────────────────────── # VPN 子网(与后台 VPN 设置中的子网保持一致) # 若后台修改了子网,需同步修改此处并重新执行脚本,或手动更新 iptables 规则 # ───────────────────────────────────────────────────────────── VPN_SUBNET="192.168.77.0/24" if [ "$(id -u)" -ne 0 ]; then echo "请使用 root 用户执行此脚本: sudo bash install_linux.sh" exit 1 fi echo ">>> 拉取最新代码..." git pull echo ">>> 安装前端依赖并构建..." cd frontend npm install npm run build cd .. echo ">>> 编译 Go 后端..." go build -o lmvpn . echo ">>> 创建 lmvpn 系统用户..." if ! id lmvpn &>/dev/null; then useradd -r -s /bin/false lmvpn echo "用户 lmvpn 已创建" else echo "用户 lmvpn 已存在,跳过创建" fi echo ">>> 部署到 /opt/lmvpn..." systemctl stop lmvpn 2>/dev/null || true mkdir -p /opt/lmvpn cp lmvpn /opt/lmvpn/ cp -r dist /opt/lmvpn/ chown -R lmvpn:lmvpn /opt/lmvpn echo ">>> 配置内核 IP 转发..." # 临时生效 sysctl -w net.ipv4.ip_forward=1 >/dev/null # 持久化 cat > /etc/sysctl.d/99-lmvpn.conf << EOF net.ipv4.ip_forward = 1 EOF sysctl -p /etc/sysctl.d/99-lmvpn.conf >/dev/null echo ">>> 配置 NAT 与转发规则..." # 自动检测默认路由出口网卡 WAN_IFACE=$(ip route show default 2>/dev/null | awk '{print $5; exit}') if [ -z "$WAN_IFACE" ]; then echo "警告: 未能自动检测出口网卡,跳过 NAT 配置,请手动设置" else echo "出口网卡: $WAN_IFACE" # 选择可用的防火墙前端:优先 nft(原生,Debian 12+ 的 iptables 是 nft 包装器,操作原生 nft nat 表会不兼容) NAT_TOOL="" if command -v nft >/dev/null 2>&1; then NAT_TOOL="nft" elif command -v iptables >/dev/null 2>&1; then NAT_TOOL="iptables" fi if [ -z "$NAT_TOOL" ]; then echo "警告: 未找到 nft 或 iptables,跳过 NAT 配置" echo " 客户端将无法上外网。请安装: apt install nftables" echo " 安装后重新执行本脚本即可自动配置" elif [ "$NAT_TOOL" = "nft" ]; then echo "使用 nft 配置 NAT..." # 幂等:先删除旧表(忽略错误),再创建 nft delete table inet lmvpn_nat 2>/dev/null || true nft add table inet lmvpn_nat nft 'add chain inet lmvpn_nat postrouting { type nat hook postrouting priority 100 ; }' nft add rule inet lmvpn_nat postrouting oifname "$WAN_IFACE" ip saddr "$VPN_SUBNET" masquerade nft 'add chain inet lmvpn_nat forward { type filter hook forward priority 0 ; policy accept ; }' nft add rule inet lmvpn_nat forward ip saddr "$VPN_SUBNET" accept nft add rule inet lmvpn_nat forward ip daddr "$VPN_SUBNET" accept # 持久化 nft 规则 mkdir -p /etc/nftables.d nft list ruleset > /etc/nftables.d/lmvpn.nft # 确保主配置文件 include 该目录 if [ -f /etc/nftables.conf ] && ! grep -q 'include "/etc/nftables.d' /etc/nftables.conf; then echo 'include "/etc/nftables.d/*.nft"' >> /etc/nftables.conf fi systemctl enable nftables 2>/dev/null || true echo "nft 规则已写入 /etc/nftables.d/lmvpn.nft" elif [ "$NAT_TOOL" = "iptables" ]; then echo "使用 iptables 配置 NAT..." # 幂等:先删除旧规则(忽略错误),再添加 iptables -t nat -D POSTROUTING -s "$VPN_SUBNET" -o "$WAN_IFACE" -j MASQUERADE 2>/dev/null || true iptables -t nat -A POSTROUTING -s "$VPN_SUBNET" -o "$WAN_IFACE" -j MASQUERADE iptables -D FORWARD -s "$VPN_SUBNET" -j ACCEPT 2>/dev/null || true iptables -D FORWARD -d "$VPN_SUBNET" -j ACCEPT 2>/dev/null || true iptables -A FORWARD -s "$VPN_SUBNET" -j ACCEPT iptables -A FORWARD -d "$VPN_SUBNET" -j ACCEPT # 持久化 iptables 规则 if command -v netfilter-persistent >/dev/null 2>&1; then netfilter-persistent save echo "iptables 规则已通过 netfilter-persistent 持久化" elif command -v iptables-save >/dev/null 2>&1; then mkdir -p /etc/iptables iptables-save > /etc/iptables/rules.v4 echo "iptables 规则已写入 /etc/iptables/rules.v4" echo "注意: 重启后规则持久化需配合 iptables-persistent 包,建议安装: apt install iptables-persistent" else echo "警告: 未找到 iptables-save,规则仅在本次运行有效,请手动持久化" fi fi fi echo ">>> 安装 systemd 服务..." cat > /etc/systemd/system/lmvpn.service << 'EOF' [Unit] Description=LMVPN Server After=network.target [Service] Type=simple User=lmvpn WorkingDirectory=/opt/lmvpn ExecStart=/opt/lmvpn/lmvpn Restart=on-failure RestartSec=5 # 授予 TUN 设备创建与网络管理能力,无需 root 运行 AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable lmvpn systemctl restart lmvpn echo ">>> 安装完成" systemctl status lmvpn --no-pager