你是否也被Centos下默認iptables規則坑過

事件需求

今天讓同事去Beta環境實踐模擬線上環境多機房異地備份,我們有一個統一登錄的數據庫,很多產品的登錄都基於這個庫做的統一登錄,所以是比較重要的一個數據庫,所以讓他做前端代碼和數據庫的異地備份,代碼好說,跟上線一樣,從git庫pull代碼做同步更新就好,數據庫則需要跨機房做異地遠程同步並備份。

MYSQL異地主從同步情況說明

MYSQL異地同步架構大致如下:

你是否也被Centos下默認iptables規則坑過

如上圖所示我們的需求就是B機房的DB2服務器MYSQL的3307實例,通過公網去同步A機房的DB2的3307的MYSQL實例中的一個數據庫(ulogin),這裡關於MYSQL主從同步的原理我就不詳細介紹了,我想這是運維人員應該必備掌握的知識點。

但是有一點大家都是清楚的,那就是B機房MYSQL實例要同步A機房的MYSQL實例的數據,那就是B機房的DB2 MYSQL實例必須要能夠連接到A機房的DB2 MYSQL實例,那問題就來了,A、B兩個機房的MYSQL實例都是沒有公網IP地址的,但是都可以通過路由訪問公網。

所以需要解決的就是B機房MYSQL實例可以連接到A機房MYSQL實例即可,具體的做法就是,我們在A機房的路由器上做了一個端口隱射:121.123.90.83:16543 ---> 10.0.0.8:3307, 這樣B機房的MYSQL實例去做同步的時候通過連接IP:121.123.90.83的16543端口即可了,到現在網絡連接的問題解決了。

但是這樣的話,雖然變異了MYSQL實例隱射暴露的端口,但是萬一被黑客掃到這端口,然後利用MYSQL的漏洞做脫褲或者其他操作還是不好,所以我們還得利用iptables在A機房DB2服務器上做一層簡單防護,控制訪問來源IP地址,這樣就有下面的事件發生了。

跳坑過程

告訴了同事大致的做這件事情的過程和思路,那臺就開始去做了。

默認我們內網的機器是不開啟iptables服務的,因為內網服務器沒有公網ip,走內網路由只能出不能進,所以不存在安全性問題。

等我把A機房端口映射工作做完之後,通知到同事,他就開始設置iptabels規則了。 同事跳坑最終導致的結果就是A機房的服務器DB2不能遠程連接上去,然後所有的服務端口也被屏蔽了。事後問題具體的跳坑過程如下:

1、清理iptables規則

# iptables -F

2、設置input表規則

# iptables -A INPUT -p tcp -s 121.134.33.89 --dport 3307 -j ACCEPT

# iptables -A INPUT -p tcp -s 10.0.0.0/16 --dport 3307 -j ACCEPT

# iptables -A INPUT -p tcp --dport 3307 -j DROP

3、保存添加的規則

# /etc/init.d/iptables save

# vim /etc/sysconfig/iptables

# Generated by iptables-save v1.4.7 on Thu Jul 13 09:17:19 2017

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [787:76250]

-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -j REJECT —reject-with icmp-host-prohibited

-A INPUT -s 121.134.33.89/32 -p tcp -m tcp —dport 3307 -j ACCEPT

-A INPUT -s 10.0.0.0/16 -p tcp -m tcp —dport 3307 -j ACCEPT

-A INPUT -p tcp -m tcp —dport 3307 -j DROP

-A FORWARD -j REJECT —reject-with icmp-host-prohibited

-A INPUT -p tcp -m state —state NEW -m tcp —dport 22000 -j ACCEPT

COMMIT

# Completed on Thu Jul 13 09:17:19 2017

5、重啟iptables服務

他認為沒有問題,所有的準備工作和設置都ok了,然後重啟服務:

# /etc/init.d/iptables restart

經過上面5個步驟他認為沒有事情了,一切ok,然後退出服務器了,但是踩坑後的悲劇發生了:A、網站告警了,報500內部錯誤,然後監控MYSQL實例的端口監控也報價了,接收到告警之後,他想登陸服務器查看具體原因,但是悲劇的是他發現遠程登陸也登陸不了,這是為什麼,從他的不走上看沒有多大問題啊,下面我給大家分析一下,默認的一條input規則的坑。

分析入坑過程

首先經過上面的背景介紹和他具體的操作過程,我們來一一分析他的操作過程:

第一步,他利用iptables -F來清理iptables的規則,他認為這樣會清理掉默認的規則,但是他錯了,因為這個命令只有在你iptables服務啟動的狀態下,才會清理掉的,因為默認規則已經在文件/etc/sysconfig/iptables中保存著呢,這樣做是沒用的,所以這步是無用功。

第二步,設置iptables的input規則沒有問題,因為他是基於第一步的思考之上的(認為默認規則已經清空了)。

第三步,保存規則這步也沒有問題,也是基於第一步的先覺條件

第四步,編輯確認規則,這步最重要,所以的過錯都來源於這步。當他編輯文件/etc/sysconfig/iptables的時候,他看到了默認規則的存在,但是他發現都是input規則(當時心裡想,應該沒有太大問題,也沒有注意到一條input表的REJECT記錄),他只是把-A INPUT -p tcp -m state —state NEW -m tcp —dport 22 -j ACCEPT這條規則的22改為了22000端口(因為我們的服務器都是修改了默認ssh遠程端口為22000的),然後放到了FORWARD表規則後面。

第五步 ,重啟iptables服務,退出服務器。

結果上面的分析,我可以清晰的告訴大家的是,出現問題就是出現在第四步,第四步就是真正忽略了默認iptables規則中的-A INPUT -j REJECT —reject-with icmp-host-prohibited記錄,下面我貼出默認的iptables的規則,然後一一解釋出來,你一看就知道為什麼了,默認規則如下:

# Generated by iptables-save v1.4.7 on Thu Jul 13 09:17:19 2017

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [787:76250]

-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -p tcp -m state —state NEW -m tcp —dport 22 -j ACCEPT

-A INPUT -j REJECT —reject-with icmp-host-prohibited

-A FORWARD -j REJECT —reject-with icmp-host-prohibited

COMMIT

# Completed on Thu Jul 13 09:17:19 2017

:INPUT ACCEPT [0:0]: 該規則表示INPUT表默認策略是ACCEPT

:FORWARD ACCEPT [0:0]: 該規則表示FORWARD表默認策略是ACCEPT

:OUTPUT ACCEPT [787:76250]: 該規則表示OUTPUT表默認策略是ACCEPT

-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT: 改規則意思是允許進入的數據包只能是剛剛我發出去的數據包的回應,ESTABLISHED:已建立的鏈接狀態。RELATED:該數據包與本機發出的數據包有關。

-A INPUT -p icmp -j ACCEPT: 改規則指的是icmp協議的包都接受通過(ping命名發出的就是icmp的包)。

-A INPUT -i lo -j ACCEPT: -i參數是指定接口,這裡的接口是lo ,lo就是Loopback(本地環回接口),意思就允許本地環回接口在INPUT表的所有數據通信。

-A INPUT -p tcp -m state —state NEW -m tcp —dport 22 -j ACCEPT: 該規則的意思就是新連接ssh默認端口22的允許進入。

重點來了:

-A INPUT -j REJECT —reject-with icmp-host-prohibited: 該規則的意思是說在INPUT表中拒絕所有其他不符合上述任何一條規則的數據包。並且發送一條host prohibited的消息給被拒絕的主機。

-A FORWARD -j REJECT —reject-with icmp-host-prohibited: 該規則的意思是說在FORWARD表中拒絕所有其他不符合上述任何一條規則的數據包。並且發送一條host prohibited的消息給被拒絕的主機。

咋們在回頭看看我同事最終save生效的規則情況:

# Generated by iptables-save v1.4.7 on Thu Jul 13 09:17:19 2017

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [787:76250]

-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -j REJECT —reject-with icmp-host-prohibited

-A INPUT -s 121.134.33.89/32 -p tcp -m tcp —dport 3307 -j ACCEPT

-A INPUT -s 10.0.0.0/16 -p tcp -m tcp —dport 3307 -j ACCEPT

-A INPUT -p tcp -m tcp —dport 3307 -j DROP

-A FORWARD -j REJECT —reject-with icmp-host-prohibited

-A INPUT -p tcp -m state —state NEW -m tcp —dport 22000 -j ACCEPT

COMMIT

# Completed on Thu Jul 13 09:17:19 2017

我想現在你應該一目瞭然的知道問題的所在了吧!

總結(亮了)

不管你是運維菜鳥還是運維老鳥,如果你也有這樣相同的遭遇,我想對你說很慶幸,你已經遭遇過了,我想你應該知道怎麼規避了,但是我個人總結幾點建議,希望對你有幫助。

運維做線上的變更或者操作的時候,一定要預先實戰演練,做好充分準備工作;

運維做線上的變更或者操作的時候,有思路了一定不要只是存放在腦子裡,按照腦子所想去做,而是寫出詳細的操作文檔,然後審核操作過程,最後根據文檔一步一步的做變更;

增強自己對運維基礎知識的認知,這個案例很明顯就是一個簡單的iptables的默認規則的問題,如果你之前就對默認規則認知很清楚,我想這個坑在你這裡是不存在的;

運維應該有意識的去提升自我的英文單詞認識能力和閱讀能力,如果你瞭解到了REJECT單詞是拒絕的意思,我想你也不會跳進坑裡,你會持有懷疑態度。

細節決定成敗,運維時時刻刻都在監控告警和背鍋的準備中,保持認真、謹慎的態度,時刻保持對運維工作持有敬畏之心。


分享到:


相關文章: