pure-ftpd 虚拟用户登录失败主因是错误启用 PAM 认证导致 fallback 至 pam_unix,应关闭 PAM 或正确配置 /etc/pam.d/pure-ftpd;需用 pure-pw mkdb 生成。pdb 数据库并显式指定路径;家目录权限、UID/GID 映射及 - l 参数顺序亦为关键排查点。

pure-ftpd 启动后报 pam_unix(pure-ftpd:auth): authentication failure
这是最典型的虚拟用户登录失败日志,说明 PAM 模块在尝试用系统用户逻辑校验时失败了——而 pure-ftpd 虚拟用户根本不该走 pam_unix 这条路。根本原因是 pure-ftpd 被错误配置为启用 PAM 认证,同时又没配好对应的 PAM 规则,导致它 fallback 到系统默认的 pam_unix.so 去查 /etc/passwd,自然找不到虚拟用户。
实操建议:
- 确认是否真的需要 PAM:虚拟用户推荐直接用
pureftpd.passwd+pure-pw管理,** 关闭 PAM 是最简单可靠的解法 ** - 检查启动参数或配置文件:确保没有
-l pam或配置项PAMAuthentication yes;对应要设为PAMAuthentication no - 若必须开 PAM(如集成 LDAP),则需手动编写
/etc/pam.d/pure-ftpd,且第一行必须是auth [success=done default=ignore] pam_succeed_if.so user ingroup ftpgroup类似规则,把虚拟用户提前放行,避免落到pam_unix
pure-ftpd 读不到 pureftpd.passwd 或提示 No such file or directory
pure-ftpd 默认不自动加载 pureftpd.passwd,它只在启用纯文本认证(-l puredb:/etc/pure-ftpd/pureftpd.pdb)时才生效,而且依赖的是编译后的二进制数据库 .pdb 文件,不是原始 .passwd。
实操建议:
-
pureftpd.passwd必须先用pure-pw mkdb编译:运行pure-pw mkdb /etc/pure-ftpd/pureftpd.pdb -f /etc/pure-ftpd/pureftpd.passwd - 确保路径权限正确:
/etc/pure-ftpd/目录需对 pure-ftpd 进程用户(通常是ftp或root)可读;pureftpd.pdb文件不能是 root-only(否则非 root 进程无法打开) - 启动命令中必须显式指定数据库路径,例如:
pure-ftpd -l puredb:/etc/pure-ftpd/pureftpd.pdb;仅放.passwd文件完全无效
用户能连上但立即被断开,日志出现 530 Login authentication failed
这通常不是认证失败,而是认证通过后,pure-ftpd 在做用户映射或家目录检查时出问题。常见于虚拟用户 UID/GID 配置错误,或家目录不存在、权限不对。
实操建议:
- 用
pure-pw show查看该用户的 UID/GID 和 Home 目录路径,确认 UID/GID 对应的系统组(如ftpgroup)存在,且 pure-ftpd 进程有权限切换到该 UID - 检查家目录是否存在、属主是否为该 UID、是否可进入(
dr-xr-xr-x或更宽松);pure-ftpd 不会自动创建家目录 - 如果用了
-u参数限制上传掩码(如-u 1000),可能导致新建文件属主异常,间接触发权限拒绝;临时去掉测试
修改 pureftpd.passwd 后不生效
pure-ftpd 不监听文件变化,pureftpd.pdb 是静态快照。改完 .passwd 必须重新生成 .pdb,且多数情况下还需重启或重载服务(取决于启动方式)。
实操建议:
- 每次改完
pureftpd.passwd,务必执行pure-pw mkdb,不要跳过 - systemd 管理的服务:改完后运行
systemctl reload pure-ftpd(前提是 service 文件里定义了ExecReload);否则得systemctl restart pure-ftpd - 注意
pure-pw命令本身不校验密码格式,输错字符(比如多空格、中文冒号)会导致.pdb解析失败,此时登录会静默失败,建议用pure-pw list验证能否正常列出用户
最常被忽略的一点:pure-ftpd 的 -l 参数顺序敏感,多个认证方式共存时,它按从左到右尝试,一旦某个失败就继续下一个;但只要有一个成功就停止。所以别把 puredb 放在 pam 后面还指望它兜底——PAM 失败前连接早就断了。






























