Apache FtpServer 1.2.1 配置参数详解
逐项解析 FtpServer 1.2.1 服务层 XML、用户属性文件与日志配置:限速并发实测、口令加密器选型、被动端口与生效矩阵
Apache FtpServer 1.2.1 配置参数详解
一、配置体系总览
FtpServer 1.2.1 的运行时行为由三层配置共同决定,全部为启动时加载、修改后需重启进程:
| 层 | 文件 | 作用域 |
|---|---|---|
| 服务层 | res/conf/ftpd-typical.xml(或自定义 XML) | 监听端口、TLS、数据连接、用户管理器、FTPLET |
| 用户层 | res/conf/users.properties | 账号、口令、主目录、限速、并发限制 |
| 日志层 | common/classes/log4j.properties | 日志级别、滚动策略、输出格式 |
三层文件的位置都相对于启动时的工作目录(本文统一为 /opt/ftpserver)。XML 遵循 Spring 自定义命名空间 http://mina.apache.org/ftpserver/spring/v1。
二、服务层配置(XML)
2.1 最小可用配置
发行包自带 res/conf/ftpd-typical.xml(去除许可注释后的实际内容):
<server xmlns="http://mina.apache.org/ftpserver/spring/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://mina.apache.org/ftpserver/spring/v1 https://mina.apache.org/ftpserver-project/ftpserver-1.0.xsd"
id="myServer">
<listeners>
<nio-listener name="default" port="2121">
<ssl>
<keystore file="./res/ftpserver.jks" password="password" />
</ssl>
</nio-listener>
</listeners>
<file-user-manager file="./res/conf/users.properties" />
</server>
2.2 server 根元素
| 属性 | 默认值 | 说明 |
|---|---|---|
| id | 无 | Spring Bean 标识,嵌入场景引用时使用,独立部署保持 myServer 即可 |
2.3 listeners 与 nio-listener
nio-listener 基于 MINA NIO 实现控制连接监听(1.2.x 仅提供 NIO 监听器)。
| 属性 | 默认值 | 说明 |
|---|---|---|
| name | 无(必填) | 监听器名称,default 即标准 FTP 端口组 |
| port | 2121(typical 样例) | 控制连接端口;21 需 root 权限或特权端口转发 |
| implicit-ssl | false | true 时端口从建连起全程 TLS(FTP 990 风格);false 为显式 AUTH SSL/TLS |
| idle-timeout | 300(秒) | 连接空闲超时,超时断开并记录日志 |
| local-address | 全部网卡 | 绑定的本机地址 |
实测监听行为(默认 typical 配置启动后):
LISTEN 0 50 *:2121 *:* users:(("java",pid=3606,fd=62))
2.4 ssl 子元素
| 参数 | 说明 |
|---|---|
| keystore file | JKS/PKCS12 密钥库路径,相对路径基于工作目录 |
| keystore password | 密钥库口令 |
| keystore key-password | 密钥条目口令(与库口令不同时设置) |
| keystore type | 密钥库类型(JKS/PKCS12),缺省自动识别 |
| keystore algorithm | KeyManagerFactory 算法,缺省 SunX509 |
| truststore file/password/type/algorithm | 双向 TLS 时配置客户端证书校验 |
重要实测结论:发行包自带 res/ftpserver.jks 是 2011 年的 SHA1withDSA/1024 位 DSA 证书,已过期且被 OpenJDK 11 默认策略禁用,显式 TLS 握手返回 alert handshake failure。必须按《安装指南》第八章重新生成 RSA 2048 密钥库后,FTPS 才能工作:
> AUTH SSL
< 234 Command AUTH okay; starting SSL connection.
(换成新 RSA 密钥库后)
-rw------- 1 user group 28 Jan 29 2025 README.txt
2.5 data-connection 子元素
<data-connection idle-timeout="60">
<active enabled="true" local-address="1.2.3.4" local-port="2323" ip-check="true" />
<passive ports="123-125" address="1.2.3.4" external-address="1.2.3.4" />
</data-connection>
| 参数 | 默认值 | 说明 |
|---|---|---|
| idle-timeout | 300(秒) | 数据连接空闲超时 |
| active enabled | true | 是否允许 PORT 主动模式 |
| active local-address / local-port | 自动 | 主动模式数据连接的源地址/源端口 |
| active ip-check | false | true 时校验 PORT 命令中的 IP 与控制连接来源一致(防跳板攻击) |
| passive ports | 随机分配 | 被动模式数据端口范围,如 50000-50100 |
| passive address | 自动 | 被动模式监听地址 |
| passive external-address | 同 address | NAT/防火墙后向客户端通告的地址 |
实测:配置 <passive ports="50000-50100" /> 并重启后,EPSV 响应的端口落在区间内:
< 229 Entering Passive Mode (|||50039|)
未配置 ports 时端口随机(实测出现过 39681),防火墙环境必须固定区间。
2.6 blacklist
<blacklist>1.2.3.0/16, 1.2.4.0/16, 1.2.3.4</blacklist>
逗号分隔的 IP/网段黑名单,命中后控制连接被拒绝。
2.7 file-user-manager
| 属性 | 默认值 | 说明 |
|---|---|---|
| file | 无(必填) | users.properties 路径 |
| encrypt-passwords | sha512(1.2.x) | 口令散列算法:clear / md5 / sha1 / sha256 / sha512 / salted |
| admin-name | admin | 管理员账号名 |
1.2.x 的默认加密器是 Sha512PasswordEncryptor,与发行包 users.properties 中的大写 MD5 值不兼容,这是开箱 530 的直接原因(详见第四章)。
2.8 db-user-manager
数据存储在关系库时的用户管理器(与 file-user-manager 二选一),需配置 data-source 与 6 条 SQL:insert-user、update-user、delete-user、select-user、select-all-users、is-admin、authenticate。建表参考发行包 res/ftp-db.sql。
2.9 native-filesystem
| 属性 | 默认值 | 说明 |
|---|---|---|
| case-insensitive | false | 路径大小写不敏感(模拟 Windows 行为) |
| create-home | true | 主目录不存在时自动创建 |
2.10 ftplets / commands / messages
- ftplets:注册自定义 Ftplet 扩展(类似 Servlet,拦截上传下载等事件)
- commands:
use-default="false"时完全替换内置命令集,可注册自定义命令实现 - messages:
<messages languages="se,no,da" />定制回复消息的多语言资源
三、用户层配置(users.properties)
3.1 参数全表
每个账号一组 ftpserver.user.<账号名>.<参数> 键:
| 参数 | 示例值 | 说明 |
|---|---|---|
| userpassword | c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec | 口令散列(128 位小写十六进制),空值表示该账号免密(匿名) |
| homedirectory | /data/ftp/demo | 用户主目录,登录后根路径;./res/home 相对于工作目录 |
| enableflag | true | 账号启用开关,false 时登录被拒 |
| writepermission | true | 写权限开关(上传/删除/改名/建目录) |
| maxloginnumber | 0 | 全服务器并发登录上限,0 不限 |
| maxloginperip | 0 | 单 IP 并发登录上限,0 不限 |
| idletime | 0 | 空闲超时秒数,0 用监听器默认值 |
| uploadrate | 0 | 上传限速,字节/秒,0 不限 |
| downloadrate | 0 | 下载限速,字节/秒,0 不限 |
发行包默认两组账号:admin(userpassword 为大写 MD5,需替换,见 3.3)与 anonymous(免密、只读、双限速 4800、单 IP 并发 2、总并发 20、空闲 300 秒)。
3.2 限速语义实测
downloadrate=10240(10 KB/s)下载 512 KB 文件:
time curl -s --user demo:demo123 ftp://127.0.0.1:2121/512kb.bin -o /dev/null
实测输出:
real 0m51.223s
512 KB ÷ 10240 B/s ≈ 51.2 秒,与实测完全吻合,确认单位为字节/秒且限速精确生效。
3.3 并发限制实测
maxloginnumber=1 时,第一个会话在线期间第二个登录被拒:
< 421 Maximum login limit has been reached.
注意 331 阶段不暴露账号是否存在:不存在的账号与口令错误的账号都返回 331(要口令)→ 530(认证失败),无法通过响应码枚举用户名。
3.4 只读账号行为实测
writepermission=false 的 readonly 用户:
- 上传:
550 /hostname.txt: Permission denied. - 删除:
450 No permission to delete /put-target.txt.
写权限覆盖 STOR/APPE/DELE/RMD/MKD/RNFR/RNTO/SITE 等全部变更类命令。
3.5 加载机制与生效条件
users.properties 由 PropertiesUserManager 在启动时一次性读入内存。实测新增 demo 用户后不重启,登录直接 530;重启后同一份文件立即生效。1.2.1 没有热加载参数,任何用户变更(增删改、改口令、改限速)都必须重启进程。
四、口令加密机制
4.1 加密器与存储格式
登录校验逻辑:客户端提交明文 → 加密器 encrypt() → 与 users.properties 中的存储值做大小写敏感快速比较(secureCompareFast)。
| encrypt-passwords | encrypt() 输出格式 | 存储值示例 |
|---|---|---|
| clear | 原文 | admin |
| md5 | 小写 32 位 MD5 十六进制 | 21232f297a57a5a743894a0e4a801fc3 |
| sha1 | 小写 40 位 SHA-1 | — |
| sha256 | 小写 64 位 SHA-256 | — |
| sha512(默认) | 小写 128 位 SHA-512 | c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec |
| salted | 随机盐盐化散列 | 盐化格式值 |
生成 SHA-512 存储值的命令(printf %s 避免换行符混入):
printf %s admin | sha512sum | awk '{print $1}'
实测输出:
c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec
4.2 clear 模式实测
XML 配置 <file-user-manager file="./res/conf/users.properties" encrypt-passwords="clear" />,userpassword 直接写明文 admin,重启后登录成功(230)。仅建议测试环境使用。
4.3 md5 模式说明
encrypt-passwords="md5" 时存储值必须是小写 MD5。发行包默认文件虽是大写 MD5,但 1.2.x 校验大小写敏感,即便切换成 md5 加密器也需先把存储值转小写才可登录。
4.4 选型建议
- 默认 sha512 已是合理基线;对外服务建议叠加 FTPS(第七章安装指南)
- salted 为每账号随机盐,抗彩虹表,但自行造数据成本高,推荐用 sha512 + 强口令策略替代
五、日志层配置(log4j.properties)
发行包日志配置位于 common/classes/log4j.properties:
log4j.rootLogger=INFO, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=./res/log/ftpd.log
log4j.appender.R.MaxFileSize=10MB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%5p] %d [%X{userName}] [%X{remoteIp}] %m%n
要点:
- 输出文件 ./res/log/ftpd.log 相对工作目录,滚动策略 10 MB × 10 份
%X{userName}与%X{remoteIp}是 FtpServer 写入的 MDC 字段,日志每行自带账号与来源 IP- 排障时把 rootLogger 调成 DEBUG 可看到协议栈细节;INFO 下已完整记录每次会话的命令交互,典型行如:
[ INFO] 2026-10-14 13:20:01,631 [admin] [127.0.0.1] SENT: 331 User name okay, need password for admin.
[ WARN] 2026-10-14 13:20:01,632 [admin] [127.0.0.1] User failed to log in
修改日志配置后同样需要重启进程。
六、配置变更生效矩阵
| 变更项 | 生效方式 |
|---|---|
| nio-listener 端口/TLS/数据连接/黑名单 | 重启进程 |
| users.properties 任何用户变更 | 重启进程(实测无热加载) |
| encrypt-passwords 切换 | 重启进程,且存储值格式必须同步更换 |
| log4j.properties | 重启进程 |
| 用户主目录下文件增删 | 即时生效(文件系统直读,无需重启) |
七、常见配置错误速查
| 现象 | 根因 | 处置 |
|---|---|---|
| 正确口令登录 530 | 默认 sha512 加密器 vs 文件里的大写 MD5 | 换小写 SHA-512 存储值 |
| TLS 握手 handshake failure | 自带 JKS 为 2011 年 DSA 证书 | 重新生成 RSA 2048 密钥库 |
| 新加用户登录 530 | 用户文件不热加载 | systemctl restart ftpserver |
| 数据连接超时 | 被动端口随机且被防火墙拦截 | passive ports 固定区间并放行 |
| NAT 后客户端 PASV 连错地址 | 未通告外部地址 | passive external-address |
| 启动即退出 Address already in use | 2121 被占 | 改端口或释放占用 |
| 上传 550 Permission denied | writepermission=false 或 OS 权限不足 | 双层权限都检查 |
| 空闲几分钟后连接被断 | idle-timeout 默认 300 秒 | 按需调大 |
八、参考链接
- 官方配置文档:https://mina.apache.org/ftpserver-project/configuration.html
- schema:https://mina.apache.org/ftpserver-project/ftpserver-1.0.xsd
- 发行包样例:res/conf/ftpd-full.xml(本文 2.4~2.10 各元素均出自该样例)
- 配套安装文档:《Ubuntu 22.04 安装 Apache FtpServer 1.2.1 指南》
- 配套运维文档:《Apache FtpServer 1.2.1 常用 CLI 命令与工具详解》