SPF Toolbox v2.2.0 配置参数详解
SPF Toolbox v2.2.0 无配置文件,配置分散在 HTTP 查询参数、源码常量与 PHP 运行时三层:本文逐项给出默认值、修改方法与实测验证闭环,含 50 个 DNSBL 区域清单、端口/超时、DMARC 前缀、dnsmasq 离线复现与缓存行为实证。
SPF Toolbox v2.2.0 配置参数详解
目标:讲清 SPF Toolbox v2.2.0 的全部可配置项——应用无独立配置文件,配置分散在 HTTP 查询参数、源码常量与 PHP 运行时三层,本文逐层给出参数含义、默认值、修改方法与实测验证闭环,并覆盖缓存行为与超时项的实测结论。
一、环境信息
本文所有修改与验证均在以下真实服务器环境实测:
- 操作系统:Ubuntu 22.04.5 LTS
- Web 服务器:Apache 2.4.52(mod_php 形态,
apache2systemd 服务托管) - PHP:8.1.2(
/etc/php/8.1/apache2/php.ini为 Web 运行时配置) - 应用版本:SPF Toolbox v2.2.0,部署于
/var/www/html/spftoolbox,属主www-data - 验证方式:每项配置修改后经
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=…&request=…'调用查询端点核对结果变化 - 辅助环境:本地
dnsmasq(自建 DNS 区域,用于验证解析器参数与离线复现)
部署过程见本专栏部署篇:《Ubuntu 22.04 安装 SPF Toolbox v2.2.0 指南》。
二、前置条件
- 已按部署篇完成 v2.2.0 安装并可通过
http://<服务器IP>/spftoolbox/正常访问; - 修改源码常量前先备份原文件(本文示例统一备份到
/tmp); - 修改 PHP 配置后需
systemctl restart apache2才生效(mod_php 不热加载 php.ini); - 修改
Blacklist.php/Port.php/Dmarc.php等源码文件后无需重启 Apache(PHP 每次请求重新编译),curl复测即生效。
三、参数查看与修改方式
关键认知:SPF Toolbox 没有配置文件。 v2.2.0 的全部可配置项分布在三个层面:
| 配置层 | 位置 | 修改后生效方式 | 适合调什么 |
|---|---|---|---|
| ① HTTP 查询参数 | URL:operations/?domain=…&request=…&port=… | 立即(每次请求独立解析) | 查询目标、查询类型、端口 |
| ② 源码常量 | operations/Blacklist.php、operations/Port.php、operations/Dmarc.php | 立即(PHP 每请求重编译,无需重启) | 黑名单区域清单、默认端口数组、连接超时、DMARC 前缀 |
| ③ PHP 运行时 | /etc/php/8.1/apache2/php.ini + /etc/resolv.conf | systemctl restart apache2(resolv.conf 立即) | 错误显示/日志、执行时限、内存、Socket 超时、DNS 上游 |
查看当前生效值的命令:
# ② 层常量值(Blacklist 区域数量)
php -r 'require "/var/www/html/spftoolbox/operations/OperationInterface.php"; require "/var/www/html/spftoolbox/operations/Blacklist.php"; echo count(Blacklist::LOOKUP_HOSTS), PHP_EOL;'
实测回显:
50
# ③ 层 PHP 运行时关键项
grep -E "^(max_execution_time|memory_limit|default_socket_timeout|display_errors|log_errors|error_reporting) " /etc/php/8.1/apache2/php.ini
实测回显:
max_execution_time = 30
memory_limit = 128M
display_errors = Off
log_errors = On
default_socket_timeout = 60
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
四、参数总览
| 参数 | 层 | 位置 | 默认值 | 作用 | 调整建议 |
|---|---|---|---|---|---|
domain | ① | URL | 必填 | 查询目标域名/IP | 传空返回空响应 |
request | ① | URL | 必填 | 查询类型,11 取值 | 传非法值返回明确错误 |
port | ① | URL | 仅 port 查询用 | 指定端口 | 空=按默认端口数组探测 |
LOOKUP_HOSTS | ② | Blacklist.php | 50 个 DNSBL 区域 | 黑名单反查清单 | 按需增删区域 |
| 默认端口数组 | ② | Port.php | [25, 53, 80, 443, 465, 587, 993] | port 查询缺省探测集 | 加自有服务端口 |
| 连接超时 | ② | Port.php | 5 秒 | fsockopen 超时 | 慢链路可放宽 |
| DMARC 前缀 | ② | Dmarc.php | "_dmarc." | DMARC 记录子域前缀 | 一般不动 |
display_errors | ③ | php.ini | Off | 错误是否进输出 | 必须保持 Off |
log_errors | ③ | php.ini | On | 错误是否进日志 | 保持 On |
max_execution_time | ③ | php.ini | 30 | 脚本 CPU 时间上限 | 一般不动(见 5.7) |
default_socket_timeout | ③ | php.ini | 60 | 未显式传超时的 Socket 默认超时 | 一般不动 |
memory_limit | ③ | php.ini | 128M | 内存上限 | 一般不动 |
| DNS 上游 | ③ | /etc/resolv.conf | 系统默认 | 所有 DNS 查询的代发出口 | 内网复现/隔离时调整 |
五、核心参数分类详解
5.1 查询入口 HTTP 参数(domain / request / port)
后端唯一入口是 operations/index.php,接收三个 GET 参数。request 的 11 个合法取值与功能对应关系如下(与界面下拉框一致):
| request 值 | 查询功能 | domain 传什么 |
|---|---|---|
a / aaaa | IPv4 / IPv6 地址 | 域名 |
mx | MX 收信服务器 | 域名 |
txt | TXT 记录(含 SPF;DKIM 用选择器子域变通) | 域名或 选择器._domainkey.域名 |
dmarc | DMARC 策略(自动拼 _dmarc.) | 裸域名 |
blacklist | 50 个 DNSBL 聚合反查 | 域名(先解析出 IP) |
whois | 注册信息(内置 phpwhois) | 域名 |
port | TCP 端口探测 | 域名或 IP,配 port 参数 |
hinfo | HINFO 记录 | 域名 |
all | 全部记录(DNS_ALL 优先回退 DNS_ANY) | 域名 |
reverseLookup | 反向解析(PTR) | IP |
三个参数的边界行为实测:
# 空 domain:整个 if 分支不成立,无任何输出
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=&request=mx'
实测回显(空响应):
# 非法 request:返回明确的错误 JSON
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=bogus'
实测回显:
[{"error": "Please check a valid DNS type"}]
# 不存在的域名:dns_get_record 返回空,序列化为 []
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=no-such-xyz-9x.com&request=mx'
实测回显:
[]
DKIM 变通验证:应用没有 DKIM 专用入口,把 选择器._domainkey.域名 整串当作 domain 走 txt 查询即可。实测 ebay 域名的 dkim 选择器:
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=dkim._domainkey.ebay.com&request=txt' | head -20
实测回显(完整 JSON):
[
{
"host": "dkim._domainkey.ebay.com",
"class": "IN",
"ttl": 3600,
"type": "TXT",
"txt": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLM0fpK\/rhklYDRJSBQ6bSyZKjQxTeEnZywzodwGAjAste2aOQzXJyZmZrjHZ0JL6Gy\/e351n1P0Yo0cVE4nEQ7WD9jo0cqVEmkf1SInnhN1FGX\/pOTjrjh7QU398YFxks\/rqnX6C1qdoeu7B4wwRhNEHUjlaH79afYqOtk0ta0wIDAQAB; n=1024;",
"entries": [
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLM0fpK\/rhklYDRJSBQ6bSyZKjQxTeEnZywzodwGAjAste2aOQzXJyZmZrjHZ0JL6Gy\/e351n1P0Yo0cVE4nEQ7WD9jo0cqVEmkf1SInnhN1FGX\/pOTjrjh7QU398YFxks\/rqnX6C1qdoeu7B4wwRhNEHUjlaH79afYqOtk0ta0wIDAQAB; n=1024;"
]
}
]
选择器名称从发件方文档或邮件原始头(DKIM-Signature: ... s=<选择器> 字段)获取;选择器猜错时返回 []。
5.2 黑名单区域清单(Blacklist.php LOOKUP_HOSTS)
operations/Blacklist.php 的 LOOKUP_HOSTS 类常量定义黑名单反查区域清单,默认 50 个。查询逻辑:先把域名解析为 IP,反转后逐区域拼接反查(如 83.99.250.142.dnsrbl.org),checkdnsrr 有 A 记录即判 FAIL,无记录判 OK。
完整默认清单(50 项,php -r 反射导出,按源码顺序):
babl.rbl.webiron.net cabl.rbl.webiron.net stabl.rbl.webiron.net
all.rbl.webiron.net crawler.rbl.webiron.net truncate.gbudb.net
dnsbl.sorbs.net safe.dnsbl.sorbs.net http.dnsbl.sorbs.net
socks.dnsbl.sorbs.net misc.dnsbl.sorbs.net smtp.dnsbl.sorbs.net
web.dnsbl.sorbs.net new.spam.dnsbl.sorbs.net recent.spam.dnsbl.sorbs.net
old.spam.dnsbl.sorbs.net spam.dnsbl.sorbs.net escalations.dnsbl.sorbs.net
block.dnsbl.sorbs.net zombie.dnsbl.sorbs.net dul.dnsbl.sorbs.net
noservers.dnsbl.sorbs.net rhsbl.sorbs.net badconf.rhsbl.sorbs.net
nomail.rhsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org
pbl.spamhaus.org sbl-xbl.spamhaus.org zen.spamhaus.org
rbl.orbitrbl.com dnsrbl.org db.wpbl.info
bad.psky.me bl.spamcop.net noptr.spamrats.com
dyna.spamrats.com spam.spamrats.com auth.spamrats.com
spamtrap.drbl.drand.net hostkarma.junkemailfilter.com blacklist.hostkarma.com
ix.dnsbl.manitu.net dnsbl.inps.de bl.blocklist.de
srnblack.surgate.net all.s5h.net rbl.realtimeblacklist.com
b.barracudacentral.org virbl.dnsbl.bit.nl
其中 webiron 系 5 个、sorbs 系 16 个、spamhaus 系 5 个、spamrats 系 4 个为主力分组;zen.spamhaus.org 与 b.barracudacentral.org 是最常引用的两个综合区域。
增删闭环实测(改完即生效,无需重启):
# 1) 删除 virbl.dnsbl.bit.nl 区域
cd /var/www/html/spftoolbox/operations
cp Blacklist.php /tmp/Blacklist.php.bak
sed -i 's/"virbl.dnsbl.bit.nl"//' Blacklist.php
time curl -s -m 120 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=blacklist' | tail -c 230
实测回显(输出尾部,virbl 条目已消失,最后一项变为 barracuda):
.com": "OK","ix.dnsbl.manitu.net": "OK","dnsbl.inps.de": "OK","bl.blocklist.de": "OK","srnblack.surgate.net": "OK","all.s5h.net": "OK","rbl.realtimeblacklist.com": "OK","b.barracudacentral.org": "OK","end of list": "end of list"}]
real 1m8.764s
user 0m0.005s
sys 0m0.001s
# 2) 还原后新增自定义区域 testbl.lab.internal 到清单头
cp /tmp/Blacklist.php.bak Blacklist.php
sed -i 's/const LOOKUP_HOSTS = \[/const LOOKUP_HOSTS = [\n "testbl.lab.internal",/' Blacklist.php
curl -s -m 120 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=blacklist' | head -c 140
实测回显(输出头部,新区域排第一;不存在的区域反查无记录判 OK):
[{"testbl.lab.internal": "OK","babl.rbl.webiron.net": "OK","cabl.rbl.webiron.net": "OK","stabl.rbl.webiron.net": "OK","all.rbl.webiron.net":
# 3) 恢复原文件
cp /tmp/Blacklist.php.bak Blacklist.php
php -r 'require "/var/www/html/spftoolbox/operations/OperationInterface.php"; require "/var/www/html/spftoolbox/operations/Blacklist.php"; echo count(Blacklist::LOOKUP_HOSTS), PHP_EOL;'
实测回显:
50
FAIL 结果解读警示:判定逻辑不校验返回值是否为 127.0.0.x 网段。实测 gmail.com 解析出的 Google IP(142.250.99.83)在 dnsrbl.org 上反查有 A 记录而判 FAIL(其余 49 个区域全部 OK):
dig +short 83.99.250.142.dnsrbl.org
实测回显:
103.224.182.253
该返回值并非 127 网段命中编码,说明此区域把大量非垃圾 IP 也列出(对 Google 段如此),因此看到 FAIL 必须人工复核:确认反查返回值是否符合该 DNSBL 的编码规范,再决定处置。调整 5.2 清单时,可把这类误报率高的区域直接删掉。
5.3 端口探测参数(Port.php 端口数组与超时)
operations/Port.php 两个默认值:端口数组 private $ports = [25, 53, 80, 443, 465, 587, 993];、连接超时 fsockopen($hostname, $port[$i], $errno, $errstr, 5) 的 5 秒。不传 port 参数时按数组逐个探测:
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=127.0.0.1&request=port&port='
实测回显(7 个默认端口,本机 80 开放):
[{
"25": "Is closed",
"53": "Is closed",
"80": "Is open",
"443": "Is closed",
"465": "Is closed",
"587": "Is closed",
"993": "Is closed"
}]
修改闭环 1——默认端口数组(新增 8080):
cd /var/www/html/spftoolbox/operations
cp Port.php /tmp/Port.php.bak
sed -i 's/private \$ports = \[25, 53, 80 , 443, 465, 587, 993\];/private \$ports = [25, 53, 80 , 443, 465, 587, 993, 8080];/' Port.php
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=127.0.0.1&request=port&port='
实测回显(8 个端口生效):
[{
"25": "Is closed",
"53": "Is closed",
"80": "Is open",
"443": "Is closed",
"465": "Is closed",
"587": "Is closed",
"993": "Is closed",
"8080": "Is closed"
}]
修改闭环 2——连接超时 5s → 2s(对被出站防火墙拦截的公网地址,响应时长随超时值同步变化):
sed -i 's/fsockopen($hostname, $port[$i], $errno, $errstr, 5)/fsockopen($hostname, $port[$i], $errno, $errstr, 2)/' Port.php
time curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=port&port=443'
实测回显(超时 2 秒生效):
[{"443": "Is closed"}]
real 0m2.044s
user 0m0.013s
sys 0m0.000s
# 还原 5 秒超时后同条件复测
cp /tmp/Port.php.bak Port.php
time curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=port&port=443'
实测回显(恢复 5 秒):
[{"443": "Is closed"}]
real 0m5.030s
user 0m0.018s
sys 0m0.000s
结论:超时参数直接线性反映到响应时长(2.044s vs 5.030s),单地址单端口探测时长≈超时值。对被拦截环境调小超时可显著加快 port 查询返回。
5.4 DMARC 查询前缀(Dmarc.php _dmarc.)
operations/Dmarc.php 把 _dmarc. 前缀硬编码为变量 $dmarc = "_dmarc.";,用户只传裸域名。RFC 7489 规定 DMARC 记录固定在 _dmarc.<域名> 子域,因此该前缀一般不应修改;但组织若使用组织域 DMARC 分发(子域继承 _dmarc.example.com),可临时改前缀排查子域记录发布情况。
修改闭环实测(改为 _dmarctest.,验证查询目标随之改变):
cd /var/www/html/spftoolbox/operations
cp Dmarc.php /tmp/Dmarc.php.bak
php -r '$s=file_get_contents("Dmarc.php"); $s=str_replace("_dmarc.","_dmarctest.",$s); file_put_contents("Dmarc.php",$s);'
grep -n "_dmarctest" Dmarc.php
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=dmarc'
实测回显(查询目标变为 _dmarctest.gmail.com,该子域无记录返回 []):
12:$dmarc = "_dmarctest.";
[]
# 还原后复测,恢复真实 DMARC 记录
cp /tmp/Dmarc.php.bak Dmarc.php
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=dmarc' | head -5
实测回显:
[
{
"host": "_dmarc.gmail.com",
5.5 PHP 运行时参数(php.ini)
Web 侧生效文件是 /etc/php/8.1/apache2/php.ini(注意不是 cli/php.ini,两套互相独立),改完必须 systemctl restart apache2。
display_errors / log_errors(最关键两项):display_errors = Off 保证 JSON 输出纯净——一旦开启,任何 PHP 告警文本都会混进 JSON 导致前端 response.json() 解析失败。实测验证:把 display_errors 改为 On 并重启后,对不存在域名的 MX 查询仍返回纯 []、whois 查询输出依旧无告警前缀(v2.2.0 的 11 类查询路径在 PHP 8.1 下未触发输出级告警);但该防线必须保持,防止未来 PHP 升级引入弃用告警时污染输出。告警细节由 log_errors = On 落到 /var/log/apache2/error.log 排查:
tail -5 /var/log/apache2/error.log
实测回显(权限类故障示例,8.1 节场景):
[Mon Oct 26 05:09:28.376387 2026] [core:error] [pid 10066] (13)Permission denied: [client 127.0.0.1:43722] AH00035: access to /spftoolbox/index.htm denied (filesystem path '/var/www/html/spftoolbox/index.htm') because search permissions are missing on a component of the path
[Mon Oct 26 05:09:28.380530 2026] [core:error] [pid 10062] (13)Permission denied: [client 127.0.0.1:43728] AH00035: access to /spftoolbox/operations/ denied (filesystem path '/var/www/html/spftoolbox/operations') because search permissions are missing on a component of the path
max_execution_time = 30 的一个反直觉现象:黑名单查询对 50 个区域逐个 checkdnsrr,部分区域无响应时总耗时实测约 88 秒,远超 30 秒上限却未被打断——Linux 上该限值只累计 CPU 时间,DNS 等待(I/O 阻塞)不计入。因此调大它并不能解决黑名单慢,真正的缓解手段是删掉无响应的 DNSBL 区域(5.2)或降低各环节超时。
default_socket_timeout = 60:仅对未显式传超时的 socket 生效;Port 查询的 fsockopen 有自己的 5 秒超时(5.3),whois 的 phpwhois 走 fsockopen 自带超时,所以该项对 SPF Toolbox 常规查询几乎无影响,保持默认即可。
memory_limit = 128M:11 类查询均为小结果集,实测从未接近上限,保持默认。
5.6 DNS 解析器与本地记录复现(/etc/resolv.conf + dnsmasq)
应用自身不指定 DNS 服务器,dns_get_record/checkdnsrr 全部走系统解析器 /etc/resolv.conf。这意味着:换上游解析器 = 全局改变所有查询的数据源,也是内网/无外网环境复现查询能力的开关。
实测在服务器本地用 dnsmasq 建一个模拟区域,验证 SPF Toolbox 从本地 DNS 拿到自造记录(可离线复现):
# 1) 建 dnsmasq 本地区域(A/MX/TXT/DMARC 四类记录)
cat > /etc/dnsmasq.d/lab.conf <<'EOF'
listen-address=127.0.0.2
bind-interfaces
port=53
server=127.0.0.11
host-record=lab.example,10.10.10.10
mx-host=lab.example,mail.lab.example,10
txt-record=lab.example,"v=spf1 ip4:10.10.10.0/24 -all"
txt-record=_dmarc.lab.example,"v=DMARC1; p=reject; rua=mailto:dmarc@lab.example"
EOF
systemctl enable --now dnsmasq
systemctl is-active dnsmasq
# 2) 把系统解析器指向本地 dnsmasq
printf 'nameserver 127.0.0.2\nsearch .\noptions edns0 trust-ad ndots:0\n' > /etc/resolv.conf
# 3) 先用 dig 确认解析器侧记录就绪
dig +short lab.example MX
dig +short lab.example TXT
实测回显:
active
10 mail.lab.example
"v=spf1 ip4:10.10.10.0/24 -all"
# 4) SPF Toolbox 全链路实测本地记录
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=lab.example&request=mx'
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=lab.example&request=txt'
curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=lab.example&request=dmarc'
实测回显(MX 与 DMARC,TXT 同理返回自造 SPF 记录):
[
{
"host": "lab.example",
"class": "IN",
"ttl": 0,
"type": "MX",
"pri": 10,
"target": "mail.lab.example"
}
]
[
{
"host": "_dmarc.lab.example",
"class": "IN",
"ttl": 0,
"type": "TXT",
"txt": "v=DMARC1; p=reject; rua=mailto:dmarc@lab.example"
}
]
本地记录全部正确返回,且 ttl 显示 0(dnsmasq 对本地记录默认返回 TTL 0)——离线复现闭环成立。验证完毕后把 /etc/resolv.conf 恢复原 nameserver,公网查询立即回归。
⚠️ 注意:部分最小化部署里
/etc/resolv.conf由部署底座挂载管理(本实测环境即如此,sed -i重命名替换时报 Device or resource busy 即属这种情况),改用重定向覆写(printf ... > /etc/resolv.conf);常规物理服务器无此限制。
5.7 缓存与超时项(应用无缓存,实测证据)
应用层无结果缓存。证据一:后端入口显式输出禁缓存头(实测响应头):
curl -sI 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=a'
实测回显:
HTTP/1.1 200 OK
Date: Mon, 26 Oct 2026 05:29:59 GMT
Server: Apache/2.4.52 (Ubuntu)
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Cache-Control: no-store, no-cache, must-revalidate
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Content-Type: text/html; charset=UTF-8
证据二:两次相同查询之间的 TTL 递减(来自解析器缓存倒计时)说明每次都是重新解析而非回放缓存。实测同一域名两次 TXT 查询 TTL 从 3600 递减:
第一次: "ttl": 3600
第二次: "ttl": 3586
超时项全景(汇总实测):
| 环节 | 超时来源 | 默认值 | 实测表现 |
|---|---|---|---|
| 端口探测 | Port.php fsockopen 参数 | 5 秒 | 被拦截地址实测 5.030s(改 2s 后 2.044s) |
| DNS 查询 | 系统解析器(resolv.conf + 上游) | 上游决定 | 正常数十毫秒;无响应区域阻塞黑名单查询 |
| whois | phpwhois 内部 fsockopen | 库内定值 | whois.verisign-grs.com 实测 1.8s 内返回 |
| 黑名单整体 | 50 区域串行累加 | 无总上限 | 实测 1m28s(含无响应区域等待) |
| PHP 执行 | max_execution_time(仅 CPU 时间) | 30 | 88s 的黑名单查询未被打断 |
TTL 显示值差异提示:实测同一域名 dig 显示 TTL 3600 而应用 JSON 显示 ttl: 5,原因是应用经系统解析器(glibc resolver → 递归链路)取得响应,递归链路上的解析器可对 TTL 做改写/压低;ttl: 0(如 dnsmasq 本地记录)表示不可缓存。解读时以「TTL>0 可缓存」定性即可,不建议跨工具直接对比 TTL 数值。
六、生产配置模板
以下为推荐的生产基线(Apache + mod_php 形态),逐项均在前文验证过:
; /etc/php/8.1/apache2/php.ini 关键项(Ubuntu 默认值,显式核对)
display_errors = Off ; JSON 纯净的第一道防线(5.5)
log_errors = On ; 告警落 /var/log/apache2/error.log
max_execution_time = 30 ; 保持默认:I/O 等待不计时,调大无益(5.5)
memory_limit = 128M ; 保持默认
default_socket_timeout = 60 ; 保持默认
# /etc/apache2/sites-enabled/000-default.conf 关键段
# 1) 访问控制(防公网滥用,账号如 admin,强口令)
<Directory /var/www/html/spftoolbox>
AuthType Basic
AuthName "SPF Toolbox"
AuthUserFile /etc/apache2/.htspf
Require valid-user
</Directory>
# 2) 文件权限(403 故障的第一修复项,8.1)
chown -R www-data:www-data /var/www/html/spftoolbox
chmod -R 755 /var/www/html/spftoolbox
# 3) (可选)删除误报率高的 DNSBL 区域,缩短黑名单查询耗时(5.2)
# 4) 出站放行:UDP 53(DNS)、TCP 43(whois)、按需出站 TCP(port 查询)
适用场景:公网或内网均可;内网部署可省去 Basic Auth 但仍建议保留文件权限基线。配置完成后执行一轮回归:request=mx 与 request=blacklist 各查一次公网域名,输出结构与部署验收一致即为配置收敛。
七、常见问题(FAQ)
7.1 改了 Blacklist.php/Port.php 没生效
PHP 每次请求重新编译脚本,源码修改本应立即生效。若未生效,排查三点:改的文件路径是否为部署目录(/var/www/html/spftoolbox/operations/)而非解压残留目录;sed 语句是否真的匹配(grep -n 确认关键字已变);浏览器/中间层是否缓存(用 curl -s 直连验证)。
7.2 黑名单查询要一分多钟
正常现象(50 区域串行 + 部分区域无响应等待,实测 1m28s)。缓解:删减 5.2 清单中无响应或误报区域;不要试图调大 max_execution_time(CPU 时间不计 I/O,见 5.5)。
7.3 request=all 只返回一条 HINFO RFC8482
解析器按 RFC 8482 拒绝 ANY 查询的合成响应。All.php 优先走 DNS_ALL(逐类型查询)正常返回全量记录;仅当全类型无记录回退 DNS_ANY 时才会撞上占位响应。需要完整清单改用 a/mx/txt 单项查询。
7.4 黑名单 FAIL 一定是垃圾邮件源吗
不一定。判定逻辑是「反查有 A 记录即 FAIL」,实测 gmail.com 的 Google IP 被 dnsrbl.org 判 FAIL(返回 103.224.182.253,非 127 网段,见 5.2)。处置前先核对该 DNSBL 的返回值编码规范,再人工定性。
7.5 想离线演示/复现查询功能
按 5.6 用 dnsmasq 建本地模拟区域,把 /etc/resolv.conf 指向它即可——A/MX/TXT/DMARC 四类记录实测全链路可复现,验证完恢复原 nameserver。
八、参考链接
- 官方仓库:https://github.com/charlesabarnes/SPFtoolbox (检索日期 2026-10-26)
- RFC 8482(Refusing Any Queries):https://www.rfc-editor.org/rfc/rfc8482
- RFC 7489(DMARC):https://www.rfc-editor.org/rfc/rfc7489
- 本专栏部署篇:《Ubuntu 22.04 安装 SPF Toolbox v2.2.0 指南》