Files
easytier_deploy/main.sh
2026-08-10 20:47:39 +00:00

356 lines
11 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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='<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 ""
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