在日常工作中,我们经常会遇到需要对公网 FTP 服务进行部署和维护的场景。本文结合实践,分享如何在 Docker 环境下安全部署 vsftpd,并解决明文 FTP 被防火墙拦截的问题。
一、问题背景
原有 FTP 服务:
- Docker 容器:fauria/vsftpd
- 端口映射:21(控制端口) + 10000–10100(被动端口)
- 用户账号密码:ftpadmin / ftpadmin
- 明文 FTP 连接
在部分网络环境下:
客户端无法连接,提示“连接被服务器关闭”
分析原因:
- 公司或上游网络策略禁止明文 FTP(21 端口)
- 明文传输存在账号密码泄露风险
- 公网开放弱密码容易被自动爆破
二、方案设计原则
为了兼顾兼容性和安全性,设计方案遵循以下原则:
- 加密传输:防止网络中明文泄露
- 密码强度:避免自动爆破
- 端口安全:规避默认端口被扫描
- 兼容原目录结构:无需迁移数据
- 低运维成本:继续使用 Docker 部署
三、具体方案(Docker + vsftpd + FTPS)
1️⃣ 生成强密码
随机生成 20 位密码:
F1v$G2aZ@2mZ2#rT3EA!
特点:
- 大小写字母、数字、符号组合
- 无规律
- 不在常见字典中
建议每个 FTP 用户都使用类似强度的密码。
2️⃣ 删除旧容器(这里我更建议先stop容器 可以随时还原)
docker rm -f vsftpd
保留挂载数据目录,不会删除原文件。
3️⃣ 启动新容器(FTPS + 改端口)
docker run -d \
--name vsftpd \
-p 2121:21 \
-p 10000-10100:10000-10100 \
-v /data/sfs-0001/ftp/ftpadmin:/home/vsftpd/ftpadmin \
-e FTP_USER=你的用户名 \
-e FTP_PASS='你的密码' \
-e PASV_ENABLE=YES \
-e PASV_MIN_PORT=10000 \
-e PASV_MAX_PORT=10100 \
-e PASV_ADDRESS=你的ip \
-e SSL_ENABLE=YES \
-e UMASK=022 \
fauria/vsftpd
参数说明
| 参数 | 说明 |
|---|---|
| -p 2121:21 | 将 FTP 控制端口映射为 2121,降低扫描风险 |
| -p 10000-10100 | 被动模式端口范围 |
| -v /data/... | 本地数据挂载目录 |
| FTP_USER / FTP_PASS | 用户名密码 |
| PASV_ADDRESS | 公网 IP,用于被动模式 |
| SSL_ENABLE | 开启 TLS 加密(FTPS) |
| UMASK=022 | 文件权限设置,安全性提高 |
4️⃣ 客户端连接方式
在 FileZilla 或其他 FTP 客户端:
- 协议:FTP – 使用显式 TLS
- 主机:你的ip
- 端口:2121
- 用户名:你的用户名
- 密码:你的密码
首次连接会提示自签名证书,选择信任即可。
5️⃣ 安全加固建议
- 限制 IP 白名单:仅允许公司或固定 IP 访问
- 定期更换密码:保证长期安全
- 日志监控 / fail2ban:防止爆破尝试
- 生产环境可考虑 SFTP:更安全、只需 22 端口,不依赖 PASV 端口范围
四、效果
经过升级:
- FTP 明文传输被 TLS 加密
- 弱密码风险解决
- 默认端口 21 改为 2121,降低被扫概率
- 保留原数据目录,兼容现有客户端
- 可长期稳定运行于公网环境
五、总结
通过 Docker + vsftpd + FTPS 的组合,既保证了原有目录结构兼容,又提升了安全性。对于公网 FTP 服务,关键是加密传输 + 强密码 + 限制访问 IP,同时尽量减少暴露的端口范围。