345 lines
11 KiB
Bash
345 lines
11 KiB
Bash
#!/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; }
|
||
|
||
# ============================================
|
||
# 用户配置变量(按需修改)
|
||
# ============================================
|
||
|
||
# VPN 网络密钥(所有节点必须一致)
|
||
SECRET='<secret_test>'
|
||
|
||
# VPN 网络名称(所有节点必须一致)
|
||
NETWORK_NAME="<test-network>"
|
||
|
||
# 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 ""
|
||
read -p "确认卸载?此操作不可恢复 [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 ""
|
||
read -p "请选择 [1/2/3]: " MODE
|
||
|
||
case "$MODE" in
|
||
3)
|
||
uninstall_easytier
|
||
;;
|
||
1)
|
||
ROLE="server"
|
||
# 服务端虚拟 IP
|
||
read -p "请输入服务端虚拟 IP [10.126.5.1]: " VIRTUAL_IP
|
||
VIRTUAL_IP="${VIRTUAL_IP:-10.126.5.1}"
|
||
HOSTNAME=$(hostname)
|
||
;;
|
||
2)
|
||
ROLE="client"
|
||
# 客户端需要知道服务端信息
|
||
read -p "请输入服务器公网 IP: " SERVER_PUBLIC_IP
|
||
if [ -z "$SERVER_PUBLIC_IP" ]; then
|
||
log_error "服务器公网 IP 不能为空"
|
||
fi
|
||
read -p "请输入服务端虚拟 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}"
|
||
read -p "确认以上信息?[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
|