天天看點

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的認證層還增加了更高的安全機制。

  

ansible安全優化篇

三、通信加密

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

  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、檢視被放行的端口

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

繼續閱讀