chroot失败主因是PureDB未加载或LDAP homeDirectory配置错误;需确认PureDB路径正确、权限可读,且LDAP中homeDirectory为绝对路径并显式声明;同时注意ChrootEveryone与客户端兼容性冲突及SELinux等系统调用限制。

chroot 失败时先查 PureDB 文件是否被正确加载
很多情况下 pure-ftpd 声称启用了虚拟用户和 chroot,但用户一登录就掉进根目录或报 530 Login authentication failed,根本原因是 PureDB 文件压根没被读取——哪怕你用 pure-pw 创建了用户、也执行了 pure-pw mkdb,服务仍可能在用系统 PAM 或空数据库。
实操建议:
- 确认启动命令里明确加了
-l puredb:/etc/pure-ftpd/pureftpd.pdb(路径必须和pure-pw mkdb输出路径一致) - 检查
/etc/pure-ftpd/conf/PureDB这个配置文件是否存在且内容为完整路径(例如/etc/pure-ftpd/pureftpd.pdb),这个文件优先级高于命令行参数 - 运行
pure-ftpd -d -f -c 5 -l puredb:/etc/pure-ftpd/pureftpd.pdb启动调试模式,观察日志里是否出现Reading passwords from /etc/pure-ftpd/pureftpd.pdb - 如果看到
Warning: can't open PureDB file或静默跳过,说明路径错、权限不对(pure-ftpd进程用户需有读权限),或文件被锁(mkdb未完成就启动服务)
LDAP 用户 chroot 失败大概率是 home 属性没设对
pure-ftpd 的 LDAP 支持不解析 homeDirectory 以外的字段,且要求该值必须是绝对路径、不能带变量、不能是符号链接目标。一旦填成 /home/vsftpd/%u 或留空,chroot 就会 fallback 到 / 或直接拒绝登录。
实操建议:
- 确保 LDAP 条目中
homeDirectory值为真实存在的绝对路径,如/var/ftp/users/alice,且该路径属主为对应用户 UID(不是用户名字符串) - 检查
/etc/pure-ftpd/conf/LDAPConfig是否指向正确的配置文件,并确认其中homeDirectory在user-attr行被显式列出(例如:user-attr uid,homeDirectory,uidNumber,gidNumber) - 用
ldapsearch -x -b "dc=example,dc=com" "(uid=alice)" homeDirectory直接验证属性值是否可读、无乱码、无空格截断 - 注意 OpenLDAP 默认不返回空属性,如果
homeDirectory字段为空,pure-ftpd会认为用户无家目录,直接拒绝 chroot
chroot 成功但无法写入:检查 ChrootEveryone 和 BrokenClientsCompatibility 冲突
启用 ChrootEveryone yes 后,所有用户(包括虚拟用户)都会被限制在家目录,但某些 FTP 客户端(尤其是 FileZilla 旧版、WinSCP 默认设置)在 chroot 环境下发送 EPSV 或尝试 CWD .. 时会触发兼容性问题,导致连接卡住或提示 550 Permission denied,看起来像权限问题,实际是协议协商失败。
实操建议:
- 临时关闭
ChrootEveryone,改用 per-user chroot(即在PureDB中为每个用户指定chroot路径),看是否恢复写入能力 - 如果必须全局 chroot,请同时开启
BrokenClientsCompatibility yes(写入/etc/pure-ftpd/conf/BrokenClientsCompatibility文件,内容为yes) - 禁用
IPv6(删掉/etc/pure-ftpd/conf/IPv6文件)能规避部分 EPSV 协商失败,尤其在 NAT 或 Docker 环境下 - 确认家目录属主是用户 UID,且父目录(如
/var/ftp/users)至少有rx权限给 ftp 组——pure-ftpd不检查父目录写权限,但客户端列目录会失败
调试时别只盯日志,用 strace 看真实系统调用
日志里只显示 530 Login authentication failed,但没说失败在哪一步:是查 PureDB 失败?是 LDAP bind 成功但没取到 homeDirectory?还是 chroot() 系统调用被拒?这时候 strace 比任何配置检查都直接。
实操建议:
- 停掉服务:
systemctl stop pure-ftpd,然后手动启动并追踪:strace -f -e trace=chroot,openat,stat,connect,bind -s 256 pure-ftpd -d -f -c 5 -l puredb:/etc/pure-ftpd/pureftpd.pdb 2>&1 | grep -E "(chroot|openat|stat|ENOENT|EACCES)" - 重点看
chroot("/var/ftp/users/alice") = 0是否出现;若返回-1 EACCES,说明路径不可访问(常见于 SELinux 启用、或挂载点 noexec/nosuid) - 如果看到反复
openat(AT_FDCWD, "/etc/pure-ftpd/pureftpd.pdb", O_RDONLY) = -1 ENOENT,说明 PureDB 路径配置彻底失效 - 注意
strace输出里 UID/GID 切换是否正常(搜索setgid/setuid),若切换失败,chroot 后的文件操作会以 ftp 用户身份执行,导致权限错乱
chroot 的真正复杂点不在配置语法,而在路径所有权、系统调用权限、协议兼容性这三层叠加。改完一个配置,一定要用真实客户端连一次,不要只信日志里的“OK”。










