#!/bin/bash # ============================================ # Easytier 一键部署/卸载脚本(服务端 / 客户端) # 功能:自动下载、解压、配置 systemd 服务并启动 Easytier VPN # 适用系统:Debian/Ubuntu/CentOS/RHEL # 支持架构:x86_64 / arm64 (aarch64) # ============================================ set -euo pipefail # ============================================ # 颜色输出函数 # ============================================ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; exit 1; } # 从终端读取用户输入(兼容 curl | bash 管道执行) tty_read() { local prompt="$1" varname="$2" if [ -r /dev/tty ]; then echo -ne "$prompt" > /dev/tty read -r "$varname" < /dev/tty else log_error "无法打开终端 /dev/tty,请确认在交互式终端中运行" fi } # ============================================ # 用户配置变量(按需修改) # ============================================ # VPN 网络密钥(所有节点必须一致) SECRET='' # VPN 网络名称(所有节点必须一致) NETWORK_NAME="" # Easytier 安装目录 EASYTIER_DIR="/opt/easytier" # 版本号 VERSION="v2.6.4" # 下载地址(GitHub 加速镜像) # 自动检测系统架构 ARCH=$(uname -m) case "$ARCH" in x86_64) ARCH_NAME="x86_64" ;; aarch64) ARCH_NAME="aarch64" ;; armv7*) ARCH_NAME="armv7" ;; *) log_error "不支持的架构: $ARCH(仅支持 x86_64/arm64/armv7)" ;; esac DOWNLOAD_URL="https://ghfast.top/https://github.com/EasyTier/EasyTier/releases/download/${VERSION}/easytier-linux-${ARCH_NAME}-${VERSION}.zip" # 下载后的 ZIP 文件名 ZIP_FILE="easytier-linux-${ARCH_NAME}-${VERSION}.zip" # 解压后的子目录名 EXTRACT_DIR="easytier-linux-${ARCH_NAME}" # ============================================ # 卸载函数 # ============================================ uninstall_easytier() { echo "" echo -e "${RED}==========================================${NC}" echo -e "${RED} Easytier VPN 卸载确认${NC}" echo -e "${RED}==========================================${NC}" echo "" echo " 将执行以下操作:" echo " 1. 停止并禁用 easytier 服务" echo " 2. 删除 systemd 服务文件" echo " 3. 删除安装目录: $EASYTIER_DIR" echo " 4. 删除下载的 ZIP 文件" echo "" tty_read "确认卸载?此操作不可恢复 [y/N]: " CONFIRM_UNINSTALL if [[ ! "$CONFIRM_UNINSTALL" =~ ^[Yy]$ ]]; then log_info "已取消卸载" exit 0 fi log_info "停止 easytier 服务..." systemctl stop easytier 2>/dev/null || true systemctl disable easytier 2>/dev/null || true log_info "删除 systemd 服务文件..." rm -f /etc/systemd/system/easytier.service systemctl daemon-reload log_info "删除安装目录: $EASYTIER_DIR" rm -rf "$EASYTIER_DIR" log_info "清理下载的 ZIP 文件..." rm -f "easytier-linux-x86_64-"*.zip rm -f "easytier-linux-aarch64-"*.zip rm -f "easytier-linux-armv7-"*.zip echo "" log_info "Easytier 已完全卸载" echo "" exit 0 } # ============================================ # 1. 检查 root 权限 # ============================================ if [ "$EUID" -ne 0 ]; then log_error "请使用 root 用户执行: sudo bash $0" fi # ============================================ # 2. 选择部署模式 # ============================================ clear echo "" echo -e "${CYAN}==========================================${NC}" echo -e "${CYAN} Easytier VPN 一键管理脚本${NC}" echo -e "${CYAN}==========================================${NC}" echo "" echo -e " ${GREEN}1.${NC} 部署为 ${GREEN}服务端${NC}" echo -e " ${YELLOW}2.${NC} 部署为 ${YELLOW}客户端${NC}" echo -e " ${RED}3.${NC} ${RED}卸载 Easytier${NC}" echo "" tty_read "请选择 [1/2/3]: " MODE case "$MODE" in 3) uninstall_easytier ;; 1) ROLE="server" # 服务端虚拟 IP tty_read "请输入服务端虚拟 IP [10.126.5.1]: " VIRTUAL_IP VIRTUAL_IP="${VIRTUAL_IP:-10.126.5.1}" HOSTNAME=$(hostname) ;; 2) ROLE="client" # 客户端需要知道服务端信息 tty_read "请输入服务器公网 IP: " SERVER_PUBLIC_IP if [ -z "$SERVER_PUBLIC_IP" ]; then log_error "服务器公网 IP 不能为空" fi tty_read "请输入服务端虚拟 IP [10.126.5.1]: " SERVER_VIRTUAL_IP SERVER_VIRTUAL_IP="${SERVER_VIRTUAL_IP:-10.126.5.1}" VIRTUAL_IP="dhcp" HOSTNAME=$(hostname) ;; *) log_error "无效选择,请输入 1 或 2" ;; esac # 校验虚拟 IP 格式(服务端模式) if [ "$ROLE" = "server" ] && [ "$VIRTUAL_IP" != "dhcp" ]; then if ! echo "$VIRTUAL_IP" | grep -qE '^([0-9]{1,3}\.){3}[0-9]{1,3}$'; then log_error "虚拟 IP 格式错误,请输入类似 10.126.5.1 的格式" fi # 校验 IP 每段数值范围 0-255 IFS='.' read -r -a IP_PARTS <<< "$VIRTUAL_IP" for part in "${IP_PARTS[@]}"; do if [ "$part" -gt 255 ] 2>/dev/null; then log_error "虚拟 IP 数值超出范围(0-255): $VIRTUAL_IP" fi done fi # 确认信息 echo "" echo -e "${CYAN}==========================================${NC}" if [ "$ROLE" = "server" ]; then echo -e " 部署模式: ${GREEN}服务端${NC}" echo " 节点名称: $HOSTNAME" echo " 虚拟 IP: $VIRTUAL_IP" else echo -e " 部署模式: ${YELLOW}客户端${NC}" echo " 节点名称: $HOSTNAME" echo " 虚拟 IP: DHCP 自动分配" echo " 服务器 IP: $SERVER_PUBLIC_IP" echo " 服务端 VIP: $SERVER_VIRTUAL_IP" fi echo " 网络名称: $NETWORK_NAME" echo -e "${CYAN}==========================================${NC}" tty_read "确认以上信息?[Y/n]: " CONFIRM CONFIRM="${CONFIRM:-Y}" if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then exec bash "$0" fi # ============================================ # 3. 处理 RPC 白名单(仅服务端) # ============================================ if [ "$ROLE" = "server" ]; then NETWORK_PREFIX=$(echo "$VIRTUAL_IP" | cut -d. -f1-3) RPC_WHITELIST="127.0.0.1,${NETWORK_PREFIX}.0/24" log_info "RPC 白名单网段: ${NETWORK_PREFIX}.0/24" fi # ============================================ # 4. Easytier 启动参数 # ============================================ if [ "$ROLE" = "server" ]; then START_ARGS=(-i "$VIRTUAL_IP" --network-name "$NETWORK_NAME" --network-secret "$SECRET" --hostname "$HOSTNAME" -l "0.0.0.0:11010" --enable-exit-node -r "0.0.0.0:15888" --rpc-portal-whitelist "$RPC_WHITELIST") else START_ARGS=(--network-name "$NETWORK_NAME" --network-secret "$SECRET" --hostname "$HOSTNAME" -p "tcp://$SERVER_PUBLIC_IP:11010" --exit-nodes "$SERVER_VIRTUAL_IP") fi # ============================================ # 5. 安装必要工具(wget、unzip) # ============================================ log_info "检查并安装必要工具..." install_pkg() { local pkg="$1" if command -v apt-get &>/dev/null; then apt-get update -qq && apt-get install -y -qq "$pkg" elif command -v yum &>/dev/null; then yum install -y "$pkg" elif command -v dnf &>/dev/null; then dnf install -y "$pkg" else log_error "无法识别包管理器,请手动安装: $pkg" fi } command -v wget &>/dev/null || { log_info "正在安装 wget..."; install_pkg wget; } command -v unzip &>/dev/null || { log_info "正在安装 unzip..."; install_pkg unzip; } # ============================================ # 6. 下载 Easytier 安装包 # ============================================ if [ ! -f "$ZIP_FILE" ]; then log_info "正在下载 Easytier ${VERSION}(架构: ${ARCH})..." if command -v wget &>/dev/null; then wget -q --show-progress -O "$ZIP_FILE" "$DOWNLOAD_URL" else curl -fSL -o "$ZIP_FILE" "$DOWNLOAD_URL" fi log_info "下载完成" else log_warn "$ZIP_FILE 已存在,跳过下载" fi # ============================================ # 7. 解压到安装目录 # ============================================ log_info "正在解压 $ZIP_FILE 到 $EASYTIER_DIR..." # 防止空变量导致危险删除 [ -z "$EASYTIER_DIR" ] && log_error "安装目录变量为空" rm -rf "$EASYTIER_DIR" mkdir -p "$EASYTIER_DIR" unzip -q -o "$ZIP_FILE" -d "$EASYTIER_DIR" if [ -d "$EASYTIER_DIR/$EXTRACT_DIR" ]; then log_info "正在调整目录结构..." mv "$EASYTIER_DIR/$EXTRACT_DIR"/* "$EASYTIER_DIR/" rmdir "$EASYTIER_DIR/$EXTRACT_DIR" fi chmod +x "$EASYTIER_DIR"/easytier-* # ============================================ # 8. 创建 systemd 服务 # ============================================ log_info "创建 systemd 服务..." if [ "$ROLE" = "server" ]; then SERVICE_DESC="Easytier VPN Server" else SERVICE_DESC="Easytier VPN Client" fi cat > /etc/systemd/system/easytier.service << EOF [Unit] Description=$SERVICE_DESC After=network-online.target Wants=network-online.target [Service] Type=simple WorkingDirectory=$EASYTIER_DIR ExecStart=$EASYTIER_DIR/easytier-core ${START_ARGS[*]} ExecStop=/bin/kill -SIGTERM \$MAINPID Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF # ============================================ # 9. 启用并启动服务 # ============================================ log_info "启动 Easytier 服务..." systemctl daemon-reload systemctl enable easytier # 先停止可能残留的旧进程,再启动 systemctl stop easytier 2>/dev/null || true systemctl start easytier # ============================================ # 10. 检查服务状态并输出结果 # ============================================ sleep 2 if systemctl is-active --quiet easytier; then if [ "$ROLE" = "server" ]; then log_info "✅ Easytier 服务端已成功启动!" else log_info "✅ Easytier 客户端已成功启动!" fi echo "" echo -e "${CYAN}==========================================${NC}" echo " 服务信息" echo -e "${CYAN}==========================================${NC}" echo " 安装目录: $EASYTIER_DIR" if [ "$ROLE" = "server" ]; then echo " 虚拟 IP: $VIRTUAL_IP" echo " 端口: 11010 (TCP/UDP), 15888 (RPC)" else echo " 虚拟 IP: DHCP 自动分配" echo " 服务器: $SERVER_PUBLIC_IP:11010" echo " 出口节点: $SERVER_VIRTUAL_IP" fi echo " 网络名: $NETWORK_NAME" echo " 节点名: $HOSTNAME" echo -e "${CYAN}==========================================${NC}" echo "" echo "========== 常用命令 ==========" echo " 查看日志: journalctl -u easytier -f" echo " 重启服务: systemctl restart easytier" echo " 停止服务: systemctl stop easytier" echo " 查看状态: systemctl status easytier" echo "==============================" echo "" else log_error "服务启动失败,请查看日志: journalctl -u easytier -n 50 --no-pager" fi