From b0fb658816f939ebdbbc339a1a47b448e0818cd3 Mon Sep 17 00:00:00 2001 From: ghol Date: Fri, 24 Oct 2025 22:05:37 +0000 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20deepseek/shell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deepseek/shell/sftp_setup.sh | 254 +++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 deepseek/shell/sftp_setup.sh diff --git a/deepseek/shell/sftp_setup.sh b/deepseek/shell/sftp_setup.sh new file mode 100644 index 0000000..7cbc973 --- /dev/null +++ b/deepseek/shell/sftp_setup.sh @@ -0,0 +1,254 @@ +#!/bin/bash + +# ============================================================================== +# 脚本名称: sftp_setup.sh +# 功能描述: 自动化配置一个安全的、chrooted的SFTP用户,用于文件备份。 +# 用户将被限制在特定目录,无法SSH登录,也无法访问系统其他部分。 +# 调用方式: sudo ./sftp_setup.sh +# 作者: AI Assistant +# 版本: 1.4 (修复Subsystem重复定义问题) +# ============================================================================== + +# --- 颜色定义,用于美化输出 --- +COLOR_GREEN='\033[0;32m' +COLOR_RED='\033[0;31m' +COLOR_YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# --- 辅助函数 --- +log_info() { + echo -e "${COLOR_GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${COLOR_YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${COLOR_RED}[ERROR]${NC} $1" + exit 1 +} + +# 检查是否以root权限运行 +check_root() { + if [[ $EUID -ne 0 ]]; then + log_error "此脚本必须以 root 权限运行。请使用 'sudo $0'" + fi +} + +# 清理旧的SFTP配置 +cleanup_old_sftp_config() { + local config_file="$1" + + log_info "正在清理旧的 SFTP 配置..." + + # 创建临时文件 + local temp_file=$(mktemp) + + # 使用更精确的模式来清理配置 + # 删除所有Subsystem sftp相关的行(包括注释和空白行后的注释) + awk ' + /^[[:space:]]*#?[[:space:]]*Subsystem[[:space:]]+sftp/ { + # 跳过这一行(删除) + next + } + /^[[:space:]]*#.*sftp.*subsystem/ { + # 删除包含sftp subsystem的注释行 + next + } + /^Match[[:space:]]+User/ { + # 如果遇到新的Match User块,停止删除 + in_old_block = 0 + } + in_old_block && /^[[:space:]]+#?[[:space:]]*(ChrootDirectory|ForceCommand|AllowTcpForwarding|X11Forwarding|PermitTunnel)/ { + # 在旧块中删除相关配置行 + next + } + { + # 打印其他所有行 + print + } + ' "$config_file" > "$temp_file" + + # 检查是否有变化 + if ! diff "$config_file" "$temp_file" &>/dev/null; then + mv "$temp_file" "$config_file" + log_info "已清理旧的 SFTP 配置。" + else + rm -f "$temp_file" + log_info "未发现需要清理的旧配置。" + fi +} + +# ============================================================================== +# 主程序 +# ============================================================================== + +log_info "开始 SFTP 用户自动配置流程..." + +# 1. 检查root权限 +check_root + +# 2. 交互式获取用户输入 +echo "--- 请输入 SFTP 用户配置信息 ---" +read -p "1. 请输入新的 SFTP 用户名: " SFTP_USERNAME +read -s -p "2. 请输入该用户的密码: " SFTP_PASSWORD +echo "" # 换行 +read -s -p "3. 请再次输入密码以确认: " SFTP_PASSWORD_CONFIRM +echo "" # 换行 +read -p "4. 请输入备份文件的根目录 (例如 /sftp/backup): " SFTP_ROOT_DIR + +# 3. 验证输入 +if [[ -z "$SFTP_USERNAME" || -z "$SFTP_PASSWORD" || -z "$SFTP_ROOT_DIR" ]]; then + log_error "用户名、密码和根目录不能为空!" +fi + +if [[ "$SFTP_PASSWORD" != "$SFTP_PASSWORD_CONFIRM" ]]; then + log_error "两次输入的密码不匹配!" +fi + +if [[ ! "$SFTP_ROOT_DIR" = /* ]]; then + log_error "根目录必须以 '/' 开头,为绝对路径!" +fi + +# 定义SFTP组和上传目录名 +SFTP_GROUP="sftpgroup" +UPLOAD_DIR_NAME="uploads" +SFTP_UPLOAD_DIR="${SFTP_ROOT_DIR}/${UPLOAD_DIR_NAME}" + +log_info "配置信息确认无误,开始执行配置..." + +# 4. 创建SFTP组 +if ! grep -q "^${SFTP_GROUP}:" /etc/group; then + log_info "创建 SFTP 专用组: ${SFTP_GROUP}" + groupadd "$SFTP_GROUP" +else + log_warn "组 '${SFTP_GROUP}' 已存在,跳过创建。" +fi + +# 5. 创建SFTP用户 +if id "$SFTP_USERNAME" &>/dev/null; then + log_warn "用户 '${SFTP_USERNAME}' 已存在,将跳过用户创建,但会重置密码和目录权限。" +else + log_info "创建 SFTP 用户: ${SFTP_USERNAME}" + useradd -G "$SFTP_GROUP" -s /sbin/nologin -d "$SFTP_ROOT_DIR" "$SFTP_USERNAME" +fi + +# 6. 设置用户密码 +log_info "为用户 '${SFTP_USERNAME}' 设置密码..." +echo "${SFTP_USERNAME}:${SFTP_PASSWORD}" | chpasswd + +# 7. 创建目录结构 +log_info "创建 SFTP 目录结构..." +mkdir -p "$SFTP_ROOT_DIR" +mkdir -p "$SFTP_UPLOAD_DIR" + +# 8. 设置目录权限 (最关键的一步) +log_info "设置目录权限..." +chown root:root "$SFTP_ROOT_DIR" +chmod 755 "$SFTP_ROOT_DIR" +chown "${SFTP_USERNAME}:${SFTP_GROUP}" "$SFTP_UPLOAD_DIR" +chmod 755 "$SFTP_UPLOAD_DIR" +log_info "权限设置完成。" + +# 9. 配置 SSHD (修复版) +SSHD_CONFIG="/etc/ssh/sshd_config" +SSHD_BACKUP="${SSHD_CONFIG}.bak.$(date +%F_%H-%M-%S)" + +log_info "配置 SSH 守护进程..." + +# 备份原始文件 +cp "$SSHD_CONFIG" "$SSHD_BACKUP" +log_info "已备份原始 sshd_config 到 ${SSHD_BACKUP}" + +# --- 修复的配置逻辑 --- + +# 1. 首先清理所有旧的SFTP相关配置 +cleanup_old_sftp_config "$SSHD_CONFIG" + +# 2. 检查是否已存在Subsystem sftp配置 +if grep -q "^Subsystem[[:space:]]\+sftp" "$SSHD_CONFIG"; then + log_warn "发现已存在的 Subsystem sftp 配置,将使用现有配置。" +else + log_info "添加新的 'Subsystem sftp internal-sftp' 配置。" + echo "Subsystem sftp internal-sftp" >> "$SSHD_CONFIG" +fi + +# 3. 清理该用户可能存在的旧配置 +log_info "清理用户 '${SFTP_USERNAME}' 的旧配置..." +# 删除该用户的所有Match块 +sed -i -e "/^Match User ${SFTP_USERNAME}$/,/^Match User\|^$/d" "$SSHD_CONFIG" + +# 4. 添加新的用户配置 +log_info "为用户 '${SFTP_USERNAME}' 添加新的 Chroot 配置..." +{ + printf "\n# --- SFTP Chroot for user: %s (由脚本自动添加) ---\n" "${SFTP_USERNAME}" + printf "Match User %s\n" "${SFTP_USERNAME}" + printf " ForceCommand internal-sftp\n" + printf " ChrootDirectory %s\n" "${SFTP_ROOT_DIR}" + printf " AllowTcpForwarding no\n" + printf " X11Forwarding no\n" + printf " PermitTunnel no\n" +} >> "$SSHD_CONFIG" + +log_info "SSH 配置更新完成。" + +# --- 配置逻辑结束 --- + +# 10. 测试SSH配置并重启服务 +log_info "正在测试 SSH 配置文件语法..." +if sshd -t; then + log_info "配置文件语法正确。" + log_info "正在重启 SSH 服务以应用配置..." + if command -v systemctl &> /dev/null; then + systemctl restart sshd + # 检查服务状态 + if systemctl is-active --quiet sshd; then + log_info "SSH 服务重启成功。" + else + log_error "SSH 服务启动失败,请检查系统日志。" + fi + else + service ssh restart + log_info "SSH 服务重启完成。" + fi +else + log_error "SSH 配置文件语法错误!服务未重启。" + log_error "以下是所有相关的 SFTP 配置行,请检查:" + grep -n -A5 -B2 "Subsystem sftp\|Match User ${SFTP_USERNAME}" "$SSHD_CONFIG" || true + log_error "请检查 /etc/ssh/sshd_config 文件,或使用备份文件 ${SSHD_BACKUP} 恢复。" + exit 1 +fi + +# 11. 验证配置 +log_info "验证 SFTP 配置..." +if grep -q "Match User ${SFTP_USERNAME}" "$SSHD_CONFIG" && \ + grep -q "ChrootDirectory ${SFTP_ROOT_DIR}" "$SSHD_CONFIG"; then + log_info "SFTP 配置验证成功。" +else + log_warn "SFTP 配置可能未正确应用,请手动检查。" +fi + +# 12. 完成 +echo "==================================================" +log_info "SFTP 用户配置完成!" +echo "==================================================" +echo -e "用户名: ${COLOR_YELLOW}${SFTP_USERNAME}${NC}" +echo -e "密码: ${COLOR_YELLOW}[已设置]${NC}" +echo -e "SFTP根目录: ${COLOR_YELLOW}${SFTP_ROOT_DIR}${NC}" +echo -e "文件上传目录: ${COLOR_YELLOW}${SFTP_UPLOAD_DIR}${NC}" +echo "" +echo -e "${COLOR_GREEN}现在,您可以在您的备份脚本中使用以下信息:${NC}" +echo -e " SERVER_USER=\"${SFTP_USERNAME}\"" +echo -e " REMOTE_DIR=\"/${UPLOAD_DIR_NAME}\"" +echo "" +echo -e "${COLOR_YELLOW}测试命令 (在服务器本机执行):${NC}" +echo -e " sftp ${SFTP_USERNAME}@localhost" +echo "" +echo -e "${COLOR_YELLOW}重要提醒:${NC}" +echo -e " 1. 确保根目录 ${SFTP_ROOT_DIR} 的所有者是 root:root" +echo -e " 2. 用户只能访问 ${SFTP_UPLOAD_DIR} 目录" +echo -e " 3. 用户无法通过SSH登录系统" +echo "==================================================" + +exit 0 \ No newline at end of file