问题背景&现象

20241109022214

在用户群中,有同学反馈 1Panel 的 FTP 功能上传文件比同类服务慢很多,尝试换了很多种连接工具,均没有效果。

我咨询了一下他的环境,Debian 12 + 最新版本的 1Panel,他说他那边是机房内网互传文件,理论上不会有公网抖动的影响。但就是很慢。用其它面板提供的 FTP 服务,上传小图片都是秒传,但是用 1Panel 之后,传相同的图片大概要 7s 以上。卡顿明显。

复现问题

首先我在实验环境中安装了 Debian 12 + v1.10.20-lts 社区版的 1Panel,根据文档,安装了 pure-ftpd 并做了相关的配置。
我尝试用 FileZilla 连接 1Panel 的 FTP 服务并上传几个文件,发现确实会感觉有明显的卡顿。

和另外一家的面板对比,他们的速度非常快。

So,这是为什么呢?

分析

对照了配置,我发现 1Panel 的配置没有什么特别的。从配置上没有定位到问题。于是我开始通过抓包,看整个 FTP 传输的过程的数据包,看看他卡在哪里了。

使用 WireShark 抓包,将时间戳作为列展示出来,查找整个过程中时延较大的 Request 和 Response。
20241109022550

如上图,我发现在 Request PASS 到列目录的过程中,存在一个将近 5s 左右的大时延。等这 5s 过后,后面的文件传输过程就非常顺利了,没有丢包或者延迟之类的现象出现。

我观察了一下,虽然我已经登录到了 FTP 上,但当上传文件的时候,还是重新走了一遍登录的过程。

所以我觉得可能慢是密码登录的时候卡住了几秒,然后再才是传输数据。

继续排查 pureftpd.passwd,发现虚拟用户的密码是类似于 $argon2id$v=19$m=8192 这样的。很明显的 1Panel 的 pure-ftpd 使用了 Argon2 相关的加密算法。

20241109103250

Argon2id 是 Argon2i 和 Argon2d 的混合体,使用依赖于数据和独立于数据的内存访问的组合,这使 Argon2i 能够抵抗侧通道缓存计时攻击,并使 Argon2d 能够抵抗 GPU 破解攻击。

Argon2 虽然更安全,但是它牺牲了更多的 CPU 和内存的资源,使得整个过程会变慢。而且会根据机器性能的差异,速度也会有所不同。

解决方案

所以最终的解决方案就是权衡安全性和性能,更换一种 pureftpd.passwd 中的加密算法。

1、更换加密算法为 bcrypt,我们可以使用 openssl 生成 bcrypt 加密的密码。

1
openssl passwd -6

2、手动替换 pureftpd.passwd 中的加密密码,文件位置:/etc/pure-ftpd/pureftpd.passwd

1
用户名:加密后的bcrypt密码:UID:GID:权限:主目录

编辑文件中对应部分,也就是第一个冒号到第二个冒号之间的内容,并保存。

3、重建数据库

1
pure-pw mkdb

重建数据库,使得密码生效。

由于 pure-pw 没有给定加密算法的选项,只能自己实现一个 pureftpd.passwd 管理器,来完成 Virtual-Users 的增删改查。这里我提了一个 PR。

效果实测

切换加密算法后。登录认证速度从 5s 左右降为 不到 1s。上传不再有卡顿感了。

20241109032446

扩展延伸

From README.Virtual-Users

Passwords are hashed with the most secure hash function your system supports.
Hashes are tried in this order: argon2, scrypt, bcrypt, SHA-512, MD5.

SHA-512 and MD5 should not be used any more. bcrypt requires crypt(3) from the C library to support it, which is commonly the case on BSD systems, but is only present on some Linux distributions.

Argon2 and scrypt are the recommended functions, and require pure-ftpd to be compiled in presence of libsodium. Note that a login attempt will require up to 64 Mb memory, and 100% of a CPU core. The number of simultaneously allowed sessions should be tuned accordingly to avoid resources starvation.