githubixx.harden_linux

加固 Linux 的 Ansible 角色

这个 Ansible 角色主要是为我的博客系列 Kubernetes 的简单方法与 Ansible - 加固实例 创建的。当然,它也可以独立使用来加固 Linux。它具有以下功能(其中一些是可选的):

  • 添加一个用于管理的常规/部署用户(例如,用于 Ansible 或 SSH 登录)
  • 调整 APT 更新间隔
  • 设置 UFW 防火墙,默认只允许 SSH 访问(如果需要,可以添加更多规则/允许的网络)
  • 调整与安全相关的 sysctl 设置
  • 调整 sshd 设置,例如禁用 sshd 密码认证,禁用 sshd 根用户登录,禁用 sshd PermitTunnel
  • 安装 sshguard 并调整白名单
  • 更改根用户密码
  • 安装/配置 网络时间同步(NTP),例如 openntpd/ntp/systemd-timesyncd
  • 修改 systemd-resolved 配置

版本

我为每个版本打上标签,并努力遵循 语义化版本控制。如果你想使用这个角色,我建议你查看最新的标签。主分支基本上是开发,而标签标记稳定版本。但一般来说,我也会尽量保持主分支的良好状态。

更新日志

变更历史:

查看完整的 CHANGELOG.md

最近更改:

v8.2.0

  • 新特性
    • 支持 Ubuntu 24.04

v8.1.0

  • 其他

    • 更新关于使用 mkpasswd 而不是 ansible 创建加密密码的注释
    • Ubuntu: 添加自动删除任务
    • 更新 Github 工作流
  • MOLECULE

    • 使用 alvistack 替代 generic Vagrant box
    • 使用不同的 IP 地址

v8.0.0

  • 重大更新/新特性

    • 引入 harden_linux_deploy_groupharden_linux_deploy_group_gid 变量。两者都是可选的。但至少 harden_linux_deploy_group 必须在 harden_linux_deploy_user 设定的情况下被指定。如果设置为 root,则不会有任何更改。
    • 如果 harden_linux_deploy_user 设定为 root,则不会有任何更改。
    • harden_linux_deploy_user 现在是可选的。如果未设定,将不会创建用户。所有以 harden_linux_deploy_user_ 开头的变量仅在 harden_linux_deploy_user 被指定时使用。另添加了 harden_linux_deploy_user_home 变量,harden_linux_deploy_user_shellharden_linux_deploy_user_homeharden_linux_deploy_user_uidharden_linux_deploy_user_password 现在都是可选的。harden_linux_deploy_user 的 $HOME 目录仅在设置了 harden_linux_deploy_user_home 时创建。
  • MOLECULE

    • 更新测试场景以反映部署用户/组更改

安装

  • 从 Github 直接下载(在克隆之前切换到 Ansible 角色目录。可以使用 ansible-config dump | grep DEFAULT_ROLES_PATH 命令找出角色路径): git clone https://github.com/githubixx/ansible-role-harden-linux.git githubixx.harden_linux

  • 通过 ansible-galaxy 命令直接从 Ansible Galaxy 下载: ansible-galaxy install role githubixx.harden_linux

  • 创建一个 requirements.yml 文件,内容如下(这将从 Github 下载角色),然后使用 ansible-galaxy role install -r requirements.yml 安装(如有需要,请更改 version):

---
roles:
  - name: githubixx.harden_linux
    src: https://github.com/githubixx/ansible-role-harden-linux.git
    version: v8.1.0

角色变量

以下变量没有默认值。您需要在 group_varshost_vars 目录中的文件中指定它们。例如,如果这些设置仅适用于一个特定主机,请为该主机创建一个文件,文件名与该主机的完全限定域名相同(例如 host_vars/your-server.example.tld),并在那里添加变量及其正确值。如果您想将这些变量应用于一个主机组,请创建一个文件 group_vars/your-group.yml,例如用该主机组名称替换 your-group(请不要与 /etc/hosts 混淆)。

如果您想设置或更改 root 用户的密码,请设置 harden_linux_root_password 变量。这是可选的。它期望一个加密密码。Ansible 不会为您加密密码。如何创建加密密码可参考 Ansible 常见问题解答。在 Linux 上,以下命令可能是最可靠的:

mkpasswd --method=sha-512

要安装一个可以无密码执行 sudo 的用户,请设置以下变量:

harden_linux_deploy_user: "a_username"
harden_linux_deploy_user_password: "a_password"
harden_linux_deploy_user_home: "/home/a_user"
harden_linux_deploy_user_uid: "9999"
harden_linux_deploy_user_gid: "9999"
harden_linux_deploy_user_shell: "/bin/bash"

harden_linux_deploy_user 指定我们要用于登录远程主机的用户。如前所述,harden_linux 角色将出于合理原因禁用根用户通过 SSH 登录。因此需要一个不同的用户。这个用户将被授予 "sudo" 权限,这对 Ansible(和/或您自己)完成工作是必需的。

harden_linux_deploy_user_password 中存储用户的加密密码。与 harden_linux_root_password 相关的内容同样适用。

用户的 $HOME 目录在 harden_linux_root_password 中指定。要设置 UID 和 GID,请使用 harden_linux_deploy_user_uidharden_linux_deploy_user_gid注意:如果用户已存在但具有不同的主目录、UID 和/或 GID,它将根据上述设置进行更改!这也适用于指定用户登录后应该使用的 shell 的 harden_linux_deploy_user_shell

harden_linux_deploy_user_public_keys 指定一个公钥 SSH 文件列表,您希望将其添加到远程主机上部署用户的 $HOME/.ssh/authorized_keys 中。如果您在这里指定 /home/deploy/.ssh/id_rsa.pub,则该本地文件的内容(在 Ansible 控制节点上)将被添加到远程主机上的部署用户的 $HOME/.ssh/authorized_keys 中。

harden_linux_optional_packages(在该角色的 v6.0.0 版本之前此变量被称为 harden_linux_required_packages)指定要在远程主机上安装的其他/可选软件包。默认情况下此变量未指定。例如:

harden_linux_optional_packages:
  - vim

与前面的变量相对, harden_linux_absent_packages 将卸载远程主机上的 OS 软件包。默认情况下此变量未指定。例如:

harden_linux_absent_packages:
  - vim

以下变量具有默认值。因此只有在需要其他值时才需要更改它们。角色默认更改一些 sshd 设置:

harden_linux_sshd_settings:
  "^PasswordAuthentication": "PasswordAuthentication no"  # 禁用密码认证
  "^PermitRootLogin": "PermitRootLogin no"                # 禁用 SSH 根登录
  "^PermitTunnel": "PermitTunnel no"                      # 禁用 tun(4) 设备转发
  "^Port ": "Port 22"                                     # 设置 sshd 端口

我个人总是更改默认 SSH 端口,因为很多暴力破解攻击发生在此端口(但当然,端口扫描器仍然能够快速找出这一点)。因此,如果您想更改端口设置,可以例如这样做:

harden_linux_sshd_settings_user:
  "^Port ": "Port 22222"

(请注意 ^Port 后的空格!)。该剧本将合并 harden_linux_sshd_settingsharden_linux_sshd_settings_user,而 harden_linux_sshd_settings_user 中的设置优先,这意味着它将覆盖 harden_linux_sshd_settings 中的 ^Port 设置/键。正如您可能已经注意到的,harden_linux_sshd_settingsharden_linux_sshd_settings_user 中的所有键都以 ^ 开头。这是因为它是一个正则表达式 (regex)。剧本中的一个任务将搜索 /etc/ssh/sshd_config 中的某行,例如 ^Port (而 ^ 表示“以...开头的行”),并用例如 Port 22222 替换该行(如果找到)。这种方式使剧本在调整 sshd_config 中的设置时非常灵活(您基本上可以替换每个设置)。您也会看到其他任务中有这种模式。所以在这种情况下所有提到的内容都成立。

接下来是一些防火墙/iptables 的默认设置。防火墙/iptables 规则和设置由 UFW 管理:

harden_linux_ufw_defaults:
  "^IPV6": 'IPV6=yes'
  "^DEFAULT_INPUT_POLICY": 'DEFAULT_INPUT_POLICY="DROP"'
  "^DEFAULT_OUTPUT_POLICY": 'DEFAULT_OUTPUT_POLICY="ACCEPT"'
  "^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="DROP"'
  "^DEFAULT_APPLICATION_POLICY": 'DEFAULT_APPLICATION_POLICY="SKIP"'
  "^MANAGE_BUILTINS": 'MANAGE_BUILTINS=no'
  "^IPT_SYSCTL": 'IPT_SYSCTL=/etc/ufw/sysctl.conf'
  "^IPT_MODULES": 'IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns"'

这些设置基本上是更改 /etc/defaults/ufw 中的值。要覆盖一个或多个默认设置,您可以通过指定上述相同的键(这是一个正则表达式)来做到这一点,例如 ^DEFAULT_FORWARD_POLICY 并简单地分配一个新值:

harden_linux_ufw_defaults_user:
  "^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="ACCEPT"'

如前所述,该剧本还将合并 harden_linux_ufw_defaultsharden_linux_ufw_defaults_user,而 harden_linux_ufw_defaults_user 中的设置优先。

接下来我们可以使用 harden_linux_ufw_rules 指定一些防火墙规则。默认情况下允许在端口 22 上进行 SSH 流量(使用 TCP 协议):

harden_linux_ufw_rules:
  - rule: "allow"
    to_port: "22"
    protocol: "tcp"

以下参数可用,具有默认值(如有):

rule (无默认值)
interface (默认 '')
direction (默认 'in')
from_ip (默认 'any')
to_ip (默认 'any')
from_port (默认 '')
to_port (默认 '')
protocol (默认 'any')
log (默认 'false')
delete (默认 'false')

一个 规则 可以具有值 allowdenylimitrejectinterface 指定规则的接口。directioninout)用于接口,依据方向的值而定。from_ip 指定源 IP 地址, from_port 指定源端口。to_ip 指定目标 IP 地址, to_port 指定目标端口。protocol 默认为 any。可能值为 tcpudpipv6espahgreigmplog 可以是 false(默认)或 true,指示是否应记录匹配该规则的新连接。delete 指示是否应删除规则。如果之前添加的规则需要被移除,那么这就很重要。仅从 harden_linux_ufw_rules 中移除规则是不够的!您必须使用 delete 删除该规则。

您还可以允许主机在特定网络上进行通信(没有端口限制),例如:

harden_linux_ufw_allow_networks:
  - "10.3.0.0/24"
  - "10.200.0.0/16"

接下来,harden_linux 角色还会更改某些系统变量(sysctl.conf / proc 文件系统)。这些设置是 Google 的建议,他们在 Google Compute Cloud OS 镜像中使用这些设置(请参阅 Google Cloud - 构建自定义映像的要求配置与 Compute Engine 导入的映像)。以下是默认设置(如果您对这些设置满意,则无需做任何事情,但我建议验证它们是否适用于您的设置):

harden_linux_sysctl_settings:
  "net.ipv4.tcp_syncookies": 1                    # 启用 syn flood 保护
  "net.ipv4.conf.all.accept_source_route": 0      # 忽略源路由的数据包
  "net.ipv6.conf.all.accept_source_route": 0      # IPv6 - 忽略 ICMP 重定向
  "net.ipv4.conf.default.accept_source_route": 0  # 忽略源路由的数据包
  "net.ipv6.conf.default.accept_source_route": 0  # IPv6 - 忽略源路由的数据包
  "net.ipv4.conf.all.accept_redirects": 0         # 忽略 ICMP 重定向
  "net.ipv6.conf.all.accept_redirects": 0         # IPv6 - 忽略 ICMP 重定向
  "net.ipv4.conf.default.accept_redirects": 0     # 忽略 ICMP 重定向
  "net.ipv6.conf.default.accept_redirects": 0     # IPv6 - 忽略 ICMP 重定向
  "net.ipv4.conf.all.secure_redirects": 1         # 忽略来自非网关主机的 ICMP 重定向
  "net.ipv4.conf.default.secure_redirects": 1     # 忽略来自非网关主机的 ICMP 重定向
  "net.ipv4.ip_forward": 0                        # 不允许网络间的流量或作为路由器
  "net.ipv6.conf.all.forwarding": 0               # IPv6 - 不允许网络间的流量或作为路由器
  "net.ipv4.conf.all.send_redirects": 0           # 不允许网络间的流量或作为路由器
  "net.ipv4.conf.default.send_redirects": 0       # 不允许网络间的流量或作为路由器
  "net.ipv4.conf.all.rp_filter": 1                # 反向路径过滤 - IP 欺骗保护
  "net.ipv4.conf.default.rp_filter": 1            # 反向路径过滤 - IP 欺骗保护
  "net.ipv4.icmp_echo_ignore_broadcasts": 1       # 忽略 ICMP 广播以避免参与 Smurf 攻击
  "net.ipv4.icmp_ignore_bogus_error_responses": 1 # 忽略错误 ICMP 错误
  "net.ipv4.icmp_echo_ignore_all": 0              # 忽略错误 ICMP 错误
  "net.ipv4.conf.all.log_martians": 1             # 记录伪造、源路由以及重定向的数据包
  "net.ipv4.conf.default.log_martians": 1         # 记录伪造、源路由以及重定向的数据包
  "net.ipv4.tcp_rfc1337": 1                       # 实施 RFC 1337 修复
  "kernel.randomize_va_space": 2                  # 随机化 mmap 基址、堆、栈以及 VDSO 页面的地址
  "fs.protected_hardlinks": 1                     # 提供对 ToCToU 竞赛条件的保护
  "fs.protected_symlinks": 1                      # 提供对 ToCToU 竞赛条件的保护
  "kernel.kptr_restrict": 1                       # 使定位内核地址更加困难
  "kernel.perf_event_paranoid": 2                 # 仅 root 可用 perf

您可以通过创建一个名为 harden_linux_sysctl_settings_user 的变量来覆盖每个单独的设置:

harden_linux_sysctl_settings_user:
  "net.ipv4.ip_forward": 1
  "net.ipv6.conf.default.forwarding": 1
  "net.ipv6.conf.all.forwarding": 1

剧本中的一个任务将合并 harden_linux_sysctl_settingsharden_linux_sysctl_settings_user,而 harden_linux_sysctl_settings_user 的设置将优先。有关设置的更多信息,请查看角色的 defaults/main.yml 文件。

如果您想启用 UFW 日志记录,请设置:

harden_linux_ufw_logging: 'on'

可能值为 onofflowmediumhighfull

接下来是 “sshguard” 设置。“sshguard” 保护免受对 SSH 的暴力破解攻击。为了避免一段时间内将自己锁定,您可以将 IP 或 IP 范围添加到白名单。默认情况下,它基本上只有“localhost”:

harden_linux_sshguard_whitelist:
  - "127.0.0.0/8"
  - "::1/128"

NTP 软件包也可以安装/配置。这是可选的。默认情况下,我建议使用 systemd-timesyncd。您也可以使用 ntp 软件包。但 openntpdsystemd-timesyncd 的优势在于它们默认不监听任何端口。如果您只想保持主机时钟同步,这完全足够。确保所有主机上的时间一致对某些服务至关重要。例如,用于证书验证、etcd、数据库、加密等。

有效的 harden_linux_ntp 选项是:

  • openntpd
  • ntp
  • systemd-timesyncd

正如前面提到的,openntpdsystemd-timesyncd 的优势在于它们默认不监听任何端口。如果您只想保持主机时钟同步,这两个中的任何一个应该可以完成工作。大多数现代 Linux 操作系统都使用 systemd,所以在这种情况下无需安装额外的软件包。要启用 openntpd,请相应设置 harden_linux_ntp,例如:

harden_linux_ntp: "openntpd"

openntpdntpdsystemd-timesyncd 的设置(见下一段)。有关进一步的选项,请查看手册页:man 5 ntpd.conf 适用于 ntpopenntpdman 5 timesyncd.conf 适用于 systemd-timesyncd

“关键”是您想要替换的设置的正则表达式,以及设置名称和设置值的组合。例如,我们想将 servers 0.debian.pool.ntp.org 替换为 servers 1.debian.pool.ntp.org。正则表达式(键)将是 ^servers 0,这意味着:

“在配置文件中搜索以 server 0 开头的行,将整行替换为 servers 1.debian.pool.ntp.org”。通过这种方式,可以将配置文件中的每个设置替换为其他东西。一些示例:

harden_linux_ntp_settings:
  "^servers 0": "servers 0.debian.pool.ntp.org"
  "^servers 1": "servers 1.debian.pool.ntp.org"
  "^servers 2": "servers 2.debian.pool.ntp.org"
  "^servers 3": "servers 3.debian.pool.ntp.org"

请注意:systemd-timesyncd 具有合理的编译时默认值。因此,通常无需更改配置(连 NTP 服务器也不需要)。因此,以下只是示例,但在实际情况下,您不需要为 systemd-timesyncd 指定 harden_linux_ntp_settings

对于 systemd-timesyncd,配置文件略有不同。在这种情况下,/etc/systemd/timesyncd.conf 的 systemd drop-in 将创建在 /etc/systemd/timesyncd.conf.d/ 中。

Debian 示例:

harden_linux_ntp_settings:
  "^#NTP=": "NTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org"

Ubuntu 示例:

harden_linux_ntp_settings:
  "^#NTP=": "NTP=ntp.ubuntu.com"

Archlinux 示例:

harden_linux_ntp_settings:
  "^#NTP=": "NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org"

使用 harden_linux_files_to_delete,可以指定一个文件列表,这些文件应在目标主机上不存在,例如:

harden_linux_files_to_delete:
  - "/root/.pw"

如果使用 systemd-resolved 进行 DNS 解析,可以通过 harden_linux_systemd_resolved_settings 调整其行为。默认情况下未指定此变量。将在 /etc/systemd/resolved.conf.d/99-override.conf 中创建 systemd drop-in 配置,并将指定的设置添加到那里。

注意:如果 /etc/systemd/resolved.conf 中已经设置了某个设置(例如 DNS=8.8.8.8),则在下面设置 DNS=9.9.9.9 将一起生效。这意味着最终设置将是 DNS=8.8.8.8 9.9.9.9。如果您不希望这样,您需要先“取消设置”该值,然后再添加您想要的新值。例如:

harden_linux_systemd_resolved_settings:
  - DNS=
  - DNS=9.9.9.9

虽然 Google DNS 服务器(8.8.8.88.8.4.4)提供快速的 DNS 查找,但当然这也是 Google 可以监视您的另一种可能性。因此,使用一些其他的 DNS 服务器至少应该是一个需要考虑的事情。但还有一点是加密 DNS 请求。systemd-resolved 支持的一个方式是 DNSOverTLSQuad9 (9.9.9.9/149.112.112.112)Cloudflare (1.1.1.1/1.0.0.1) 支持 DNSOverTLS
因此,以下 systemd-resolved 设置为 Quad9 和 Cloudflare DNS 配置 IPv4 和 IPv6。设置 DNSOverTLS=opportunistic 使用 DNSOverTLS,如果 DNS 服务器支持它,则回退到普通未加密 DNS(详见 resolved.conf.5):

harden_linux_systemd_resolved_settings:
  - DNS=
  - DNS=9.9.9.9 1.1.1.1 2606:4700:4700::1111 2620:fe::fe
  - FallbackDNS=
  - FallbackDNS=149.112.112.112 1.0.0.1 2620:fe::9 2606:4700:4700::1001
  - DNSOverTLS=
  - DNSOverTLS=opportunistic

此外,还可以影響软件包管理器的缓存行为。例如,对于 Ubuntu:

# 如果不希望更新软件包缓存,则将其设置为 "false"
harden_linux_ubuntu_update_cache: true

# 设置软件包缓存有效时间
harden_linux_ubuntu_cache_valid_time: 3600

对于 Archlinux:

# 如果不希望更新软件包缓存,则将其设置为 "false"
harden_linux_archlinux_update_cache: true

示例剧本

如果您通过 ansible-galaxy install githubixx.harden_linux 安装了角色,则可以像以下示例那样将角色包含到您的剧本中:

- hosts: webservers
  roles:
    - githubixx.harden_linux

测试

该角色具有一个小型测试设置,使用 Molecule、libvirt (vagrant-libvirt) 和 QEMU/KVM 创建。请查看我的博客文章 使用 Molecule、libvirt (vagrant-libvirt) 和 QEMU/KVM 测试 Ansible 角色 了解如何设置。测试配置在 这里

然后可以执行 molecule:

molecule converge

这将在支持的不同 Linux 操作系统上设置几个虚拟机 (VM),并相应地设置 harden_linux 角色。还包括一个小的验证步骤:

molecule verify

要清理,请运行:

molecule destroy

许可

GNU 通用公共许可证 第 3 版

作者信息

www.tauceti.blog

安装
ansible-galaxy install githubixx.harden_linux
许可证
gpl-3.0
下载
3.3k
拥有者
Senior System Engineer - Python, Go, Cloud, Kubernetes, Commodore, Retro, 80's ;-)