一、前言
我的服务器半个月前中过木马,具体见这篇文章: 服务器被植入流量劫持后门(跳转世界杯赌球网站)的排查与解决方案 后门连着海外的C2服务器,Docker里还藏着挖矿程序。清理干净之后我意识到一件事:没有防护的服务器,在互联网上就像没锁门的房子,是条狗都能进来撒泡尿。
于是我试着弄了这么一个日报程序,这套每日汇报方案是经过我自己实操用了多台服务器布署后的实践总结,囊括了Ubuntu、CentOS、Debain等市面上主流Linux服务器系统,从系统加固、SSH安全、fail2ban防暴力破解,到每天自动发邮件汇报安全状况。从程序写出来到今天为止,三天了,经过不断优化、更迭,差不多能达到我理想中的状态了,所以我把它分享出来,希望能帮到同样在维护服务器的你。
2026-06-30 更新说明
- 服务端增加api key功能,供客户端调用
- 增加 Windows、macOS 客户端(付费)
- 服务端改为定时采集 + 文件缓存策略,客户端查询毫秒级响应
- 数据保留 180 天,每天自动清理超期数据
- 服务端源代码、预编译二进制同步更新
二、系统初始化
2.1 更新系统
刚买的服务器系统包可能比较旧,先更新到最新版本,避免因为旧版本的已知漏洞被入侵。
# ------------------- Ubuntu / Debian 系统 -------------------
# apt 是 Ubuntu/Debian 的包管理器
# update = 更新软件源列表(检查有哪些新版本可用)
# upgrade -y = 升级所有已安装的软件包(-y 表示自动确认,不弹询问)
apt update && apt upgrade -y
# ------------------- CentOS 系统 -------------------
# yum 是 CentOS 的包管理器,update 同时更新源和升级包
yum update -y2.2 安装基础工具
安装一些后续操作会用到的常用命令行工具。
| 工具 | 作用 |
|---|---|
curl | 用来下载文件、调用 API、测试网络请求 |
wget | 下载文件(和 curl 类似,但更专注于文件下载) |
git | 用来克隆代码仓库(如果需要从 GitHub 下载源码时用到) |
vim | 一个命令行文本编辑器(编辑配置文件用) |
# ------------------- Ubuntu / Debian -------------------
apt install -y curl wget git vim
# ------------------- CentOS -------------------
yum install -y curl wget git vim2.3 设置时区
把服务器的时间设成北京时间(CST,东八区)。否则定时任务(比如每天 00:01 发日报)会按 UTC 时间执行,和你的预期差 8 个小时。
# 设置时区为亚洲/上海(北京时间)
timedatectl set-timezone Asia/Shanghai
# 查看当前时间,确认是否生效
date
# 正常应该输出类似:Thu Jun 25 00:01:00 CST 2026
# 注意末尾的 CST 表示中国标准时间2.4 设置主机名
给服务器起一个容易辨识的名字,这样在终端提示符、邮件标题里都能看到,方便区分多台服务器。
# 把 your-server-name 换成你想取的名字,例如:
# hostnamectl set-hostname web-server
# hostnamectl set-hostname mail-server
hostnamectl set-hostname your-server-name三、SSH 安全加固(最重要的一步 ⭐)
3.1 修改默认 SSH 端口
SSH 默认端口 22 是互联网上扫描器的首选目标,新服务器上线几分钟内就会被扫描。改成一个不常用的高位端口,能过滤掉 99% 的自动扫描。
# 用 vim 打开 SSH 配置文件(vim 是命令行文本编辑器)
# 如果不会用 vim,也可以用 nano:nano /etc/ssh/sshd_config
vim /etc/ssh/sshd_config在文件中找到这一行(一般在第 15 行左右):
#Port 22把 # 删掉(去掉注释),把 22 改成你选的高位端口:
Port 32958选端口的建议:
- ✅ 推荐:
32958、23254、18957、42196(4-5 位数字,好记就行) - ❌ 避免:
2222、22222、8822(这些常见替代端口一样会被扫描) - ❌ 避免:
22附近的端口(21、23等也会被批量扫描)
三种系统注意: SSH 配置文件都在 /etc/ssh/sshd_config,位置一样,没有区别。3.2 生成密钥对(在自己电脑上操作,不是服务器)
服务器登录方式有两种:密码(会被暴力破解)和密钥(几乎不可能被破解)。密钥登录的原理是生成一对文件——私钥和公钥。私钥你留着,公钥放服务器上,登录时服务器验证你是否有对应的私钥。没有私钥的人就算知道密码也登录不了。
# 在你自己电脑的终端执行(Mac 的「终端」、Windows 的 PowerShell)
# -t ed25519 = 指定密钥加密算法(ed25519 是目前最安全的)
# -f ~/.ssh/... = 指定密钥保存路径,后面的名字改成你的服务器名方便管理
ssh-keygen -t ed25519 -f ~/.ssh/服务器名称_密钥执行后会问两次密码短语(passphrase),直接按两下回车跳过——这样登录时不需要额外输入。完成后,在 ~/.ssh/ 目录下会生成两个文件:
~/.ssh/服务器名称_密钥 ← 私钥(相当于你的钥匙,绝对不能给别人看)
~/.ssh/服务器名称_密钥.pub ← 公钥(相当于锁芯,放在服务器上)⚠️ 私钥必须妥善保管,谁拿到它就能登录你的服务器,不要上传到公共代码仓库,不要复制到不安全的设备上。
3.3 上传公钥到服务器
把上一步生成的公钥(.pub 文件)放到服务器的 authorized_keys 文件中。有两种方式:
方式一:用 ssh-copy-id(推荐,最简单)
# -p 32743 = 指定 SSH 端口(改成你上一步设置的新端口)
# -i ~/.ssh/xxx.pub = 指定公钥文件
# root@你的服务器IP = 以 root 用户登录你的服务器
ssh-copy-id -p 32743 -i ~/.ssh/服务器名称_密钥.pub root@你的服务器IP按提示输入当前 root 密码即可。命令会自动把公钥追加到服务器的正确位置。
方式二:手动上传(如果方式一不可用)
# 第一步:在服务器上创建 .ssh 目录(设置正确权限)
ssh -p 32743 root@你的服务器IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
# 第二步:把本地公钥内容追加到服务器上的 authorized_keys 文件
cat ~/.ssh/服务器名称_密钥.pub | ssh -p 32743 root@你的服务器IP \
"cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"3.4 禁用密码登录,锁定 SSH 配置
密钥上传成功后,就可以关闭不安全的密码登录方式了。再次编辑 SSH 配置文件:
vim /etc/ssh/sshd_config把以下几项逐一修改(可以直接找到对应行改,也可以直接替换整个文件内容):
# ===== 端口(改成你前面设置的值)=====
Port 32743
# ===== 只允许 SSH 协议版本 2(版本 1 有已知漏洞)=====
Protocol 2
# ===== 允许 root 登录,但只接受密钥方式(prohibit-password = 禁止密码)=====
PermitRootLogin prohibit-password
# ===== 启用公钥认证(刚才上传的密钥就是靠这个选项生效)=====
PubkeyAuthentication yes
# ===== 禁止密码认证(这步做完后,没有密钥就登录不了)=====
PasswordAuthentication no
# ===== 也禁止其他不安全的认证方式=====
ChallengeResponseAuthentication no
# ===== 只接受公钥认证=====
AuthenticationMethods publickey
# ===== 最多允许 3 次认证失败=====
MaxAuthTries 3
# ===== 最多 5 个同时连接=====
MaxSessions 5
# ===== 每 5 分钟检测客户端是否还活着=====
ClientAliveInterval 300
# ===== 连续 2 次没响应就断开=====
ClientAliveCountMax 2
# ===== 30 秒内必须完成登录=====
LoginGraceTime 30
# ===== 只允许 root 用户通过 SSH 登录=====
AllowUsers root
# ===== 日志记录到系统日志=====
SyslogFacility AUTH
LogLevel VERBOSE
# ===== 禁止 X11 转发(一般用不上)=====
X11Forwarding no
# ===== 只允许用安全的加密算法(防止算法攻击)=====
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com3.5 重启 SSH 并验证
配置改完后,需要重启 SSH 服务才能生效。
# ------------------- Ubuntu / Debian -------------------
# Ubuntu 和 Debian 的 SSH 服务名是 ssh(注意不是 sshd)
systemctl restart ssh
# ------------------- CentOS -------------------
# CentOS 的 SSH 服务名是 sshd
systemctl restart sshd最关键的一步:验证密钥登录是否正常
# 新开一个终端窗口(千万不要关当前这个窗口),测试密钥登录
ssh -p 32743 -i ~/.ssh/服务器名称_密钥 root@你的服务器IP如果成功登录了,恭喜你,SSH 安全加固完成。
⚠️ 重要:在确定新窗口能登录之前,绝对不要关闭当前的 SSH 窗口。 万一密钥配置有问题,你还能通过当前窗口修复。确认新窗口正常后,再关闭旧窗口。
🔑 之后的登录方式——只能用密钥登录:
# 每次连接都需要指定端口和密钥文件
ssh -p 32743 -i ~/.ssh/服务器名称_密钥 root@你的服务器IP为了方便,可以把配置写进 ~/.ssh/config(这样就不用每次敲端口和密钥了):
# 在本地电脑执行
echo "
Host my-server
HostName 你的服务器IP
Port 32743
User root
IdentityFile ~/.ssh/服务器名称_密钥
" >> ~/.ssh/config之后只需要 ssh my-server 就能连上了。
四、防火墙
防火墙的作用是控制哪些端口对外开放,防止不必要的服务暴露在公网上。原则是:默认拒绝所有入站流量,只放行需要的端口。
Ubuntu / Debian 用 UFW
UFW是 Ubuntu/Debian 自带的防火墙管理工具,用起来很简单。
# ------------------- 安装 UFW -------------------
apt install -y ufw
# ------------------- 设置默认策略 -------------------
# 默认拒绝所有入站连接(别人连不上你的服务器)
ufw default deny incoming
# 默认允许所有出站连接(你的服务器可以正常访问外网)
ufw default allow outgoing
# ------------------- 放行必要的端口 -------------------
# 注意:32958 要改成你前面设置的 SSH 端口
ufw allow 32958/tcp comment 'SSH'
# 如果你要跑网站,需要放行 80(HTTP)和 443(HTTPS)
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
# 如果后续部署了其他服务(如数据库、VPN 等),按需增加
# ufw allow 8080/tcp comment '自定义服务'
# ------------------- 启用防火墙 -------------------
# --force 表示直接启用,不弹确认询问
ufw --force enable
# ------------------- 查看规则 -------------------
ufw status numbered后续管理命令:
# 放行新端口
ufw allow 12345/tcp comment '新服务'
# 删除规则
ufw delete allow 12345/tcp
# 查看日志(看哪些 IP 被拦截了)
tail -f /var/log/ufw.logCentOS 用 firewalld
CentOS 默认使用 firewalld 管理防火墙,用法和 UFW 不同,但效果一样。
# ------------------- 安装 firewalld(通常已预装)-------------------
yum install -y firewalld
# 启动并设置开机自启
systemctl enable --now firewalld
# ------------------- 放行必要的端口 -------------------
# --zone=public = 应用到公共区域
# --add-port=... = 允许的端口/协议
# --permanent = 永久生效(重启后保留)
# 注意:32958 要改成你的 SSH 端口
firewall-cmd --zone=public --add-port= 32958/tcp --permanent
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
# 重新加载使规则生效
firewall-cmd --reload
# ------------------- 查看规则 -------------------
firewall-cmd --list-all五、fail2ban 防暴力破解(核心 ⭐)
虽然前面已经禁用了密码登录,但攻击者仍然会尝试连接你的 SSH 端口。fail2ban 会监控系统日志,发现有人尝试登录失败就自动封禁它的IP,连尝试的机会都不给。
5.1 安装
# ------------------- Ubuntu / Debian -------------------
# fail2ban = 暴力破解防护工具
# geoip-bin = IP 归属地查询工具(让日报能显示攻击者来自哪个国家)
apt install -y fail2ban geoip-bin
# ------------------- CentOS -------------------
yum install -y fail2ban geoip5.2 配置策略
创建一个自定义配置文件,覆盖默认的 SSH 防护规则:
# 创建配置目录
mkdir -p /etc/fail2ban/jail.d
# 写入配置文件(cat > 文件 << 'EOF' 的意思是:将下面几行内容写入到文件中)
cat > /etc/fail2ban/jail.d/sshd-custom.conf << 'EOF'
[sshd]
enabled = true
port = 32958
maxretry = 1
bantime = -1
findtime = 600
backend = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd
EOF配置参数详解:
| 参数 | 值 | 含义 |
|---|---|---|
enabled | true | 启用这个规则 |
port | 32958 | 监控你的 SSH 端口(改成你自己设置的) |
maxretry | 1 | 1 次失败就封禁。因为我们已经禁用了密码登录,任何密码尝试都是恶意的 |
bantime | -1 | 永久封禁(-1 表示永远,不解封) |
findtime | 600 | 在 10 分钟窗口内累计失败次数 |
backend | systemd | 通过 systemd 的 journal 读取 SSH 日志 |
journalmatch | _COMM=sshd | 匹配 SSH 进程的日志条目(不同系统有差异) |
5.3 journalmatch 适配(不同系统有区别)
journalmatch 的值取决于你的系统 SSH 服务名,配置错了 fail2ban 就检测不到登录尝试。
# ----- 查看你的 SSH 服务名(用这个命令确认)-----
systemctl list-units --type=service | grep ssh
# 根据输出结果选择对应的配置:
#
# 如果输出 ssh.service(Ubuntu/Debian 常见):
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd
# 如果输出 sshd.service(CentOS 常见):
journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd
systemctl list-units --type=service | grep ssh
# 确认 fail2ban 能正确匹配日志
journalctl -u ssh.service --since "-5 min" | grep "Invalid user\|Failed password"5.4 启动并验证
# 重启 fail2ban 使配置生效
systemctl restart fail2ban
# 等待 2 秒让服务完全启动
sleep 2
# 查看 SSH 防护状态
# 如果显示 Active: active (running) 说明启动成功
fail2ban-client status sshd输出示例:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0 ← 当前累计失败次数
| |- Total failed: 0 ← 总失败次数
`- Actions
|- Currently banned: 0 ← 当前被封禁的 IP 数
|- Total banned: 0 ← 累计封禁的 IP 数测试 fail2ban 是否真的能封禁:
# 打开一个新终端,故意输错密码登录一次
# 注意:这里用密码方式尝试,你的密钥不会触发封禁
ssh -p 32958 root@你的服务器IP
# 随便输入一个错误密码
# 回到原来终端,再次查看封禁状态
fail2ban-client status sshd如果看到 Currently banned: 1,说明 fail2ban 生效了——这个 IP 永远不能再用 SSH 连接你的服务器了。
5.5 子网自动封段(可选但推荐)
如果你留意日报数据,会发现攻击 IP 经常来自同一个 C 段(比如 213.209.159.x 有十几个不同 IP 在换着尝试)。这时只封单个 IP 不够,应该把整个 /24 段一起封了。
这个功能内置在日报程序里,每 30 分钟自动扫描一次 fail2ban 的封禁列表,如果发现同一个 C 段有 ≥2 个 IP 被封,就自动通过 iptables 封禁整个子网。
# 在 config.yml 中启用:
# subnet_ban:
# enabled: true
# threshold: 2 # 同 C 段 ≥2 个 IP 触发封段
# check_interval: 30 # 每 30 分钟扫描一次具体配置在下一章「部署日报程序」中详细说明。
六、部署日报程序
6.1、项目结构
server-report/
├── go/ # 服务端 Go 源码
│ ├── main.go # 入口(--serve 启动API)
│ ├── config.go # 配置管理
│ ├── serve.go # HTTP API 服务器
│ ├── report_api.go # 日报数据构建
│ ├── report_json.go # JSON 数据模型
│ ├── fail2ban.go # fail2ban 管理 + 地理位置
│ ├── system.go # 系统信息采集
│ ├── ssh_auth.go # SSH 审计
│ ├── network.go # 网络连接分析
│ ├── firewall.go # 防火墙统计
│ ├── services.go # 服务列表
│ ├── changes.go # 系统变更追踪
│ ├── security.go # 安全检测
│ ├── mail.go # 邮件发送
│ ├── subnet.go # 子网封禁
│ └── util.go # 工具函数
├── gosrc/ # 编译好的服务端二进制程序
│ ├── server-report
│ └── config.yml # 示例配置
├── Client/ # 客户端
│ ├── ServerReport.app # macOS,付费
│ └── ServerReport.exe # Windows 付费
└── README.md# 创建目录
mkdir -p /data/server-report
cd /data/server-report
# 下载二进制(替换为实际下载地址)
下载日报程序压缩包后,上传到/data/server-report目录并解压
chmod 755 server-report6.2、服务器端自行编译
cd go
GOOS=linux GOARCH=amd64 go build -o ../data/server-report .或者直接使用预编译的二进制
/data/server-report6.3、上传到服务器
scp server-report root@你的服务器IP:/data/server-report/server-report
scp config.sample.yml root@你的服务器IP:/data/server-report/config.sample.yml
ssh root@你的服务器IP "mv /data/server-report/config.sample.yml /data/server-report/config.yml"
ssh root@你的服务器IP "chmod +x /data/server-report/server-report"6.4 修改配置文件
# 编辑配置文件
ssh root@你的服务器IP "vi /data/server-report/config.yml"server:
name: "myserver" # 你的服务器名称(邮件标题中用)
ip: "" # 留空自动获取公网 IP
ssh_port: 32958 # 改成你自己的SSH登陆端口
api_key: "your-api-key-here" # API 密钥(建议32位大小写字母加数字)
api_port: 8080
smtp:
server: "mail.example.com" # SMTP 服务器地址
port: 465 # 465=SSL / 587=STARTTLS
ssl: true
user: "user@example.com" # SMTP帐号
password: "your-password" # SMTP密码
mail:
to: "admin@example.com" # 接收日报的邮箱
from: "user@example.com" # 发件人地址
subject: "服务器日报 - {name} / {ip} - {date}" # 发件邮箱标题
schedule:
report_at: "00:01" # 每天发送时间,24小时制
modules:
system: true # 系统健康
ssh_auth: true # SSH 登录审计
fail2ban: true # fail2ban 封禁统计
network: true # 网络连接
firewall: false # 防火墙(UWF/firewalld 统计)
services: true # 服务列表
changes: true # 系统变更
security: true # 安全检测
security:
fail2ban:
enabled: true
maxretry: 1
bantime: -1
findtime: 600
journalmatch: "_SYSTEMD_UNIT=ssh.service + _COMM=sshd"
subnet_ban:
enabled: true # 是否启用子网自动封段
threshold: 2 # 同 C 段 ≥2 个 IP 被封时封整个段
check_interval: 30 # 每 30 分钟扫描一次6.4.1、配置文件说明
| 字段 | 说明 | 默认值 |
|---|---|---|
server.name | 服务器名称,用于邮件标题 | 必填 |
server.ip | 固定 IP,留空自动获取 | 自动 |
server.ssh_port | SSH 端口 | 22 |
server.api_key | API 认证密钥(建议32位随机字符串) | 必填 |
server.api_port | API 监听端口 | 8080 |
smtp.* | 邮件发送配置 | 必填 |
mail.* | 邮件接收配置 | 必填 |
modules.* | 各功能模块开关 | true |
security.fail2ban.maxretry | 封禁阈值 | 1 |
security.fail2ban.bantime | 封禁时长(秒,-1=永久) | -1 |
security.subnet_ban.threshold | 封段阈值 | 2 |
6.4.2、API Key 说明
| 项目 | 说明 |
|---|---|
| 长度要求 | 建议 32 位 随机字符串(如 a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6) |
| 字符范围 | 建议使用大小写字母 + 数字(a-z, A-Z, 0-9),不支持中文或特殊符号 |
| 生成方式 | 在服务端 config.yml 中手动设置,客户端填相同的值 |
| 用途 | 认证请求来源,防止未授权访问 API |
| 安全性 | api_key 通过 URL 参数传输,建议搭配防火墙 IP 白名单使用 |
6.4.3、生成示例命令:
# Linux 生成32位随机API Key
tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 32 | head -1
# macOS 生成32位随机API Key
openssl rand -hex 166.5、预编译的二进制目录结构
最终 /data/server-report/ 目录下应该只有两个文件:
/data/server-report/
├── server-report ← 二进制文件(7.8MB)
└── config.yml ← 配置文件整个系统就这两个文件,迁移到新服务器时整个目录拷走就行。
6.6、手动测试
/data/server-report/server-report --run-once如果配置正确,你的邮箱会收到一封测试日报邮件。
6.7、配置定时任务
注:第6.7-6.8条为旧版定时发送邮件服务使用,新版仍可使用。
# 每天 00:01 发送日报
cat > /etc/cron.d/server-report << 'EOF'
1 0 * * * root /data/server-report/server-report
EOF
# 每 30 分钟检查一次子网封禁(如果启用了 subnet_ban)
cat > /etc/cron.d/ban-subnet << 'EOF'
*/30 * * * * root /data/server-report/server-report --subnet-scan
EOF
chmod 644 /etc/cron.d/server-report /etc/cron.d/ban-subnet关于
/etc/cron.d/的注意事项:
- 文件必须有一个空行结尾(否则 cron 可能不执行)
- 文件名不要包含
.以外的特殊字符如果定时任务不执行,可以改用
crontab -e方式:(crontab -l 2>/dev/null; echo "1 0 * * * /data/server-report/server-report") | crontab -
6.8、验证定时任务
# 查看已安装的 cron 任务
cat /etc/cron.d/server-report
# 或查看用户 crontab(如果用 crontab 方式)
crontab -l6.9、创建 systemd 服务
cat > /etc/systemd/system/server-report-api.service << 'EOF'
[Unit]
Description=Server Report API Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/data/server-report/server-report --serve
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable server-report-api.service
systemctl start server-report-api.service6.10、验证服务
# 查看服务状态
systemctl status server-report-api.service
# 测试 API
curl "http://IP:8080/api/v1/report?key=your-api-key-here"6.11、API 端口放行
如果使用客户端需要远程连接API,需在防火墙放行端口:
ufw allow 8080/tcp # Ubuntu/Debian
firewall-cmd --add-port=8080/tcp # CentOS/RHEL6.12、更新服务端
# 停止服务
systemctl stop server-report-api.service
# 备份旧版本
mv /data/server-report/server-report /data/server-report/server-report.bak
# 上传新版本
scp server-report-linux root@服务器IP:/data/server-report/server-report
ssh root@服务器IP "chmod +x /data/server-report/server-report"
# 启动服务
systemctl start server-report-api.service6.13、定时任务(数据采集策略)
服务端每小时自动采集一次系统数据,保存为 today.json,客户端查询时直接读文件返回(毫秒级响应)。每天凌晨将前一天数据归档为 YYYY-MM-DD.json,保留 180 天。
| 时间 | 任务 | 说明 |
|---|---|---|
| 每小时(0分) | --save-report | 采集系统数据更新 today.json |
| 每天 00:01 | --save-report --archive | 将前一天数据归档为 YYYY-MM-DD.json |
| 每天 03:00 | journalctl 清理 | 清理 180 天前的系统日志 |
| 每天 03:00 | 报告文件清理 | 删除 reports/ 中超过 180 天的 .json 文件 |
设置方式(已配置好,无需手动操作):
crontab -l
# 输出:
# 0 * * * * /data/server-report/server-report --save-report
# 1 0 * * * /data/server-report/server-report --save-report --archive
# 0 3 * * * /usr/bin/journalctl --vacuum-time=180d --quiet
# 0 3 * * * find /data/server-report/reports -name "*.json" -mtime +180 -delete6.14、日志管理
服务状态和系统错误日志通过 journalctl 管理。每天凌晨 3 点自动清理 180 天前的日志和归档报告文件。
手动清理:
# 清理 180 天前的日志
journalctl --vacuum-time=180d
# 删除旧归档报告
find /data/server-report/reports -name "*.json" -mtime +180 -delete6.15、命令说明
| 命令 | 说明 |
|---|---|
server-report --serve | 启动 API 服务(供客户端调用) |
server-report --save-report | 立即采集一次数据并保存到 today.json |
server-report --save-report --archive | 将前一天数据归档为 YYYY-MM-DD.json |
server-report --run-once | 立即发送一次邮件日报 |
server-report --subnet-scan | 手动扫描并封禁恶意子网 |
server-report --version | 查看版本 |
server-report --help | 查看帮助 |
七、日报内容解读
7.1、服务器安全日志客户端主界面

7.2、SSH登陆审计封禁列表

7.3、fail2ban封禁列表

7.4、针对中国IP单独进行了市级显示

7.5、IP-C段封禁效果以及其它模块

八、常见问题排查
Q1:收不到邮件
检查步骤:
# 1. 手动触发发送,看有没有报错
/data/server-report/server-report --run-once
# 2. 确认 SMTP 配置是否正确
cat /data/server-report/config.yml | grep -E "smtp:|server:|port:|user:|password:|mail:"
# 3. 确认 SSL 端口可连通
echo | openssl s_client -connect mail.example.com:465 -servername mail.example.com 2>/dev/null | head -5
# 4. 如果 SSL 证书验证失败,程序会自动降级,但需要确认 SMTP 账号密码正确常见问题:
- 密码包含特殊字符(
'、;、$等),需要用双引号包裹:password: "your'pass;word" - 465端口被运营商屏蔽(尤其是家庭宽带),可以试试587(STARTTLS)
- SMTP服务商要求开启「允许低安全性应用访问」
Q2:IP 归属地显示英文,没有中文
# 检查是否安装了 geoip-bin
geoiplookup 8.8.8.8
# 如果没安装
apt install -y geoip-bin # Ubuntu/Debian
yum install -y geoip # CentOSQ3:成功登录记录出现 @ 方式: key
这是新版 OpenSSH 日志格式变化导致的用户名解析问题,不影响功能。如果介意,可以升级到最新版二进制。
Q4:系统错误日志里很多看不懂的提示
日报已经内置了白噪音过滤列表,以下类型的错误会被自动过滤:
| 错误类型 | 原因 | 是否影响安全 |
|---|---|---|
no more sessions | SSH 并发限制 | ❌ 正常 |
AF_VSOCK CID | 虚拟机不支持 VSOCK | ❌ 正常 |
systemd-ssh-generator | 同上 | ❌ 正常 |
soft lockup | CPU 瞬时过载 | ❌ 正常 |
kdump / Crash recovery kernel | 内核崩溃转储服务未启动 | ❌ 正常 |
sendmail 相关 | sendmail 已卸载 | ❌ 正常 |
如果还有其他看不懂的错误,检查是否是服务器上的业务程序(如 MySQL、Nginx、PHP-FPM)的正常日志,也可以发给AI查询。
也非常欢迎大家在文章下方给我留言,把系统错误日志贴给我(无伤大雅的并影响每日汇报内容需要去掉的),我将一一进行汇总,对程序进行更新并重新布发升级版。
Q5:定时任务不执行
# 1. 检查 cron 服务状态
systemctl is-active cron # Ubuntu/Debian
systemctl is-active crond # CentOS
# 2. 检查 /etc/cron.d/ 文件格式
cat -A /etc/cron.d/server-report
# 正常输出应以 $ 结尾(表示有新行)
# 3. 如果还不行,改用 crontab 方式:
(crontab -l 2>/dev/null; echo "1 0 * * * /data/server-report/server-report") | crontab -Q6:不同系统版本 SSH 日志格式不同
日报程序已经兼容了以下格式:
| 系统版本 | SSH 日志格式 |
|---|---|
| Debian 12 (OpenSSH < 9.8) | Failed password for invalid user xxx |
| Debian 13 (OpenSSH ≥ 9.8) | Invalid user xxx from IP + 旧格式并存 |
| Ubuntu 20.04+ | Failed password for invalid user xxx |
| CentOS 7+ | Failed password for invalid user xxx |
Q7:如何更新日报程序
# 下载新版二进制
经常访问本地址查看站长有无更新,若有新版重新下载上传到服务器即可。
# 设置权限
chmod 755 /data/server-report/server-report
# 配置文件和之前的任务不受影响Q8:客户端提示"连接失败"或"获取日报失败"
- 确认服务器 API 端口(默认 8080)在防火墙上已放行
- 确认客户端填写的 API Key 与服务端
config.yml中的api_key一致 - 确认能从客户端网络访问服务器 IP 和端口:
telnet 服务器IP 8080 - 服务端每小时自动采集数据,客户端查询为毫秒级响应;如果刚好在第一小时部署还未生成缓存,会实时采集一次(约20-30秒),之后即可秒回
Q9:客户端找不到配置文件
macOS:~/.config/server-report/servers.json
Windows:程序目录下的 config/servers.json
使用"导入数据"功能(📂 按钮)可从备份目录恢复配置和日报缓存。
九、API 接口
获取日报
GET /api/v1/report?key=你的API密钥响应格式:
{
"status": "ok",
"server": "服务器名称",
"timestamp": "2026-06-29 10:30:00",
"date": "2026-06-28 → 2026-06-29",
"sections": [
{
"id": "system",
"title": "系统健康",
"type": "system",
"data": {
"hostname": "...",
"ip": "...",
"uptime": "...",
"load": "...",
"cpu": "...",
"memory": { "used": "...", "total": "...", "percent": 0 },
"disks": [{ "mount": "/", "used": "...", "total": "...", "percent": 0 }]
}
},
{
"id": "ssh_auth",
"title": "SSH 登录审计",
"type": "ssh_auth",
"data": {
"failed_total": 0,
"failed_ips": 0,
"failed_detail": [{ "ip": "1.2.3.4", "count": 5, "users": ["root"], "first": "...", "last": "...", "location_cn": "中国", "location_en": "China", "location_detail": "广东省广州市" }],
"success_total": 0,
"success_list": [{ "ip": "1.2.3.4", "count": 1, "method": "publickey" }]
}
},
{
"id": "fail2ban",
"title": "fail2ban 封禁统计",
"type": "fail2ban",
"data": {
"total_banned": 0,
"current_banned": 0,
"banned_ips": [{ "ip": "1.2.3.4", "location_cn": "美国", "location_en": "USA", "ban_time": "...", "users": ["root"], "attempts": 10, "subnet": "1.2.3.0/24" }],
"banned_subnets": [{ "subnet": "1.2.3.0/24", "ip_count": 3 }]
}
},
{
"id": "network",
"title": "网络连接与流量",
"type": "network",
"data": { "established": 0, "time_wait": 0, "total": 0, "top_conns": [], "listening_ports": [], "traffic": [] }
},
{
"id": "firewall",
"title": "防火墙拦截统计",
"type": "firewall",
"data": { "total_blocks": 0, "top_src": [], "top_dst": [] }
},
{
"id": "services",
"title": "运行中的系统服务",
"type": "services",
"data": { "total": 0, "running": [] }
},
{
"id": "changes",
"title": "系统变更记录",
"type": "changes",
"data": { "packages": [] }
},
{
"id": "security",
"title": "安全检测",
"type": "security",
"data": { "suid_ok": true, "new_users": [], "suspicious": [], "online_users": [], "errors": [] }
}
]
}健康检查
GET /api/v1/ping?key=你的API密钥十、客户端(付费)
10.1 macOS 客户端
运行: 拷贝 ServerReport.app 到应用程序目录直接打开即可使用。
数据存储: ~/.config/server-report/
servers.json— 服务器配置列表reports/*.json— 历史日报缓存
10.2 Windows 客户端
运行: 直接双击 ServerReport.exe
数据存储: 程序所在目录下的 config/ 文件夹
config/servers.json— 服务器配置列表config/reports/*.json— 历史日报缓存
10.3、客户端功能列表:
功能列表:
| 功能 | 说明 |
|---|---|
| 多服务器管理 | 左侧列表添加/编辑/删除多台服务器,右键菜单操作 |
| 日报展示 | 8 个功能区块,数据结构与服务端 API 完全对应 |
| SSH 审计 | 表格展示:IP、国家(归属地)、封禁时间、尝试用户、次数,次数超 10 标红 |
| fail2ban | 累计/当前封禁数,国家下拉筛选,表头可排序(IP/国家/封禁时间/尝试用户/次数),C段子网点击展开 |
| 日历 | 📅 按钮弹出日历,可切换年月,有数据的日期加重颜色背景 |
| 手动刷新 | ↻ 按钮重新拉取日报 |
| 导入数据 | 📂 按钮从目录选择器导入配置和缓存 |
| 显示切换 | 👁 按钮(在 show/hide 间切换)控制服务器列表IP显示 |
| 导出配置 | 右键服务器 → 导出,下载 servers.json |
| 关于页面 | 关于窗口,含版本、开发信息、GitHub 链接 |
10.4、日报服务器程序下载,免费开放
下载地址,蓝奏云网盘,回复可见:
10.5、客户端下载(付费)
10.6、项目反馈
如果你在使用过程中遇到问题,或者有功能建议,下方留言吧,或者给我发邮件。
本项目不提供技术支持,若需技术支持,可以有尝代部署,收费60元/台,B站或抖音粉丝半价。
mail:me@rongyan.cc
兄弟牛逼啊 这么快就能变现。。。
赚点零花钱嘛:)
感谢
看了视频来的,主要想要日报程序
感谢
感谢
感谢分享
感谢博主的分享