使用Ansible Galaxy实现安全配置自动化,守护安稳睡眠

本文详细介绍了如何利用Ansible Galaxy自动化部署SSH安全配置、防火墙规则、fail2ban防护及日志收集系统,通过可复现的剧本实现Linux服务器的一键安全加固,提升蓝队工作效率。

使用Ansible Galaxy实现安全配置自动化

作者:Jordan Drysdale
发布日期:2016年7月11日

注意: 本文中提到的技术和工具可能已过时,不适用于当前环境。但本文仍可作为学习机会,可能有助于更新或集成到现代工具和技术中。

作为“蓝队”成员,工作常常充满压力。在强大的Linux基础设施环境中工作会有所帮助,但Ansible能带来巨大助力。在所有环境中,无论涉及何种操作系统,我们都需要确保系统的远程访问安全。Ansible Galaxy充满了有趣的角色,让蓝队成员的生活更轻松。通过Ansible Galaxy,我们可以利用几个角色快速、有效地保护Linux服务器,并以易于复制的方式实现。

在保护远程访问时,基于密钥的SSH和有时使用的双因素认证(2FA)可以提供额外的安心层。此外,难以想象放弃防御而“裸奔”,因此防火墙是标准要求。何不加入fail2ban来防御通过iptables对开放服务的暴力攻击?我真心喜欢这个服务组合。🙂 “哦,你尝试了三次通过HTTPS认证?fail2ban,请暂时封锁这个IP。谢谢,好的。”最后但同样重要的是,让我们将所有内容转储到logstash,在Kibana中进行Geo-IP映射以实现出色的可视化,最终,好好休息一下。

首先,检查我们的Ansible版本:

1
2
3
ansible@tw17ch01:/etc/ansible/roles/sshd$ dpkg -l |grep ansible
ii  ansible   2.1.0.0-1ppa~trusty        all        
一个极其简单的IT自动化平台

接下来,安装、配置和部署SSHd,使用一个包含所有可能变量的Galaxy角色。我们将添加角色,进行一些更改,然后构建一个剧本来部署新角色。链接在此 – https://galaxy.ansible.com/mattwillsher/sshd/

Ansible服务器魔法:

1
2
3
4
5
6
7
8
9
ansible@tw17ch01:/etc/ansible/playbooks$ sudo ansible-galaxy install mattwillsher.sshd

[sudo] password for ansible:
– 下载角色'sshd',由mattwillsher拥有
– 从 https://github.com/willshersystems/ansible-sshd/archive/v0.4.4.tar.gz 下载角色
– 提取 mattwillsher.sshd 到 /etc/ansible/roles/mattwillsher.sshd
– mattwillsher.sshd 安装成功

ansible@tw17ch01:/etc/ansible/playbooks$ sudo mv mattwillsher.sshd/ sshd/

Galaxy角色大多在其“角色目录”内创建标准结构,如果不存在的话:

1
2
3
4
5
ansible@tw17ch01:/etc/ansible/roles/sshd$ ls

defaults   handlers  meta  tasks  tests  vars

ansible@tw17ch01:/etc/ansible/roles$ sudo nano sshd/vars/Ubuntu_14.yml

强烈建议修改默认端口,完全禁用root登录,并添加一行 PasswordAuthentication no。确保修改的文件适用于部署角色的操作系统。

接下来,安装、配置和部署防火墙以阻止所有内容。链接在此 – https://galaxy.ansible.com/geerlingguy/firewall/

1
2
3
4
5
6
7
8
9
ansible@tw17ch01:/etc/ansible/roles$ sudo ansible-galaxy install geerlingguy.firewall

[sudo] password for ansible:
– 下载角色'firewall',由geerlingguy拥有
– 从 https://github.com/geerlingguy/ansible-role-firewall/archive/1.0.9.tar.gz 下载角色
– 提取 geerlingguy.firewall 到 /etc/ansible/roles/geerlingguy.firewall
– geerlingguy.firewall 安装成功

ansible@tw17ch01:/etc/ansible/roles$ sudo mv geerlingguy.firewall/ chains/

进行一些编辑:

1
ansible@tw17ch01:/etc/ansible/roles$ sudo nano chains/defaults/main.yml

防火墙修改比sshd角色内置的复杂性更容易理解。我的系统只需要上述列出的SSH端口和HTTPS。对chains角色的另一个修改:

1
ansible@tw17ch01:/etc/ansible/roles$ sudo nano chains/templates/firewall.bash.j2

我添加了以下规则,因为我现在不关心来自DO droplet的出站流量。

1
2
3
#  允许所有出站流量 - 
#  你可以/应该修改此规则以仅允许特定流量!
iptables -A OUTPUT -j ACCEPT

chains角色应该准备好了。

接下来,安装、配置和部署fail2ban以保护服务。链接在此 – https://galaxy.ansible.com/tersmitten/fail2ban/

1
2
3
4
5
6
7
ansible@tw17ch01:/etc/ansible/roles$ sudo ansible-galaxy install tersmitten.fail2ban
- 下载角色'fail2ban',由tersmitten拥有
- 从 https://github.com/Oefenweb/ansible-fail2ban/archive/v1.5.0.tar.gz 下载角色
- 提取 tersmitten.fail2ban 到 /etc/ansible/roles/tersmitten.fail2ban
- tersmitten.fail2ban 安装成功

ansible@tw17ch01:/etc/ansible/roles$ sudo mv tersmitten.fail2ban/ banner/

进行一些编辑:

1
ansible@tw17ch01:/etc/ansible/roles$ sudo nano banner/defaults/main.yml

我必须对sshd服务配置进行一些更改以反映使用非标准端口。我还添加了HTTPS的服务配置。查看完目录结构的其余部分后,这个角色也准备好了。

最后,安装、配置和部署filebeat以将日志文件发送到有用的目的地。链接在此 – https://galaxy.ansible.com/jpnewman/elk-filebeat/

1
2
3
4
5
6
7
ansible@tw17ch01:/etc/ansible/roles$ sudo ansible-galaxy install jpnewman.elk-filebeat
- 下载角色'elk-filebeat',由jpnewman拥有
- 从 https://github.com/jpnewman/ansible-role-elk-filebeat/archive/master.tar.gz 下载角色
- 提取 jpnewman.elk-filebeat 到 /etc/ansible/roles/jpnewman.elk-filebeat
- jpnewman.elk-filebeat 安装成功

ansible@tw17ch01:/etc/ansible/roles$ sudo mv jpnewman.elk-filebeat/ logger/

最后,为将来在现有ELK堆栈中进行勘探,设置跨互联网的TLS日志传输。这假设已经完成了一系列工作:

  1. 完全可操作的ELK堆栈
  2. 为logstash准备的TLS/PKI基础设施,并且证书可通过logger角色部署
  3. 网络防火墙上的logstash端口转发
  4. 可选的redis集群以处理大量日志处理
1
ansible@tw17ch01:/etc/ansible/roles$ sudo nano logger/defaults/main.yml

在这里,我修改了elastic和logstash主机以指向基础设施目的地。记得我们之前讨论过的相当标准的目录结构吗?是的,将你的logstash-forward.crt文件复制到 ../roles/logger/files/certs/,剧本智能将交付。我们又准备好了。让我们滚动并查看一些内容以确保一切正常。

1
2
3
4
ansible@tw17ch01:/etc/ansible/roles$ ls
banner  chains  logger  sshd   ### 所有角色都存在
> vi ../ansible/hosts #将新主机添加到你的ansible hosts文件
> ansible dropper ping -m 12.34.56.78 | SUCCESS => {         "changed": false,         "ping": "pong" } ansible@tw17ch01:/etc/ansible/roles$ sudo nano ../playbooks/NewDrop.yml ### 角色很棒。投入时间。 - hosts: all   become: yes   roles:         # 部署标准SSH配置         - { role: sshd }         # 安装iptables         - { role: chains }         # 添加filebeat         - { role: logger }         # 部署和配置fail2ban         - { role: banner }  

此部署的手动部分在此处发生。SSH到新的droplet并创建一个sudo用户。是的,这可以自动化,我们将在另一天以另一种方式写关于此的内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
ssh root@NewDropIP
useradd ansible -m -s /bin/bash
passwd ansible
UNIX Pass:
UNIX Pass:
su - ansible
mkdir .ssh
touch .ssh/authorized_keys
echo "ssh-rsa AAAAB3N <KEY REDACTED> IClTJ1E1 ansible@tw17ch01" >> .ssh/authorized_keys
exit
visudo   ## 添加 ansible ALL=(ALL:ALL) ALL

ansible@tw17ch01:/etc/ansible$ sudo nano hosts  ### 添加 [dropper] 和 NewDropIP
ansible@tw17ch01:/etc/ansible$
ansible@tw17ch01:/etc/ansible$ ansible-playbook playbooks/NewDrop.yml -l dropper -u ansible -K
SUDO password:

PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
主机 '12.34.56.78 (12.34.56.78)' 的真实性无法确定。
ECDSA 密钥指纹是 5f:<redacted>:1f。
你确定要继续连接吗(是/否)?是
输入密钥 '/home/ansible/.ssh/id_rsa' 的密码:
ok: [12.34.56.78]
TASK [sshd : 设置操作系统相关变量] ***************************************
ok: [12.34.56.78] => (item=/etc/ansible/roles/sshd/vars/Ubuntu_14.yml)
TASK [sshd : 操作系统受支持] **************************************************
ok: [12.34.56.78]
TASK [sshd : 已安装] ********************************************************
ok: [12.34.56.78] => (item=[u'openssh-server', u'openssh-sftp-server'])
TASK [sshd : 运行目录] ****************************************************
ok: [12.34.56.78]
TASK [sshd : 配置] ****************************************************
changed: [12.34.56.78]
TASK [sshd : 服务已启用并运行] **************************************
ok: [12.34.56.78]
TASK [sshd : 注册此角色已运行] **********************************
ok: [12.34.56.78]
TASK [chains : 确保iptables已安装(RedHat)。] *************************
skipping: [12.34.56.78]
TASK [chains : 确保iptables已安装(Debian)。] *************************
ok: [12.34.56.78]
TASK [chains : 首次运行剧本时刷新iptables。] *******************
changed: [12.34.56.78]
TASK [chains : 将防火墙脚本复制到位。] *******************************
changed: [12.34.56.78]
TASK [chains : 将防火墙初始化脚本复制到位。] **************************
changed: [12.34.56.78]
TASK [chains : 确保防火墙已启用并将在启动时启动。] *********
changed: [12.34.56.78]
TASK [logger : 创建目录以存储ssl证书] ******************************
changed: [12.34.56.78]
TASK [logger : 复制SSL证书] **************************************************
changed: [12.34.56.78]
TASK [logger : 安装Filebeat依赖项] **********************************
ok: [12.34.56.78]
TASK [logger : 检查Filebeat是否已处于正确版本] **************
changed: [12.34.56.78]
TASK [logger : 下载Filebeat代理] ****************************************
changed: [12.34.56.78]
TASK [logger : 安装Filebeat代理] *****************************************
changed: [12.34.56.78]
TASK [logger : 为Filebeat配置创建目录] ***********************
changed: [12.34.56.78]
TASK [logger : 为Filebeat配置创建目录] ***********************
changed: [12.34.56.78]
TASK [logger : 配置Filebeat] *********************************************
changed: [12.34.56.78]
TASK [logger : 配置Filebeat prospectors] *********************************
[弃用警告]:使用裸变量已弃用。更新你的剧本  ### 需要清理此剧本
 以便环境值使用完整变量语法
('{{prospectors}}')此功能将在未来版本中移除。可以通过在ansible.cfg中设置deprecation_warnings=False来禁用弃用警告。
changed: [12.34.56.78] => (item={u'paths': [{u'log_paths': [u'/var/log/syslog', u'/var/log/auth.log'], u'document_type': u'syslog'}], u'type': u'syslog', u'id': u'syslog'})
changed: [12.34.56.78] => (item={u'paths': [{u'log_paths': [u'/var/log/*.log'], u'document_type': u'log', u'exclude_files': [u'^syslog

太棒了!我们刚刚推出了解决我(或大多数管理员)担心的几乎所有问题的解决方案。让我们SSH过去看看,确保没有东西被搞砸,并验证一切看起来都很好。

SSH:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
ansible@tw17ch03:~$ cat /etc/ssh/sshd_config
# ansible 管理:/etc/ansible/roles/sshd/templates/sshd_config.j2 于 2016-04-16 12:32:30 由 root 在 tw17ch01 上修改
Port 22444
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
AcceptEnv LANG LC_*
ChallengeResponseAuthentication no
HostbasedAuthentication no
IgnoreRhosts yes
KeyRegenerationInterval 3600
LogLevel INFO
LoginGraceTime 120
PasswordAuthentication no
[...............]
X11Forwarding yes

iptables:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
ansible@tw17ch03:~$ sudo iptables -L

[sudo] password for tendans:
Chain INPUT (policy ACCEPT)

target         prot opt source                 destination              
ACCEPT         all  —  anywhere               anywhere                
ACCEPT         tcp  —  anywhere               anywhere                 tcp dpt:22444
ACCEPT         tcp  —  anywhere               anywhere                 tcp dpt:https
ACCEPT         icmp —  anywhere               anywhere                
ACCEPT         udp  —  anywhere               anywhere                 udp spt:ntp
ACCEPT         all  —  anywhere               anywhere                 state RELATED,ESTABLISHED
LOG            all  —  anywhere               anywhere                 limit: avg 15/min burst 5 LOG level debug prefix “Dropped by firewall: ”
DROP           all  —  anywhere               anywhere                

Chain FORWARD (policy ACCEPT)
target         prot opt source                 destination              
Chain OUTPUT (policy ACCEPT)
target         prot opt source                 destination              
ACCEPT         all  —  anywhere               anywhere                
ACCEPT         udp  —  anywhere               anywhere                 udp dpt:ntp

FileBeat:

1
2
3
4
5
6
ansible@tw17ch03:~$ cat /etc/filebeat/filebeat.yml

################### Filebeat配置示例 #########################
############################# Filebeat ######################################
filebeat:
# 要获取数据的prospectors列表。

Fail2Ban:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
tendans@tw17ch03:~$ cat /etc/fail2ban/jail.local
# ansible 管理:/etc/ansible/roles/banner/templates/etc/fail2ban/jail.local.j2 于 2016-05-30 05:57:15 由 root 在 tw17ch01 上修改
[……]


[ssh]

enabled = true
port = 22444
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
findtime = 600

[https]

enabled = true
port = https
filter = https
logpath = /var/log/auth.log
maxretry = 6
findtime = 600

就是这样,全部完成。剧本看起来很好,所有角色都按预期部署。配置文件已更新,SSH允许我们远程访问。哦,对了,这里有一个Kibana可视化,显示了通过FileBeat打包日志传输过来的远程连接的源Geo-IP映射,并向一位未具名的同事致敬,干杯!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计