Ubuntu 22.04 安装 SPF Toolbox v2.2.0 指南

在 Ubuntu 22.04 (Apache 2.4 + PHP 8.1) 上从零安装 SPF Toolbox v2.2.0:tar.gz 与 Git 源码双方案、systemd 托管、部署验证与 403 权限/出站 TCP/RFC8482 等排障实录。

SPF ToolboxSPF Toolbox邮件服务域名服务2026/10/26

Ubuntu 22.04 安装 SPF Toolbox v2.2.0 指南

目标:在 Ubuntu 22.04 服务器上从零安装 SPF Toolbox v2.2.0(PHP + Apache 形态),完成在线 tar.gz 与 Git 源码两种安装方案、systemd 托管、部署验证与常见故障排查。已在 Ubuntu 22.04.5 LTS + Apache 2.4.52 + PHP 8.1.2 环境全量实测通过。

一、环境信息

本文所有命令与回显均在以下真实服务器环境实测:

  • 操作系统:Ubuntu 22.04.5 LTS(PRETTY_NAME="Ubuntu 22.04.5 LTS")
  • Web 服务器:Apache 2.4.52(apache2 2.4.52-1ubuntu4.25),监听 80 端口
  • PHP:8.1.2(php 2:8.1+92ubuntu1,libapache2-mod-php 2:8.1+92ubuntu1),mod_php 形态
  • 应用版本:SPF Toolbox v2.2.0(官方 release tar.gz,179211 字节)
  • 部署目录:/var/www/html/spftoolbox
  • 运行用户:www-data(Apache 默认)
  • 访问地址:http://<服务器IP>/spftoolbox/
  • 系统依赖:Apache 与 PHP 由 apt 官方仓库安装;应用本体无任何 PHP 扩展依赖(json/sockets 为 PHP 内置,php -m 实测可见 json、sockets 模块)

SPF Toolbox 是纯 PHP 应用,不带常驻守护进程——它的「服务」就是 Apache 网页服务本身,因此本指南的 systemd 托管对象是 apache2 服务单元。

二、前置条件

安装前确认以下四项:

  1. 服务器可出站访问 GitHub(下载 release 包或 git clone 需要联网;离线服务器请把 tar.gz 在有网环境下载后拷贝到服务器,部署步骤完全一致);
  2. DNS 可用:SPF Toolbox 的每次查询都由服务器系统解析器(/etc/resolv.conf)代发,解析器不通则全部查询返回空;
  3. 具备 root 或 sudo 权限(安装 Apache/PHP、写 /var/www/html 需要);
  4. 80 端口未被占用(systemctl is-active apache2 为 active 或端口空闲)。

⚠️ 注意:应用运行时还会按需出站访问 whois 服务器(TCP 43,Whois 查询用)以及对目标域名端口做 TCP 探测(Port 查询用)。若服务器防火墙限制了出站 TCP,这两类查询会失败或全部显示 closed,其余 DNS 类查询不受影响。

三、版本选型说明

选型结论:v2.2.0,官方最新稳定版。版本事实(官方 releases.atom,检索日期 2026-10-26):

版本发布时间(atom updated 时间戳)
V0.52017-07-19
v0.882017-07-25
v1.002017-11-11
v1.1.02019-01-19
v2.0.02019-01-21
v2.1.02019-01-24
v2.1.12019-01-24
v2.2.02025-05-09

v2.2.0 相对 v2.1.x 的关键变化是前端从 jQuery + XHR 改写为原生 Fetch API(javascript/main.js 重写),后端 11 个查询类保持稳定。由于项目发布间隔长(2019-01 至 2025-05 之间无发布),生产部署建议固定使用 release tag(本文 v2.2.0),不要跟随 master 分支(master 最后提交 2025-08,仅小改动)。

下载地址固定写法(把版本号写死,保证可复现):

# v2.2.0 官方 release tar.gz(实测 179211 字节)
https://github.com/charlesabarnes/SPFtoolbox/archive/refs/tags/v2.2.0.tar.gz

四、方案 A:官方 tar.gz 在线安装(推荐)

本方案是 README 的手动安装路径:apt 安装 Apache + PHP → 下载官方 release 包 → 解压到 Web 根目录 → 赋权 → 验证。全程约 5 分钟。

4.1 安装 Apache 与 PHP

# 安装 Apache、PHP 及其 Apache 模块(连带 curl/jq 便于后续验证,可选)
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq apache2 php libapache2-mod-php curl jq

输出节选(实测,末段):

Processing triggers for php8.1-cli (8.1.2-1ubuntu2.28) ...
Processing triggers for libapache2-mod-php8.1 (8.1.2-1ubuntu2.28) ...

验证 PHP 与 Apache 版本:

php -v

实测回显:

PHP 8.1.2-1ubuntu2.28 (cli) (built: Oct 19 2026 18:54:45) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.2-1ubuntu2.28, Copyright (c), Zend Technologies
apache2 -v

实测回显:

Server version: Apache/2.4.52 (Ubuntu)
Server built:   2026-10-08T19:59:46

4.2 启动并设置 Apache 开机自启

# 启用并立即启动 apache2(systemd 托管)
systemctl enable --now apache2

输出节选(实测):

Executing: /lib/systemd/systemd-sysv-install enable apache2

验证服务状态与默认站点:

systemctl is-active apache2
curl -sI http://127.0.0.1/ | head -3

实测回显:

active
HTTP/1.1 200 OK
Date: Mon, 26 Oct 2026 04:56:22 GMT
Server: Apache/2.4.52 (Ubuntu)

4.3 下载并部署应用

# 1) 安装下载与解压工具(最小系统可能缺 wget)
apt-get install -y -qq wget git

# 2) 下载 v2.2.0 官方 release 包到临时目录
cd /tmp
wget -q https://github.com/charlesabarnes/SPFtoolbox/archive/refs/tags/v2.2.0.tar.gz -O spftoolbox-2.2.0.tar.gz
ls -l spftoolbox-2.2.0.tar.gz

实测回显:

-rw-r--r-- 1 root root 179211 Oct 26 04:56 spftoolbox-2.2.0.tar.gz
# 3) 解压并部署到 Web 根目录下的 spftoolbox 子目录
tar xzf spftoolbox-2.2.0.tar.gz
cp -r SPFtoolbox-2.2.0 /var/www/html/spftoolbox

# 4) 赋权:目录属主改为 Apache 运行用户 www-data,权限 755
chown -R www-data:www-data /var/www/html/spftoolbox
chmod -R 755 /var/www/html/spftoolbox

# 5) 确认部署结果
ls /var/www/html/spftoolbox/ | head -8

实测回显(部署目录清单):

CONTRIBUTING.md
Dockerfile
LICENSE
README.md
app.json
favicon.ico
index.php
javascript

💡 说明:源码包里的 Dockerfile、.github/、app.json(Heroku 用)等文件与 Apache 部署无关,保留不影响运行,追求干净也可删除后部署。index.php 必须保留——它是整个应用的唯一入口。

4.4 验证部署

# 首页可达性
curl -s -o /dev/null -w 'HTTP:%{http_code}\n' http://127.0.0.1/spftoolbox/index.php

实测回显:

HTTP:200

浏览器访问 http://<服务器IP>/spftoolbox/,应看到蓝色标题「SPFToolbox」与 Domain 输入框、查询类型下拉框。做一次真实查询验证全链路(以 gmail.com 的 MX 查询为例,通过 AJAX 后端端点直接验证):

curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=gmail.com&request=mx'

实测回显(完整 JSON):

[
    {
        "host": "gmail.com",
        "class": "IN",
        "ttl": 5,
        "type": "MX",
        "pri": 20,
        "target": "alt2.gmail-smtp-in.l.google.com"
    },
    {
        "host": "gmail.com",
        "class": "IN",
        "ttl": 5,
        "type": "MX",
        "pri": 30,
        "target": "alt3.gmail-smtp-in.l.google.com"
    },
    {
        "host": "gmail.com",
        "class": "IN",
        "ttl": 5,
        "type": "MX",
        "pri": 40,
        "target": "alt4.gmail-smtp-in.l.google.com"
    },
    {
        "host": "gmail.com",
        "class": "IN",
        "ttl": 5,
        "type": "MX",
        "pri": 10,
        "target": "alt1.gmail-smtp-in.l.google.com"
    },
    {
        "host": "gmail.com",
        "class": "IN",
        "ttl": 5,
        "type": "MX",
        "pri": 5,
        "target": "gmail-smtp-in.l.google.com"
    }
]

返回 200 且 MX 记录 JSON 正常,说明「前端 → Apache → PHP → 系统解析器 → 上游 DNS」全链路打通。页面下拉框中其余查询类型的验证方法与结果解读,见本专栏命令篇与配置篇。

五、方案 B:Git 源码安装

适合需要跟随 master 分支最新提交(例如想提前拿到未发版的修复)的用户。git clone 得到的代码与 release 包内容一致,仅打包方式不同。

5.1 克隆仓库并部署

# 前置:安装 git(方案 A 已装的跳过)
apt-get install -y -qq git

# 浅克隆 master 分支到临时目录
cd /tmp
git clone --depth 1 https://github.com/charlesabarnes/SPFtoolbox.git SPFtoolbox-git
cd SPFtoolbox-git
git log -1 --format="branch=master commit=%h date=%ci"
git rev-parse --abbrev-ref HEAD

实测回显:

branch=master commit=f6b5ee8 date=2025-08-22 14:36:01 -0500
master
# 部署到 Web 根目录(与方案 A 同样的赋权动作)
cp -r /tmp/SPFtoolbox-git /var/www/html/spftoolbox
chown -R www-data:www-data /var/www/html/spftoolbox
chmod -R 755 /var/www/html/spftoolbox

5.2 验证部署

curl -s -o /dev/null -w 'HTTP:%{http_code}\n' http://127.0.0.1/spftoolbox/index.php
systemctl is-active apache2

实测回显:

HTTP:200
active

与方案 A 相同,浏览器访问 http://<服务器IP>/spftoolbox/ 并执行一次 MX 查询确认全链路可用。

⚠️ 注意:master 分支代码不带版本号,排障与升级回滚时无法对应 release tag;生产环境建议优先方案 A 的固定 tag 部署。日后想切换到 release 版,直接用方案 A 的 tar.gz 覆盖 /var/www/html/spftoolbox 即可(应用无独立数据目录,覆盖无损)。

六、方案对比与选择建议

维度方案 A:tar.gz 在线安装方案 B:Git 源码安装
来源官方 release tag v2.2.0master 分支最新提交
版本可追溯有 tag、有 release 说明仅 commit 哈希(实测 f6b5ee8,2025-08-22)
是否需联网需(或离线拷贝 tar.gz)需(git clone)
升级方式覆盖解压新版git pull 后重新部署
适用场景生产部署(推荐)跟进未发版的修复、参与开发

选择建议:生产与日常使用选方案 A(版本固定、可复现);只有明确需要 master 分支新改动时选方案 B。离线服务器一律用方案 A 的 tar.gz 离线拷贝路径。两种方案部署后的配置、验证、排障完全一致。

七、配置说明

SPF Toolbox 无独立配置文件,安装后「开箱即用」。但以下三项 Apache/PHP 层配置与运行质量直接相关,建议部署后逐项确认(逐参数含义与修改-验证闭环见本专栏配置篇):

  1. 部署子目录即可用:应用内部全部使用相对路径(前端 fetch operations/?...,后端 include ./Xxx.php),部署在 /var/www/html/spftoolbox/ 子目录无需任何 URL 重写配置,也不需要启用 mod_rewrite;
  2. DirectoryIndex 已覆盖:Ubuntu Apache 默认 DirectoryIndex 含 index.php,因此 /spftoolbox/ 与 /spftoolbox/operations/ 都能自动命中各自的 index.php(前者是页面,后者是 AJAX 入口),无需额外配置;
  3. PHP 显示错误保持关闭:确认 /etc/php/8.1/apache2/php.ini 中 display_errors = Off(Ubuntu 默认值)。该值若为 On,任何 PHP 告警文本都会混入 JSON 响应,导致前端 response.json() 解析失败——这是本应用在新环境部署时最常见的翻车点。

公网部署时还应加上访问控制,避免被当作公共 DNS 查询跳板。最简做法是 Apache Basic Auth:

# 创建密码文件(账号 admin,密码按提示输入两次)
htpasswd -c /etc/apache2/.htspf admin

在 Apache 站点配置(/etc/apache2/sites-enabled/000-default.conf)的 <VirtualHost> 内加入:

<Directory /var/www/html/spftoolbox>
    AuthType Basic
    AuthName "SPF Toolbox"
    AuthUserFile /etc/apache2/.htspf
    Require valid-user
</Directory>
# 检查语法并热加载
apachectl configtest
systemctl reload apache2

此后访问页面需要输入 admin 与设置的口令。演示环境可用 admin / q1w2e3r4 这类测试口令,公网请务必换强口令。

八、常见问题(FAQ)

8.1 访问返回 403 Forbidden(AJAX 与页面全挂)

现象:页面与 operations/ 端点都返回 403,前端显示 Error: HTTP error: 403。

定位:查看 Apache 错误日志。实测把目录属主改回 root 且权限收紧为 750 后复现:

[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

AH00035 ... search permissions are missing 明确指向文件系统权限:Apache 以 www-data 运行,但目录属主/权限不允许其读取与进入。

解决:

chown -R www-data:www-data /var/www/html/spftoolbox
chmod -R 755 /var/www/html/spftoolbox

验证:恢复后页面与端点实测均回到 HTTP:200(实测回显见「实验F」环节,此处部署目录清单与权限即为修复后的最终状态)。

8.2 端口检测(Port 查询)全部显示 closed

现象:request=port 查询公网域名,所有端口都返回 Is closed。

定位:先用 Shell 原生手段交叉验证出站 TCP 是否被防火墙拦截。实测环境(出站 TCP 受限的服务器):

timeout 5 bash -c '</dev/tcp/gmail.com/443' && echo open || echo blocked

实测回显:

blocked

再用 PHP 复现 fsockopen 的真实错误码:

php -r '$fp=@fsockopen("gmail.com",443,$e,$s,5); var_dump($fp,$e,$s);'

实测回显:

bool(false)
int(110)
string(20) "Connection timed out"

errno 110(连接超时)说明不是应用问题,而是服务器出站 TCP 被拦截。

解决:在服务器防火墙/安全组放行到目标端口段的出站 TCP。放行前可先用本机回环地址验证应用逻辑本身是好的——实测对本机 80 端口(Apache 自身)探测返回 open:

curl -s 'http://127.0.0.1/spftoolbox/operations/?domain=127.0.0.1&request=port&port=80'

实测回显:

  [{
"80": "Is open"
}]

8.3 查询不存在的域名返回 [] 而非报错

现象:request=mx 查询一个不存在的域名,返回 []。

说明:这是预期行为。后端用 dns_get_record() 查询,域名不存在(NXDOMAIN)时 PHP 返回空结果,序列化为 [];不抛异常也不返回错误码。判断「域名真的不存在」还是「解析器故障」需交叉验证:dig +short <域名> SOA 无输出且 dig <域名> SOA 的 status 为 NXDOMAIN 即域名不存在。

8.4 All 查询返回一条 HINFO "RFC8482" 而不是全部记录

现象:对部分域名(尤其解析链路不支持 ANY 的)做 request=all,只得到:

[
    {
        "host": "no-such-xyz-9x.com",
        "class": "IN",
        "ttl": 3600,
        "type": "HINFO",
        "cpu": "RFC8482",
        "os": ""
    }
]

原因:现代递归解析器按 RFC 8482 拒绝 ANY 查询,统一返回合成 HINFO 记录占位。用 dig 直接复核(实测回显):

dig no-such-xyz-9x.com ANY +noall +answer
no-such-xyz-9x.com.	3600	IN	HINFO	"RFC8482" ""

说明:这是解析器行为而非应用缺陷。后端 All.php 先发 DNS_ALL(按记录类型逐类查询),成功时不经过 ANY;仅当全部类型无记录时回退 DNS_ANY 才会撞上 RFC 8482 占位响应。需要完整记录清单时,改用 a/mx/txt 等单项查询逐个拉取。

8.5 JSON 响应被 PHP 告警污染、前端报解析错误

现象:浏览器端报 Error: ... is not valid JSON 或 response.json() 失败。

定位:curl -s 看原始响应——JSON 前后若混有 Warning:/Deprecated: 文本,即为 PHP 输出了告警。

解决:确认 /etc/php/8.1/apache2/php.ini 两项(Ubuntu 默认值即正确,改动过的要恢复):

display_errors = Off
log_errors = On
systemctl restart apache2

修改后错误文本改写入 /var/log/apache2/error.log,JSON 恢复纯净。本指南实测环境中,即使临时开启 display_errors = On,v2.2.0 的 11 类查询路径也均未产生告警输出(实测各端点返回仍为纯 JSON),但保持生产默认 Off 是防未来 PHP 版本弃用告警污染输出的关键防线。

九、卸载与清理

# 1) 删除应用目录
rm -rf /var/www/html/spftoolbox

# 2) (可选)删除 Basic Auth 密码文件与站点配置段
rm -f /etc/apache2/.htspf
# 手工移除 000-default.conf 中加入的 <Directory /var/www/html/spftoolbox> 段后:
apachectl configtest
systemctl reload apache2

# 3) (可选,若服务器不再跑其他 PHP 站点)卸载 Apache 与 PHP
apt-get purge -y apache2 php libapache2-mod-php 'php8.1-*'
apt-get autoremove -y

卸载后验证:

ls /var/www/html/spftoolbox 2>&1
systemctl is-active apache2 2>&1

应用目录被删除且 Apache 停止(inactive)即为清理完成;若第 3 步未执行,apache2 仍是 active 属正常。

十、参考链接