ansible安全優化篇


一、安全概況

  對與一台全新安裝的服務器,尤其是直接面向公網的服務器來說:最重要的一項配置就是安全配置。

  針對非授權連接和截取通信信息等攻擊行為,避免攻擊手段帶來的危害,處理方法有以下方法:

  1. 使用安全加密的通信方式——使用https加密傳輸;
  2. 禁止root用戶遠程登錄並充分利用sudo;
  3. 移除非必需的軟件,只開發需要用到的端口;
  4. 遵守權限最小化原則;
  5. 及時更新操作系統和軟件——修復舊版本的bug,並使用新版本的最佳性能;
  6. 使用合理配置過的、有針對性的防火牆;
  7. 確保日志文件被及時遷移、存放和切割;
  8. 監測系統登錄情況,封掉可疑的IP地址;
  9. 正確使用SELinux和AppArmor。

二、SSH與遠程連接簡介

  一、Telnet

  Telnet協議誕生於20世紀60年代后期,最初被應用到基於TCP協議的大型私有網絡之中,默認端口是23號端口。

  Telnet是一種文本協議,用於在不同網絡間傳輸數據。Telnet屬於底層協議,至今它依然是我們現在使用的很多通信協議的基礎,比如HTTP、FTP以及POP3。

  隨着SSH的到來,Telnet開始逐漸退出遠程管理的舞台。

  二、SSH

  SSH(Secure Shell)誕生於1995年,由芬蘭人Tatu Ylonen開發。他看到了文本通信的安全缺陷,這促使他開發一款強加密的遠程管理工具——SSH。

  SSH的連接加密方式非常類似於HTTP的SSL加密,同時SSH的認證層還增加了更高的安全機制。

  

三、通信加密

  一、為了保證服務器的安全性,我們需要:

  1. 禁止SSH基於密碼登錄(禁止密碼登錄之前,務必確認SSH可以成功秘鑰認證登錄),使用更為安全的秘鑰認證來加密通信
  2. 禁止root用戶遠程登錄
  3. 同時改變SSH服務的默認端口號

  二、實現功能

  1、實現sshd_config.yml文件如下

- 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

  2、實現方法

  使用ansible的linefile模塊對SSH的三大安全配置選項進行設置,隨便使用handler了重啟,來使修改生效。

  3、需要注意的點

  若改變了某些Inentory主機的SSH配置,比如更改了默認的端口號,此時我們需要在ansible的Inventory文件中使用ansible_ssh_port變量明確地為該主機重新指定新配置的端口號。

四、禁止root遠程登錄

  使用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將普通用戶提權

  使用ansible修改sudo的配置文件,使普通用戶擁有和root用戶一樣的權限。

  1、實現方式一:使用lineinfile

---
    - name: 為普通用戶賦予所有root權限
        lineinfile:
            dest: /etc/sudoers
            regexp: '^%wzs'
            line: 'wzs ALL=(All) NOPASSWD: ALL'
            state: present

  使用lininfile模塊操作可能達不到預期的效果。所以使用這種方式時,應該認真檢查,確保修改后語法的正確性。

  更好的更改方式是遠程執行visudo命令,更改sudo命令,並防止錯誤修改造成命令的不可用。

  2、實現方式二:ansible主機修改sudo配置文件,使用visudo命令

---

    - name: Copy validated sudoers file into place.
        copy:
            src: sudoers
            dest: /etc/sudoers
            validate: 'visudo -cf %s'

  %s是一個文件路徑的占位符,在文件被復制到遠程主機之前,他會被替換為src后面的文件。

五、操作系統簡介

  一、未使用配置文件管理工具的痛點

   在配置文件管理工具流行之前,服務器經常會殘留一些不再使用的軟件服務,以及這些服務所使用的端口。這不僅使服務器變得緩慢臃腫,同時這些開放的端口和老舊的軟件都易受到外部攻擊,造成潛在風險。

  及時關閉服務器上不再需要的服務,卸載不相關的軟件,並清理不再需要執行crontab任務,這不僅可以幫助服務器“瘦身”,還可以提高服務器的安全性。

  二、使用ansible配置管理

  使用ansible來管理維護服務器架構,上面的痛點輕松解決。

  1、解決方式:

  1. 使用事先寫好的Playbook或Role快速地部署一台全新的服務器來取代舊服務器。
  2. 簡單地列出一個需要刪除的軟件列表,利用ansible進行批量卸載。

  2、使用ansible批量卸載不需要的軟件

---
    - name: 卸載不需要的軟件
        yum: name={{ item }} state=absent purge=yes
        with_items:
            - apache2
            - nano
            - php

  注意:state不同選項的區別

  1. present,installed是安裝套件,而latest則是指安裝最新的套件,也就是會使用 yum mirror 上最新的版本。
  2. absent, removed 是刪除套件,沒有什么區別

  3、ansible批量操作

    1、服務、文件

  在ansible中,像yum、apt、file、mysql_db這些模塊,他們都有一個相同的選項state,設置其值為absent,可以將指定的任務軟件、文件或者數據庫刪除掉。妥善利用這些功能,可以大大提高運維人員的工作效率,節省大量時間。

    2、端口

  只開放需要用到的端口,關閉哪些可有可無的端口,將大大減少外部環境對主機的攻擊面,同時也會降低防火牆的復雜度。

  舉例:不加任何限制就對外開放25端口會給外部網絡提供大量的主機信息。所以。若你的主機不是一台SMTP服務器的話,務必關閉這個端口。同時,也要確保哪些需要被開啟的端口,只能連接依賴的客戶端。

六、遵守權限最小化原則

  生產環境中,主機上的所有用戶、應用以及進程都應該只允許訪問他們本身需要訪問的信息(文件)和資源(內存、網絡等)——一點也不多,一點也不少

  在權限最小化原則實施的過程中,最直接的也是最基本的兩個方向:用戶權限管理和文件權限管理。

  一、用戶管理

  系統上的每一個新增用戶的權限默認都是被適當限制過的。新增用戶通常都有一個家目錄,且用戶對家目錄下的所有文件和目錄具有最搞權限,但是對於家目錄以外的目錄與文件的權限都需要重新賦予。

  為用戶新增權限的方法有兩種

  1. 添加用戶到其他用戶組中,已繼承該用戶組的權限
  2. 為用戶開放sudo權限,使得其可以以root或者其他用戶的身份來執行命令或者訪問文件

   二、文件權限管理

  ansible中每一個與文件管理相關的模塊中都有文件權限管理的選項可用,這些選項包括:owner、group和mode。每一次使用copy、template、file等模塊來操作管理文件時,都應該使用這些選項來明確指定文件的權限及其歸屬。

  1、實踐:gitlab的配置文件應該只能被root用戶讀取和修改,其他任何用戶都沒有權限

---
    - name: 設置gitlab配置文件的權限
        file:
            path: /etc/gitlab/gitlab.rb
            owner: root
            group: root
            mode: 0600

  2、配置文件或者目錄權限

  為了滿足用戶對某些文件或目錄的權限需求,正確的做法是修改文件或目錄的權限來適應用戶,而不是擴大用戶權限來得到某些權限的滿足。

  例如:web服務器上httpd用戶或者Nginx用戶對網站文件擁有權限。

七、定期維護更新

  服務器每一年所有軟件的安全更新有上百次甚至更多。其中有一些是針對修復對系統有嚴重威脅的漏洞的,若這些漏洞沒有及時更新軟件或打相應的補丁,將會對系統安全造成嚴重威脅。

  應該定期進行補丁維護和軟件更新檢查。在對線上生產服務器上的軟件打補丁或者更新升級之前,應該在非關鍵服務器或環境相同的測試服務器上進行測試,在確定沒問題的情況下再對線上生產服務器進行操作。

  一、手動更新

  使用ansible命令對服務器上所有軟件更新升級操作。

  然而,在有些情況下我們只需實施與安全相關的更新,或者只更新某些軟件;在仍需要使用這兩個命令的前提下,可以通過修改yum軟件和apt軟件的配置文件來進行定義。

  1、對於RedHat和CentOS等系統來說,使用如下命令

ansible webservers -m yum -a "name=* state=latest"

  2、對於Debian和Ubuntu等系統來說,使用如下命令

ansible webservers -m apt -a "upgrade=dist update_cache=yes"

  二、自動定時更新

  可以在系統上設置每天或每周定時進行軟件更新,這樣可以使系統更新這一動作更穩定、更有規律地執行下去,從而減少人力成本。

  但在現實中,有些環境是不允許機器自動更新軟件的,因為自動更新本身蘊含着一些風險。比如:有些軟件的最新版確實修正了之前版本的一些不足,但是它的新增功能可能與系統上自己開發的一些程序的兼容性不足,從而使得整個系統不可用。

  若你的系統上不存在這些問題,那么使用自動定時更新軟件,可以更進一步增加系統安全性。

  1、自動更新RedHat系統上的軟件

  對於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

  2、自動更新Debian系統上的軟件

  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防火牆

  管理防火牆的工具,比如iptables、ufw以及firewalld等。

  一、在Debian及衍生系統,ansible的ufw模塊來完成

  使用ansible開關閉Debian系統中除了22(SSH)、80(HTTP)、123(NTP)端口以外的其他的所有端口。

  1、代碼實現

---
    - 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 }

  2、上面playbook任務運行之后,登錄對方主機,使用sudo ufw status verbose命令

  二、在RedHat及其衍生系統中,我們使用ansible的firewalld模塊來管理防火牆

   1、代碼實現

---
    - 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目錄下的防火牆配置文件來進行配置。

  2、查看被放行的端口

sudo firewall-cmd --zone=external --list-all


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM