对与一台全新安装的服务器,尤其是直接面向公网的服务器来说:最重要的一项配置就是安全配置。
针对非授权连接和截取通信信息等攻击行为,避免攻击手段带来的危害,处理方法有以下方法:
Telnet协议诞生于20世纪60年代后期,最初被应用到基于TCP协议的大型私有网络之中,默认端口是23号端口。
Telnet是一种文本协议,用于在不同网络间传输数据。Telnet属于底层协议,至今它依然是我们现在使用的很多通信协议的基础,比如HTTP、FTP以及POP3。
随着SSH的到来,Telnet开始逐渐退出远程管理的舞台。
SSH(Secure Shell)诞生于1995年,由芬兰人Tatu Ylonen开发。他看到了文本通信的安全缺陷,这促使他开发一款强加密的远程管理工具——SSH。
SSH的连接加密方式非常类似于HTTP的SSL加密,同时SSH的认证层还增加了更高的安全机制。
- hosts: example tasks: - name: 修改SSH配置文件的安全选项 lineinfile: dest: /etc.ssh/sshd_config regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present with_items: - { regexp: "^PasswordAuthentication", line: "PasswordAuthentication no" } - { regexp: "^PermitRootLogin", line: "PermitRootLogin no" } - { regexp: "^Port", line: "Port 2849" } notify: restart ssh handlers: - name: restart ssh service: name=ssh state=restarted
使用ansible的linefile模块对SSH的三大安全配置选项进行设置,随便使用handler了重启,来使修改生效。
若改变了某些Inentory主机的SSH配置,比如更改了默认的端口号,此时我们需要在ansible的Inventory文件中使用ansible_ssh_port变量明确地为该主机重新指定新配置的端口号。
使用lineinfile模块来配置SSH完全禁止使用root用户远程登录。
Linux系统的sudo命令可以让普通用户以root(也可以指定为其他用户)的权限来执行指定命令,这样不仅减少了root用户和管理时间,同样也提高了安全性。sudo命令可以在执行敏感的高权限命令时,更加有针对性,从而减少高权限命令误操作的几率。
ansible本身也提倡尽量使用普通用户来管理主机,只有必须使用root权限的任务中,才使用sudo变量来实现Linux命令行中的sudo功能。
--- - name: Restart Apache. service: name=httpd state=restarted sudo: yes
在任务或playbook中可以通过添加sudo_user:[username]关键字来指定sudo后具体以哪个用户的权限来执行操作,而不仅仅是root用户。
需要注意的是:sudo_user关键字必须在有sudo关键字的前提下才生效。
使用ansible修改sudo的配置文件,使普通用户拥有和root用户一样的权限。
--- - name: 为普通用户赋予所有root权限 lineinfile: dest: /etc/sudoers regexp: '^%wzs' line: 'wzs ALL=(All) NOPASSWD: ALL' state: present
使用lininfile模块操作可能达不到预期的效果。所以使用这种方式时,应该认真检查,确保修改后语法的正确性。
更好的更改方式是远程执行visudo命令,更改sudo命令,并防止错误修改造成命令的不可用。
--- - name: Copy validated sudoers file into place. copy: src: sudoers dest: /etc/sudoers validate: 'visudo -cf %s'
%s是一个文件路径的占位符,在文件被复制到远程主机之前,他会被替换为src后面的文件。
在配置文件管理工具流行之前,服务器经常会残留一些不再使用的软件服务,以及这些服务所使用的端口。这不仅使服务器变得缓慢臃肿,同时这些开放的端口和老旧的软件都易受到外部攻击,造成潜在风险。
及时关闭服务器上不再需要的服务,卸载不相关的软件,并清理不再需要执行crontab任务,这不仅可以帮助服务器“瘦身”,还可以提高服务器的安全性。
使用ansible来管理维护服务器架构,上面的痛点轻松解决。
--- - name: 卸载不需要的软件 yum: name={{ item }} state=absent purge=yes with_items: - apache2 - nano - php
注意:state不同选项的区别
在ansible中,像yum、apt、file、mysql_db这些模块,他们都有一个相同的选项state,设置其值为absent,可以将指定的任务软件、文件或者数据库删除掉。妥善利用这些功能,可以大大提高运维人员的工作效率,节省大量时间。
只开放需要用到的端口,关闭哪些可有可无的端口,将大大减少外部环境对主机的攻击面,同时也会降低防火墙的复杂度。
举例:不加任何限制就对外开放25端口会给外部网络提供大量的主机信息。所以。若你的主机不是一台SMTP服务器的话,务必关闭这个端口。同时,也要确保哪些需要被开启的端口,只能连接依赖的客户端。
生产环境中,主机上的所有用户、应用以及进程都应该只允许访问他们本身需要访问的信息(文件)和资源(内存、网络等)——一点也不多,一点也不少。
在权限最小化原则实施的过程中,最直接的也是最基本的两个方向:用户权限管理和文件权限管理。
系统上的每一个新增用户的权限默认都是被适当限制过的。新增用户通常都有一个家目录,且用户对家目录下的所有文件和目录具有最搞权限,但是对于家目录以外的目录与文件的权限都需要重新赋予。
为用户新增权限的方法有两种
ansible中每一个与文件管理相关的模块中都有文件权限管理的选项可用,这些选项包括:owner、group和mode。每一次使用copy、template、file等模块来操作管理文件时,都应该使用这些选项来明确指定文件的权限及其归属。
--- - name: 设置gitlab配置文件的权限 file: path: /etc/gitlab/gitlab.rb owner: root group: root mode: 0600
为了满足用户对某些文件或目录的权限需求,正确的做法是修改文件或目录的权限来适应用户,而不是扩大用户权限来得到某些权限的满足。
例如:web服务器上httpd用户或者Nginx用户对网站文件拥有权限。
服务器每一年所有软件的安全更新有上百次甚至更多。其中有一些是针对修复对系统有严重威胁的漏洞的,若这些漏洞没有及时更新软件或打相应的补丁,将会对系统安全造成严重威胁。
应该定期进行补丁维护和软件更新检查。在对线上生产服务器上的软件打补丁或者更新升级之前,应该在非关键服务器或环境相同的测试服务器上进行测试,在确定没问题的情况下再对线上生产服务器进行操作。
使用ansible命令对服务器上所有软件更新升级操作。
然而,在有些情况下我们只需实施与安全相关的更新,或者只更新某些软件;在仍需要使用这两个命令的前提下,可以通过修改yum软件和apt软件的配置文件来进行定义。
ansible webservers -m yum -a "name=* state=latest"
ansible webservers -m apt -a "upgrade=dist update_cache=yes"
可以在系统上设置每天或每周定时进行软件更新,这样可以使系统更新这一动作更稳定、更有规律地执行下去,从而减少人力成本。
但在现实中,有些环境是不允许机器自动更新软件的,因为自动更新本身蕴含着一些风险。比如:有些软件的最新版确实修正了之前版本的一些不足,但是它的新增功能可能与系统上自己开发的一些程序的兼容性不足,从而使得整个系统不可用。
若你的系统上不存在这些问题,那么使用自动定时更新软件,可以更进一步增加系统安全性。
对于RedHat 6及其以后的版本的系统(包括Fedora和CentOS)都可以使用一个叫YUM-cron的软件进行软件包更新管理。其用法很简单,使用yum安全后,保证开机开启就可以了。使用ansible来实现如下即可
--- - name: 安装yum-cron yum: name=yum-cron state=present - name: 运行yum-cron并设置开机启动 services: name=yum-cron state=started enabled=yes
更多的配置可以通过修改yum的配置文件/etc/yum.conf
Debian系统及其衍生版都使用一款名叫unattended-upgrades的软件来实现自动化软件包更新管理,这款软件和前面讲的YUM-cron一样,非常便于安装和配置,并且支持多配置文件,存放于/etc/apt/apt.conf.d/。
--- - name: 安装unattended-upgrades apt: name=unattended-upgrades state=present - name: 将配置文件复制到配置目录中 template: src: "../templates/{{ item }}.j2" dest: "/etc/apt/apt.conf.d/{{ item }}" owner: root group: root mode: 0644 with_items: - 10periodic - 50unattended-upgrades
复制unattended-upgrades配置文件中10periodic的内容如下
APT::Periodic::Update-Package-Lists "1"; //显示更新包列表,0表示停用设置 APT::Periodic::Download-Upgradeable-Packages "1"; //下载更新包,0表示停用设置 APT::Periodic::AutocleanInterval "7"; //7天自动删除 APT::Periodic::Unattended-Upgrade "1"; //启动自动更新,0表示停用自动更新
配置文件50unattended-upgrades的内容如下
Unattended-Upgrade::Automatic-Reboot "false"; Unattended-Upgrade::Allowed-Origins { "Ubuntu lucid-security"; "Ubuntu lucid-updates; };
这个配置文件提供了更新配置选项,比如对于那些更新后需要重启服务器才能生效的软件,在更新过这些软件后,是否自动重启服务器,以及在检查更新软件,需要检测那些APT源来查找更新等。
管理防火墙的工具,比如iptables、ufw以及firewalld等。
使用ansible开关闭Debian系统中除了22(SSH)、80(HTTP)、123(NTP)端口以外的其他的所有端口。
--- - name: 使用ufw模块来管理那些端口需要开启 ufw: rule: "{{ item.rule }}" port: "{{ item.port }}" proto: "{{ item.proto }}" with_item: - { rule: 'allow', port: 22, proto: 'tcp' } - { rule: 'allow', port: 80, proto: 'tcp' } - { rule: 'allow', port: 123, proto: 'ucp' } - name: 配置网络进出方向的默认规则 ufw: direction: "{{ item.direction }}" policy: "{{ item.policy }}" state: enabled with_items: - { direction: outgoing, policy: allow } - { direction: incoming, policy: deny }
--- - name: 使用firewalld模块管理端口 firewalled: state: "{{ item.state }}" port: "{{ item.port }}" zone: external immediate: yes permanent: yes with_items: - { state: 'enabled', port: '22/tcp' } - { state: 'enabled', port: '80/tcp' } - { state: 'enabled', port: '123/ucp' }
注意:
1、immediate选项从ansible版本1.9之外开始引入,用来定义规则在配置完成是否立即生效。若使用的是1.9之前的版本的,那么需要重启防火墙来让新规则生效,或者将permanent选项的值设为no。
2、firewalld模块并不能针对网络进出口方向进行管理,但是我们可以借助iptables模块或者直接修改/etc/firewalld目录下的防火墙配置文件来进行配置。
sudo firewall-cmd --zone=external --list-all