Apache mod_ftp 0.9.6 配置参数详解

系统梳理 Apache mod_ftp 0.9.6-beta 全部 26 个配置指令与 FTPOptions 14 个子选项,含默认值、生效验证与生产模板。

Apache mod_ftpmod_ftpApacheFTPWeb 服务器配置详解2026/10/15

Apache mod_ftp 0.9.6 配置参数详解

目标:逐项讲清 Apache mod_ftp 0.9.6-beta 的全部配置指令(含义、默认值、允许的上下文),并在 Ubuntu 22.04 + Apache 2.4.52 环境中对关键参数逐一实测验证,最后给出可直接落地的生产推荐模板。已在 Ubuntu 22.04 实测通过。

一、环境信息

项目内容
操作系统Ubuntu 22.04.5 LTS
系统架构x86_64
httpd 版本Apache/2.4.52(apt 发行包,MPM:event/prefork 均实测)
mod_ftp 版本0.9.6-beta(模块安装路径 /usr/lib/apache2/modules/mod_ftp.so)
源码目录/opt/httpd-ftp
指令清单来源/opt/httpd-ftp/modules/ftp/mod_ftp.c 中 ftp_cmds[] 指令注册表
配置文件/etc/apache2/conf-available/ftpd.conf
示例账号ftpuser / q1w2e3r4(htpasswd 文件认证)

再次强调:mod_ftp 0.9.6-beta 发布于 2009 年 10 月且至今仍是 beta、多年未发新版,本文所有默认值均从源码指令注册表与实测行为两方面核对,凡实测与官方文档不一致处均已注明。

二、配置体系与加载链

mod_ftp 作为 httpd 模块,配置完全融入 httpd 配置体系。Ubuntu apache2 的加载链为:

/etc/apache2/apache2.conf
 ├─ IncludeOptional mods-enabled/*.load      ← ftp.load: LoadModule ftp_module /usr/lib/apache2/modules/mod_ftp.so
 ├─ IncludeOptional mods-enabled/*.conf
 ├─ IncludeOptional conf-enabled/*.conf      ← ftpd.conf: FTP 站点与指令
 └─ IncludeOptional sites-enabled/*.conf

解说:mod_ftp 的模块注册放 mods-enabled(a2enmod ftp 生成),站点指令放 conf-enabled(a2enconf ftpd 生成)。指令分为两类上下文:多数 FTP 指令为 server config / virtual host 级(源码标注 RSRC_CONF),FTPUmask/FTPDirUmask 可用于 Directory 与 .htaccess(OR_FILEINFO),FTPReadmeMessage 任意位置(OR_ALL)。

启动后从错误日志可直接确认模块版本:

[Wed Oct 14 17:47:36.347380 2026] [mpm_prefork:notice] [pid 7455] AH00163: Apache/2.4.52 (Ubuntu) mod_ftp/0.9.6 configured -- resuming normal operations

三、端口监听与协议启用

这三个指令是 FTP 服务能“接通”的前提,放在站点配置最顶部:

Listen 21 ftp
AcceptFilter ftp none
<VirtualHost _default_:21>
    FTP On
</VirtualHost>
指令说明
Listen 21 ftp监听 21 端口并标记为 ftp 协议;协议标记决定该端口连接走 FTP 处理链
AcceptFilter ftp none关闭该协议的内核 accept 过滤;FTP 由服务器先发 220 横幅,不过滤才能正常握手
FTP On在当前虚拟主机启用 FTP 服务(默认 Off),是 mod_ftp 的总开关

逐项解说:Listen 的第二个参数是协议名,mod_ftp 注册了 "ftp" 协议名;若写成 Listen 21 不带协议名,端口虽开但按 HTTP 处理,客户端会收到 HTTP 响应。AcceptFilter 取 none 是官方示例配置的原样写法。FTP 只能在虚拟主机/服务器级配置,不能放进 Directory。

四、指令详解

以下 26 个指令来自源码 ftp_cmds[] 注册表,按功能分组。所有“实测”一栏均在本文环境验证。

4.1 横幅与消息类

指令取值默认说明
FTPBannerMessage字符串系统默认横幅登录后 220 横幅,支持 %-变量
FTPExitMessage字符串无QUIT 时 221 附加消息
FTPReadmeMessage字符串无按目录设置的 README 提示消息
FTPDocRootEnv环境变量名无依据环境变量(如 LDAP 属性)动态设定 DocumentRoot
FTPHomeDir路径无用户主目录所在父目录,配合 FTPJailUser 使用
FTPJailUserOn/OffOff禁止用户离开其主目录

实测:本文配置 FTPBannerMessage "Welcome to Apache mod_ftp (Ubuntu 22.04)" 后,netcat 登录横幅第一行为:

220-Welcome to Apache mod_ftp (Ubuntu 22.04)
220 node1.modftp.example FTP Server (Apache/2.4.52 (Ubuntu)) ready.

解说:横幅支持 %T 时间、%a 客户端 IP、%u 用户名等变量(与 FTP 日志变量同源,源码 ftp_message.c 的 ftp_message_generate())。多行消息用 220- 前缀逐行发出,最后一行 220 结束。

4.2 超时与登录限制类

指令取值默认说明
FTPTimeoutLogin秒120发出 USER 前允许的等待时间
FTPTimeoutIdle秒600两条命令间最大空闲时间,超时断开
FTPTimeoutData秒300数据连接建立/传输超时
FTPMaxLoginAttempts次数3密码错误最大尝试次数,超限断开
FTPLimitLoginUser数字无单用户并发登录上限
FTPLimitLoginIP数字无单 IP 并发登录上限
FTPLimitLoginServer数字无服务器总并发登录上限
FTPLimitDBFile路径无并发限制计数 DBM 文件位置
FTPDataBlockSize字节数32768数据传输块大小

实测:本文按官方推荐设置 FTPTimeoutLogin 120 / FTPTimeoutIdle 600 / FTPTimeoutData 300 / FTPMaxLoginAttempts 3,正常登录与传输不受影响。FTPLimitLogin* 三件套需同时配置 FTPLimitDBFile 才持久生效,DBM 文件目录需对 www-data 可写;未配置时指令不生效(源码在无 DB 文件时直接返回成功)。

4.3 数据连接类(主动/被动模式核心)

💡 技术拓展:再次对照两种数据通道。主动模式(PORT/EPRT):客户端把自己的地址端口通过 PORT 告诉服务器,服务器发起数据连接——服务端出站端口可由 FTPActiveRange 限定;被动模式(PASV/EPSV):服务器开数据端口等客户端来连——监听范围由 FTPPASVrange 限定。防火墙友好度上被动模式占优,是当前主流;mod_ftp 两种模式同时支持,实测均通过。本文配置以被动模式为主、FTPActiveRange 作为主动模式加固。

指令取值默认说明
FTPPASVrange最小端口 最大端口随机高端口被动模式数据端口监听范围
FTPPASVaddrIP自动探测响应 PASV 时通告的地址(多 IP/NAT 场景)
FTPPASVbindaddrIP全部地址被动数据端口实际绑定的地址
FTPActiveRange最小 [最大]随机主动模式服务器出站端口范围
FTPEPSVIgnoreFamilyOn/OffOffEPSV 忽略客户端地址族(NAT/翻译环境)
FTPLowPortSock套接字名无低端口号数据连接辅助守护进程的套接字

实测一:配置 FTPPASVrange 50000 50100 后用原始会话验证 PASV 响应端口:

printf 'USER ftpuser\r\nPASS q1w2e3r4\r\nPASV\r\nQUIT\r\n' | nc 127.0.0.1 21

回显(输出节选):

230 User ftpuser logged in
227 Entering Passive Mode (127,0,0,1,195,80)

解说:227 响应按 h1,h2,h3,h4,p1,p2 编码端口,实际端口 = p1×256 + p2 = 195×256 + 80 = 50000,正好落在配置区间下界,指令生效。

实测二:FTPLowPortSock 启动时会在错误日志打印守护进程就绪信息:

[Wed Oct 14 17:47:36.345010 2026] [:notice] [pid 7456] FTP low numbered port daemon waiting for port requests

解说:mod_ftp 通过一个独立的低端口辅助进程(源码 ftp_lowportd.c)以 root 权限创建 20 端口等低端口数据连接套接字,worker 进程按需取用;这是 Apache 以非 root 运行时仍能做主动模式 20 端口连接的机制。

4.4 文件属性类

指令取值默认说明
FTPUmask八进制0022新建文件的权限掩码
FTPDirUmask八进制0022新建目录的权限掩码

实测:FTPUmask 022 下上传的文件权限为 644(rw-r--r--),与 7.1 节 lftp 列表中 -rw-r--r-- 一致。这两个指令可用于 Directory 块,实现不同目录不同掩码。

4.5 FTPImplicitSSL 与 FTPOptions

FTPImplicitSSL(On/Off,默认 Off):启用隐式 FTPS——控制连接建立即进入 TLS 握手(经典 990 端口风格)。FEAT 能力表中出现的 AUTH TLS 属于显式 FTPS(客户端发 AUTH TLS 命令升级连接),两者不同:显式方式由 mod_ssl 提供、客户端主动升级;隐式方式由本指令声明。启用前需先为虚拟主机配置 mod_ssl(SSLEngine on 与证书),官方示例配置中给出了完整写法。

FTPOptions(RAW_ARGS,可写多个子选项)是 mod_ftp 的行为开关集,源码 mod_ftp.c 的 ftp_options() 定义了 14 个子选项,逐项说明如下表:

子选项默认说明
RequireSSL关要求客户端在 USER/PASS 前完成 AUTH TLS
CheckMaxClients关按 httpd 并发能力检查服务器是否已满
RemoveUserGroup关列表中隐藏真实 user/group 归属
NLSTShowDirs关NLST 输出中包含目录
NLSTIsLIST关把 NLST 直接映射为 LIST(含权限列)
LISTIsNLST关把 LIST 直接映射为 NLST(仅文件名)
CreateHomeDirs关登录时主目录不存在则自动创建(需配 FTPHomeDir)
ShowUnAuthorizedFiles关LIST 中显示无权限文件(默认隐藏)
AllowProxyPORT关允许主动模式数据连接来自非客户端 IP
AllowProxyPASV关允许被动模式数据连接来自非客户端 IP
VirtualHostByUser关按 user@hostname 解析虚拟主机
StripHostname关从 user@hostname 中剥离主机名部分
NoUTF8Feature关从 FEAT 能力表隐藏 UTF8

实测:本文实测 FTPOptions NoUTF8Feature,重启后 FEAT 能力表仍显示 UTF8(回显如下)——该子选项在 0.9.6-beta 对 httpd 2.4.52 下未生效,疑为模块缺陷,仅作现象记录,不影响传输正确性:

211-Extensions supported
 EPSV
 TVFS
 UTF8
 MDTM
 EPRT
 SIZE
 PBSZ
 PROT
 AUTH TLS
 REST STREAM
211 End

解说:AllowProxyPASV/AllowProxyPORT 默认关闭是安全设计——被动数据连接只接受与控制连接相同来源 IP 的客户端(源码 ftp_data_connection.c 校验),防止他人抢占数据端口(FTP Bounce 攻击面之一)。公网部署建议保持默认关闭。

五、认证与访问控制

mod_ftp 登录认证挂在 DocumentRoot 对应的 Directory 块上(登录动作等价于对根目录做一次权限检查)。本文实测配置:

<Directory "/srv/ftpdocs">
    AuthType Basic
    AuthName "FTP Authentication"
    AuthUserFile "/etc/apache2/ftpd.passwd"
    require valid-user
</Directory>

逐项解说:AuthType Basic 指定 HTTP Basic 机制(FTP 的 USER/PASS 被映射为 Basic 凭据);AuthUserFile 指向 htpasswd 生成的口令文件;require valid-user 表示任一文件内用户均可登录。生成口令文件的命令与回显:

htpasswd -cb /etc/apache2/ftpd.passwd ftpuser q1w2e3r4
Adding password for user ftpuser

需要控制“谁能写”时,用 httpd 的 Limit 指令包裹写命令。官方示例的思路(限定仅 incoming 可写):

<Directory "/srv/ftpdocs">
    <Limit MKD RMD STOR DELE RNFR>
        Order deny,allow
        Deny from all
    </Limit>
</Directory>
<Directory "/srv/ftpdocs/incoming">
    <LimitExcept MKD RMD STOR DELE RNFR>
        Allow from all
    </LimitExcept>
</Directory>

解说:mod_ftp 把 STOR(上传)、DELE(删除)、MKD/RMD(建/删目录)、RNFR/RNTO(改名)等 FTP 命令映射为可被 Limit 管控的方法名,因此 httpd 的授权语法可直接约束 FTP 行为。匿名访问可改用 AuthBasicProvider anon 加 mod_authn_anon(若发行包提供),本文以文件认证为准。

六、日志参数详解

mod_ftp 定义了两类专用日志:命令日志(记录每条 FTP 命令)与传输日志(记录每次文件传输)。

LogFormat    "%u [%a] %r" command_log_fmt
LogFormat    "%{%b %e %H:%M:%S %Y}t %T %a %B %U %M %F %d %W %u %S %Z %Y" transfer_log_fmt
CustomLog /var/log/apache2/ftp_command.log command_log_fmt
CustomLog /var/log/apache2/ftp_transfer.log transfer_log_fmt

命令日志实测内容:

ftpuser [127.0.0.1] TYPE A
ftpuser [127.0.0.1] LIST
ftpuser [127.0.0.1] QUIT

传输日志实测内容(13 列):

Oct 14 17:02:24 2026 0 127.0.0.1 0 / a _ - r ftpuser ftp 0 *

传输日志字段逐列解说:

列内容实测值含义
1%t 自定义时间Oct 14 17:02:24 2026传输时间
2%T0传输耗时(秒)
3%a127.0.0.1客户端地址
4%B0字节数
5%U/文件名
6%Ma类型:a=ASCII b=BINARY
7%F_压缩标记:C/U/T/_
8%d-方向:o=下载 i=上传
9%Wr访问类别:r=真实用户 a=匿名 g=来宾
10%uftpuser用户名
11%Sftp服务名
12%Z0认证方式位掩码
13%Y*认证用户 ID

注意:LogFormat 别名必须先定义再被 CustomLog 引用,若漏定义,日志文件会写入字面量 command_log_fmt(实测踩坑)。两条日志可用 SetEnvIf 条件开关(示例配置中提供了按匿名用户记录命令日志的模板)。

七、生产推荐模板

# /etc/apache2/conf-available/ftpd.conf —— 生产推荐模板
LogFormat    "%u [%a] %r" command_log_fmt
LogFormat    "%{%b %e %H:%M:%S %Y}t %T %a %B %U %M %F %d %W %u %S %Z %Y" transfer_log_fmt

Listen 21 ftp
AcceptFilter ftp none

<VirtualHost _default_:21>
    ServerAdmin  admin@example.com
    DocumentRoot "/srv/ftpdocs"
    FTP On

    # 横幅避免泄露版本细节
    FTPBannerMessage "FTP service ready"
    # 会话与传输超时
    FTPTimeoutLogin  60
    FTPTimeoutIdle   300
    FTPTimeoutData   300
    FTPMaxLoginAttempts 3
    # 文件/目录权限掩码
    FTPUmask         027
    FTPDirUmask      027
    # 被动端口区间(同步放行防火墙)
    FTPPASVrange     50000 50100

    <Directory "/srv/ftpdocs">
        AuthType Basic
        AuthName "FTP Authentication"
        AuthUserFile "/etc/apache2/ftpd.passwd"
        require valid-user
    </Directory>

    ErrorLog  /var/log/apache2/ftp_error.log
    CustomLog /var/log/apache2/ftp_command.log command_log_fmt
    CustomLog /var/log/apache2/ftp_transfer.log transfer_log_fmt
</VirtualHost>

模板要点逐项说明:横幅去版本信息;登录超时收紧到 60 秒;掩码 027 使文件 640/目录 750,组内可协作、其他不可读;PASV 端口 100 个,匹配中等并发;如需 SSL,追加 SSLEngine、证书三件与 FTPOptions RequireSSL。模板中示例账号 ftpuser/q1w2e3r4 仅用于演示,生产请通过 htpasswd 生成独立口令。

八、常见问题(FAQ)

Q1:FTPPASVaddr 什么时候必须配? A:当服务器在 NAT/负载均衡之后、对外地址与网卡地址不一致时。PASV 响应默认通告连接进入的本机地址,客户端在公网会拿到内网地址导致数据连接失败。把对外 IP 写进 FTPPASVaddr 即可,本文内网实测无需配置。

Q2:FTPTimeoutIdle 设多大合适? A:默认 600 秒平衡了体验与资源占用。若客户端使用图形工具长时间挂机,可放宽到 1800;面向公网建议收紧到 300 以减少空置连接。超时断开后客户端报 "connection closed by remote host"。

Q3:FTPLimitLoginUser/IP/Server 配了却不生效? A:三个限制指令依赖 FTPLimitDBFile 指定的 DBM 计数文件。未配置 DB 文件时限制不生效;配置后还需保证目录对 www-data 可写,并确认加载了 mod_dbm 依赖(Ubuntu 默认已含)。

Q4:FTPOptions 可以写多个子选项吗?分隔符是什么? A:可以,FTPOptions 是 RAW_ARGS 指令,空格分隔即可,例如 FTPOptions RemoveUserGroup NLSTShowDirs。全部 14 个子选项见 4.5 节表格。

Q5:为什么我的 FEAT 里没有 AUTH TLS? A:AUTH TLS/PBSZ/PROT 出现在 FEAT 的前提是虚拟主机启用了 mod_ssl。只设 FTPImplicitSSL 而不装证书,客户端发起 TLS 升级仍会失败。本文实测 FEAT 显示 AUTH TLS 是因为虚拟主机具备 SSL 能力的模块注册,但未配证书时不应生产启用。

Q6:FTPJailUser 要配 FTPHomeDir 吗? A:是。FTPJailUser Off 时用户以 DocumentRoot 为根;On 时用户进入 FTPHomeDir/用户名 作为家目录并被禁越界。两者必须成对出现,且目录需预先存在或配合 FTPOptions CreateHomeDirs 自动创建。

Q7:FTPUmask 与系统 umask 的关系? A:FTPUmask 只作用于 FTP 新建文件/目录(配合 mod_ftp 的写入路径),不影响 httpd 其他行为。实测 022 上传文件为 644;改为 027 则为 640。指令允许 Directory 级覆写,可对 incoming 目录用更宽松掩码。

Q8:NoUTF8Feature 配置后 FEAT 仍显示 UTF8,是指令无效吗? A:实测确实如此(见 4.5 节回显),0.9.6-beta 在 httpd 2.4.52 上该子选项未生效,属上游缺陷。UTF8 能力仅是声明,传输内容仍按字节流处理,一般无需处理;如必须隐藏需改源码重编。

Q9:能在一台 httpd 上跑多个 FTP 站点吗? A:可以。FTP 端口绑定在 VirtualHost 上,配多个不同端口的虚拟主机(21、2121...)各挂 DocumentRoot 与认证即可;同端口区分用户再分站可尝试 FTPOptions VirtualHostByUser + StripHostname(按 user@host 解析),本文未实测该组合,建议先在测试环境验证。

Q10:指令写错位置为何 configtest 直接报错? A:mod_ftp 指令有上下文限制(多数 RSRC_CONF)。放进 Directory 会得到 "FTP not allowed here" 类错误。速查上下文见第四章各表;FTPUmask/FTPDirUmask/FTPReadmeMessage 是仅有的三个可进 Directory/.htaccess 的 FTP 指令。

九、参考链接