接手一台裸奔的CentOS服务器,第一件事不是装业务,而是锁门。安全基线配置是所有运维动作的前置条件,但手动一台台去改SSH端口、禁root登录、配防火墙,不仅效率低下,更容易因为疲劳导致遗漏。Ansible的出现让这件事从手工作坊进化到了流水线,你只需要写一次剧本,就能让几十上百台服务器在几分钟内完成标准化加固。下面直接进入具体的实施方法,从环境准备到完整的Playbook编写,每一步都可落地执行。
被控节点的最小化准备Ansible基于SSH工作,被控端不需要安装Agent,但需要Python环境。CentOS 7和8默认安装了Python 2.7或3.6,Ansible控制端会调用它来执行模块。首先要确保被控节点的SSH服务正常运行,并且控制端已经生成了SSH密钥对。在控制端执行ssh-keygen -t ed25519生成更安全的Ed25519密钥,然后用ssh-copy-id将公钥分发到所有目标服务器。这一步完成后,务必在sshd_config中关闭密码认证,只保留密钥登录,否则你的自动化工具反而成了暴力破解的入口。
资产清单与动态分组逻辑安全基线不是一刀切,数据库服务器和Web应用服务器的策略肯定不同。Inventory文件需要按角色分组,而不是简单地把所有IP堆在一起。一个典型的hosts.ini应该这样组织:
[db_servers] 192.168.10.11 192.168.10.12 [web_servers] 192.168.10.21 192.168.10.22 [all_servers:children] db_servers web_servers
分组之后,可以在Playbook中针对不同组应用不同的变量和任务。比如数据库服务器需要开启特定的端口规则,而Web服务器需要限制可执行目录权限。这种分层管理方式让安全策略的粒度足够细,又不会造成配置冲突。
账号与认证加固的核心任务第一道防线永远是身份认证。系统默认的root账号是攻击者的首要目标,必须禁止其直接SSH登录。同时建立普通用户并配置sudo权限,所有运维操作通过sudo执行,留下审计痕迹。使用Ansible的user和lineinfile模块可以精确控制这些配置:
- name: 创建运维用户并设置SSH密钥
user:
name: opsadmin
groups: wheel
password: "{{ 'YourPassword' | password_hash('sha512') }}"
shell: /bin/bash
state: present
- name: 部署SSH公钥到运维用户
authorized_key:
user: opsadmin
key: "{{ lookup('file', '/path/to/public_key.pub') }}"
state: present
- name: 禁止root SSH登录
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin no'
validate: 'sshd -t -f %s'
注意validate参数的运用,它会在修改文件前检查配置文件语法,防止错误的配置导致SSH服务启动失败,这是生产环境操作的关键保护措施。同时要禁用空密码账户、锁定长期未登录的账号,这些都可以通过authconfig或直接操作/etc/shadow来完成。
SSH服务深度加固仅仅禁止root登录远远不够。SSH协议本身有一些不安全的旧版本和算法需要禁用。修改sshd_config时,要确保只使用协议版本2,限制允许登录的用户组,设置登录超时,以及关闭X11转发和TCP端口转发等不需要的功能。完整的SSH加固任务应该包含以下配置项:
- name: 配置SSH安全参数
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
validate: 'sshd -t -f %s'
loop:
- { regexp: '^Protocol', line: 'Protocol 2' }
- { regexp: '^AllowUsers', line: 'AllowUsers opsadmin' }
- { regexp: '^ClientAliveInterval', line: 'ClientAliveInterval 300' }
- { regexp: '^ClientAliveCountMax', line: 'ClientAliveCountMax 0' }
- { regexp: '^X11Forwarding', line: 'X11Forwarding no' }
- { regexp: '^AllowTcpForwarding', line: 'AllowTcpForwarding no' }
- { regexp: '^MaxAuthTries', line: 'MaxAuthTries 3' }
notify: restart sshd
使用loop循环处理多个配置项,比逐个写lineinfile任务更简洁。notify触发器确保只有配置真正发生变化时才重启SSH服务,减少对业务连接的中断风险。对于使用旧版加密算法的场景,还需要通过Ciphers和MACs指令指定高强度的加密套件,排除arcfour、cbc模式等已知弱算法。
防火墙策略的自动化部署CentOS 7之后默认使用firewalld,但很多生产环境仍然习惯用iptables。无论选择哪种,Ansible都有对应模块。推荐使用firewalld模块,因为它支持富规则和区域管理,更适合动态环境。首先要确保firewalld服务启动并设置为开机自启,然后添加必要的服务规则,最后将默认区域设置为drop,只开放明确允许的端口:
- name: 启动并启用firewalld
systemd:
name: firewalld
state: started
enabled: yes
- name: 设置默认拒绝策略
command: firewall-cmd --set-default-zone=drop
- name: 仅开放SSH和业务端口
firewalld:
service: "{{ item }}"
permanent: yes
state: enabled
zone: drop
loop:
- ssh
- http
- https
- name: 重载防火墙规则
command: firewall-cmd --reload
这里有一个容易被忽视的细节:必须先添加允许规则,再将默认区域改为drop,否则你会瞬间切断自己的SSH连接。Ansible的任务是顺序执行的,利用这个特性可以避免把自己锁在服务器外面。对于多网卡服务器,还可以将不同网卡划分到不同zone,实现更精细的访问控制。
系统内核参数的安全调优网络层的攻击防御依赖内核参数的正确配置。通过sysctl模块可以批量设置安全相关参数。重点是启用TCP SYN Cookie防护、禁用IP源路由、关闭ICMP重定向接受、开启反向路径过滤等。这些配置能有效防御SYN Flood、IP欺骗和路由劫持等常见攻击:
- name: 配置安全相关的内核参数
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: yes
reload: yes
loop:
- { name: 'net.ipv4.tcp_syncookies', value: '1' }
- { name: 'net.ipv4.conf.all.accept_source_route', value: '0' }
- { name: 'net.ipv4.conf.all.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.all.rp_filter', value: '1' }
- { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: '1' }
- { name: 'net.ipv4.conf.all.log_martians', value: '1' }
- { name: 'kernel.randomize_va_space', value: '2' }
kernel.randomize_va_space设置为2表示启用完整的地址空间布局随机化,这是防御缓冲区溢出攻击的重要手段。log_martians开启火星地址记录,能帮助发现网络中的异常流量。这些参数调整后立即生效且重启不丢失,是性价比最高的加固措施之一。
审计与日志系统的自动化配置没有审计的安全是假安全。auditd服务负责记录系统调用事件,rsyslog负责集中收集日志。通过Ansible可以确保这两个服务正常运行,并配置关键文件和目录的审计规则。特别是对/etc/passwd、/etc/shadow、/etc/sudoers等敏感文件的修改行为,必须留下不可篡改的记录:
- name: 安装并启动auditd
yum:
name: audit
state: present
- name: 配置审计规则
template:
src: audit.rules.j2
dest: /etc/audit/rules.d/audit.rules
notify: restart auditd
- name: 确保rsyslog运行
systemd:
name: rsyslog
state: started
enabled: yes
审计规则文件建议使用Jinja2模板管理,因为不同角色的服务器需要监控的系统调用不同。数据库服务器要重点审计数据文件目录的访问,Web服务器要监控上传目录的执行行为。模板化之后,只需要在Inventory中定义变量,就能为不同分组生成差异化的审计策略。
软件包与服务的精简原则最小化安装原则是安全基线的重要组成部分。服务器上每多一个软件包,就多一份攻击面。用Ansible的package模块可以批量卸载不必要的软件,同时用systemd模块禁用不需要的服务。编译工具、X11库、旧版网络服务等都是重点清理对象:
- name: 卸载危险或无用的软件包
yum:
name:
- telnet-server
- rsh-server
- ypbind
- tftp-server
- xinetd
state: absent
- name: 禁用不需要的服务
systemd:
name: "{{ item }}"
state: stopped
enabled: no
loop:
- avahi-daemon
- cups
- postfix
- bluetooth
注意postfix在某些监控场景中用于发送告警邮件,卸载前要确认业务依赖。这种清理工作最好在服务器上线初期完成,运行中的系统要分批次灰度执行,避免误删关键组件。
Playbook的整体编排与执行策略将所有任务整合到一个主Playbook中,利用Ansible的角色机制组织文件结构。一个标准的项目目录应该包含tasks、handlers、templates、vars等子目录。主入口文件site.yml负责引用各角色,并通过tags标记不同阶段的任务,方便按需执行:
---
- name: 执行CentOS安全基线加固
hosts: all_servers
become: yes
roles:
- account_security
- ssh_hardening
- firewall_config
- kernel_tuning
- audit_logging
- package_cleanup
执行时使用ansible-playbook -i hosts.ini site.yml --check先做预检查,确认所有变更符合预期后再去掉--check正式运行。对于已经在运行的生产服务器,建议先用--limit限制到一台测试机,验证通过后再全量推送。Ansible的幂等性保证了多次执行不会产生副作用,但首次大规模加固前一定要做好快照或备份。
持续合规与定期检查机制安全基线不是一次性的工作。系统更新、业务变更、新漏洞的披露都可能导致基线偏移。可以编写一个检查模式的Playbook,定期以check模式运行,并将结果输出到日志分析平台。如果发现配置被手动修改过,Ansible会报告changed状态,这时就要决定是回滚配置还是更新基线标准。结合定时任务,比如每周执行一次ansible-playbook site.yml --check --diff,就能持续监控所有服务器的合规状态,把安全从被动响应转变为主动防御。
