infra-lab-de/Raspberry-Pi-SSH-Server
GitHub: infra-lab-de/Raspberry-Pi-SSH-Server
该项目是一套树莓派 SSH 服务器的完整安全加固实践方案,通过公钥认证、nftables 防火墙、持久化日志和自动安全更新等措施系统性减少攻击面。
Stars: 0 | Forks: 0
# Raspberry Pi SSH 服务器
保护 Raspberry Pi 上的 SSH 访问——一个关于 Linux 基础、SSH 加固和网络安全的实践实验室项目。
## 构建内容
一台配置了加固 SSH 服务器的 Raspberry Pi,作为安全远程访问的基础。出发点是一个标准的 SSH 安装,包含密码登录、未使用的开放服务且没有防火墙——目标是将攻击面系统地减少到实际用途所需的最小程度。访问完全通过公钥认证进行,密码登录已不再可能。
## 系统环境
- 服务器:Raspberry Pi 5 2 GB 内存,Raspberry Pi OS
- 客户端:ThinkPad E16 32 GB 内存,Windows 11 专业版
## 配置产物
- SSH 配置:`/etc/ssh/sshd_config`
- 登录横幅:`/etc/ssh/banner.txt`
- 防火墙:`nftables`,配置文件位于 `/etc/nftables.conf`
- 持久化日志:`/etc/systemd/journald.conf.d/99-persistent.conf`
## 执行的 SSH 加固
作为 SSH 加固的一部分,多种不需要或不安全的访问方式已被禁用。这包括禁用直接 root 登录、停用 PAM 认证,以及将 SSH 访问限制为特定的 IP 地址。因此,只有使用指定认证方式的明确允许的连接才可能发生。
### SSH 密钥对
SSH 密钥对在客户端系统上生成,随后仅将公钥传输到 Raspberry Pi 上。私钥仅保留在客户端系统上,且在任何时候都不会传输到 Raspberry Pi 上。
使用的算法:
- `ed25519`(现代椭圆曲线算法)
- 私钥:`id_ed25519`
- 公钥:`id_ed25519.pub`
## 网络安全
为了分析攻击面,首先使用 `nmap` 进行了端口扫描。在此过程中识别了可访问的网络服务。
随后,在端口 `111` 上检测到的不必要的服务 `rpcbind` 被停止并禁用。
通过移除不必要的服务,减少了系统上潜在攻击点的数量。
## 防火墙 (nftables)
除了 SSH 方面的保护外,还使用 `nftables` 设置了专用的防火墙,以在网络层面控制传入流量:
- Input 链的默认策略设置为 `drop` —— 所有未明确允许的内容都将被丢弃
- 允许 Loopback 流量以及已经建立和相关的连接,丢弃无效数据包
- 仅明确开放 SSH 端口,并进一步将其限制为特定的 IP 地址
- 有针对性地允许 ICMP (Ping),但同样限制为特定的 IP 地址,以便仍能测试可达性
- 所有被丢弃的传入流量在被丢弃之前都会被额外记录(`log prefix "NFT INPUT DROP:"`)——这样可以追踪哪些连接尝试被防火墙拒绝
## SSH 访问
在建立连接时,会显示一个自定义的登录横幅,该横幅在认证之前出现,并提示需授权访问以及受到监控。
## 监控与日志
SSH 登录尝试通过 systemd 日志进行追踪——无论连接尝试成功还是失败,都会被记录下来。
结合防火墙层面丢弃数据包的日志记录,这提供了两个层面的可见性:防火墙拒绝了什么,以及谁实际通过了 SSH 服务的认证。
自 Bookworm 版本起,Raspberry Pi OS 不再包含 `rsyslog`,因此传统的文本日志(如 `/var/log/auth.log`)不再存在——日志记录完全通过 `journald` 运行。
**问题:** 默认情况下,Raspberry Pi OS 仅将日志记录存储在 RAM 中(`Storage=volatile`),这意味着所有日志在每次重启时都会丢失。原因是位于 `/usr/lib/systemd/journald.conf.d/40-rpi-volatile-storage.conf` 的内置系统配置强制指定了此模式,并覆盖了主配置(`/etc/systemd/journald.conf`)中的自定义更改。
**解决方案:** 位于 `/etc/systemd/journald.conf.d/99-persistent.conf` 的自定义 Drop-in 配置仅针对性地覆盖了这一项设置,而不会更改 Raspberry Pi 自带的文件。
重启 `systemd-journald` 后,日志将跨重启持久保存。
**存储空间:** 由于日志现在持久保存在 SD 卡上,因此应控制并在需要时限制 journal 的最大大小。例如,可以通过 journald 配置中的大小或时间限制来实现。
## 自动安全更新
为了定期安装与安全相关的更新,在 Raspberry Pi OS 上配置了 `unattended-upgrades`。
自动更新已配置为系统每天 **03:00** 查找安全更新并自动安装。
## 有意不使用 fail2ban
考虑过 `fail2ban`,但最终决定有意不使用。原因是:通过在登录尝试失败后封锁 IP 来防御暴力破解,主要针对的是从任意 IP 进行密码登录的场景——而这种攻击向量在这里已经在两个独立的层面上被排除了:
- **防火墙层面 (nftables):** 仅允许您自己的 IP 访问 SSH 端口,所有其他连接尝试在到达 SSH 服务之前都会被丢弃
- **应用层面 (sshd_config):** 通过 `AllowUsers` 额外限制为同一 IP,此外仅允许公钥认证,密码登录已被完全禁用
因此,攻击者不仅要绕过防火墙并伪造您的 IP 地址,还必须窃取有效的私钥——对于这种情况,`fail2ban` 的速率限制并不能提供实质性的额外保护。
这里有意选择了一种精简的安全架构,有针对性地使用现有的保护机制,仅在确实能带来增值时才添加额外的组件。
## 进一步的加固措施与未来考虑
目前的防护已经减少了系统的主要攻击面,特别是在 SSH 访问、网络过滤和日志记录方面。为了更全面地加固 Raspberry Pi,可以考虑采取进一步的措施:
### 禁用不必要的服务
原则上应禁用或移除不需要的本地服务,以进一步减少潜在的可攻击组件。
示例:
- 禁用未使用的硬件服务,如 Bluetooth
- 关闭不需要的打印服务,如 `CUPS`
- 移除或禁用默认安装但对当前用途不需要的其他服务
基本原则是:每个活跃的服务都构成了额外的攻击面,只有在确实需要时才应运行。
### 权限管理和用户加固
用户和权限管理可以进一步收紧:
- 审查现有用户账户
- 移除不需要的用户
- 最小化组成员身份
- 根据最小权限原则(`Least Privilege`)限制文件权限
- 检查并保护 `sudo` 权限
目标是确保用户和进程仅拥有其各自任务所需的权限。
### 内核加固
内核层面的额外保护措施可以进一步提高系统安全性:
- 通过 `sysctl` 调整安全相关的内核参数
- 在内核层面限制网络行为
- 针对特定攻击技术激活额外的保护机制
- 检查已加载的内核模块并禁用不需要的组件
### 定期安全审查
可以使用额外的审计工具来定期评估安全状态。
示例:
- 使用 `Lynis` 执行系统安全审计
- 使用 `nmap` 再次进行端口扫描以检查可访问的服务
- 分析系统和认证日志
- 在更改后检查防火墙规则和 SSH 配置
定期审计有助于及早发现新的配置错误,并长期维持系统的安全性。
## 截图
**登录横幅**

**之前的 nmap 扫描**

**之后的 nmap 扫描**

**SSH 配置片段**

**nftables 规则**

**持久化日志**

**用于自动安全更新的 Systemd 定时器**

标签:nftables, SSH安全加固, 内存分配, 系统加固, 网络安全, 运维, 隐私保护