从零到一:Linux 服务器安全加固 + 日报监控完整部署指南
文章目录

从零到一:Linux 服务器安全加固 + 日报监控完整部署指南

RONGYAN
2026-06-26 / 8 评论 / 51 阅读 / 耗时: 26 ms /

一、前言

我的服务器半个月前中过木马,具体见这篇文章: 服务器被植入流量劫持后门(跳转世界杯赌球网站)的排查与解决方案 后门连着海外的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 -y

2.2 安装基础工具

安装一些后续操作会用到的常用命令行工具。

工具作用
curl用来下载文件、调用 API、测试网络请求
wget下载文件(和 curl 类似,但更专注于文件下载)
git用来克隆代码仓库(如果需要从 GitHub 下载源码时用到)
vim一个命令行文本编辑器(编辑配置文件用)
# ------------------- Ubuntu / Debian -------------------
apt install -y curl wget git vim

# ------------------- CentOS -------------------
yum install -y curl wget git vim

2.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

选端口的建议:

  • ✅ 推荐:32958232541895742196(4-5 位数字,好记就行)
  • ❌ 避免:2222222228822(这些常见替代端口一样会被扫描)
  • ❌ 避免:22 附近的端口(2123 等也会被批量扫描)
三种系统注意: 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.com

3.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.log

CentOS 用 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 geoip

5.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

配置参数详解:

参数含义
enabledtrue启用这个规则
port32958监控你的 SSH 端口(改成你自己设置的)
maxretry11 次失败就封禁。因为我们已经禁用了密码登录,任何密码尝试都是恶意的
bantime-1永久封禁(-1 表示永远,不解封)
findtime600在 10 分钟窗口内累计失败次数
backendsystemd通过 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-report

6.2、服务器端自行编译

cd go
GOOS=linux GOARCH=amd64 go build -o ../data/server-report .
或者直接使用预编译的二进制
/data/server-report

6.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_portSSH 端口22
server.api_keyAPI 认证密钥(建议32位随机字符串)必填
server.api_portAPI 监听端口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 16

6.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 -l

6.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.service

6.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/RHEL

6.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.service

6.13、定时任务(数据采集策略)

服务端每小时自动采集一次系统数据,保存为 today.json,客户端查询时直接读文件返回(毫秒级响应)。每天凌晨将前一天数据归档为 YYYY-MM-DD.json,保留 180 天。

时间任务说明
每小时(0分)--save-report采集系统数据更新 today.json
每天 00:01--save-report --archive将前一天数据归档为 YYYY-MM-DD.json
每天 03:00journalctl 清理清理 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 -delete

6.14、日志管理

服务状态和系统错误日志通过 journalctl 管理。每天凌晨 3 点自动清理 180 天前的日志和归档报告文件。

手动清理:

# 清理 180 天前的日志
journalctl --vacuum-time=180d

# 删除旧归档报告
find /data/server-report/reports -name "*.json" -mtime +180 -delete

6.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登陆审计封禁列表

服务器安全日志客户端SSH登陆审计封禁列表

7.3、fail2ban封禁列表

服务器安全日志客户端fail2ban封禁列表

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

服务器安全日志客户端-针对中国IP单独进行了市级显示

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

服务器安全日志客户端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         # CentOS

Q3:成功登录记录出现 @ 方式: key

这是新版 OpenSSH 日志格式变化导致的用户名解析问题,不影响功能。如果介意,可以升级到最新版二进制。

Q4:系统错误日志里很多看不懂的提示

日报已经内置了白噪音过滤列表,以下类型的错误会被自动过滤:

错误类型原因是否影响安全
no more sessionsSSH 并发限制❌ 正常
AF_VSOCK CID虚拟机不支持 VSOCK❌ 正常
systemd-ssh-generator同上❌ 正常
soft lockupCPU 瞬时过载❌ 正常
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:客户端提示"连接失败"或"获取日报失败"

  1. 确认服务器 API 端口(默认 8080)在防火墙上已放行
  2. 确认客户端填写的 API Key 与服务端 config.yml 中的 api_key 一致
  3. 确认能从客户端网络访问服务器 IP 和端口:telnet 服务器IP 8080
  4. 服务端每小时自动采集数据,客户端查询为毫秒级响应;如果刚好在第一小时部署还未生成缓存,会实时采集一次(约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、客户端下载(付费)

价格: 25.00 元
VIP会员价格:25.00元终身会员免费
温馨提示:登录付款后可永久阅读隐藏内容。 付费可读

10.6、项目反馈

如果你在使用过程中遇到问题,或者有功能建议,下方留言吧,或者给我发邮件。
本项目不提供技术支持,若需技术支持,可以有尝代部署,收费60元/台,B站或抖音粉丝半价。
mail:me@rongyan.cc

你认为这篇文章怎么样?
  • 0
    点赞
  • 0
  • 0
  • 0
    滑稽
  • 0
    尴尬
  • 0
    睡觉
  • 打赏
    打赏

评论 (8)

取消
  1. Jonty
    未知地址
    沙发

    兄弟牛逼啊 这么快就能变现。。。

    回复 删除 垃圾 马赛克
    1. RONGYAN 作者
      江苏省常州市
      @ Jonty

      赚点零花钱嘛:)

      回复 删除 垃圾 马赛克
  2. axiang
    河南省新乡市
    板凳

    感谢

    回复 删除 垃圾 马赛克
  3. 匿名
    贵州省黔南布依族苗族自治州
    地毯

    看了视频来的,主要想要日报程序

    回复 删除 垃圾 马赛克
  4. ax
    河南省驻马店市
    第4楼

    感谢

    回复 删除 垃圾 马赛克
  5. 1
    山西省晋中市
    第5楼

    感谢

    回复 删除 垃圾 马赛克
  6. 大树
    未知地址
    第6楼

    感谢分享

    回复 删除 垃圾 马赛克
  7. 匿名
    广东省深圳市
    第7楼

    感谢博主的分享

    回复 删除 垃圾 马赛克
头像
邮箱:
I P:
互动: