Ubuntu 22.04 安装 Apache FtpServer 1.2.1 指南

从零在 Ubuntu 22.04 安装 Apache FtpServer 1.2.1:下载校验、SHA-512 口令坑、FTPS 密钥库重建、systemd 托管与客户端连通全流程实测

Apache FtpServerFtpServerApacheFTPJava安装部署Ubuntu 22.042026/10/14

Ubuntu 22.04 安装 Apache FtpServer 1.2.1 指南

一、环境信息

本文所有命令与回显均在以下环境实测采集,读者在其他环境操作时输出可能略有差异。

项目值
操作系统Ubuntu 22.04.5 LTS(GNU/Linux x86_64)
内核5.15.0
主机名node1.ftp.example
IP172.17.0.4
登录账号root / q1w2e3r4
JavaOpenJDK 11.0.32.1(openjdk-11-jre-headless)
目标版本Apache FtpServer 1.2.1(2025-01-29 构建)
安装目录/opt/apache-ftpserver-1.2.1(软链 /opt/ftpserver)
监听端口2121(控制连接,默认端口)

Apache FtpServer 是 Apache MINA 旗下的纯 Java FTP 服务器,发行包仅约 4.3 MB,解压即可运行,无需数据库与编译步骤。

二、前置条件

2.1 更新软件源并安装基础工具

apt-get update

实测输出(节选):

Get:1 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [128 kB]
...
Reading package lists... Done
Building dependency tree... Done
DEBIAN_FRONTEND=noninteractive apt-get install -y curl wget openjdk-11-jre-headless

实测输出(节选):

Setting up openjdk-11-jre-headless:amd64 (11.0.32.1+1-0ubuntu1~22.04) ...
Setting up curl (7.81.0-1ubuntu1.21) ...
Setting up wget (1.21.2-2ubuntu1.1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.14) ...

2.2 验证 Java

java -version

实测输出:

openjdk version "11.0.32.1" 2026-08-18
OpenJDK Runtime Environment (build 11.0.32.1+1-post-1ubuntu1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 11.0.32.1+1-post-1ubuntu1-22.04-Ubuntu, mixed mode, sharing)

FtpServer 1.2.1 官方要求 Java 8 及以上,实测 OpenJDK 11 运行正常。若使用 OpenJDK 17 亦兼容。

2.3 规划磁盘目录

目录用途
/opt/downloads发行包存放
/opt/apache-ftpserver-1.2.1程序目录
/opt/ftpserver软链接(便于升级与脚本引用)
/data/ftp/demoFTP 用户主目录示例
/opt/ftpserver/res/log运行日志(发行包自带)

三、版本选型与下载

3.1 版本说明

FtpServer 的发行包挂在 Apache MINA 的下载目录下(/mina/ftpserver/),当前发行版为 1.1.4 与 1.2.1,本文选 1.2.1。历史版本(1.0.x、1.1.0~1.1.1)可在 archive.apache.org 查询。

各版本现状:

版本线最新版本说明
1.2.x1.2.1当前推荐版本,口令默认 SHA-512 散列
1.1.x1.1.4维护线
1.0.x1.0.6仅存档,不建议新部署

3.2 下载发行包

mkdir -p /opt/downloads && cd /opt/downloads
curl -sS -O https://dlcdn.apache.org/mina/ftpserver/1.2.1/apache-ftpserver-1.2.1-bin.tar.gz \
     -O https://dlcdn.apache.org/mina/ftpserver/1.2.1/apache-ftpserver-1.2.1-bin.tar.gz.sha512
ls -lh

实测输出:

total 4.3M
-rw-r--r-- 1 root root 4.3M Oct 14 13:18 apache-ftpserver-1.2.1-bin.tar.gz
-rw-r--r-- 1 root root  292 Oct 14 13:18 apache-ftpserver-1.2.1-bin.tar.gz.sha512

3.3 校验 SHA-512

官方 .sha512 文件内容为按 8 位分组的十六进制串:

cat apache-ftpserver-1.2.1-bin.tar.gz.sha512

实测输出:

./apache-ftpserver-1.2.1-bin.tar.gz: 133D0537 220F7408 EEBB6945 70DE6FC1
                                     48DCB397 0BE6A7D6 FA5D305D 3A833161
                                     C68BD889 46E126CC 31A17604 1B7CEF8D
                                     040309CD 6AEE0710 8BFC26CC 663DF73C

本地计算并比对(去掉分组空格、统一小写):

sha512sum apache-ftpserver-1.2.1-bin.tar.gz | awk '{print $1}' > calc.sha
grep -oE '[0-9A-F]{8}( [0-9A-F]{8}){3}' apache-ftpserver-1.2.1-bin.tar.gz.sha512 | tr -d ' \n' | tr 'A-Z' 'a-z' > expected.sha
cat calc.sha && cat expected.sha
[ "$(cat calc.sha)" = "$(cat expected.sha)" ] && echo CHECKSUM-OK || echo CHECKSUM-FAIL

实测输出:

133d0537220f7408eebb694570de6fc148dcb3970be6a7d6fa5d305d3a833161c68bd88946e126cc31a176041b7cef8d040309cd6aee07108bfc26cc663df73c
133d0537220f7408eebb694570de6fc148dcb3970be6a7d6fa5d305d3a833161c68bd88946e126cc31a176041b7cef8d040309cd6aee07108bfc26cc663df73cCHECKSUM-OK

四、安装步骤

4.1 解压并建立软链接

cd /opt
tar xzf downloads/apache-ftpserver-1.2.1-bin.tar.gz
ln -s /opt/apache-ftpserver-1.2.1 /opt/ftpserver
ls -l /opt/ftpserver

实测输出:

lrwxrwxrwx 1 root root 27 Oct 14 13:19 /opt/ftpserver -> /opt/apache-ftpserver-1.2.1

4.2 发行包目录结构

ls /opt/ftpserver

实测输出:

DEPENDENCIES  LICENSE  LICENSE.slf4j.txt  LICENSE.springframework.txt  NOTICE  README.txt
bin  common  res
目录/文件说明
bin/启动脚本:ftpd.sh(Linux)、ftpd.bat、ftpd.exe、ftpdw.exe(Windows 服务)、service.bat
common/classes/扩展类与 log4j.properties
common/lib/全部依赖 jar(共 13 个)
res/conf/服务端配置:ftpd-typical.xml、ftpd-full.xml、users.properties
res/home/默认用户主目录
res/log/运行日志 ftpd.log 输出目录
res/ftpserver.jks自带示例 TLS 密钥库(见第八章,已过期不可直接用)
res/ftp-db.sql数据库用户管理器的建表参考 SQL

查看依赖清单:

ls /opt/ftpserver/common/lib

实测输出:

aopalliance-1.0.jar
ftplet-api-1.2.1.jar
ftpserver-core-1.2.1.jar
jcl-over-slf4j-1.7.36.jar
log4j-api-2.24.3.jar
log4j-core-2.24.3.jar
mina-core-2.2.4.jar
reload4j-1.2.19.jar
slf4j-api-1.7.36.jar
slf4j-reload4j-1.7.36.jar
spring-beans-2.5.5.jar
spring-context-2.5.5.jar
spring-core-2.5.5.jar

核心依赖:mina-core 2.2.4(网络框架)、Spring 2.5.5(XML 配置解析)、log4j2/reload4j(日志)。

五、首次启动验证

5.1 前台启动

cd /opt/ftpserver
bin/ftpd.sh res/conf/ftpd-typical.xml

实测输出:

Using XML configuration file res/conf/ftpd-typical.xml...
FtpServer started

启动后进程保持前台运行。ftpd.sh 不支持后台参数,生产部署须配合 systemd(第八章)或 nohup。

另开终端确认监听端口(2121 为 ftpd-typical.xml 中 nio-listener 默认配置):

ss -tlnp | grep java

实测输出:

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

5.2 匿名账号连通测试

发行包默认 users.properties 中 anonymous 账号口令为空、只读:

curl --user anonymous: ftp://127.0.0.1:2121/

实测输出:

-r--------   1 user group           28 Jan 29  2025 README.txt

返回 230 与目录列表说明服务器已正常工作。此时 admin 账号尚不能登录,原因见第六章。

六、用户配置(重要:默认文件必须修改)

6.1 发行包默认口令的问题

发行包 res/conf/users.properties 自带的 admin 账号口令为 admin,存储值是大写 MD5:

ftpserver.user.admin.userpassword=21232F297A57A5A743894A0E4A801FC3

FtpServer 1.2.x 的 PropertiesUserManagerFactory 默认使用 Sha512PasswordEncryptor(而非老版本的 MD5),登录校验时会把客户端提交的明文口令做小写 SHA-512 后与存储值做大小写敏感比较。因此默认文件里的 MD5 值无论大小写都无法通过校验,直接登录必然失败。

实测失败过程(口令为 admin/admin 时):

curl --user admin:admin ftp://127.0.0.1:2121/

实测输出:

curl: (67) Access denied: 530

服务端日志(res/log/ftpd.log)同步记录:

[ INFO] 2026-10-14 13:20:01,631 [admin] [127.0.0.1] SENT: 331 User name okay, need password for admin.
[ INFO] 2026-10-14 13:20:01,632 [admin] [127.0.0.1] RECEIVED: PASS *****
[ WARN] 2026-10-14 13:20:01,632 [admin] [127.0.0.1] User failed to log in
[ WARN] 2026-10-14 13:20:02,132 [admin] [127.0.0.1] Login failure - admin
[ INFO] 2026-10-14 13:20:02,133 [admin] [127.0.0.1] SENT: 530 Authentication failed.

6.2 生成正确的 SHA-512 口令值

printf %s admin | sha512sum | awk '{print $1}'

实测输出:

c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec

将 users.properties 中 admin 的 userpassword 替换为上述小写 SHA-512 值:

sed -i 's/^ftpserver.user.admin.userpassword=.*/ftpserver.user.admin.userpassword=c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec/' /opt/ftpserver/res/conf/users.properties

6.3 重启服务并验证 admin 登录

重启后再次测试:

curl --user admin:admin ftp://127.0.0.1:2121/

实测输出:

-rw-------   1 user group           28 Jan 29  2025 README.txt
-rw-------   1 user group           26 Oct 14 13:20 upload-test.txt

登录成功(230),且 admin 具备写权限(列表字段为 rw-)。

6.4 新增业务用户

在 users.properties 末尾追加用户段落。以下创建 demo 用户(口令 demo123,主目录 /data/ftp/demo,限速 10 KB/s,并发 1):

mkdir -p /data/ftp/demo
printf %s demo123 | sha512sum | awk '{print $1}'

实测输出:

45153ecd716a4b5bb7779d43fb38b3b115e384425ce7d4a75fc410199b19558055dd6d09b8b96847ad658f1c474ed081c252e40a0078dd8b0a41bebefa857721
ftpserver.user.demo.userpassword=45153ecd716a4b5bb7779d43fb38b3b115e384425ce7d4a75fc410199b19558055dd6d09b8b96847ad658f1c474ed081c252e40a0078dd8b0a41bebefa857721
ftpserver.user.demo.homedirectory=/data/ftp/demo
ftpserver.user.demo.enableflag=true
ftpserver.user.demo.writepermission=true
ftpserver.user.demo.maxloginnumber=1
ftpserver.user.demo.maxloginperip=0
ftpserver.user.demo.idletime=0
ftpserver.user.demo.uploadrate=10240
ftpserver.user.demo.downloadrate=10240

注意事项:

  • users.properties 在 1.2.1 中启动时一次性加载,新增或修改用户后必须重启进程才生效(实测结论,见第十二章 FAQ)
  • 主目录不存在时登录后首次列目录会报错,建议提前创建

七、方案对比

方案适用场景优点缺点
发行包独立部署(本文)独立 FTP 服务器零编译、4.3 MB 即装即用、自带 systemd 可托管能力无内置高级虚拟化存储
嵌入式 Java API应用内嵌文件服务与业务进程同生命周期、可编程 Ftplet 扩展需要开发与依赖管理
vsftpd系统级静态文件服务C 实现、性能高用户与业务系统集成弱,非 Java 生态
数据库用户管理器(db-user-manager)用户量大、集中管理用户存 DB、SQL 认证需额外建表与数据源配置

八、FTPS 加密配置

8.1 自带密钥库不能直接用

ftpd-typical.xml 默认引用 ./res/ftpserver.jks(口令 password)。该密钥库是 2011 年生成的示例证书:

keytool -list -v -keystore /opt/ftpserver/res/ftpserver.jks -storepass password | head -12

实测输出(节选):

Alias name: apache ftpserver example
Creation date: Jun 19, 2011
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Apache FtpServer Example, OU=MINA, O=Apache Software Foundation, C=US
Valid from: Sun Jun 19 10:01:23 GMT 2011 until: Wed Jun 18 10:01:23 GMT 2014
Signature algorithm name: SHA1withDSA (weak)
Subject Public Key Algorithm: 1024-bit DSA key (weak)

证书已于 2014 年过期,且 SHA1withDSA + 1024 位 DSA 在 OpenJDK 11 的默认 jdk.tls.disabledAlgorithms 中被禁用。客户端显式开启 TLS 时握手直接失败:

> AUTH SSL
< 234 Command AUTH okay; starting SSL connection.
* TLSv1.3 (IN), TLS alert, handshake failure (552):
curl: (35) error:0A000410:SSL routines::sslv3 alert handshake failure

8.2 重新生成 RSA 密钥库

keytool -genkeypair -alias ftpserver -keyalg RSA -keysize 2048 -validity 3650 \
  -keystore /opt/ftpserver/res/ftpserver-rsa.jks -storepass password -keypass password \
  -dname "CN=node1.ftp.example, O=Demo, C=CN"

实测输出(节选):

ftpserver, Oct 14, 2026, PrivateKeyEntry,
Certificate fingerprint (SHA-256): 03:AF:60:F9:48:02:EA:D7:A6:83:F4:5C:3E:99:0F:D9:2A:27:52:C5:E4:FF:31:95:82:8D:59:57:0A:A4:DA:C2

8.3 修改配置启用 FTPS

将 ftpd-typical.xml 中 keystore 指向新密钥库:

<ssl>
    <keystore file="./res/ftpserver-rsa.jks" password="password" />
</ssl>

重启后用 curl 显式 TLS 验证:

curl -k --ssl-reqd --user admin:admin ftp://127.0.0.1:2121/

实测输出:

-rw-------   1 user group           28 Jan 29  2025 README.txt
-rw-------   1 user group           26 Oct 14 13:20 upload-test.txt

AUTH SSL → 234 → TLS 握手 → 登录 230 → 列表成功,FTPS 可用。内网亦可用 --ssl 放宽要求;对公网服务建议强制 TLS 并尽快用受信任 CA 证书替换自签名证书。

九、systemd 托管

9.1 编写服务单元

ftpd.sh 本身不支持 JVM 参数透传,systemd 直接调用 java 最干净(classpath 通配符由 JVM 自己展开)。创建 /etc/systemd/system/ftpserver.service:

[Unit]
Description=Apache FtpServer 1.2.1
Documentation=https://mina.apache.org/ftpserver-project/
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/ftpserver
ExecStart=/usr/bin/java -Xms256m -Xmx256m -classpath common/classes:common/lib/* org.apache.ftpserver.main.CommandLine res/conf/ftpd-typical.xml
Restart=on-failure
RestartSec=5
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

要点:

  • WorkingDirectory 必须是 /opt/ftpserver,配置里的相对路径(./res/conf/...)全部基于它解析
  • 堆内存 256MB 起步,按并发量在 256~512MB 区间调整
  • SuccessExitStatus=143 避免 systemd 把 stop 信号误判为失败

9.2 启用并启动

systemctl daemon-reload
systemctl enable --now ftpserver

实测输出(节选):

Created symlink /etc/systemd/system/multi-user.target.wants/ftpserver.service → /etc/systemd/system/ftpserver.service.

9.3 状态确认

systemctl status ftpserver --no-pager -n 3

实测输出:

● ftpserver.service - Apache FtpServer 1.2.1
     Loaded: loaded (/etc/systemd/system/ftpserver.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2026-10-14 13:27:33 UTC; 5s ago
       Docs: https://mina.apache.org/ftpserver-project/
   Main PID: 4760 (java)
      Tasks: 26 (limit: 5753)
     Memory: 78.5M
        CPU: 2.398s
     CGroup: /system.slice/.../system.slice/ftpserver.service
             └─4760 /usr/bin/java -Xms256m -Xmx256m -classpath "common/classes:common/lib/*" org.apache.ftpserver.main.CommandLine res/conf/ftpd-typical.xml

Oct 14 13:27:33 node1.ftp.example systemd[1]: Started Apache FtpServer 1.2.1.

journalctl 中可看到启动横幅:

journalctl -u ftpserver -n 5 --no-pager

实测输出:

Oct 14 13:27:33 node1.ftp.example systemd[1]: Started Apache FtpServer 1.2.1.
Oct 14 13:27:33 node1.ftp.example java[4760]: Using XML configuration file res/conf/ftpd-typical.xml...
Oct 14 13:27:34 node1.ftp.example java[4760]: FtpServer started

十、客户端连通验证

10.1 curl 上传下载全流程

echo 'hello from ftpserver demo' > /tmp/upload-test.txt
curl -T /tmp/upload-test.txt --user admin:admin ftp://127.0.0.1:2121/
curl -s --user admin:admin ftp://127.0.0.1:2121/upload-test.txt

实测输出:

hello from ftpserver demo

10.2 lftp 完整会话

lftp -u admin,admin 127.0.0.1 -p 2121 -e 'set ftp:ssl-allow no; ls; put /tmp/upload-test.txt; ls -l; bye'

实测输出:

-rw-------   1 user group           28 Jan 29  2025 README.txt
-rw-------   1 user group           26 Oct 14 13:20 upload-test.txt
258 bytes transferred
-rw-------   1 user group           28 Jan 29  2025 README.txt
-rw-------   1 user group          258 Oct 14 13:32 upload-test.txt

若客户端与服务器都启用了 TLS 但证书是自签名,curl 需要加 -k,lftp 需要 set ssl:verify-certificate no。

10.3 限速与并发限制实测

demo 用户配置了 downloadrate=10240(字节/秒)与 maxloginnumber=1,行为与配置精确一致:

  • 下载 512 KB 文件耗时 51.2 秒(10240 B/s 精确生效)
  • 已有连接未断开时第二个登录被拒绝:
< 421 Maximum login limit has been reached.

只读用户(writepermission=false)上传与删除分别被拒绝:

< 550 /hostname.txt: Permission denied.
< 450 No permission to delete /put-target.txt.

十一、配置汇总

配置项路径/值说明
服务配置/opt/ftpserver/res/conf/ftpd-typical.xml监听 2121、TLS、用户文件
用户文件/opt/ftpserver/res/conf/users.propertiesSHA-512 散列口令
日志配置/opt/ftpserver/common/classes/log4j.propertiesINFO、滚动 10MB×10
运行日志/opt/ftpserver/res/log/ftpd.log含用户名与远端 IP
systemd 单元/etc/systemd/system/ftpserver.service开机自启、异常自动拉起
TLS 密钥库/opt/ftpserver/res/ftpserver-rsa.jksRSA 2048,口令 password

firewalld/ufw 环境需放行 2121 及被动端口段(本文未启用防火墙;如启用请参考 FAQ 12.6)。

十二、常见问题 FAQ

12.1 admin/admin 登录报 530 Authentication failed

原因:1.2.x 默认口令加密器是 SHA-512,发行包 users.properties 中的大写 MD5 不被接受。按第六章把 userpassword 换成小写 SHA-512 值后重启即可。判断口令属于哪种格式:小写 128 位十六进制 = SHA-512,32 位十六进制 = MD5(需配合 encrypt-passwords="md5"),$1$... 开头 = salted。

12.2 修改 users.properties 后不生效

users.properties 由 PropertiesUserManager 在启动时一次性加载,1.2.1 无热加载与轮询机制,改完必须 systemctl restart ftpserver。修改前已连接的会话不受影响。

12.3 客户端 TLS 握手失败(alert handshake failure)

自带 ftpserver.jks 是 2011 年 SHA1withDSA/1024 位证书,已过期且被现代 JDK 禁用。按第八章重新生成 RSA 2048 密钥库并更新 keystore 路径。

12.4 启动报 JAVA_HOME is not defined correctly

ftpd.sh 找不到可执行的 java。安装 openjdk-11-jre-headless 后重试,或显式 export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64。systemd 方式直接写 /usr/bin/java 全路径可完全规避。

12.5 启动报 Address already in use

2121 端口被占用:ss -tlnp | grep 2121 找到占用进程,或修改 ftpd-typical.xml 中 nio-listener 的 port。

12.6 防火墙环境被动模式连不上

控制连接 2121 通但数据连接超时。在 nio-listener 内配置固定被动端口段并放行:

<data-connection>
    <passive ports="50000-50100" />
</data-connection>

实测配置后 EPSV 返回端口落在区间内:229 Entering Passive Mode (|||50039|)。防火墙同步放行 50000-50100。NAT 环境还需 <passive external-address="公网IP" />。

12.7 上传文件报 550 Permission denied

writepermission=false 的用户不可写。检查该用户段落是否配置 ftpserver.user.<name>.writepermission=true,同时确认服务器进程对主目录有 OS 层写权限。

12.8 匿名登录看到的是 /opt/ftpserver/res/home

anonymous 的 homedirectory 默认指向 ./res/home。改 homedirectory 并重启即可;口令留空(userpassword=)即代表匿名可登录。

12.9 日志里大量 WARN User failed to log in

口令错误或账号未启用(enableflag=false)。结合 WARN 行上下的 USER/PASS 记录确认账号名;口令格式错配(12.1)是最常见原因。

12.10 如何迁移到数据库用户管理

把 ftpd-typical.xml 的 file-user-manager 换成 db-user-manager(含 data-source 与 6 条 SQL),参考发行包 res/ftp-db.sql 建表,表结构含 userid/userpassword/homedirectory 等列。

十三、卸载

systemctl disable --now ftpserver
rm -f /etc/systemd/system/ftpserver.service
systemctl daemon-reload
rm -f /opt/ftpserver
rm -rf /opt/apache-ftpserver-1.2.1 /opt/downloads/apache-ftpserver-1.2.1-bin.tar.gz*
rm -rf /data/ftp

如需彻底清理 Java 环境:apt-get purge -y openjdk-11-jre-headless。

十四、参考链接