pure-ftpd 虚拟用户 chroot 失败的 PureDB / LDAP 配置校验

3次阅读

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

pure-ftpd 虚拟用户 chroot 失败的 PureDB / LDAP 配置校验

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 是否指向正确的配置文件,并确认其中 homeDirectoryuser-attr 行被显式列出(例如:user-attr uid,homeDirectory,uidNumber,gidNumber
  • ldapsearch -x -b "dc=example,dc=com" "(uid=alice)" homeDirectory 直接验证属性值是否可读、无乱码、无空格截断
  • 注意 OpenLDAP 默认不返回空属性,如果 homeDirectory 字段为空,pure-ftpd 会认为用户无家目录,直接拒绝 chroot

chroot 成功但无法写入:检查 ChrootEveryoneBrokenClientsCompatibility 冲突

启用 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”。

text=ZqhQzanResources