Certimate & Cloudflare Tunnel Management Script for Debian/Ubuntu

#!/bin/bash

#================================================================================
# Certimate & Cloudflare Tunnel Management Script for Debian/Ubuntu
#
# Author: Gemini
# Version: 2.0 (Final Fix - Re-added missing update_software function)
#
# This script provides a comprehensive toolkit to deploy, manage, update,
# backup, and uninstall Certimate with Cloudflared Tunnel.
#================================================================================

# --- Configuration Variables ---
CERTIMATE_SERVICE_NAME="certimate.service"
CLOUDFLARED_SERVICE_NAME="cloudflared.service"
CLOUDFLARED_CONFIG_DIR="/etc/cloudflared"
SYSTEMD_DIR="/etc/systemd/system"
BACKUP_DIR="/opt/certimate_backups"

# --- Helper Functions ---

print_color() {
    case "$2" in
        "green") color="\e[32m";; "red")   color="\e[31m";;
        "yellow")color="\e[33m";; "blue")  color="\e[34m";;
        *)       color="\e[0m";;
    esac
    echo -e "${color}${1}\e[0m"
}

print_error() {
    case "$2" in
        "red")   color="\e[31m";; "yellow")color="\e[33m";;
        *)       color="\e[31m";;
    esac
    echo -e "${color}${1}\e[0m" >&2
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        print_color "错误:此脚本必须以 root 权限运行。" "red"; exit 1
    fi
}

press_enter_to_continue() {
    read -p "按 [Enter] 键继续..."
}

get_service_status_line() {
    local service_name="$1"; local display_name="$2"; local status_str status_color enabled_str
    if systemctl is-active --quiet "$service_name"; then
        status_str="● Running"; status_color="green"
    else
        status_str="○ Stopped"; status_color="red"
    fi
    if systemctl is-enabled --quiet "$service_name"; then
        enabled_str="(enabled)"
    else
        enabled_str="(disabled)"
    fi
    printf "%-12s: [%s] %s\n" "$display_name" "$(print_color "$status_str" "$status_color")" "$enabled_str"
}

detect_arch() {
    case "$(uname -m)" in
        "x86_64") ARCH="amd64" ;; "aarch64") ARCH="arm64" ;;
        *) print_error "错误:不支持的系统架构: $(uname -m)。" "red"; exit 1 ;;
    esac
    echo "$ARCH"
}

get_certimate_download_url() {
    local arch="$1"; local release_type="$2"; local api_url=""; local jq_filter=""
    if [[ "$release_type" == "stable" ]]; then
        api_url="https://api.github.com/repos/certimate-go/certimate/releases/latest"
        jq_filter=".assets[] | select(.name | endswith(\"linux_${arch}.zip\")) | .browser_download_url"
        print_error "正在从 GitHub API 获取最新稳定版本信息..." "yellow"
    else
        api_url="https://api.github.com/repos/certimate-go/certimate/releases"
        jq_filter=".[0].assets[] | select(.name | endswith(\"linux_${arch}.zip\")) | .browser_download_url"
        print_error "正在从 GitHub API 获取最新(含预发布)版本信息..." "yellow"
    fi
    local api_response; api_response=$(curl -s -L -H "Accept: application/vnd.github.v3+json" -H "User-Agent: Certimate-Management-Script" "$api_url")
    if echo "$api_response" | jq -e '.message' > /dev/null; then
        local error_msg; error_msg=$(echo "$api_response" | jq -r '.message')
        print_error "错误:从 GitHub API 获取信息失败: ${error_msg}" "red"; return 1
    fi
    local download_url; download_url=$(echo "$api_response" | jq -r "$jq_filter")
    if [ -z "$download_url" ] || [ "$download_url" == "null" ]; then
        print_error "错误:无法在最新版本中找到适用于 'linux_${arch}.zip' 的下载链接。" "red"; return 1
    fi
    echo "$download_url"; return 0
}

# --- Core Logic Functions ---

deploy_system() {
    print_color "--- 欢迎使用 Certimate & Cloudflare Tunnel 部署向导 ---" "blue"
    if [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "检测到系统似乎已经部署过了。如果您想重新部署,请先卸载。" "yellow"; return; fi
    print_color "\n[步骤 1/7] 收集必要信息..." "blue"
    read -p "请输入 Certimate 的安装目录 (默认: /opt/certimate): " CERTIMATE_INSTALL_DIR
    CERTIMATE_INSTALL_DIR=${CERTIMATE_INSTALL_DIR:-/opt/certimate}
    read -p "请输入运行 Certimate 服务的用户名 (默认: nobody): " CERTIMATE_USER
    CERTIMATE_USER=${CERTIMATE_USER:-nobody}
    if ! id "$CERTIMATE_USER" &>/dev/null; then
        read -p "用户 '$CERTIMATE_USER' 不存在。是否创建系统用户? [Y/n]: " create_user_choice
        if [[ "${create_user_choice:-Y}" =~ ^[Yy]$ ]]; then useradd -r -s /bin/false "$CERTIMATE_USER"; print_color "用户 '$CERTIMATE_USER' 创建成功。" "green"; else print_color "操作中止。" "red"; return; fi
    fi
    local CERTIMATE_PORT
    while true; do
        read -p "请输入 Certimate 的监听端口 (默认: 8090): " CERTIMATE_PORT; CERTIMATE_PORT=${CERTIMATE_PORT:-8090}
        if ! [[ "$CERTIMATE_PORT" =~ ^[0-9]+$ ]] || [ "$CERTIMATE_PORT" -lt 1 ] || [ "$CERTIMATE_PORT" -gt 65535 ]; then print_color "无效的端口号。请输入 1-65535 之间的数字。" "red"; continue; fi
        if ss -Hltn sport eq ":${CERTIMATE_PORT}" | grep -q 'LISTEN'; then print_color "端口 ${CERTIMATE_PORT} 已被占用,请换一个。" "red"; else print_color "端口 ${CERTIMATE_PORT} 可用。" "green"; break; fi
    done
    read -p "请输入您要使用的公共域名 (例如: certs.yourdomain.com): " PUBLIC_HOSTNAME
    if [ -z "$PUBLIC_HOSTNAME" ]; then print_color "错误:公共域名不能为空。" "red"; return; fi
    print_color "\n[步骤 2/7] 安装依赖软件..." "blue"; apt-get update >/dev/null; apt-get install -y curl wget jq unzip >/dev/null; print_color "依赖安装完成。" "green"
    print_color "\n[步骤 3/7] 安装 Certimate..." "blue"
    read -p "是否安装最新的非稳定(Pre-release)版本? [y/N]: " unstable_choice
    local release_type="stable"; if [[ "$unstable_choice" =~ ^[Yy]$ ]]; then release_type="prerelease"; fi
    ARCH=$(detect_arch); print_color "检测到系统架构为: $ARCH" "yellow"
    DOWNLOAD_URL=$(get_certimate_download_url "$ARCH" "$release_type")
    if [ $? -ne 0 ]; then print_color "部署中止。" "red"; return; fi
    print_color "正在从 $DOWNLOAD_URL 下载..." "yellow"; mkdir -p "$CERTIMATE_INSTALL_DIR"
    wget -q -O "/tmp/certimate.zip" "$DOWNLOAD_URL"; unzip -o "/tmp/certimate.zip" -d "$CERTIMATE_INSTALL_DIR"; rm "/tmp/certimate.zip"; chmod +x "${CERTIMATE_INSTALL_DIR}/certimate"
    local user_group; user_group=$(id -gn "$CERTIMATE_USER"); chown -R "${CERTIMATE_USER}:${user_group}" "$CERTIMATE_INSTALL_DIR"
    print_color "Certimate 安装并解压到 $CERTIMATE_INSTALL_DIR" "green"; print_color "数据将存储在默认目录: ${CERTIMATE_INSTALL_DIR}/pb_data" "yellow"
    print_color "\n[步骤 4/7] 安装 Cloudflare Tunnel..." "blue"
    rm -f /etc/apt/sources.list.d/cloudflared.list; mkdir -p --mode=0755 /usr/share/keyrings
    curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
    echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared buster main' | tee /etc/apt/sources.list.d/cloudflared.list >/dev/null
    apt-get update >/dev/null; apt-get install -y cloudflared >/dev/null
    if ! command -v cloudflared &> /dev/null; then print_color "错误: cloudflared 安装失败。" "red"; return; fi; print_color "cloudflared 安装成功。" "green"
    print_color "\n[步骤 5/7] 授权并创建隧道..." "blue"; press_enter_to_continue; cloudflared tunnel login
    TUNNEL_NAME="certimate-tunnel"; local TUNNEL_CREATE_OUTPUT; TUNNEL_CREATE_OUTPUT=$(cloudflared tunnel create "$TUNNEL_NAME" 2>&1)
    local CRED_FILE_PATH; CRED_FILE_PATH=$(echo "$TUNNEL_CREATE_OUTPUT" | grep -o -E '/.*\.json' | head -n 1)
    local TUNNEL_UUID
    if [ -n "$CRED_FILE_PATH" ] && [ -f "$CRED_FILE_PATH" ]; then
        TUNNEL_UUID=$(basename "$CRED_FILE_PATH" .json); print_color "隧道 '$TUNNEL_NAME' 创建成功!" "green"
    else
        TUNNEL_UUID=$(cloudflared tunnel list | grep -Fw "$TUNNEL_NAME" | awk '{print $1}')
        if [ -z "$TUNNEL_UUID" ]; then print_color "错误:创建或查找隧道 '$TUNNEL_NAME' 失败。" "red"; echo "$TUNNEL_CREATE_OUTPUT"; return; fi
        CRED_FILE_PATH="${HOME}/.cloudflared/${TUNNEL_UUID}.json"
        if [ ! -f "$CRED_FILE_PATH" ]; then print_color "错误:找不到凭证文件: ${CRED_FILE_PATH}" "red"; return; fi
        print_color "找到已存在的隧道 '$TUNNEL_NAME'。" "green"
    fi
    print_color "\n[步骤 6/7] 生成配置文件..." "blue"; mkdir -p "$CLOUDFLARED_CONFIG_DIR"
    cat > "${CLOUDFLARED_CONFIG_DIR}/config.yml" << EOF
tunnel: ${TUNNEL_UUID}
credentials-file: ${CLOUDFLARED_CONFIG_DIR}/${TUNNEL_UUID}.json
ingress:
  - hostname: ${PUBLIC_HOSTNAME}
    service: http://127.0.0.1:${CERTIMATE_PORT}
  - service: http_status:404
EOF
    cp "$CRED_FILE_PATH" "${CLOUDFLARED_CONFIG_DIR}/"; print_color "Cloudflared 配置文件创建成功。" "green"
    print_color "\n[步骤 7/7] 创建并启动系统服务..." "blue"
    cat > "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" << EOF
[Unit]
Description=Certimate Go Service
After=network.target
[Service]
Type=simple
User=${CERTIMATE_USER}
Group=$(id -gn "${CERTIMATE_USER}")
WorkingDirectory=${CERTIMATE_INSTALL_DIR}
ExecStart=${CERTIMATE_INSTALL_DIR}/certimate serve --http="127.0.0.1:${CERTIMATE_PORT}"
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target
EOF
    cloudflared service install >/dev/null; print_color "系统服务文件已创建。" "green"
    print_color "正在启动服务..." "yellow"; systemctl daemon-reload
    systemctl enable "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1
    systemctl restart "$CERTIMATE_SERVICE_NAME"; systemctl restart "$CLOUDFLARED_SERVICE_NAME"
    print_color "正在为 ${PUBLIC_HOSTNAME} 创建 DNS 记录..." "yellow"; cloudflared tunnel route dns "$TUNNEL_NAME" "$PUBLIC_HOSTNAME"
    print_color "\n🎉 部署完成! 🎉" "green"; print_color "请稍等片刻,然后通过以下地址访问您的 Certimate 实例:" "yellow"; print_color "https://${PUBLIC_HOSTNAME}" "blue"; echo; manage_services "status"
}

# [FIXED] Re-added the missing update_software function
update_software() {
    clear
    print_color "--- 软件更新 ---" "blue"
    echo "1. 更新 Certimate"
    echo "2. 更新 Cloudflared"
    echo "3. 全部更新"
    echo "0. 返回主菜单"
    read -p "请输入选项: " choice

    case $choice in
        1) update_certimate ;;
        2) update_cloudflared ;;
        3) update_certimate; update_cloudflared ;;
        0) return ;;
        *) print_color "无效选项。" "red" ;;
    esac
}

update_certimate() {
    print_color "\n--- 正在更新 Certimate ---" "blue"
    if ! command -v unzip &> /dev/null; then print_color "正在安装 'unzip'..." "yellow"; apt-get update >/dev/null; apt-get install -y unzip > /dev/null; fi
    SERVICE_FILE="${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}"
    if [ ! -f "$SERVICE_FILE" ]; then print_color "错误:找不到 Certimate 服务文件。" "red"; return; fi
    read -p "是否更新到最新的非稳定(Pre-release)版本? [y/N]: " unstable_choice
    local release_type="stable"; if [[ "$unstable_choice" =~ ^[Yy]$ ]]; then release_type="prerelease"; fi
    CERTIMATE_INSTALL_DIR=$(grep -oP 'WorkingDirectory=\K.*' "$SERVICE_FILE")
    CERTIMATE_USER=$(grep -oP 'User=\K.*' "$SERVICE_FILE")
    if [ -z "$CERTIMATE_INSTALL_DIR" ]; then print_color "错误:无法解析安装目录。" "red"; return; fi
    ARCH=$(detect_arch); DOWNLOAD_URL=$(get_certimate_download_url "$ARCH" "$release_type")
    if [ $? -ne 0 ]; then print_color "更新中止。" "red"; return; fi
    print_color "正在下载最新版本..." "yellow"; wget -q -O "/tmp/certimate_new.zip" "$DOWNLOAD_URL"
    print_color "停止 Certimate 服务..." "yellow"; systemctl stop "$CERTIMATE_SERVICE_NAME"
    print_color "备份旧版本并解压新版本..." "yellow"
    if [ -f "${CERTIMATE_INSTALL_DIR}/certimate" ]; then mv "${CERTIMATE_INSTALL_DIR}/certimate" "${CERTIMATE_INSTALL_DIR}/certimate_old_$(date +%F)"; fi
    unzip -o "/tmp/certimate_new.zip" -d "$CERTIMATE_INSTALL_DIR"; rm "/tmp/certimate_new.zip"; chmod +x "${CERTIMATE_INSTALL_DIR}/certimate"
    if [ -n "$CERTIMATE_USER" ]; then
        local user_group; user_group=$(id -gn "$CERTIMATE_USER"); chown -R "${CERTIMATE_USER}:${user_group}" "$CERTIMATE_INSTALL_DIR"
    fi
    print_color "启动 Certimate 服务..." "yellow"; systemctl start "$CERTIMATE_SERVICE_NAME"; print_color "Certimate 更新成功!" "green"
}

manage_services() {
    ACTION=$1; if [ -z "$ACTION" ]; then clear; print_color "--- 服务管理 ---" "blue"; echo "1. 启动所有服务"; echo "2. 停止所有服务"; echo "3. 重启所有服务"; echo "4. 查看所有服务状态"; echo "0. 返回主菜单"; read -p "请输入选项: " choice; case $choice in 1) ACTION="start";; 2) ACTION="stop";; 3) ACTION="restart";; 4) ACTION="status";; 0) return;; *) print_color "无效选项。" "red"; return;; esac; fi
    if ! [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "错误:系统尚未部署。" "red"; return; fi
    print_color "\n正在对服务执行 [${ACTION}] 操作..." "yellow"
    if [ "$ACTION" == "status" ]; then print_color "\n--- Certimate 服务状态 ---" "blue"; systemctl status "$CERTIMATE_SERVICE_NAME" --no-pager; print_color "\n--- Cloudflared 服务状态 ---" "blue"; systemctl status "$CLOUDFLARED_SERVICE_NAME" --no-pager; else systemctl "$ACTION" "$CERTIMATE_SERVICE_NAME"; systemctl "$ACTION" "$CLOUDFLARED_SERVICE_NAME"; print_color "\n操作完成!" "green"; fi
}

update_cloudflared() {
    print_color "\n--- 正在更新 Cloudflared ---" "blue"; apt-get update >/dev/null; apt-get install -y cloudflared; print_color "Cloudflared 更新完成。正在重启服务..." "yellow"; systemctl restart "$CLOUDFLARED_SERVICE_NAME"; print_color "服务已重启。" "green"
}

backup_config() {
    print_color "\n--- 备份配置文件 ---" "blue"; SERVICE_FILE="${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}"
    if [ ! -f "$SERVICE_FILE" ]; then print_color "错误:系统尚未部署。" "red"; return; fi
    CERTIMATE_INSTALL_DIR=$(grep -oP 'WorkingDirectory=\K.*' "$SERVICE_FILE")
    mkdir -p "$BACKUP_DIR"; BACKUP_FILENAME="certimate_backup_$(date +%Y-%m-%d_%H-%M-%S).tar.gz"
    BACKUP_FILE_PATH="${BACKUP_DIR}/${BACKUP_FILENAME}"; print_color "将要备份以下内容:" "yellow"
    echo "- ${SERVICE_FILE}"; [ -d "$CERTIMATE_INSTALL_DIR" ] && echo "- ${CERTIMATE_INSTALL_DIR}"; [ -d "$CLOUDFLARED_CONFIG_DIR" ] && echo "- ${CLOUDFLARED_CONFIG_DIR}"
    BACKUP_ITEMS=""; [ -f "$SERVICE_FILE" ] && BACKUP_ITEMS+=" $SERVICE_FILE"; [ -d "$CERTIMATE_INSTALL_DIR" ] && BACKUP_ITEMS+=" $CERTIMATE_INSTALL_DIR"; [ -d "$CLOUDFLARED_CONFIG_DIR" ] && BACKUP_ITEMS+=" $CLOUDFLARED_CONFIG_DIR"
    if [ -z "$BACKUP_ITEMS" ]; then print_color "错误:找不到任何需备份的文件。" "red"; return; fi
    tar -czf "$BACKUP_FILE_PATH" $BACKUP_ITEMS; print_color "\n备份成功!文件保存在: ${BACKUP_FILE_PATH}" "green"
}

restore_config() {
    print_color "\n--- 从备份恢复配置 ---" "blue"; read -p "请输入备份文件 (.tar.gz) 的完整路径: " BACKUP_FILE_PATH
    if [ ! -f "$BACKUP_FILE_PATH" ]; then print_color "错误:备份文件不存在!" "red"; return; fi
    read -p "警告:此操作将覆盖现有配置!确定吗? [y/N]: " confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then print_color "操作已取消。" "yellow"; return; fi
    print_color "停止服务..." "yellow"; systemctl stop "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1
    print_color "正在从备份文件中提取..." "yellow"; tar -xzpf "$BACKUP_FILE_PATH" -C /
    print_color "重新加载 systemd 并重启服务..." "yellow"; systemctl daemon-reload
    systemctl restart "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME"; print_color "\n恢复完成!" "green"; manage_services "status"
}

uninstall_system() {
    print_color "\n--- 卸载 Certimate 和 Cloudflare Tunnel ---" "blue"
    if ! [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "错误:系统尚未部署。" "red"; return; fi
    read -p "警告:此操作将停止服务并删除相关文件!确定吗? [y/N]: " confirm
    if [[ ! "$confirm" =~ ^[Yy]$ ]]; then print_color "卸载已取消。" "yellow"; return; fi
    print_color "正在停止并禁用服务..." "yellow"; systemctl stop "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1; systemctl disable "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1
    print_color "正在删除文件..." "yellow"; SERVICE_FILE="${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}"; CERTIMATE_INSTALL_DIR=$(grep -oP 'WorkingDirectory=\K.*' "$SERVICE_FILE"); DEFAULT_DATA_DIR="${CERTIMATE_INSTALL_DIR}/pb_data"
    rm -f "$SERVICE_FILE" "${SYSTEMD_DIR}/${CLOUDFLARED_SERVICE_NAME}"
    if [ -d "$CERTIMATE_INSTALL_DIR" ]; then print_color "删除 Certimate 安装目录: $CERTIMATE_INSTALL_DIR" "yellow"; rm -rf "$CERTIMATE_INSTALL_DIR"; fi
    if [ -d "$DEFAULT_DATA_DIR" ]; then print_color "删除 Certimate 数据目录: $DEFAULT_DATA_DIR" "yellow"; rm -rf "$DEFAULT_DATA_DIR"; fi
    systemctl daemon-reload; print_color "正在卸载 cloudflared 软件包..." "yellow"
    apt-get purge -y cloudflared >/dev/null; rm -f /etc/apt/sources.list.d/cloudflared.list*
    apt-get update >/dev/null
    read -p "是否删除 Cloudflare 配置目录 (${CLOUDFLARED_CONFIG_DIR})? [y/N]: " delete_config
    if [[ "$delete_config" =~ ^[Yy]$ ]]; then print_color "正在删除配置目录..." "red"; rm -rf "$CLOUDFLARED_CONFIG_DIR"; print_color "配置已删除。" "green"; else print_color "配置文件已保留。" "yellow"; fi
    print_color "\n卸载完成!" "green"; print_color "请注意:您可能需要手动登录 Cloudflare Dashboard 删除 DNS 记录和隧道。" "yellow"
}

main_menu() {
    while true; do
        clear
        print_color "======================================================" "blue"
        print_color "     Certimate & Cloudflare Tunnel 综合管理脚本     " "blue"
        print_color "             (版本 2.0 - 最终修正版)             " "blue"
        print_color "======================================================" "blue"
        echo
        if [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then
            print_color "当前服务状态:" "yellow"
            get_service_status_line "$CERTIMATE_SERVICE_NAME" "Certimate"
            get_service_status_line "$CLOUDFLARED_SERVICE_NAME" "Cloudflared"
            echo
        fi
        echo "1. 部署系统 (首次安装)"; echo "2. 管理服务 (启/停/重/查)"; echo "3. 更新软件"
        echo "4. 备份配置文件"; echo "5. 从备份恢复配置"; echo "6. 卸载系统"
        echo "0. 退出脚本"
        echo
        read -p "请输入您的选项 [0-6]: " main_choice

        case $main_choice in
            1) deploy_system; press_enter_to_continue ;;
            2) manage_services; press_enter_to_continue ;;
            3) update_software; press_enter_to_continue ;;
            4) backup_config; press_enter_to_continue ;;
            5) restore_config; press_enter_to_continue ;;
            6) uninstall_system; press_enter_to_continue ;;
            0) print_color "感谢使用!再见!" "green"; exit 0 ;;
            *) print_color "无效的选项。" "red"; sleep 2 ;;
        esac
    done
}

# --- Script Entry Point ---
check_root
main_menu

Certimate & Cloudflare Tunnel Management Script for Debian/Ubuntu》有 2 个想法

  1. 214646

    作者你好,另一个帖子回复总是自动删除,只能这里问下,请问BBR原版内核不能用的话,我使用 11. 使用BBR+FQ加速 用哪个内核, 我看评论XANMOD只能bbr3,官方cloud可能无法开机,用原版bbr加速的话哪个内核合适。

    回复

回复 214646 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理