这是 Arcivéo Monitor 的安装、配置与维护指南。 各章节按主题分组:总体概览、面板部署、接入安全工具、内置模块及诊断。 命令可通过右侧按钮复制。
面板安装说明位于各自独立的分步页面。请选择方式:
Arcivéo Monitor 是一款服务器安全面板。它收集已安装工具(Fail2ban、UFW、Lynis、ModSecurity、AIDE、ClamAV、Auditd、CrowdSec、Suricata、Falco 等)的数据,并在统一界面中呈现,包含仪表盘、攻击地图以及每个工具的详情页。
该监控面板本身不是主动防护手段,不会自行拦截攻击。它的职责是聚合已在运行的各类工具的信息,并以易读的方式呈现。
监控仅在本地运行——它必须安装在所监控的同一台服务器上。不使用任何 SSH 或远程 API。
所有命令(fail2ban-client、ufw status、ipset list 等)都由面板以 Web 服务器用户身份执行(通常为 www-data,在主机面板上则为站点账户),并仅授予极小范围的 sudo 权限——只针对特定工具,而非全局 root 访问权限。结果会被解析并显示在浏览器中。
评分从满分开始,每发现一个问题就相应扣分:
PermitRootLogin yes)— −20结果:80+ = 受保护,60–79 = 需注意,<60 = 有风险。
WebAuthn — 一种通过硬件密钥实现的无密码认证标准。支持 YubiKey、Touch ID、Face ID、Windows Hello、Passkey。
使用密码登录后,系统会要求通过已注册的密钥进行确认。即使密码泄露,没有实体密钥或生物识别也无法登录。
如需配置,请在侧边菜单中打开 WebAuthn 密钥,然后点击“注册密钥”。请一次注册两个密钥:如果唯一的密钥丢失或损坏,将无法用它登录面板。
面板可将安全报告发送到 Telegram 和邮箱(可手动触发,也可按计划发送)。在“设置”中进行配置。
Telegram。需要机器人令牌和 chat id:
@BotFather 发送 → /newbot → 获取形如 令牌 123456:ABC... 的字符串。@userinfobot 发送消息,或打开 https://api.telegram.org/bot<TOKEN>/getUpdates 并找到 "chat":{"id":...}。电子邮件。在“设置”→ Email 中可二选一:
re_...)和已验证的发件域名。报告状态:“注意”或“正常”。标题仅在出现真实问题或有待处理操作时才显示“注意”:发现 ClamAV 威胁、AIDE 检测到文件变更、Falco 严重事件(过去 24 小时内的 Emergency/Alert/Critical)、Monit 中有服务宕机、需要重启、SSL 即将到期(≤14 天)或有待安装的安全更新。背景噪声——机器人的 SSH 暴力尝试、被 fail2ban 封禁的 IP、Suricata 告警、Lynis 警告以及已被拦截的 ModSecurity 请求——不会提升状态,因此报告中的这些数字本身并不意味着“注意”。
详细监控模块(Lynis、UFW、ModSecurity、攻击地图、AIDE、ClamAV 等)需在拥有有效许可证时才会开放。没有许可证时,仪表盘、设置和账户仍可使用,而各模块会显示“需要许可证”卡片。
在个人中心购买后,您会获得一个形如 ARCIVEO-XXXX-XXXX-XXXX-XXXX 的激活码。需要将它“激活”到您面板的域名上——这会把激活码转换为已签名的许可证文件([license] 区块),再将其粘贴进面板。
如何激活(3 步):
my.arciveo.com → “许可证”/“许可证激活”栏目——复制 ARCIVEO-… 激活码。monitor.example.com)。点击激活——系统会生成绑定到该域名的许可证文件,并显示在带有“复制”按钮的字段中。面板会以加密方式验证密钥:签名、域名绑定和有效期。
config.php 中的 APP_URL 常量取值,且只输入主机名——不含 https://、不含 www 前缀。激活为一次性操作:激活码会转换为所输入域名的许可证,无法再次激活——若域名填错,密钥将无法用于您的面板,而激活码也会被消耗。因此请仔细输入域名。面板的所有主要参数都通过普通的 define() 常量集中在根目录(与 public/ 文件夹同级)的单个 config.php 文件中。该文件在安装时创建;很少需要手动修改——主要是在更换域名、迁移或连接到其他数据库时。任何修改后请重启 PHP-FPM(否则由于 OPcache,改动不会生效)。
请将您自己的值填入高亮处;其余部分保持原样:
数据库。 连接 MySQL/MariaDB 的凭据:
DB_HOST — 数据库主机,几乎总是 localhost;DB_NAME — 面板数据库的名称;DB_USER — 数据库用户(仅能访问自己的数据库);DB_PASS — 该用户的密码;DB_CHARSET — 连接编码,请保持 utf8mb4。应用。
APP_URL — 面板的完整地址(如 https://monitor.example.com)。必须与激活许可证所用的域名一致——否则密钥将被拒绝(见“许可证”一节);TIMEZONE — PHP 时区:仅影响面板显示日期和时间的方式。对 cron 任务的运行时间没有影响——那里使用的是系统时区(见“所有 cron 任务”)。会话时长。 SESSION_LIFETIME — 会话空闲超时秒数(滑动式:有活动时刷新)。默认 28800 = 8 小时;空闲超过该时长后,面板会要求重新登录。例如 3600 = 1 小时,86400 = 一天。
错误日志。 错误永远不会显示给访客,而是写入 logs/php_errors.log——可在“应用日志”页面查看。这些行(display_errors=0、log_errors=1、error_log 路径)通常无需修改——设置直接写在文件中,不依赖 php.ini。
public/ 同级),而本面板的 Web 根目录(DocumentRoot)正是面板根目录,而非 public/。文件本身不会“泄露”:根目录的 .htaccess 对它设有明确禁止(Require all denied)——服务器会返回 403。即便没有这条规则,源码也不会泄露:这是 PHP——服务器会执行它,而不是以文本形式输出。以防万一:请勿将其发布到公共代码库,也不要把含真实密码的文件发给技术支持。文件权限为 640。
UFW(Uncomplicated Firewall)是 nftables/iptables 的简易接口。它会关闭所有入站端口,仅放行明确允许的端口。“UFW 防火墙”页面显示状态和规则。
ufw enable 之前,请务必放行 SSH(ufw allow OpenSSH),否则您将失去对服务器的访问。
deny 规则关闭的端口不会被视为可从外部访问。
Skipping adding existing rule 并非错误。 UFW 以此提示完全相同的规则已存在,因而不会重复添加。重新运行自动配置(该操作是幂等的)时出现此提示属正常情况,无需处理。
当失败登录尝试次数超过阈值时自动封禁 IP。可分析 SSH、nginx、Apache 及其他服务的日志。
基础安装见上文。这里是可产生数十个活跃 jail 和数千条封禁记录的实用配置:通用设置、关键 jail,以及从 ipsum 列表自动封禁恶意 IP。
文件 /etc/fail2ban/jail.local — 通用设置和最重要的 jail:
ignoreip 中填入您自己的 IP 和受信任网段,否则可能会把自己封禁。修改后执行:sudo fail2ban-client reload。
把 ipsum 封禁列表自动加载到 root 的 crontab(sudo crontab -e):level 1(10 万余个 IP)会加载到 ipsum 集合中,并在防火墙上拦截(详见“IPset 封禁列表”一节):
ipsum——仪表盘正是读取它(“IPset ipsum”卡片)。级别:levels/1.txt — 覆盖范围最大,levels/3.txt — 更精确(3 个以上来源)。
为何“安全监控”分为两个区域。 防护在两个层面运作,仪表盘不会将它们混在一起:
sshd、apache-*、nginx-* 等 jail)以及严重惯犯(recidive jail——已被多次封禁者)。这些是真正试图入侵您的 IP——它们会出现在攻击地图和“时间轴”上。ipset ipsum,在防火墙上以 DROP 规则拦截。这些地址大多根本没有接触过您的服务器——会被提前拦截;“IPset ipsum”计数器显示预防性拦截了多少个。区别很简单:被动响应是“这些发起了攻击并被封禁”,预防性是“这些在尝试之前就已被拦截”。以前 recidive 会人为塞入 ipsum 的 list-3(因此有旧的“列表型 recidive”划分);现在 recidive 只包含真正的惯犯,预防性拦截全部由防火墙负责。
ipsum 是一个每日更新的公开恶意 IP 列表。监控面板会在仪表盘和攻击地图上显示已加载的地址数量,并将其纳入安全评分(若未加载该集合则 −10)。
不使用 fail2ban 的最简方案——单独一个 ipsum 集合,通过 iptables 进行封锁:
@reboot 上。顺便用 create … -exist 命令设定上限 maxelem 300000(默认 65536——level 1 装不下,会报“Hash is full”):
ipsum 集合中,如果防火墙由安装程序管理(全新 VPS——“完整”/“精简”配置),则会用 DROP 规则把该集合接入 UFW——来自这些 IP 的流量会被真正封锁。该规则位于 ESTABLISHED,RELATED 之后,因此现有连接(包括您的 SSH)不会中断——只拦截来自列表的新连接。集合会在 ipsum-load.service 服务加载时、先于防火墙恢复(否则 UFW 无法启动),并由 cron 在 04:00 更新。在已配置好的服务器上(面板、自有防火墙),安装程序不会改动防火墙——此时 ipsum 仅作为仪表盘和攻击地图的列表,需要时可手动添加 DROP 规则(最简方案用 iptables … --match-set ipsum … -j DROP——见上文)。自动安装时无需手动做任何操作。
Fail2ban 的现代替代方案,具备集体威胁情报能力:既有来自社区的封禁,也支持自定义规则。需要单独的 bouncer 才能将封禁应用到防火墙。
systemctl is-active crowdsec 检查)。启动:sudo systemctl enable --now crowdsec;如果崩溃,请查看 sudo journalctl -u crowdsec -n 30。任何处于“未运行”状态的服务(Suricata、Falco、Monit、MySQL)都适用同样的规则。
stream halted / 封禁未生效。 这是遗留的 api 密钥:bouncer 已从 cscli bouncers list 中删除,但它的旧密钥仍留在 /etc/crowdsec/bouncers/*.yaml 中。请重新注册 bouncer 并填入新的密钥:
AIDE(Advanced Intrusion Detection Environment)会对文件系统做一次快照,并在每次检查时报告 /etc、/bin、/usr 中的改动。安装完成后必须初始化数据库(aideinit)。
aideinit 期间,终端会在 Running aide --init... 这一行停留 5–15 分钟——这是正常的(对整个文件系统做哈希,磁盘负载较高)。请勿按 Ctrl+C 中断。如果进程“卡住”却没有任何输出——可能它在等待一个隐藏提示 Overwrite existing aide.db.new [Yn]? 的回答(请按 Y)。可从另一个会话检查其活动状态:pgrep -af aide。
aideinit 错误:“21_aide_spamassassin … printf: invalid number”(return code 20)——这是 Ubuntu 22.04 中 AIDE 配置片段的已知缺陷。数据库无法创建。请移除损坏的片段后重试:
aideinit,要么(Ubuntu 24.04)/var/lib/aide 目录以 700 模式创建、www-data 无法访问——用 sudo chmod 755 /var/lib/aide 解决(见上方代码块)。“尚未检查”= 数据库已存在,但还没执行过检查——这不是错误。监控从 /var/log/aide/aide.log 读取结果。
/etc/cron.daily/aide 可能不会以所需格式写入 /var/log/aide/aide.log(且这些系统中已不再有 aide.wrapper)。更可靠的做法是添加自己的、带显式 --config 的 cron——它以 root 身份、644 模式写入日志,监控无需额外分组即可读取:
chmod 755 /var/lib/aide 以及 02:00 的检查 cron——无需任何手动操作。
sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db。
Linux 上的反病毒扫描器。特别适合扫描 /var/www 以查找 PHP shell 和恶意代码。
enable --now 后 clamd 守护进程仍显示“未激活”?三个常见原因:
1. 配置文件中残留 Example 行——只要它存在,clamd 就拒绝启动:
2. 未下载病毒特征库——没有它 clamd 无法启动:
3. 只是正在加载——clamd 将约 800 万条特征加载进内存需要 30–60 秒。请稍候再检查:systemctl is-active clamav-daemon(状态为 activating → 仍在加载)。
sudo journalctl -u clamav-daemon -n 30 --no-pager。
clamd 守护进程只是将特征保存在内存中,它本身不会按计划扫描任何内容。面板显示的是计划扫描的结果,因此需要一个执行扫描并写入日志的 cron。自动安装会部署封装脚本 /usr/local/bin/clamav-scan.sh 和一个 01:30 的 cron——首次运行后“已扫描文件数”和“上次扫描”即会填充。无需等待计划立即运行:sudo /usr/local/bin/clamav-scan.sh。
Linux Malware Detect (LMD) — 针对 Web 威胁的恶意软件扫描器:PHP shell、Web 后门、下载器。它使用 ClamAV 引擎,并以自有签名加以补充。
maldet --report。
update-rc.d: error: unable to read /etc/init.d/maldet 这一行——它是无害的。maldet 不使用 init.d,签名更新和扫描通过 /etc/cron.daily/maldet 运行。如果下面能看到 installation completed,则说明一切安装成功。
apt 安装的,而是安装在 /usr/local/maldetect;在启用 open_basedir 时,它是否存在会通过 shell 检查——请参见“页面为空,但服务器上有数据”一节。
网络入侵检测系统:在数据包层面分析流量,并掌握数千种攻击特征。它是对 ModSecurity 的补充(后者工作在 HTTP 层,Suricata 工作在 TCP/IP 层)。
/var/log/suricata/eve.json,而目录权限为 750,Web 服务器(www-data)无法读取。请为该目录开放进入权限——目录内的文件仍受保护:
通过 eBPF/内核模块拦截系统调用,实时检测异常:nginx 派生的 shell、Web 进程读取 /etc/passwd、写入 /bin 等。
journalctl -u falco 读取 Falco 事件(无需 sudo — 通过 systemd-journal 组)。请确认 www-data 已加入该组 — 参见手动安装页面上的“配置 sudo”(第 2 项)。
/etc/passwd、写入系统目录)。在平稳运行的服务器上一天内零个严重事件,正是健康状态。
journalctl 读取需要访问日志的权限;为让面板稳定地看到事件,自动安装会为 Falco 启用 file_output → /var/log/falco/falco.log,并为服务设置 UMask=0022(日志可被 Web 服务器读取)。在全新安装上无需手动配置这些。
ModSecurity — 面向 Apache 或 Nginx 的 Web 防火墙(WAF)。可拦截应用层攻击:SQL 注入、XSS、路径遍历和扫描器。
IncludeOptional /etc/modsecurity/*.conf 这一行加载配置,而软件包只放置了 modsecurity.conf-recommended —— 它不符合 *.conf 通配符。如果不将它复制为 modsecurity.conf,SecRuleEngine 就仍为 Off:模块已加载、CRS 规则已加载,但流量不会被检查,也不会生成审计日志。中间模式 DetectionOnly 只会将事件写入日志,而不拦截请求 —— 面板会以黄色显示该状态。
面板对审计日志的访问权限。 日志 /var/log/apache2/modsec_audit.log 归 root 所有(权限 640),Web 用户无法读取。面板通过一个包装脚本获取数据 —— 请创建它:
SecRuleEngine 指令:带缩进的行位于 <LocationMatch>/<Directory> 块内部(例如为 phpMyAdmin 关闭 WAF),并不决定全局模式。www-data,在 HestiaCP 中站点进程池以站点所有者身份运行(例如 admin)—— 请用 grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf 检查。X-Forwarded-For 头中读取攻击者的真实 IP。统计中只会包含触发了规则的事务:SecAuditLogRelevantStatus 指令会将任何 4xx/5xx 响应写入审计日志,因此普通的 403/500 也会进入其中 —— 面板不会将它们计为 WAF 事件。---RULES--- 块用于“所有已启用规则”栏目 —— 面板不仅显示已触发的规则,还会显示所有已加载的 CRS 规则和自定义规则。循环 for f in … 中的三个路径是 CRS 规则和本地补充规则的典型位置;如果您的布局不同(软件包将文件放到自己的目录,或自定义规则不在 /etc/modsecurity/custom-rules.conf),请用 sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null 命令找出实际路径并将其填入列表。如果包装脚本较旧(没有此部分)—— 该栏目只会显示“不可用”警告,页面其余部分仍照常工作。
Auditd(Linux Audit Daemon)在内核层记录系统调用:登录与登出、sudo 命令、失败的身份验证尝试、文件更改。监控面板会显示当天的登录、失败尝试和 sudo 命令。
ausearch(/usr/sbin/ausearch)读取事件,必要时用 tail 命令从 /var/log/audit/audit.log 读取。两者都必须加入 sudoers。
监控各项服务(nginx、php-fpm、mysql 等),并在其崩溃时自动重启。可通过 email 发送告警。
monit status 获取服务列表。/etc/monit/monitrc 中必须启用 HTTP 接口(set httpd 块并带 allow localhost),否则 monit status 会返回错误。
monitrc 中的 set httpd 行被注释掉了(默认为 # set httpd port 2812 …)。请取消该块的注释并允许 localhost。(2) 仅启用 httpd 本身并不会监控任何东西——Monit 只统计由 check 语句声明的项;没有这些语句,即便接口正常运行列表也是空的。最小可用配置:
conf.d,其中 httpd 监听 2812 并附带一组检查项——全新安装无需手动配置。
PSAD 分析 iptables 日志,识别端口扫描和网络攻击,并为每个来源分配威胁等级(1–5)。可与 fail2ban 和 Suricata 配合使用。
psad --Status 读取数据(需加入 sudoers)。若未开启 iptables 日志记录,此页面将为空 — 在没有扫描发生前,这属于正常现象。
Mandatory Access Control(强制访问控制)会限制程序能访问哪些文件和资源,即使程序被攻破也是如此。Ubuntu/Debian 默认使用 AppArmor(通常已安装并处于启用状态)。
aa-status 读取状态(需加入 sudoers)。它会显示处于 enforce/complain 模式的配置文件数量,以及没有配置文件的进程。
“已加载配置文件”多于 enforce + complain 属于正常现象。 AppArmor 4.x(Ubuntu 24.04 及更新版本)新增了 unconfined 模式:配置文件已加载到内核,但不施加任何限制。Ubuntu 会将数十个使用 user namespaces 的程序(浏览器、torrent 客户端等)的配置文件标记为该模式。存在此类配置文件时,“已加载配置文件”卡片会变为琥珀色并显示其数量——例如已加载 120 个、enforce 26 个时显示 unconfined: 90。真正提供保护的只有 enforce 模式下的配置文件;Ubuntu 22.04(AppArmor 3.x)没有此模式,数字始终吻合。
unconfined 模式的配置文件切换到 enforce,只有在充分了解后才应进行:它们被禁用并非出于失误,而是因为否则会导致相应程序无法正常工作。complain 模式下的配置文件则不同:规则早已写好,只是尚未生效而已。
debsums 会校验已安装软件包的文件是否与仓库中的校验和一致——用于发现被篡改的系统二进制文件(作为 AIDE 的补充)。完整校验需要 1–2 分钟,因此通过 cron 运行,面板则从 data/debsums/debsums.log 读取结果并自动按类别归类(只有二进制文件和库才重要)。
任务写入 root 的 cron(sudo crontab -e)。现成的封装脚本 debsums-scan.sh 放入 /usr/local/bin/(chmod +x;参见 cron 任务汇总),它会自动将报告写入面板的 data/debsums/。
封装脚本 debsums-scan.sh 会自动找到面板的 data/——无需指定路径。
/etc/(配置文件)和 /usr/share/(资源)的变更通常是正常的——面板会用单独的颜色标记它们。真正值得警惕的是二进制文件和库的变更(/bin、/sbin、/usr/lib 等)——“二进制文件 / 库”卡片显示的正是这些。
Lynis 可手动运行,也可通过 cron 运行。报告应保存到项目的 data/lynis/ 目录——监控会读取 lynis-report.dat 文件。
lynis-scan.sh(无需等待 cron):显示“扫描中……”,并在完成后自动刷新报告。为此,Web 用户需要一条 sudoers 规则来运行该脚本——安装程序会自动将其添加到 /etc/sudoers.d/monitor。如果面板是手动安装或较早安装的,请用文件中已指定的同一用户补上这条规则:
Logwatch 应将每日报告以 .txt 格式保存到项目的 data/logwatch/ 目录。监控面板会显示最新报告及归档。
网络监控无需安装——它是面板的内置页面。该页面从本地来源展示服务器的网络状态:
/proc/net/dev;ip;ss;journalctl -k。前三个来源无需 sudo即可工作,因此接口、流量、连接和端口会立即显示。“内核事件”模块使用 journalctl -k——它通过 systemd-journal 组读取(“sudo 配置”,第 2 步),无需 sudo。检查 Web 用户是否都能访问:
UFW BLOCK 记录不会出现在这里——它们位于“UFW 防火墙”和“攻击地图”页面。模块为空并显示绿色对勾 = 一天内没有网络故障。
内置页面会显示三项内容:
df);占用率 ≥90% 时刻度条变红;lsblk),仅显示真实设备(loop/snap 已隐藏);smartctl)。剩余空间和设备列表无需配置即可使用。SMART 需要安装 smartmontools 软件包。Web 进程无法直接访问磁盘设备,因此 SMART 数据通过 cron 采集并写入 data/disk/smart.txt 文件,再由面板读取。
该任务需加入 root 的 cron(sudo crontab -e)。现成的封装脚本 smart-scan.sh 放入 /usr/local/bin/(chmod +x;参见 cron 任务汇总),会自动写入面板的 data/disk/。
封装脚本 smart-scan.sh 会自动找到面板的 data/ —— 无需手动填写路径。内部使用 lsblk -e7,11 排除 loop/cdrom。
本页展示服务器过去 24 小时的负载历史——Load Average、CPU 占用与 I/O 等待、RAM/Swap、网络流量(接收/发送)、磁盘 I/O(读取/写入)、磁盘与 inode 占用、打开的文件描述符和 MySQL 连接数,以及当前的 TCP 连接数和进程数。
数据由 cron/collect_metrics.php 采集——每 5 分钟将一份计数器的“原始”快照(/proc/loadavg、/proc/meminfo、/proc/stat、/proc/net/dev、/proc/diskstats、df/df -i、/proc/sys/fs/file-nr、SHOW GLOBAL STATUS LIKE 'Threads_connected')写入数据库表 system_metrics;百分比和速率由本页根据相邻两份快照的差值自行计算(磁盘/inode/描述符占用及 MySQL 连接数为瞬时值,不做换算)。无需 sudo——这些数据源无需 root 权限即可读取。每次写入时会自动删除 24 小时前的数据点。
封装脚本 collect-metrics-all.sh(见 cron 任务汇总)会自动查找服务器上所有已安装的面板实例,并以站点所有者身份运行每个实例的 cron/collect_metrics.php。
负载告警(“设置”→“负载告警”)——当 CPU/RAM/磁盘/inode 超过阈值时,面板会向 Telegram/Email 发送通知(与每日报告使用相同的渠道,无需单独为告警启用),并在指标恢复正常后再发送一条通知。在超阈值持续期间不会重复刷屏:只有经历“恢复正常 → 再次超限”的循环后,才会发送下一条通知。
collect_metrics.php 在每次运行时(每 5 分钟)检查——无需单独的 cron。“是否已通知”的状态保存在 data/alerts_state.json 中,阈值则保存在面板设置里。
“攻击地图”页面通过 geoiplookup 命令根据 IP 判定所属国家。如未安装 GeoIP 包,将无法识别国家,地图上也不会出现标记点:
/usr/share/GeoIP/GeoIP.dat 所有人均可读取,结果缓存于 tmp/geoip_cache.json。地图本身(Leaflet + OpenStreetMap 瓦片)在浏览器中加载——打开面板的电脑需连接互联网。
两张内置的仪表盘卡片,展示的不是工具的“开/关”,而是服务器的真实安全状态。无需安装,本地读取,无需 sudo。
外部暴露 — 有多少服务监听所有网卡(0.0.0.0/[::])并可从外部访问。若数据库或缓存(MySQL、PostgreSQL、Redis、MongoDB、Memcached、Elasticsearch)向外暴露,会以红色高亮 — 这是直接的漏洞(安全评分 −10)。来源:ss -tuln。
127.0.0.1(MySQL/PostgreSQL 配置中的 bind-address,Redis 中的 bind 127.0.0.1),或在 UFW 中关闭该端口。
127.0.0.1(loopback)的服务仅服务器自身可见 — 即使端口“开放”,外部也无法访问。因此绑定到 loopback、监听 25 端口的 Postfix 是安全的:自动配置会设置 inet_interfaces = loopback-only(外加中性的 smtpd_banner — 消除 Lynis 关于版本泄露的 MAIL-8818 提示)。“外部暴露”卡片仅将监听 0.0.0.0/[::] 的服务计为对外暴露;loopback 服务不计入其中。
/etc/postfix/main.cf 中设置 smtpd_banner = $myhostname ESMTP(不含版本和操作系统)与 inet_interfaces = loopback-only,然后执行 sudo systemctl restart postfix。
安全更新 — 有多少安全补丁待安装,以及内核更新后是否需要重启(存在补丁时安全评分 −5)。来源:/usr/lib/update-notifier/apt-check、文件 /var/run/reboot-required。详细列表见“安全更新”页面。
update-notifier-common)。若缺少 apt-check — 监控面板会通过 apt-get -s upgrade 统计补丁。
安全更新自动安装(unattended-upgrades) — 在“安全更新”页面有一张单独的卡片,显示是否已启用安全补丁的自动安装以及上次运行时间。无需 sudo — 状态通过 apt-config dump 读取。
备份是最重要的保障:数据丢失比任何入侵都更可怕。需要两样东西——服务器/网站备份,以及单独的面板数据库备份(其中包含用户、WebAuthn 密钥、设置和许可证)。
方案 A —— HestiaCP:在用户的 Backup 选项卡 → 点击创建备份按钮(或在服务器设置中按计划自动执行)。备份会包含网站及其数据库。
方案 B —— 手动(cron):转储数据库 + 打包面板的 data/ 目录:
更新到新版本。 请先做好备份。然后重新上传代码文件,同时保留您的数据:
public/、includes/、assets/、cron/、database/,以及根目录下的 .htaccess(前端控制器——路由不能沿用旧版本)、manifest.json、sw.js;config.php(数据库信息)、data/(报告)、logs/、tmp/(会话与缓存)。SSH_FX_PERMISSION_DENIED——Permission denied。面板文件归 www-data 所有(安装时就是这样设置的),而 SFTP 客户端是以您自己的用户连接的,没有写入权限。把整个面板都交给 www-data“为了能用”正是导致这个错误的原因;下面给出三种方法,任何一种都能解决问题。
data/(报告)、tmp/(会话与缓存)、logs/;它们仍归 www-data 所有。其余都是代码,Web 服务器只需读取,而 www-data 组凭 644 权限即可读取。附带的好处是:PHP 出现漏洞时也无法改写面板文件。在主机面板(HestiaCP 之类)上无需方案 A:那里站点文件本就归您用来 SFTP 登录的账户所有,而 Web 服务器按组读取它们。
chmod 都会重置 ACL 掩码,访问权限便悄然消失。如果在“整理权限”之后上传再次遇到 Permission denied——请重新执行两条 setfacl 命令。
2 即 setgid:通过 SFTP 上传的文件仍留在 www-data 组中,否则面板无法覆盖它们。采用方案 C 后,请在 FileZilla 中重新连接——新的用户组只在重新登录后生效。检查:id deploy(应出现 www-data 组)和 ls -ld /path/to/monitor(drwxrwsr-x——字母 s 表示 setgid 已设置)。
迁移到另一台服务器:
config.php、data/。mysqldump → 导入到新服务器;并在 config.php 中更新数据库信息。adm 组成员身份、cron 任务。如果您无法登录——所有问题都可以直接在服务器的数据库中修复。打开数据库(名称见 config.php):
丢失 WebAuthn 安全密钥(无法通过第二因素)——请关闭 2FA,使用密码登录,然后注册新的安全密钥:
忘记密码——请设置新的哈希值(在服务器上生成后替换进去):
用 IP 过滤把自己封了——请关闭该限制:
sudo mysql,或使用 phpMyAdmin / 主机面板中的数据库版块。恢复后请重新启用 WebAuthn 和 IP 过滤。
任务汇总位于服务器的 root crontab中(通过 sudo crontab -e 添加)。只保留您所用工具对应的行;并按您的服务器调整路径。
sudo crontab -l,并确认 cron 服务处于活动状态。
config.php 中的 TIMEZONE。 TIMEZONE 常量只影响 PHP(面板如何显示日期),但 cron 守护进程按操作系统的系统时间运行任务。如果服务器时区与您不一致,“08:00”的报告就会在错误的时间送达。示例:服务器处于另一时区(Asia/Bangkok,UTC+7),而您在上海(UTC+8)→“08:00”的报告在您本地时间的 09:00 才送达。请检查,并在需要时把系统时区改为您所在时区:
0 8 * * * 这一行就会在本地时间 08:00 触发。否则就得去移动 cron 本身,但夏令时/冬令时切换时偏移又会再次错开——因此正确做法是配置系统时区。
crontab.txt)位于项目旁的 system/ 文件夹中,在 public_html 之外。这不是网站的一部分——无需上传到 web 根目录;请按系统路径放置到服务器上(如上面的 crontab):
lynis-scan.sh → /usr/local/bin/(chmod +x)——运行 lynis audit system,扫描期间设置标志 /tmp/lynis-running,并把 lynis-report.dat 复制到面板的 data/lynis/;logwatch_daily.sh → /usr/local/bin/(chmod +x)——在 data/logwatch/ 中生成每日 Logwatch 报告(sshd、fail2ban、sudo、postfix);smart-scan.sh → /usr/local/bin/(chmod +x)——把磁盘状态(smartctl)记录到 data/disk/;debsums-scan.sh → /usr/local/bin/(chmod +x)——在 data/debsums/ 中检查软件包完整性(debsums);clamav-scan.sh → /usr/local/bin/(chmod +x)——ClamAV 对危险路径(web、home、temp)进行杀毒扫描;把汇总写入 /var/log/clamav/scan.log,ClamAV 页面从此处读取(上面 crontab 中的 01:30 行);load-ipsum.sh → /usr/local/bin/(chmod +x)——就地更新 ipset 集合 ipsum(level 1),不中断生效中的防火墙规则(上面 crontab 中的 04:00 行);daily-report-all.sh → /usr/local/bin/(chmod +x)——运行面板的报告 cron/daily_report.php(上面 crontab 中的 08:00 行);daily_report.php ——已包含在面板中(cron/daily_report.php),通过 daily-report-all.sh 运行,无需单独安装;collect-metrics-all.sh → /usr/local/bin/(chmod +x)——运行面板的 cron/collect_metrics.php(“性能”页面,上面 crontab 中的 */5 行);collect_metrics.php 已包含在面板中,无需单独安装;crontab.txt (system/cron/) ——任务样例;把需要的行通过 sudo crontab -e 录入。/usr/local/bin/。 无法直接从 FileZilla 写入该目录——它归 root 所有,SFTP 客户端会收到 SSH_FX_PERMISSION_DENIED。步骤如下:先把文件上传到 /tmp(所有人都可写入),再用一条命令把它移动到位:
/tmp——不是 /var/tmp,也不是面板内部的 tmp/(后者归 www-data 所有,对您的用户是封闭的)。在 FileZilla 的目录树中,/tmp 是顶层分支,与 var 并列,而不在它内部。
/usr/local/bin/,日志为 /var/log/arciveo-cron.log)——无需手动操作。
/home/*/web/*/public_html 和 /var/www/* 来查找面板安装位置,并把报告放到各自的 data/。如果面板位于其他路径——请把它加到脚本内的 for app in … 行中,否则 Lynis/SMART/debsums/Logwatch 的报告不会进入面板。
logs/cron.log 文件由 root crontab 首次创建——它将归 root 所有,面板中的“cron 日志”标签页既无法读取也无法清空。请提前以 web 用户身份创建该文件(网站目录的所有者;在 HestiaCP 上是相应账户,例如 admin)——这样 root crontab 就只会追加内容,而不更改所有者:
stat -c %U /path/to/monitor。
sudo crontab -e),否则它会被执行两次。
sudo crontab(那会让任何获得面板会话访问权的人直接提权到 root),而是一个只有两条命令(list/set)的狭窄脚本,它只操作专用注释之间的自有区块。安装一次即可:
www-data——请检查网站的 PHP-FPM 池以哪个用户运行(ps -o user= -C php-fpm),并把它填入 sudoers 行。
public/crontab_monitor.php 文件通过 FTP/SFTP 以与网站其他文件不同的系统用户(例如 root)上传,web 服务器将无法读取它。请与相邻文件核对所有者和权限并使其一致:
监控面板通过 dpkg-query(APT 软件包数据库)检测工具是否存在。如果工具不是通过 apt 安装(手动安装、来自 snap 或从源码编译),dpkg 就无法识别它。
500 错误——请检查 PHP、nginx 及监控端自身的日志:
www-data 运行,而是以用户账户身份运行(例如 admin——站点目录的所有者)。所有 sudo 规则以及组成员身份(adm、systemd-journal)都必须配置到这个用户上,否则即使服务正在运行,模块也会显示“未激活 / 0”。查看 PHP 的真实用户:ps -o user= -C php-fpm | sort -u,或站点目录的所有者 stat -c '%U' /path/to/monitor。之后下面所有命令中都用它替换 www-data。自动安装会自行识别 Web 用户并将 sudoers 配置到该用户上。
数据不显示——几乎总是因为未配置 sudo 权限。请以 Web 用户身份检查具体命令(将 www-data 替换为您自己的)。-n 标志 = 不使用密码,与 PHP 一致——如果提示输入密码,就说明 sudoers 里没有该规则:
sudo aa-status 能列出配置文件,而“AppArmor”页面却显示“未激活”)。原因:Web 用户没有该模块对应命令的 sudo 权限。请从上面列表中检查该命令:如果提示输入密码——就在 /etc/sudoers.d/monitor 中补上缺失的行(“配置 sudo”)。常见的“新增”命令:/usr/sbin/aa-status(MAC)、/usr/sbin/psad --Status(PSAD)。
apache2ctl、ausearch、aa-status 或 ss,或者 Web 用户不在 adm/systemd-journal 组中(fail2ban/auth/modsec 日志以及 journalctl——Falco 和内核事件——都从这里读取)。
现象:服务器上确实有数据(通过 shell 可以看到),但页面却显示"无数据"或状态不正确——例如 AIDE 显示"未初始化",但数据库其实已创建。
原因在于 open_basedir:许多面板和主机商会将 PHP-FPM 进程池限制在域名目录内,因此 PHP 函数 file_exists()、file_get_contents()、filemtime() 访问系统路径(/var/lib/aide、/var/log、/proc……)时会被阻止。监控通过标准系统命令(cat、test、stat)读取这些路径,从而绕过该限制。
open_basedir 的问题。正确的解决办法是使用系统命令读取(AIDE 和网络监控已经这样做了)。无需将 open_basedir 扩展到 /var、/proc,那样做也不够安全。
监控面板通过 443 端口直接连接域名来检查证书。如果服务器自身无法访问该域名,或端口被防火墙拦截,检查将无法通过。
/etc/nginx/sites-enabled/、/etc/nginx/conf.d/)和 Apache 配置(/etc/apache2/sites-enabled/)中获取域名,并加上 HTTP_HOST 中的当前主机。
监控面板以 config.php 中的用户连接 MySQL,该用户只能访问自己的数据库。MySQL 在 information_schema 中只显示有权限的数据库,因此其余的看不到。
要让监控面板看到所有数据库,请给该用户仅授予只读权限(用 root 执行一次;替换为 config.php 中的用户名):
sudo mysql:数据库列表通过它自己的 PDO 连接获取。
PostgreSQL 需要 postgres 用户级别的访问权限,而面板的 Web 用户并不具备该权限。从 PHP 中开放宽泛的 sudo psql 并不安全——面板改为调用一个不带参数的受限包装脚本,它只输出版本、连接数以及各数据库及其大小的列表。请创建它:
monitor-pgstat 行(手动安装的第 13 步),并且不要创建该脚本:PostgreSQL 卡片将只是保持未激活状态。
面板显示发生了什么;下面说明在常见情形下该怎么办。总的原则:不要慌张,先和合法活动(您的操作、更新、备份)对照核实,再按严重程度处置。
ignoreip。/etc 之外、/usr/share 之外)——可能被替换。请核对软件包:debsums PACKAGE_NAME,如有疑问就重新安装它(apt install --reinstall)。127.0.0.1,或在 UFW 中封闭端口。这是真实的漏洞。certbot renew 或面板中的设置)。sudo apt update && sudo apt upgrade;内核更新后请重启服务器。