搜尋此網誌

2012年11月7日 星期三

[工具介紹] 利用 iptables 的敲門機制保護 ssh 服務

DoorKnock之前我介紹過利用 fail2ban 來封鎖嘗試使用暴力破解登入 ssh 的有心份子,但是如果你有嚴重的潔癖,看到滿滿的登入錯誤訊息就渾身不舒服想要更進一步降低此一風險,還有一些措施可以施作,其中最常見的建議就是不要使用預設的埠號 (TCP:22)。改用其他埠號雖然看似很有效,但是一旦遇到埠號掃描的攻擊行為並被有心份子知道實際使用的埠號,其實就跟使用預設埠號沒啥兩樣。如果我們可以隱藏實際使用的埠號,並於特殊情況下才予以現形,那就不用擔心埠號掃描的攻擊方式了。

我們可以利用 iptables 內建的 recent module 來達成此一目標,想要連結 ssh 服務的一方必須先對某個特定的埠號進行"敲門"動作,iptables 才會對此 IP 位址開放 ssh 服務所使用的埠號。以下我們就透過實際的例子來加以說明,實作的環境是 CentOS 6:

  1. 修改 ssh  服務所使用的埠號
    ssh 服務的設定檔為 /etc/ssh/sshd_config,將
    #Port 22
    改為
    Port 2222
    其中 2222 表示我們想要 sshd 服務所使用的埠號。
  2. 重新啟動 ssh 服務
    指令為
    service sshd restart
  3. 匯出 iptables 所使用的設定
    指令為
    iptables-save > /tmp/iptables
    如果你使用其他工具 (如webmin) 來設定 iptables,那麼就不需要進行 iptables 規則的匯入與匯出,可以直接加入所需規則。
  4. 修改 iptables 的規則
    在 /tmp/iptables 適當的位置加入用紅色標示的兩行規則 (請務必加在 default policy 之前):
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT      
    -A INPUT -p tcp --dport 54321 -m recent --set --name SSH-PHASE1
    -A INPUT -p tcp --dport 2222 -m recent --rcheck --seconds 5 --name SSH-PHASE1 -j ACCEPT

    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    其中 54321 是我們用來敲門的埠號,而 2222 則是 ssh 服務實際上所使用的埠號。同時記得刪除 ssh 服務的預設規則
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
  5. 匯入 iptables 的規則
    指令是
    iptables-restore < /tmp/iptables
  6. 測試新的規則
    從另外一台主機執行下列指令
    telnet ip_address 54321; ssh ip_address –p 2222
    其中 ip_address 請換成前一台主機的 IP 位址。順利的話,應該可以看到 ssh 的登入提示符號。如果我們在 telnet 與 ssh 兩個指令之間停頓超過 5 秒,將無法連結至 ssh 服務,也就是說每次敲門後的開放只保留 5 秒,5 秒過後又自動加以關閉。如以一來,即使利用埠號掃描攻擊也很難發現 ssh 服務真正使用的埠號。
  7. 刪除規則暫存檔
    指令是
    rm –f /tmp/iptables
  8. 將規則寫入 iptables 的啟動設定
    如果測試無誤,我們就可以把規則寫入 iptables 的啟動設定,以確保每次啟動 iptables 時都能套用此一設定。指令是
    service iptables save

透過兩行簡單的iptables 規則設定,我們大幅減少 ssh 服務埠號被偵測出的可能性,對 ssh 服務的保護將更加完善。最後,即使使用了 iptables 的敲門機制來保護 ssh 的服務埠, fail2ban 依舊有其必要性,理由如下:

  • fail2ban 不只可用來保護 ssh 服務,還可以用來保護包含 ftp 與 pop3 在內的各項網路服務。
  • 通常 iptables 規則中總會有些例外 IP 位址可以對系統暢行無阻,雖說這些 IP 位址多為內部使用,但是別忘了內部使用的 IP 位址並不等於絕對安全。
  • 避免日後有人不小心移除了相關設定。相信我,這種糗事發生的機會比你想像中還來的高出許多。
  • 一旦知道這個"敲門"用的埠號後,此一機制同樣可能遭受暴力攻擊。什麼人會知道這個敲門埠號?你猜對了,正是離職員工!

2012年11月6日 星期二

[工具介紹] 利用 lsyncd 達成 Linux 下的目錄"即時"同步

windows-8-transfer7數位資料對一個企業的重要性,我想已經不用我在此多加贅述。而這些數位化的資料,除了存在於資料庫當中,其實還有不少是以檔案形式存在著。對於資料庫,通常我們除了定期備份之外,還會考慮到備援的機制 (如常見的主從式架構),以確保資料庫的高可用性。但是對於檔案呢?往往可能就沒有那麼受到重視了。備份或許有之,但是是否有也良好的備援機制呢?檔案的備援有多種可能性,從分散式儲存機制 (如 DRBD),到分散式檔案系統 (如 GFS2, Hadoop Distributed File System),選擇性可說是五花八門。儘管選擇相當多,但是這些機制通常都必須在建立系統前就一併加以規劃,而且受到支援平台的限制。有些機制甚至在使用上也與傳統的檔案系統不盡相同,再再提高了管理人員與系統開發人員的進入門檻。對於大部分的系統而言,可能原先已經存在許多檔案並存放在"一般"的檔案系統 (如 ext3) 之內,有什麼好的方法可以讓這些系統無痛地達成備援的機制?
對 Linux 系統而言,基本上我們只要達成目錄的同步再加上如 heartbeat 的監測機制,就可以達到檔案的備援機制。而要達到目錄的同步,最簡單也是最常見的一種方式就是透過排程定期呼叫 rsync 將主目錄內的檔案同步至備援主機的目錄。這方法雖然很簡單,也確實可行,但是他有一個主要的問題,那就是當目錄結構一大,比對與同步的時間將會拖的很長。如此一來,表示排程間隔的時間不能太短,也就是兩個目錄所出現的時間差距也會隨之增加。而今天我要介紹的這個工具 – lsyncd,雖然也是透過 rsync 進行同步,但是 lsyncd 透過監測目錄的寫入動作,僅針對變動的部份進行同步,可以大幅提高同步的效率。而 lsyncd 的同步觸發條件預設為間隔 20 秒或累積 1000 次的寫入事件,而且這兩個參數還可以依據實際的狀況加以調整。不可否認,lsyncd + rsync 很難達成真正的即時同步,但是對於大部分的狀況,數秒的差距應該是可以被接受的。而因為 lsyncd 只需安裝在主目錄的系統上,所以對於備援主機的限制較少,甚至是不同的檔案系統都沒關係
在 Linux 下面,通常可以找到 lsyncd 的套件直接加以安裝,只是版本上可能會有所不同。以 CentOS 為例,可以在 EPEL 這個 repository 中找到 lsyncd 的套件,版本為 2.0.4。前面提到,只有主目錄的主機需要安裝 lsyncd,而用來當做備援的主機是不需要安裝的。安裝後,必須自行建立一個設定檔,檔案路徑雖然沒有什麼限制,但是我的建議是使用 /etc/lsyncd.conf 以便管理。在 /etc/lsyncd.conf 檔內輸入下列內容:
settings = {   
   logfile = "/var/log/lsyncd.log",    
   statusFile = "/var/run/lsyncd.status",    
   nodaemon = false,    
   log = all    
}

sync {   
   default.rsync,    
   source = "/data",    
   target = "192.168.1.2:/data",    
   rsyncOps = {"-avz", "--delete"},    
   delay = 10    
}

其中 source 與 target 請分別改成你想要同步的主目錄及備援主機的目錄。設定完畢之後,透過指令lsyncd /etc/lsyncd.conf
就可以啟動 lsyncd 的同步功能了。在使用 lsyncd 時,有下列幾點事情需要注意:
  1. 因為新版的 rsync 已經預設使用 ssh 當做傳輸的方式,所以可以直接設定使用 rsync 即可。如果 rsync 版本過舊,可以將 sync 方式由 rsync 改為 rsyncssh。也就是說,我們必須確保主目錄的主機可以直接透過 ssh 登入備援主機,而不需要輸入密碼。除了利用 rsync + ssh 的方式,也可以透過 rsync 的 target,如此一來就不需要 ssh 了。
  2. lsyncd 預設不會同步檔案的所有權與權限,因此我們透過 rsyncOps 這個參數來改變 lsyncd 呼叫 rsync 的行為。
  3. 透過 delay = 10 這個設定,我們要求 lsyncd 將同步間隔時間由預設的 20 秒改為 10 秒。
  4. 我們必須確保所有的寫入動作發生於主目錄的主機上,而在一般的情況下,這應該是不成問題的。但是如果我們自找麻煩地在主目錄掛載了其他主機的目錄,那麼這些掛載而來目錄的寫入動作,將無法被 lsyncd 監測到,所以也就無法同步
  5. lsyncd 透過 inotify 作為監測目錄寫入的機制,而 inotify 可監測的數量則受到 fs.inotify.max_user_watches 這個參數的限制。如果 lsyncd 欲監測的目錄數量超過系統的上限,並不會出現錯誤訊息,而是多餘的目錄直接被忽略。為了避免此一現象的發生,我們在啟動 lsyncd 後可以先透過指令
    sysctl fs.inotify.max_user_watches
    確認系統的設定值。之後在 /var/run/lsyncd.status 中找到類似下列的訊息
    Inotify watching 34567 directories
    其中 34567 表示 lsyncd 供監測了 34567 個目錄。如果兩個數字很接近,請增加系統所允許的上限值以便讓 lsyncd 完整監測並同步所有的目錄。
    透過下列指令我們可以將 inotify 可監測的數量上限變更為 40000
    echo 40000 > /proc/sys/fs/inotify/max_user_watches
    如果我們希望每次開機後此一設定值都自動變更為 40000,請修改 /etc/sysctl.conf,加上下列設定
    fs.inotify.max_user_watches = 40000
  6. CentOS 所安裝的 lsyncd 並沒有提供啟動腳本,因此請在 /etc/rc.local 加上設定
    /usr/bin/lsyncd /etc/lsyncd.conf
    如此一來,開機時 lsyncd 才會自動執行。
雖然 lsyncd 無法真正達成目錄的"即時"同步,但是在可接受的誤差範圍內,lsyncd 有著安裝簡單與適用範圍廣泛的優點,對於檔案備援來說絕對是一個令人心動的選擇。

About