22.3 ProFTPD(基于 MySQL)
技巧
通过 Windows 自带 FTP 客户端连接 ProFTPD 服务器时不会出现乱码。
22.3.1 安装 ProFTPD
注意
本节基于 MySQL 8.0。有关 MySQL 的安装和基本设置,请参见其他章节。
请自行安装配置 MySQL 8.x,需确保与 proftpd-mod_sql_mysql 安装的 databases/mysql8X-client 版本一致。
安装 ProFTPD 及其 MySQL 模块:
# pkg install proftpd proftpd-mod_sql_mysql或使用 Ports 安装:
# cd /usr/ports/ftp/proftpd/ && make install clean
# cd /usr/ports/databases/proftpd-mod_sql_mysql/ && make install clean22.3.2 ProFTPD 配置文件
编辑 ProFTPD 的配置文件 /usr/local/etc/proftpd.conf:
技巧
示例文件参见 /usr/local/etc/proftpd.conf.sample。
ServerName "Test Ftp Server" # FTP 服务器名称
ServerType standalone # 独立运行模式
DefaultServer on # 设置为默认服务器
ServerIdent on "FTP Server ready" # 客户端连接时显示的服务器标识
Port 21 # 监听端口
Umask 022 # 文件创建掩码
# 超时设置
TimeoutLogin 300 # 登录超时时间(秒)
TimeoutIdle 36000 # 空闲超时时间(秒)
TimeoutNoTransfer 36000 # 无传输超时时间(秒)
# 资源限制
User proftpd # 运行服务的用户
Group proftpd # 运行服务的用户组
RLimitMemory 256M 256M # 内存限制
RLimitOpenFiles 1024 1024 # 打开文件数量限制
PassivePorts 50000 60000 # 被动模式端口范围
# 日志配置
LogFormat default "%h %l %u %t \"%r\" %s %b" # 默认日志格式
LogFormat auth "%v [%P] %h %t \"%r\" %s" # 认证日志格式
SystemLog /var/log/proftpd/proftpd.log # 系统日志路径
TransferLog /var/log/proftpd/xfer.log # 文件传输日志路径
ExtendedLog /var/log/proftpd/auth.log AUTH auth # 扩展认证日志
# MySQL 模块加载
LoadModule mod_sql.c
LoadModule mod_sql_mysql.c
LoadModule mod_sql_passwd.c
# 只允许访问各自的目录
DefaultRoot ~ # 将用户限制于主目录内
# 允许覆盖文件
AllowOverwrite on # 允许文件覆盖
<Global>
# 数据库连接
SQLConnectInfo proftpd@localhost proftpd 123456 # 数据库连接信息(用户、主机、密码)
# 密码认证设置
SQLAuthTypes SHA256 # 使用 SHA256 加密认证
SQLPasswordEngine on # 启用 SQL 密码引擎
# 用户表映射
SQLUserInfo users username password uid gid homedir shell # 映射 users 表字段
SQLDefaultGID 2000 # 默认 GID
SQLDefaultUID 2000 # 默认 UID
RequireValidShell off # 不要求有效 Shell
# 认证顺序
AuthOrder mod_sql.c
SQLAuthenticate users # 使用 SQL 用户表认证
# 登录统计
SQLNamedQuery getcount SELECT "CONCAT('Total logins: ', count) FROM users WHERE username='%u'" # 查询登录次数
SQLNamedQuery updatecount UPDATE "count=count+1 WHERE username='%u'" users # 更新登录次数
SQLShowInfo PASS "230" "%{getcount}" # 显示登录统计信息
SQLLog PASS updatecount # 记录登录统计
# 文件操作日志
SQLNamedQuery log_work FREEFORM "INSERT INTO worklog (user_name, file_and_path, bytes, send_time, client_ip, client_name, client_command) VALUES ('%u', '%f', %b, NULLIF('%T', ''), '%a', '%h', '%m')" # 文件操作日志记录
SQLLog RETR,STOR,DELE log_work # 将 RETR、STOR、DELE 操作记录到 worklog 表
</Global>创建日志目录:
# mkdir /var/log/proftpd警告
若未手动创建目录,系统将提示
proftpd[3435]: warning: handling possibly truncated configuration data at line 65 of '/usr/local/etc/proftpd.conf'。
技巧
ProFTPD 配置文件 /usr/local/etc/proftpd.conf 有语法检查命令
proftpd -t -d5。
本配置中,服务器主动模式使用端口 21,被动模式使用端口 50000-60000,须确保防火墙已放行上述端口。
对于 PF 防火墙,通过以下规则实现:
允许从外部接口 $ext_if(需要改为实际网络接口)到本机端口 21 及 50000-60000 的 TCP 入站流量:
pass in quick on $ext_if proto tcp from any to $ext_if port { 21, 50000:60000 }22.3.3 相关文件结构
/usr/local/etc/
├── proftpd.conf # ProFTPD 主配置文件
└── proftpd.conf.sample # ProFTPD 配置示例文件22.3.4 创建用户
出于安全考虑,以非 root 用户身份运行 ProFTPD。添加新用户:
# adduser
Username: proftpd # 用户名
Full name: FTP User # 用户全名
Uid (Leave empty for default):
Login group [proftpd]:
Login group is proftpd. Invite proftpd into other groups? []:
Login class [default]:
Shell (sh csh tcsh bash nologin) [sh]: nologin # 不允许登录系统
Home directory [/home/proftpd]:
Home directory permissions (Leave empty for default):
Enable ZFS encryption? (yes/no) [no]:
Use password-based authentication? [yes]: no
Lock out the account after creation? [no]:
Username : proftpd
Password : <disabled>
Full Name : FTP User
Uid : 1002
ZFS dataset : zroot/home/proftpd
Class :
Groups : proftpd
Home : /home/proftpd
Home Mode :
Shell : /usr/sbin/nologin
Locked : no
adduser: INFO: Successfully created ZFS dataset (zroot/home/proftpd).
adduser: INFO: Successfully added (proftpd) to the user database.
Add another user? (yes/no) [no]:
Goodbye!22.3.5 MySQL 数据库相关
创建 MySQL 数据库和用户:
CREATE DATABASE `proftpd` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 创建 proftpd 数据库,使用 utf8mb4 字符集和通用校对规则创建数据库用户和密码:
CREATE USER 'proftpd'@'localhost' IDENTIFIED BY '123456'; -- 创建 MySQL 用户 proftpd,仅允许从本地主机连接
GRANT SELECT, INSERT, UPDATE, DELETE ON proftpd.* TO 'proftpd'@'localhost'; -- 授予 proftpd 用户对 proftpd 数据库的增删改查权限
FLUSH PRIVILEGES; -- 刷新权限,使配置立即生效创建数据表:
USE proftpd; -- 选择 proftpd 数据库
-- 创建 users 表
DROP TABLE IF EXISTS users;
CREATE TABLE `users` (
`username` VARCHAR(30) NOT NULL, -- 用户名
`descr` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, -- 用户描述
`password` VARCHAR(64) NOT NULL, -- 用户密码(SHA-256 加密)
`uid` INT(11) DEFAULT NULL, -- 用户 UID
`gid` INT(11) DEFAULT NULL, -- 用户 GID
`homedir` VARCHAR(255) DEFAULT NULL, -- 用户主目录
`shell` VARCHAR(255) DEFAULT NULL, -- 用户 Shell
`count` INT(11) NOT NULL DEFAULT 0, -- 登录次数统计
PRIMARY KEY (`username`) -- 主键为 username
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- 创建 worklog 表
DROP TABLE IF EXISTS worklog;
CREATE TABLE worklog (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, -- 日志 ID,自增主键
date TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP(0), -- 操作时间
user_name VARCHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, -- 用户名
file_and_path VARCHAR(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, -- 文件及路径
bytes BIGINT UNSIGNED DEFAULT NULL, -- 文件大小
send_time VARCHAR(9) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, -- 文件传输时间
client_ip VARCHAR(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, -- 客户端 IP
client_name TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, -- 客户端名称
client_command VARCHAR(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, -- 客户端命令
PRIMARY KEY (id),
UNIQUE INDEX id (id)
) ENGINE=InnoDB CHARACTER SET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;
-- 插入测试用户
INSERT INTO `proftpd`.`users` (`username`, `descr`, `password`, `uid`, `gid`, `homedir`, `shell`, `count`)
VALUES ('test', 'Test user', SHA2('FTPpassword_here', 256), '1002', '1002', '/home/www/ftp', NULL, '0'); -- 添加测试用户记录已创建以下内容:
- FTP 用户名
test - FTP 登录密码
FTPpassword_here - UID
1002 - GID
1002
警告
上面的 UID 和 GID 必须与 proftpd 用户相同,否则仅有读取权限而无写入权限。
可以通过以下方式获取用户 proftpd 的 UID、GID 及所属组信息:
sh# id proftpd uid=1002(proftpd) gid=1002(proftpd) groups=1002(proftpd)
测试数据库连接:
# mysql -u proftpd -p -h localhost proftpd # 使用 proftpd 用户连接本地主机上的 proftpd 数据库,系统提示输入密码
proftpd@localhost [proftpd]> show databases; -- 显示 MySQL 服务器上的所有数据库列表
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| proftpd |
+--------------------+
3 rows in set (0.00 sec)
proftpd@localhost [proftpd]> use proftpd; -- 选择 proftpd 数据库作为当前操作的数据库
Database changed
proftpd@localhost [proftpd]> select * from users; -- 查询 users 表中的所有记录
+----------+-----------+------------------------------------------------------------------+------+------+---------------+-------+-------+
| username | descr | password | uid | gid | homedir | shell | count |
+----------+-----------+------------------------------------------------------------------+------+------+---------------+-------+-------+
| test | Test user | d1d6930fda5f964acba51ec4c35d0ddb3b36d25bfef59f1120abd2e4f9f140d9 | 1002 | 1002 | /home/www/ftp | NULL | 0 |
+----------+-----------+------------------------------------------------------------------+------+------+---------------+-------+-------+
1 row in set (0.00 sec)创建目录和测试 FTP 用户:
# mkdir -p /home/www/ftp # 创建 FTP 用户的主目录及子目录
# chown -R proftpd:proftpd /home/www/ftp # 设置目录所有者和所属组为 proftpd
# chmod -R 775 /home/www/ftp # 设置目录权限为 775,允许同组用户读写22.3.6 服务操作
配置完成后,启动并管理 ProFTPD 服务:
# service proftpd enable # 设置 ProFTPD 服务开机启动
# service proftpd start # 启动 ProFTPD 服务
# service proftpd stop # 停止 ProFTPD 服务
# service proftpd restart # 重启 ProFTPD 服务以用户名 test、密码 FTPpassword_here 登录 FTP。