Apache FtpServer 1.2.1 配置参数详解

逐项解析 FtpServer 1.2.1 服务层 XML、用户属性文件与日志配置:限速并发实测、口令加密器选型、被动端口与生效矩阵

Apache FtpServerFtpServerApache配置详解参数调优2026/10/14

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 端口组
port2121(typical 样例)控制连接端口;21 需 root 权限或特权端口转发
implicit-sslfalsetrue 时端口从建连起全程 TLS(FTP 990 风格);false 为显式 AUTH SSL/TLS
idle-timeout300(秒)连接空闲超时,超时断开并记录日志
local-address全部网卡绑定的本机地址

实测监听行为(默认 typical 配置启动后):

LISTEN 0      50                 *:2121            *:*    users:(("java",pid=3606,fd=62))

2.4 ssl 子元素

参数说明
keystore fileJKS/PKCS12 密钥库路径,相对路径基于工作目录
keystore password密钥库口令
keystore key-password密钥条目口令(与库口令不同时设置)
keystore type密钥库类型(JKS/PKCS12),缺省自动识别
keystore algorithmKeyManagerFactory 算法,缺省 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-timeout300(秒)数据连接空闲超时
active enabledtrue是否允许 PORT 主动模式
active local-address / local-port自动主动模式数据连接的源地址/源端口
active ip-checkfalsetrue 时校验 PORT 命令中的 IP 与控制连接来源一致(防跳板攻击)
passive ports随机分配被动模式数据端口范围,如 50000-50100
passive address自动被动模式监听地址
passive external-address同 addressNAT/防火墙后向客户端通告的地址

实测:配置 <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-passwordssha512(1.2.x)口令散列算法:clear / md5 / sha1 / sha256 / sha512 / salted
admin-nameadmin管理员账号名

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-insensitivefalse路径大小写不敏感(模拟 Windows 行为)
create-hometrue主目录不存在时自动创建

2.10 ftplets / commands / messages

  • ftplets:注册自定义 Ftplet 扩展(类似 Servlet,拦截上传下载等事件)
  • commands:use-default="false" 时完全替换内置命令集,可注册自定义命令实现
  • messages:<messages languages="se,no,da" /> 定制回复消息的多语言资源

三、用户层配置(users.properties)

3.1 参数全表

每个账号一组 ftpserver.user.<账号名>.<参数> 键:

参数示例值说明
userpasswordc7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec口令散列(128 位小写十六进制),空值表示该账号免密(匿名)
homedirectory/data/ftp/demo用户主目录,登录后根路径;./res/home 相对于工作目录
enableflagtrue账号启用开关,false 时登录被拒
writepermissiontrue写权限开关(上传/删除/改名/建目录)
maxloginnumber0全服务器并发登录上限,0 不限
maxloginperip0单 IP 并发登录上限,0 不限
idletime0空闲超时秒数,0 用监听器默认值
uploadrate0上传限速,字节/秒,0 不限
downloadrate0下载限速,字节/秒,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-passwordsencrypt() 输出格式存储值示例
clear原文admin
md5小写 32 位 MD5 十六进制21232f297a57a5a743894a0e4a801fc3
sha1小写 40 位 SHA-1—
sha256小写 64 位 SHA-256—
sha512(默认)小写 128 位 SHA-512c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec
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 use2121 被占改端口或释放占用
上传 550 Permission deniedwritepermission=false 或 OS 权限不足双层权限都检查
空闲几分钟后连接被断idle-timeout 默认 300 秒按需调大

八、参考链接