搜尋此網誌

2013年9月23日 星期一

[工具介紹] 利用 knockd 實現複雜的敲門機制

funny-bear-knocking-door去年我介紹過如何利用 iptables 的 recent 模組來保護如 ssh 之類的網路服務。今天我要介紹的這個服務 – knockd,也可以達成類似的目的。不過不同於 iptables 的作法,knockd 可以輕鬆支援用多個網路埠的組合當做敲門的鑰匙,而且這些網路埠並不會對敲門動作的封包有所回應,可以達到更高的隱密性。此外,如果要保護的服務一多,將保護機制獨立在 iptables 的規則設定之外,也可以簡化 iptables 的複雜度,以避免設定錯誤的情況發生。
在今天的範例中,我們需要兩台 Linux 主機,其中一台當做利用 knockd 機制保護 ssh 服務的主機 (名稱為 knockd.cyril.idv,IP 位址為 192.168.199.103),另外一台用戶端電腦則是用來測試是否可以正常連上受保護的 ssh 服務 (名稱為 client.cyril.idv,IP位址為 192.168.199.102)。採用的 Linux 版本為 32 位元的 CentOS 6.4。為了測試方便,我們在兩台電腦的 /etc/hosts 各加上下列設定:
192.168.199.102 client.cyril.idv client
192.168.199.103 knockd.cyril.idv knockd
接下來,我們就一步步完成今天的範例。

第一階段 安裝與設定 knockd 服務
此階段的操作皆在 ssh 服務主機 (knockd.cyril.idv) 上進行。
  1. 加入對應的 repo
    新增檔案 /etc/yum.repos.d/nux-misc.repo 並加入下列內容
    [nux-misc]
    name=Nux Misc
    baseurl=http://li.nux.ro/download/nux/misc/el6/i386/
    enabled=0
    gpgcheck=1
    gpgkey=http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
  2. 安裝 knock 服務
    指令是
    [root@knockd ~]# yum --enablerepo=nux-misc install knock-server –y
  3. 將目前執行中的防火牆規則導入至檔案
    指令是
    [root@knockd ~]# iptables-save > /tmp/iptables.sav
  4. 修改防火牆規則檔案
    直接修改上述檔案,將內容改為
    # Generated by iptables-save v1.4.7 on Mon Aug 17 21:32:51 2012
    *filter
    :INPUT DROP [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [149:22436]
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT
    # Completed on Mon Dec 17 21:32:51 2012
    除了將 INPUT 的預設動作由 ACCEPT 改為 DROP 之外,也移除掉原本 ssh 服務 (TCP Port 22) 的開放規則。
  5. 匯入新的防火牆規則
    指令是
    [root@knockd ~]# iptables-restore < /tmp/iptables.sav
  6. 移除防火牆規則檔案
    指令是
    [root@knockd ~]# rm –f /tmp/iptables.sav
  7. 確認目前的防火牆規則
    指令是
    [root@knockd ~]# iptables-save
    應可以看到類似下列的訊息:
    # Generated by iptables-save v1.4.7 on Mon Aug 17 21:42:57 2012
    *filter
    :INPUT DROP [17:1672]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [149:22436]
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT
    # Completed on Mon Dec 17 21:42:57 2012
  8. 將目前的防火牆規則寫入系統設定
    指令是
    [root@knockd ~]# service iptables save
  9. 設定 knockd
    knock 服務預設的設定檔是 /etc/knockd.conf,修改成如下:
    [options]
            UseSyslog
    
    [opencloseSSH]
            sequence      = 4567:tcp,5678:tcp,6789:tcp
            seq_timeout   = 15
            tcpflags      = syn
            start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport ssh -j ACCEPT      
            cmd_timeout   = 10
            stop_command  = /sbin/iptables -D INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
  10. 設定 knock 服務自動啟動
    指令是
    [root@knockd ~]# chkconfig knockd on
  11. 啟動 knock 服務
    指令是
    [root@knockd ~]# service knockd start

第二階段 安裝 knock 用戶端程式
雖然 knock 使用的敲門技術可以透過許多工具來產生所需的敲門封包,但是使用 knock 內建的工具可以簡化指令的操作。不過如果要進行比較複雜的敲門動作 (也就是送出比較複雜的封包),那就還是必須借助更複雜的封包產生工具了。
此階段的操作皆在 ssh 用戶端電腦 (client.cyril.idv) 上進行。
  1. 加入對應的 repo
    新增檔案 /etc/yum.repos.d/nux-misc.repo 並加入下列內容
    [nux-misc]
    name=Nux Misc
    baseurl=http://li.nux.ro/download/nux/misc/el6/i386/
    enabled=0
    gpgcheck=1
    gpgkey=http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
  2. 安裝 knock 用戶端工具
    指令是
    [root@client ~]# yum install --enablerepo=nux-misc knock –y

第三階段 測試 knock 機制
  1. 直接嘗試連結 ssh 服務
    指令是
    [root@client ~]# ssh knockd
    我們發現指令一直沒有回應,必須透過 Ctrl-C 才能跳脫。
  2. 使用敲門機制
    指令是
    [root@client ~]# knock knockd 4567:tcp 5678:tcp 6789:tcp && ssh knockd
    此時我們應該可以透過 ssh 服務正常連結至主機 knockd (192.168.199.103),並看到類似下列訊息:
    Last login: Mon Aug 17 21:40:42 2012 from client.cyril.idv
    [root@knockd ~]#
  3. 檢查 knock 服務的日誌
    knock 服務預設會將日誌寫入 /var/log/secure 這個檔案中,在 ssh 服務主機 (192.168.199.103) 我們可以看到類似下列的訊息
    Aug 17 21:45:31 knockd knockd: waiting for child processes...
    Aug 17 21:45:31 knockd knockd: shutting down
    Aug 17 21:45:31 knockd knockd: starting up, listening on eth0
    Aug 17 21:45:42 knockd knockd: 192.168.199.102: opencloseSSH: Stage 1
    Aug 17 21:45:42 knockd knockd: 192.168.199.102: opencloseSSH: Stage 2
    Aug 17 21:45:42 knockd knockd: 192.168.199.102: opencloseSSH: Stage 3
    Aug 17 21:45:42 knockd knockd: 192.168.199.102: opencloseSSH: OPEN SESAME
    Aug 17 21:45:42 knockd knockd: opencloseSSH: running command: /sbin/iptables -A INPUT -s 192.168.199.102 -p tcp --dport ssh -j ACCEPT
    Aug 17 21:45:42 knockd sshd[2472]: Accepted publickey for root from 192.168.199.102 port 52920 ssh2
    Aug 17 21:45:42 knockd sshd[2472]: pam_unix(sshd:session): session opened for user root by (uid=0)
    Aug 17 21:45:52 knockd knockd: 192.168.199.102: opencloseSSH: command timeout
    Aug 17 21:45:52 knockd knockd: opencloseSSH: running command: /sbin/iptables -D INPUT -s 192.168.199.102 -p tcp --dport ssh -j ACCEPT
透過 knock 所提供的敲門機制,我們可以建立起複雜的敲門機制。以上述的例子而言,我們必須依序連接 3 個 TCP 埠,才能順利連結 ssh 服務。除了 TCP 埠,我們也可以選擇 UDP 埠。而因為對 knock 機制而言,其實只是在接受到敲門訊息後呼叫特定的指令,所以除了 iptables 的指令外,也可以用來呼叫其他指令,以達成不同的管理目的。

2013年9月17日 星期二

[工具介紹] 利用 glusterfs 達成目錄即時自動同步與高可用性

glusterfs-logo去年我介紹過利用 lsyncd 這個套件來達成目錄的同步備援,今天則要利用 glusterfs 來達成類似的效果。雖說類似,但是 lsyncd 與 glusterfs 相比有下列差別:
  • lsyncd 監測目錄的變動,並定期 (或達到一定的異動次數) 將異動同步到另外一個目錄。因為 lsyncd 採用 inotify 監測技術,所以如果目錄內的檔案或子目錄一多,就可能會產生無法監測的問題。
  • lsyncd 本身並沒有支援高可用性,必須利用其它機制 (如 heartbeat) 來達成高可用性。
  • 被同步的目錄通常僅能當做備援,無法作為負載平衡之用。不但在資源使用上較為浪費,擴充性也比較差。
嚴格來說,拿 lsyncd 與 glusterfs 相比並不是一件公平且合理的事情,因為 glusterfs 本身是一個完整的分散式檔案系統,所以在功能上本就遠比 lsyncd 這類工具來的強大許多。用最簡單的說法,glusterfs 可以將許多不同的儲存空間整合在一起,變成一個分散式的虛擬儲存空間。glusterfs 所管理的虛擬儲存空間除了可以具備分散的特性 (distributed, 也就是將不同的檔案存放在不同的儲存空間) 之外,glusterfs 還提供了複製 (replicated, 也就是同一個檔案存放在兩個以上的儲存空間) 以及分條 (stripped, 也就是將一個檔案打散在多個不同的儲存空間) 的選項。這些選項可以單獨使用,也可以一起套用。今天我要跟大家分享的就是透過複製特性來達成目錄的自動同步與高可用性。
範例需要三台 Linux 系統,其中兩台作為 glusterfs 的服務端,另外一台則作為 glusterfs 的用戶端,所使用的環境皆為 CentOS 6.4。相關架構如下:
glusterfs
為了方便起見,我們讓這三台 Linux 之間可以透過主機名稱進行連結,所以我們在 /etc/hosts 設定如下:
192.168.199.100 server1.cyril.idv server1
192.168.199.101 server2.cyril.idv server2
192.168.199.102 client.cyril.idv client
接下來就讓我們一起一步步完成今天的範例吧。

第一階段:glusterfs 服務端的基本安裝
此階段的步驟必須在 server1 與 server2 上皆予以執行。
  1. 安裝 glusterfs 的 repo
    指令為
    wget http://download.gluster.org/pub/gluster/glusterfs/3.3/LATEST/EPEL.repo/glusterfs-epel.repo -O /etc/yum.repos.d/glusterfs-epel.repo
    註1:雖然目前 glusterfs 的最新版本為 3.4,但是 GA 版本仍為 3.3,所以在這個範例中我選擇使用 3.3 的 repo。
    如果系統已經安裝 EPEL 的 repo,裡面就包含了 glusterfs 3.2 的相關 RPM 套件。但仍建議停用 EPEL 內的 glusterfs 套件,而改採用上述的套件。
  2. 安裝 glusterfs 的服務器套件
    指令為
    yum install glusterfs-server -y
  3. 設定 glusterfs 服務開機後自動啟動
    指令為
    chkconfig glusterd on
  4. 啟動 glusterfs 服務
    指令為
    service glusterd start
  5. 修改防火牆設定
    在 glusterfs 官方文件中提到應該開啟 TCP 111, 24007, 24008, 24009 以及之後的數個埠號,至於要開到幾個埠號,則跟 brick 數量有關。以這個例子而言,應該開啟 TCP 111, 24007, 24008, 24009, 24010, 24011 等埠號。
    修改完後記得確認防火牆規則是否已經生效。指令為
    iptables –L -n
    執行後應可以看到類似下列資訊
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0      
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:111
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24007
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24008
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24009
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24010
    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:24011
    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
    Chain FORWARD (policy ACCEPT)
    target     prot opt ource               destination
    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
    Chain OUTPUT (policy ACCEPT)     
    target     prot opt source               destination

第二階段:glusterfs 服務端的服務設定
此階段的指令僅需在 server1 予以執行即可。
  1. 將 server2 加入可信任的儲存池 (Trusted Stroage Pool)
    指令為
    [root@server1 ~]gluster peer probe server2.cyril.idv
    執行後應可看到下列訊息
    Probe successful
  2. 確認信任關係
    指令為
    [root@server1 ~]gluster peer status
    執行後應可看到類似下面的訊息
    Number of Peers: 1
    
    Hostname: server2.cyril.idv
    Uuid: f44e01c6-e889-432a-8056-cf7174421324
    State: Peer in Cluster (Connected)
  3. 建立 Volume
    在 glusterfs 的架構中,每一個 volume 就代表了單獨的虛擬檔案系統。建立 volume 的指令為
    [root@server1 ~]gluster volume create datavol replica 2 transport tcp server1.cyril.idv:/data server2.cyril.idv:/data
    執行後應可看到下列訊息
    Creation of volume datavol has been successful. Please start the volume to access data.
    註2:glusterfs 會自動建立不存在的 /data 目錄。此外,在建立 volume 時,我們不需要特別指定虛擬檔案系統的屬性 (像是分散與否),glusterfs 會自動根據相關參數 (如 brick 數) 決定此一虛擬檔案系統的屬性。
  4. 啟動 Volume
    指令為
    [root@server1 ~]gluster volume start datavol
    執行後應可看到下列訊息
    Starting volume datavol has been successful
  5. 確認服務之間的連線已經正常連結
    指令為
    [root@server1 ~]netstat –tap | grep glusterfsd
    執行後應可看到類似下列的訊息
    tcp        0      0 *:24009                     *:*                         LISTEN      2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server2.cyril.idv:exp2      ESTABLISHED 2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server1.cyril.idv:1020      ESTABLISHED 2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server2.cyril.idv:1020      ESTABLISHED 2343/glusterfsd
    tcp        0      0 server1.cyril.idv:24009     server1.cyril.idv:1023      ESTABLISHED 2343/glusterfsd
    tcp        0      0 localhost:1020              localhost:24007             ESTABLISHED 2343/glusterfsd
  6. 查詢 volume 的狀態
    指令為
    [root@server1 ~]gluster volume info datavol
    執行後應可看到類似下列訊息
    
    Volume Name: datavol
    Type: Replicate
    Volume ID: 185ef7c6-7c7f-461d-8690-eec24a1a4c38
    Status: Started
    Number of Bricks: 1 x 2 = 2
    Transport-type: tcp
    Bricks:
    Brick1: server1.cyril.idv:/data
    Brick2: server2.cyril.idv:/data
    其中 Type 資訊表示這是一個複製的 (Replicate) 虛擬檔案系統。
  7. 為了增加安全性,我們可以限制只有 client 電腦的 IP 才能連上此一虛擬檔案系統
    指令為
    [root@server1 ~]gluster volume set datavol auth.allow 192.168.199.102
    執行後應可看到下列訊息
    Set volume successful
  8. 再次確認 volume 的狀態
    指令同樣為
    [root@server1 ~]gluster volume info datavol
    執行後應可看到類似下列訊息
    
    Volume Name: datavol
    Type: Replicate
    Volume ID: 185ef7c6-7c7f-461d-8690-eec24a1a4c38
    Status: Started
    Number of Bricks: 1 x 2 = 2
    Transport-type: tcp
    Bricks:
    Brick1: server1.cyril.idv:/data
    Brick2: server2.cyril.idv:/data
    Options Reconfigured:
    auth.allow: 192.168.199.102

第三階段:glusterfs 用戶端的安裝
  1. 安裝 glusterfs 的 repo
    指令為
    [root@client ~]wget http://download.gluster.org/pub/gluster/glusterfs/3.3/LATEST/EPEL.repo/glusterfs-epel.repo -O /etc/yum.repos.d/glusterfs-epel.repo
  2. 安裝 glusterfs 用戶端的套件
    指令為
    [root@client ~]yum install glusterfs-client -y
  3. 建立掛載點
    指令為
    [root@client ~]mkdir /mnt/glusterfs/data –p
  4. 掛載虛擬檔案系統
    指令為
    [root@client ~]mount.glusterfs server1.cyril.idv:/datavol /mnt/glusterfs/data
  5. 確認掛載的結果
    指令為
    [root@client ~]mount –t fuse.glusterfs
    執行後應可看到類似下列訊息
    server1.cyril.idv:/datavol on /mnt/glusterfs/data type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)
  6. 設定開機自動掛載
    修改 /etc/fstab,加上下列設定
    server1.cyril.idv:/datavol /mnt/glusterfs/data glusterfs defaults 0 0
  7. 重新開機
    指令為
    [root@client ~]sync; shutdown –r now
  8. 確認開機自動掛載是否成功
    指令同樣為
    [root@client ~]mount –t fuse.gluserfs
    執行後應可看到類似下列訊息
    server1.cyril.idv:/datavol on /mnt/glusterfs/data type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)
  9. 測試檔案的操作
    指令為
    [root@client ~]echo "Hello GlusterFS" >> /mnt/glusterfs/data/test0
  10. 確認檔案的同步複製
    我們可以同時在 server1 與  server2 的 /data 下看到 test0 這個檔案,而且內容皆為 "Hello GlusterFS"。
至此,我們已經完成利用 glusterfs 建立目錄即時同步的架構。接下來我們將透過更多的例子,看看此一架構可以提供何種程度的高可用性。
註3:如果我們直接在 server1 或 server2 上針對檔案系統 (也就是 /data) 進行異動的操作 (如新增檔案),將無法對達到同步的效果,甚至連用戶端也無法接受到這些異動。

第四階段:高可用性測試
  1. 關閉 server1
    指令為
    [root@server1 ~]sync;shutdown –h now
  2. 修改檔案內容
    指令為
    [root@client ~]echo "Hello GlusterFS Replication" >> /mnt/glusterfs/data/test0
    雖然 server1 已經關機,但是我們依舊可以對原本掛載的目錄進行讀寫,其讀寫的目的地會自動變成 server2。
  3. 確認 server2 上檔案 test0 的內容
    指令為
    [root@server2 ~]# cat /data/test0
    執行後應可看到下列訊息
    Hello GlusterFS
    Hello GlusterFS Replication
  4. 開啟 server1
  5. 確認 server1 上檔案 test0 的內容
    指令為
    [root@server1 ~]# cat /data/test0
    執行後應可看到下列訊息
    Hello GlusterFS
    Hello GlusterFS Replication
    註4:glusterfs 具備自動修復 (heal) 的功能,如果目錄下的資料較多,自動修復所需的時間也會跟著增長。在自動修復期間雖然服務端的檔案可能會有不一致的現象發生,但是 glusterfs 會確保用戶端只會看到最新的檔案。
  6. 再次關閉 server1
    指令同樣為
    [root@server1 ~]sync;shutdown –h now
  7. 卸載用戶端上的目錄掛載
    指令為
    [root@client ~]umount /mnt/glusterfs/data
  8. 再次掛載目錄
    指令為
    [root@client ~]mount -a
    執行後應可看到下列訊息
    Mount failed. Please check the log file for more details.      
    註5:掛載失敗的原因在於 server1 已經關機,所以用戶端自然無法進行連結。雖然 glusterfs 在掛載後的讀寫具備自動切換的能力,但是掛載時的動作卻無法自動切換。
  9. 修改掛載的參數,使其支援備用掛載主機
    修改 /etc/fstab,將原本
    server1.cyril.idv:/datavol /mnt/glusterfs/data glusterfs defaults 0 0
    修改為
    server1.cyril.idv:/datavol /mnt/glusterfs/data glusterfs defaults,backupvolfile-server=server2.cyril.idv 0 0
  10. 再次掛載目錄
    指令為
    [root@client ~]mount –a
  11. 確認掛載結果
    指令為
    [root@client ~]mount –t fuse.glusterfs      
    執行後應可看到下列訊息
    server2.cyril.idv:/datavol on /mnt/glusterfs/data type fuse.glusterfs (rw,default_permissions,allow_other,max_read=131072)
    註6:在此我們可以看到掛載主機已經從 server1 改為 server2了。透過此一參數,可以避免 glusterfs 在掛載目錄時因為單一主機失效而掛載失敗。
透過 glusterfs,我們可以輕鬆建立一個可自動同步且具備高可用性的目錄。更棒的是,如果未來我們發現這個目錄有空間不足或效能低落的情況發生,只要加上更多的 brick,就可以直接在線上進行擴充的工作,不用再擔心因為資料轉移所造成的過多時間花費與停機時間了。

About