diff --git a/setup-cloudflare-ssh-access.sh b/setup-cloudflare-ssh-access.sh index 70db327..6702cf5 100644 --- a/setup-cloudflare-ssh-access.sh +++ b/setup-cloudflare-ssh-access.sh @@ -21,24 +21,9 @@ SSO_USERNAME="" ACCOUNT_ID="" API_TOKEN="" TUNNEL_TOKEN="" +CA_PUB_FILE="" INSTALL_METHOD="config" # 默认使用配置文件方式 -# 检查必要工具 -check_deps() { - # 检查whiptail是否安装 - if ! command -v whiptail &> /dev/null; then - echo -e "${YELLOW}正在安装whiptail...${NC}" - if [ -f /etc/debian_version ]; then - apt-get update && apt-get install -y whiptail - elif [ -f /etc/redhat-release ]; then - yum install -y newt - else - echo -e "${RED}无法安装whiptail,请手动安装后重试${NC}" - exit 1 - fi - fi -} - # 检查是否为root用户 check_root() { if [ "$EUID" -ne 0 ]; then @@ -47,142 +32,145 @@ check_root() { fi } -# 收集用户输入 -collect_user_input() { - # 显示欢迎信息 - whiptail --title "Cloudflare Tunnels SSH配置" \ - --msgbox "欢迎使用Cloudflare Tunnels SSH配置工具\n\n此脚本将帮助您设置Cloudflare Tunnels和短期证书\n以便通过Web SSH安全地访问您的服务器。" \ - 15 60 +# 打印帮助信息 +print_usage() { + echo -e "${BLUE}Cloudflare Tunnels SSH配置工具${NC}" + echo -e "此脚本将帮助您设置Cloudflare Tunnels和短期证书以便通过Web SSH安全地访问您的服务器。" + echo + echo -e "使用方法:" + echo -e " ${YELLOW}./setup-cloudflare-ssh-access.sh${NC}" + echo + echo -e "您将需要提供以下信息:" + echo -e " 1. 安装方式: 'token'(推荐) 或 'config'" + echo -e " 2. 对于token方式: Cloudflare Tunnel Token" + echo -e " 3. 对于config方式: Tunnel ID 和凭证文件路径" + echo -e " 4. 访问SSH的域名 (例如: terminal.mydomain.com)" + echo -e " 5. 与SSO登录匹配的本地用户名" + echo -e " 6. Cloudflare SSH证书文件路径" + echo +} + +# 读取用户输入 +read_input() { + echo -e "${GREEN}=====================================================${NC}" + echo -e "${BLUE}欢迎使用Cloudflare Tunnels SSH配置工具${NC}" + echo -e "${GREEN}=====================================================${NC}" + echo # 选择安装方式 - INSTALL_METHOD=$(whiptail --title "选择安装方式" \ - --menu "请选择Cloudflare Tunnel的安装配置方式:" 15 70 2 \ - "token" "使用Token令牌直接安装(推荐,更简单)" \ - "config" "手动配置(高级选项,需要更多配置)" \ - 3>&1 1>&2 2>&3) + echo -e "${YELLOW}请选择Cloudflare Tunnel的安装配置方式:${NC}" + echo -e "1. 使用Token令牌直接安装(推荐,更简单)" + echo -e "2. 手动配置(高级选项,需要更多配置)" + read -p "请输入选择 [1/2]: " install_choice - if [ $? -ne 0 ]; then - echo -e "${RED}操作已取消${NC}" - exit 1 - fi - - if [ "$INSTALL_METHOD" = "token" ]; then + if [ "$install_choice" = "1" ]; then + INSTALL_METHOD="token" + # 获取Tunnel Token - TUNNEL_TOKEN=$(whiptail --title "Tunnel Token" \ - --inputbox "请输入Cloudflare提供的Tunnel Token:\n(形如: eyJhIjoixxxxxxx...,在创建Tunnel后,选择要安装的连接器时提供)" \ - 10 70 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$TUNNEL_TOKEN" ]; then - echo -e "${RED}操作已取消或Token为空${NC}" + echo -e "${YELLOW}请输入Cloudflare提供的Tunnel Token:${NC}" + echo -e "(形如: eyJhIjoixxxxxxx...,在创建Tunnel后,选择要安装的连接器时提供)" + read -p "> " TUNNEL_TOKEN + if [ -z "$TUNNEL_TOKEN" ]; then + echo -e "${RED}错误: Token不能为空${NC}" exit 1 fi # 获取主机名 - HOSTNAME=$(whiptail --title "主机名" \ - --inputbox "请输入访问SSH的域名:\n(例如: terminal.mydomain.com,需要先在DNS中设置好指向Cloudflare)" \ - 10 70 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$HOSTNAME" ]; then - echo -e "${RED}操作已取消或主机名为空${NC}" + echo -e "${YELLOW}请输入访问SSH的域名:${NC}" + echo -e "(例如: terminal.mydomain.com,需要先在DNS中设置好指向Cloudflare)" + read -p "> " HOSTNAME + if [ -z "$HOSTNAME" ]; then + echo -e "${RED}错误: 域名不能为空${NC}" exit 1 fi else + INSTALL_METHOD="config" + # 获取Tunnel ID - TUNNEL_ID=$(whiptail --title "Tunnel ID" \ - --inputbox "请输入您的Cloudflare Tunnel ID:\n(这是在Cloudflare Zero Trust控制台创建的Tunnel的唯一标识符)" \ - 10 60 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$TUNNEL_ID" ]; then - echo -e "${RED}操作已取消或Tunnel ID为空${NC}" + echo -e "${YELLOW}请输入您的Cloudflare Tunnel ID:${NC}" + echo -e "(这是在Cloudflare Zero Trust控制台创建的Tunnel的唯一标识符)" + read -p "> " TUNNEL_ID + if [ -z "$TUNNEL_ID" ]; then + echo -e "${RED}错误: Tunnel ID不能为空${NC}" exit 1 fi # 获取Credential File路径 - CREDENTIAL_FILE=$(whiptail --title "凭证文件路径" \ - --inputbox "请输入Cloudflare凭证文件的完整路径:\n\n凭证文件是创建Tunnel时由Cloudflare生成的JSON文件,\n通常命名为.json,包含连接到Cloudflare所需的密钥。\n一般保存在/root/.cloudflared/或~/.cloudflared/目录下。" \ - 15 70 "/root/.cloudflared/${TUNNEL_ID}.json" \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$CREDENTIAL_FILE" ]; then - echo -e "${RED}操作已取消或凭证文件路径为空${NC}" + echo -e "${YELLOW}请输入Cloudflare凭证文件的完整路径:${NC}" + echo -e "凭证文件是创建Tunnel时由Cloudflare生成的JSON文件," + echo -e "通常命名为.json,包含连接到Cloudflare所需的密钥。" + echo -e "一般保存在/root/.cloudflared/或~/.cloudflared/目录下。" + read -p "> " CREDENTIAL_FILE + if [ -z "$CREDENTIAL_FILE" ]; then + echo -e "${RED}错误: 凭证文件路径不能为空${NC}" exit 1 fi # 检查凭证文件是否存在 if [ ! -f "$CREDENTIAL_FILE" ]; then - whiptail --title "错误" \ - --msgbox "凭证文件 $CREDENTIAL_FILE 不存在!\n\n请确保文件路径正确。如果您尚未创建Tunnel或下载凭证文件,\n请先在Cloudflare Zero Trust控制台中完成这些步骤。" \ - 12 70 + echo -e "${RED}错误: 凭证文件 $CREDENTIAL_FILE 不存在!${NC}" + echo -e "${RED}请确保文件路径正确。如果您尚未创建Tunnel或下载凭证文件,${NC}" + echo -e "${RED}请先在Cloudflare Zero Trust控制台中完成这些步骤。${NC}" exit 1 fi # 获取主机名 - HOSTNAME=$(whiptail --title "主机名" \ - --inputbox "请输入访问SSH的域名:\n(例如: terminal.mydomain.com,需要先在DNS中设置好指向Cloudflare)" \ - 10 70 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$HOSTNAME" ]; then - echo -e "${RED}操作已取消或主机名为空${NC}" + echo -e "${YELLOW}请输入访问SSH的域名:${NC}" + echo -e "(例如: terminal.mydomain.com,需要先在DNS中设置好指向Cloudflare)" + read -p "> " HOSTNAME + if [ -z "$HOSTNAME" ]; then + echo -e "${RED}错误: 域名不能为空${NC}" exit 1 fi fi # 获取SSO用户名 - SSO_USERNAME=$(whiptail --title "SSO用户名" \ - --inputbox "请输入与SSO登录匹配的本地用户名:\n(重要:此用户名必须与您在SSO中使用的用户名完全一致)" \ - 10 70 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$SSO_USERNAME" ]; then - echo -e "${RED}操作已取消或用户名为空${NC}" + echo -e "${YELLOW}请输入与SSO登录匹配的本地用户名:${NC}" + echo -e "(重要:此用户名必须与您在SSO中使用的用户名完全一致)" + read -p "> " SSO_USERNAME + if [ -z "$SSO_USERNAME" ]; then + echo -e "${RED}错误: 用户名不能为空${NC}" exit 1 fi - # 获取Cloudflare账户ID - ACCOUNT_ID=$(whiptail --title "Cloudflare账户ID" \ - --inputbox "请输入您的Cloudflare账户ID:\n(可在Cloudflare仪表板的右侧栏底部找到)" \ - 10 70 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$ACCOUNT_ID" ]; then - echo -e "${RED}操作已取消或账户ID为空${NC}" + # 获取SSH CA证书文件 + echo -e "${YELLOW}请输入Cloudflare SSH证书文件的路径:${NC}" + echo -e "这是从Cloudflare Zero Trust控制台获取的SSH CA公钥文件" + echo -e "在Zero Trust控制台 > Access > Service Auth > SSH 中找到并下载" + read -p "> " CA_PUB_FILE + if [ -z "$CA_PUB_FILE" ]; then + echo -e "${RED}错误: 证书文件路径不能为空${NC}" exit 1 fi - # 获取API Token - API_TOKEN=$(whiptail --title "Cloudflare API令牌" \ - --inputbox "请输入您的Cloudflare API令牌:\n(需要有SSH审核编辑权限,可在Cloudflare控制台的'我的个人资料'>'API令牌'中创建)" \ - 12 70 \ - 3>&1 1>&2 2>&3) - if [ $? -ne 0 ] || [ -z "$API_TOKEN" ]; then - echo -e "${RED}操作已取消或API令牌为空${NC}" + # 检查证书文件是否存在 + if [ ! -f "$CA_PUB_FILE" ]; then + echo -e "${RED}错误: 证书文件 $CA_PUB_FILE 不存在!${NC}" + echo -e "${RED}请确保文件路径正确。${NC}" exit 1 fi # 显示摘要并确认 + echo -e "${GREEN}=====================================================${NC}" + echo -e "${BLUE}配置摘要:${NC}" + if [ "$INSTALL_METHOD" = "token" ]; then - CONFIRM=$(whiptail --title "确认配置" --yesno "\ -配置摘要: -- 安装方式: 使用Token直接安装 -- Token: ${TUNNEL_TOKEN:0:10}... -- 域名: $HOSTNAME -- 用户名: $SSO_USERNAME -- 账户ID: $ACCOUNT_ID -- API令牌: ${API_TOKEN:0:5}... - -是否确认继续?" 16 60 3>&1 1>&2 2>&3) + echo -e "安装方式: 使用Token直接安装" + echo -e "Token: ${TUNNEL_TOKEN:0:10}..." else - CONFIRM=$(whiptail --title "确认配置" --yesno "\ -配置摘要: -- 安装方式: 手动配置 -- Tunnel ID: $TUNNEL_ID -- 凭证文件: $CREDENTIAL_FILE -- 域名: $HOSTNAME -- 用户名: $SSO_USERNAME -- 账户ID: $ACCOUNT_ID -- API令牌: ${API_TOKEN:0:5}... - -是否确认继续?" 18 60 3>&1 1>&2 2>&3) + echo -e "安装方式: 手动配置" + echo -e "Tunnel ID: $TUNNEL_ID" + echo -e "凭证文件: $CREDENTIAL_FILE" fi - if [ $? -ne 0 ]; then + echo -e "域名: $HOSTNAME" + echo -e "用户名: $SSO_USERNAME" + echo -e "SSH证书文件: $CA_PUB_FILE" + echo -e "${GREEN}=====================================================${NC}" + + echo -e "${YELLOW}是否确认继续? [y/N]${NC}" + read -p "> " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then echo -e "${RED}操作已取消${NC}" exit 1 fi @@ -314,55 +302,13 @@ create_user() { setup_short_lived_cert() { echo -e "${BLUE}步骤4: 设置Cloudflare短期证书...${NC}" - # 检查是否安装了curl和jq - if ! command -v jq &> /dev/null; then - echo -e "${YELLOW}正在安装jq...${NC}" - if [ -f /etc/debian_version ]; then - apt-get update && apt-get install -y jq - elif [ -f /etc/redhat-release ]; then - yum install -y jq - else - echo -e "${RED}无法确定包管理器,请手动安装jq${NC}" - exit 1 - fi - fi + echo -e "${YELLOW}正在配置SSH使用Cloudflare短期证书...${NC}" - echo -e "${YELLOW}正在从Cloudflare API获取SSH CA公钥...${NC}" - - # 尝试GET请求 - RESPONSE=$(curl -s "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/gateway_ca" \ - --header "Authorization: Bearer ${API_TOKEN}") - - # 检查是否成功获取 - if echo "$RESPONSE" | grep -q "access.api.error.gateway_ca_not_found"; then - echo -e "${YELLOW}SSH CA不存在,正在创建...${NC}" - - # 创建新的SSH CA - RESPONSE=$(curl -s --request POST \ - "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/gateway_ca" \ - --header "Authorization: Bearer ${API_TOKEN}") - fi - - # 提取公钥 - if ! PUBLIC_KEY=$(echo "$RESPONSE" | jq -r '.result.public_key'); then - echo -e "${RED}无法获取公钥。请检查您的ACCOUNT_ID和API_TOKEN${NC}" - echo -e "${RED}API响应: $RESPONSE${NC}" - exit 1 - fi - - if [ "$PUBLIC_KEY" = "null" ]; then - echo -e "${RED}获取公钥失败。请检查您的ACCOUNT_ID和API_TOKEN${NC}" - echo -e "${RED}API响应: $RESPONSE${NC}" - exit 1 - fi - - echo -e "${GREEN}成功获取SSH CA公钥${NC}" - - # 创建ca.pub文件 - echo "$PUBLIC_KEY" > /etc/ssh/cloudflare-ca.pub + # 复制证书文件到SSH配置目录 + cp "$CA_PUB_FILE" /etc/ssh/cloudflare-ca.pub chmod 644 /etc/ssh/cloudflare-ca.pub - echo -e "${GREEN}公钥已保存至 /etc/ssh/cloudflare-ca.pub${NC}" + echo -e "${GREEN}证书已复制至 /etc/ssh/cloudflare-ca.pub${NC}" # 更新SSH配置 grep -q "^PubkeyAuthentication yes" /etc/ssh/sshd_config || echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config @@ -421,8 +367,8 @@ verify_installation() { main() { check_root - check_deps - collect_user_input + print_usage + read_input echo -e "${BLUE}开始配置Cloudflare Tunnels和短期证书...${NC}" @@ -433,12 +379,10 @@ main() { configure_local_ssh verify_installation - whiptail --title "配置完成" \ - --msgbox "Cloudflare Tunnels和短期证书配置已完成!\n\n现在您可以通过 ${HOSTNAME} 使用Web SSH访问您的服务器。" \ - 12 60 - + echo -e "${GREEN}=====================================================${NC}" echo -e "${GREEN}配置完成!${NC}" - echo -e "${YELLOW}现在您可以通过 ${HOSTNAME} 使用Web SSH访问您的服务器${NC}" + echo -e "${GREEN}现在您可以通过 ${HOSTNAME} 使用Web SSH访问您的服务器${NC}" + echo -e "${GREEN}=====================================================${NC}" } main "$@"