[特殊字符] Linux SFTP 安全部署终极指南(CentOS/RHEL 7+)
核心目标:创建一个只能传文件、无法登录系统、被锁在自家“牢笼”里的专用账户。
📖 本文摘要:本文是一份 Linux SFTP Chroot 禁锢配实操指南,从零开始带你完成 OpenSSH 安装、用户创建、
sshd_config关键配置(内置 SFTP 子系统 + Match 限制块)、权限隔离及防火墙放行等全流程。文中特别指出了StrictModes位置错误、家目录归属 root 等常见踩坑点,并附报错速查表,助你快速搭建一个只能传文件、无法登录系统的安全 SFTP 环境。
第一步:安装 OpenSSH 服务
# 安装服务(系统一般自带,此步保证不缺组件)sudoyuminstall-yopenssh-server# 启动并设置开机自启sudosystemctlenablesshdsudosystemctl start sshd第二步:创建用户组和用户
# 1. 创建一个匹配组(用于在配置中识别哪些用户需要被禁锢)sudogroupaddsftpgroup# 2. 创建用户,指定家目录、加入组、禁止 Shell 登录# -m 创建家目录,-G 加入附属组,-s 禁止登录sudouseradd-m-Gsftpgroup-s/usr/sbin/nologin sftpuser# 3. 设置密码sudopasswdsftpuser💡 解释:
-s /usr/sbin/nologin禁止了 Shell,但 SFTP 服务不受影响;sftpgroup将作为Match规则的“门票”。
第三步:配置 SSH 服务(/etc/ssh/sshd_config)—— 关键核心
使用vim编辑配置文件:
sudovim/etc/ssh/sshd_config请按以下顺序修改(顺序错了会报错):
3.1 替换全局 SFTP 子系统(解决报错根源)
找到原本的Subsystem sftp /usr/libexec/openssh/sftp-server,将其整行替换为:
Subsystem sftp internal-sftp🚨 不要注释掉,直接替换。这样所有用户默认使用内置 SFTP,完美兼容后续的
Chroot禁锢环境,避免subsystem request failed报错。
3.2 在文件中间(Match块之前)添加全局安全参数
建议放在Subsystem下方,例如:
Banner /etc/sshbanner # 登录提示(文件需自己创建,没有可忽略此行) LogLevel INFO # 日志级别 MaxAuthTries 3 # 防暴力破解 PubkeyAuthentication yes # 允许密钥登录 PermitEmptyPasswords no # 禁止空密码 StrictModes yes # 【注意】必须放在 Match 之前!3.3 在文件最末尾添加 Match 限制块
Match Group sftpgroup ChrootDirectory %h ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no💡 解释:
StrictModes等全局设置必须放在Match外面,否则sshd -t会报错not allowed within a Match block。
第四步:验证配置并重载服务(必须执行)
# 1. 严格检查语法,无任何输出代表完全正确sudosshd-t# 2. 若上一步无报错,平滑重载使配置生效(不中断现有连接)sudosystemctl reload sshd第五步:设置目录权限(最容易踩坑,请盯紧)
根据ChrootDirectory的内核安全要求,以及我们推荐的权限隔离方案,执行以下命令:
# 1. 【铁律】将用户家目录的根交给 root(否则 chroot 失败)sudochownroot:root /home/sftpusersudochmod755/home/sftpuser# 2. 创建实际用于读写的子目录,并完全交给 sftpuser 自己sudomkdir/home/sftpuser/uploadsudochownsftpuser:sftpuser /home/sftpuser/uploadsudochmod750/home/sftpuser/upload# 750 比 755 更严谨,只允许自己和同组用户🔍 为什么这么改?
- 根目录必须归 root:Linux 内核强制要求
chroot的目录必须由root拥有,否则连接会瞬间断开。- 子目录归 sftpuser:因为根目录只读,用户无法写文件,所以必须有一个子目录交给用户。采用
sftpuser:sftpuser而非sftpuser:sftpgroup,意味着只有该用户拥有完整权限,其他任何普通用户都无法染指,隔离性更好。
第六步:防火墙放行(如果开启)
sudofirewall-cmd--permanent--add-service=sshsudofirewall-cmd--reload第七步:功能测试与验证
测试连接:
sftpsftpuser@127.0.0.1输入密码后,看到sftp>提示符即为成功。
验证禁锢效果(在sftp>提示符下执行):
sftp> pwd # 显示 / (实际路径已被映射到 /home/sftpuser) sftp> ls -l # 只能看到 upload,看不到系统的 /etc /var 等 sftp> cd upload # 进入自己的工作目录 sftp> put /etc/hosts . # 尝试上传文件(应成功) sftp> ls # 能看到上传的文件 sftp> get hosts # 下载文件 sftp> rm hosts # 删除文件(注意 SFTP 不支持 rm -rf)🔒 高级加固建议(可选)
禁用密码,强制密钥登录(最安全):
- 在
sshd_config中加入PasswordAuthentication no。 - 提前将客户端公钥写入
/home/sftpuser/.ssh/authorized_keys(记得把.ssh目录归sftpuser所有)。
- 在
安装 Fail2ban防爆破:
sudoyuminstall-yepel-release fail2bansudosystemctlenablefail2ban--now
🧩 常见报错与对号入座(终极速查表)
| 报错现象 | 原因 | 解决办法 |
|---|---|---|
subsystem request failed | 未使用内置 SFTP 或完全注释了 Subsystem | 改为Subsystem sftp internal-sftp |
sshd -t报not allowed within Match | StrictModes等误放入 Match 块 | 移到Match行之前 |
连接后立刻断开,日志显示Permission denied | 家目录/home/sftpuser不属于 root | 执行sudo chown root:root /home/sftpuser |
登录后ls看不到任何目录 | 忘记创建子目录 | 创建upload并赋予sftpuser权限 |
访问result目录报Permission denied | 该目录属于 root,普通用户无权查看 | 忽略它,只用自己拥有的upload目录 |
| SFTP 无法递归删除文件夹 | rm命令不支持-r参数 | 进入目录手动删文件,或使用支持递归的客户端(如 lftp) |
