使用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日志传输。这假设已经完成了一系列工作:
- 完全可操作的ELK堆栈
- 为logstash准备的TLS/PKI基础设施,并且证书可通过logger角色部署
- 网络防火墙上的logstash端口转发
- 可选的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映射,并向一位未具名的同事致敬,干杯!