專題二 - 實體主機母系統 (Host) 的設計
上次更新日期 2019/07/07
之所以要架設虛擬機器,是因為虛擬機器具有可以簡單方便回收的動作,而且設定方面較有彈性,能夠解決我們實體機器不足的問題。 那因為虛擬機器已經負責了原本實體主機所應該要執行的任務,因此,我們的實體機器母系統 (Host OS) 就得要有能力提供更加穩定的環境, 讓在這個母系統上面跑的客戶端系統 (Guest OS, 其實就是虛擬機器) 可以提供更好的效能與服務。
因此,這個 Host OS 上面,應該盡量減少不必要的服務,同時減少讓用戶登入的機會,也限制了連線的管理員身份, 這樣在系統的保護上面,可能會比較好一些。此外,效能方面也需要進行一些調整,如果 Host OS 效能已經很爛, 那麼 Guest OS 的效能當然會更糟!所以,這得要好好的來設計一下較好喔!
- Host OS 的整理
- 效能測試軟體
- 特別的防火牆管理與跳板管理 (knockd, fail2ban)
- 參考資料
Host OS 的整理
上週我們主要的目的是讓整個系統的硬體資源穩定耐操!本週我們則需要針對這個母系統來進行一些設計,除了可以讓我們掌握住系統的狀態之外, 也能夠減少不必要的資安問題。不過,在開始之前,我們大概針對母系統與客戶系統做個簡單的說明。
- 母系統:就是 Host OS,亦即是實體主機上面的作業系統。
- 虛擬機器:就是 Virtual Machine 簡稱 VM,也就是在母系統上面模擬出來的一個虛擬的機器!這個機器有 CPU、記憶體、磁碟與相關的週邊設備。
- 客戶端系統:就是 Guest OS,也就是在 VM 上面安裝的作業系統。
Host OS 大概是最重要的!畢竟它是所有 VM 的最底層系統,沒有 Host OS,所有的 VM 當然就不存在!因此,這個 Host OS 就得要比較穩定,而且要針對你的系統進行一些優化才好:
- 系統軟體自動更新與維護:
讓你的母系統能夠更快、更有效率的自我更新,這也是相當重要的步驟!此外,鳥哥不喜歡有持續的校時服務, 因此,定期執行時間校準,也是很重要的!所以,就來建立一隻自我維護的腳本吧!
- 先檢查時間,同時進行網路自動校時!
# date <==單純查閱時間喔! # timedatectl <==檢測日期時間與時區 # date --help <==可以自行檢查如何設定喔! # hwclock [-rw] <==查看 BIOS 的時間鐘
- 修改 yum 來源,直接指向崑山計中 (http://ftp.ksu.edu.tw)
# cd /etc/yum.repos.d/ # vim CentOSxxx # yum repolist [all] # yum clean all
- 進行一次全系統更新
# yum update
- 觀察一下核心的項目 (rpm -qa | grep kernel | sort) 以及核心位置的目錄資料 (/lib/modules)
# rpm -qa | grep kernel | sort # rpm -e kernel-xxx # ll /lib/modules
- 在 /root/bin 底下,建立一隻名為 maintain.sh 的 shell script,且每日 1:20 執行這個指令。
# mkdir /root/bin # vim /root/bin/maintain.sh # chmod a+x /etc/crontab # vim /etc/crontab
- 在 maintain.sh 裡面:
- 先對我們主機所在環境可以網路校時的主機進行校時的任務: ntpdate 120.114.100.1
- 進行全系統更新
- 先檢查時間,同時進行網路自動校時!
- 讓系統維護狀態可以讓你瞧見:
如同上面的情況,我們每天進行系統的維護,但是維護的結果到底是誰可以看得到?難道得要登入系統來查閱? 似乎沒必要如此~如果能夠將資料每日彙整成一份 email 寄給我們,似乎會是比較好的管理行為!那是否要架設 mail server 呢? 好像不必要喔!來玩玩先!
- 因為我們的環境裡面已經有既有的 mail server,所以無須重新自己設定 mail server,因為目的不同! 我們只需要讓這部 server 的訊息,可以傳送到外部的 public mail server 即可。
- 修改 /etc/postfix/main.cf 的內容,將 relayhost 設定為 [mail.ksu.edu.tw] 的模樣, 重新啟動 postfix 之後,就支援信件轉送到 relayhost 的機器上了!
- 再加上 /etc/aliases 修改 root 的收件人成為 root: root,yourname@mail.ksu.edu.tw 這樣,
當 root 有信件時,就可以送一份給你在 mail.ksu.edu.tw 上面的帳號!如果沒有,那可能還是收不到...
# echo "relay test" | mail -s 'check' root # mail # tail -n 100 /var/log/maillog
- 系統安全強化:
還有一些小細節需要處理一下比較好!包括服務的關閉、防火牆的處理、特殊連線服務的處置等等行為, 這都與你的系統安全有關喔!另外,系統安全除了所謂的網路安全之外,還有資料安全!我們得要隨時去檢查硬碟是否正常運作! 因為資料都在上頭的緣故啊!
- 未來可能會開發一些奇怪的東西,因此建議 SELinux 設定改為 permissive 即可。
# vim /etc/selinux/config # getenforce
- 將不必要的服務關閉,對 Internet 提供服務的,只需要 port 22 即可
- 記得讓 root 不能登入系統
- 記得讓管理員一般帳號可以透過 sudo 切換身份
- 記得 sshd_config 將 DNS 反查功能關閉
# netstat -tlunp # vim /etc/ssh/sshd_config # 這裡處理 root 無法 ssh 以及 DNS 反查取消 # systemctl restart sshd
- 將 firewalld 服務關閉,改成 iptables 的狀態。
- 預設的防火牆規則啟動
- 放行所在地內部區域網路 (本例為資訊傳播系) 的 ssh 連線
- 記得需要處理一下其他可能需要針對你常用的 IP 進行完全解鎖的功能。
- NAT 的部份,針對 192.168.19.0/24 這一段進行 SNAT 的設定。
- 記得 ip_forward 需要啟用喔!
# yum install iptables-ser* # systemctl disable firewalld # systemctl stop firewalld # systemctl start iptables # systemctl enable iptables # iptables-save # iptables-save > firewall.sh # vim firewall.sh
- 定期觀察你的磁碟陣列狀態:
- lsblk
- cat /proc/mdstat
- mdadm --detail /dev/md126 (注意看 State 必須要是 clean 才好!)
- 透過 smart 查看系統上面的所有硬碟資訊: smartctl --scan
- 透過 smart 列出兩顆實體硬碟的狀態: smartctl --all /dev/sda
- 透過 smart 自我測試磁碟的好壞: smartctl -t [short|long] /dev/sda
- 將磁碟陣列檢測的結果,比較重要的項目列出到 /root/bin/maintain.sh 裡面去喔!很重要!很重要!
- 未來可能會開發一些奇怪的東西,因此建議 SELinux 設定改為 permissive 即可。
- 系統效能調整:
所謂的效能有 CPU 效能、網路效能、磁碟 I/O 效能等等,底下我們就一項一項來處理相關的效能問題!
- CPU 與系統:先透過 CentOS 官方提供的效能調校服務 (tuned) 來處理預設的效能問題:
為了簡化系統優化的設定流程, Red Hat 有推出一套名為 tuned 的服務,這個服務提供了 tuned-adm 的指令來協助我們設定。 這個服務會依據你的系統使用情境,來給予不同的優化設定,包括 CPU 與核心參數的優化! 作法相對得很簡單:
- 先透過 tuned-adm list 來查看目前的系統自動調整效能
- 可以使用 tuned-adm profile XXX 來設定好使用的 profile
- 現在,請將你的 tuned profile 指定為 virtual-host 或者是 throughput-performance 的相關類型!
- 事實上,還有個 tuned-adm recommend 與 tuned-adm verify 之類的方式來推薦與檢查喔! 如果想要知道 verify 到底在檢查什麼?可以查閱 /var/log/tuned/tuned.log 的內容喔。
- 核心參數:可以針對主機的網路參數進行優化,這通常是 tuned-adm 沒有指定到的部份。
不過設定後,比較有影響的應該是內網互相連線的狀態,外網倒是影響不大的。
# vim /etc/sysctl.d/vbird.conf net.core.optmem_max = 262144 net.core.rmem_default = 262144 net.core.wmem_default = 262144 net.core.rmem_max = 8388608 net.core.wmem_max = 8388608 net.ipv4.tcp_rmem = 4096 87380 8388608 net.ipv4.tcp_wmem = 4096 65536 8388608 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_sack = 0 net.ipv4.tcp_timestamps = 0 net.ipv4.tcp_syncookies = 0 net.core.netdev_max_backlog = 10000 net.ipv4.ip_forward = 1 # sysctl -p /etc/sysctl.d/vbird.conf
可以將上述的資料寫入 /etc/sysctl.d/somename.conf ,未來會自動生效,或者使用『 sysctl -p filename 』立刻啟動! - 網卡的效能調整:一般網卡為了節省 CPU 的效能,所以預設都會將很多莫名其妙的事情交給網卡自己做。
不過,這樣的效能好像並不見得會很好!尤其是在大量資料接收傳送時,這些動作可能會影響到系統的網路效能!
所以,作為 Server 的角度來看,最好將底下的設定停用較佳!
# ip link show # ethtool -i [nicname] # vim /root/bin/performance.sh #!/bin/bash for nic in [nicname] do ifconfig ${nic} txqueuelen 10000 ethtool -G ${nic} rx 4096 tx 4096 ethtool -K ${nic} lro off gro off done # chmod a+x /root/bin/performance.sh # vim /etc/rc.d/rc.local sh /root/bin/performance.sh # chmod a+x /etc/rc.d/rc.local
可將上述的資料寫入 /etc/rc.d/rc.local,每次自動生效 - 磁碟 I/O 調整:因為 VM 還是會讀到本機的檔案,而檔案在本機的 Software RAID 上頭,因此,
當然就得要針對 Host 系統進行一些調整較好。基本上,Linux 大致上會針對本機的 software raid 進行最佳化,
不過,我們還是可以進行一些微調的。
# 先查詢硬碟是否啟動了 NCQ 呢? # dmesg | grep NCQ [ 1.941177] ata2.00: 976773168 sectors, multi 16: LBA48 NCQ (depth 31/32) [ 2.018528] ata4.00: 976773168 sectors, multi 16: LBA48 NCQ (depth 31/32) [ 2.039796] ata3.00: 976773168 sectors, multi 16: LBA48 NCQ (depth 31/32) [ 2.043903] ata1.00: 976773168 sectors, multi 16: LBA48 NCQ (depth 31/32) # 如果出現了 NCQ (depth 31/32) ,那就代表啟用了!如果是只有 1/32,就代表支援但沒啟用。 # echo 1 > /sys/block/sda/device/queue_depth # 這代表關閉 NCQ 喔!如果將 1 換成 31,就代表啟用!
因為我們目前的環境下,使用到的是 RAID10 的 Intel 主機板內建磁碟陣列,可以透過作業系統來處理資料的定位, 似乎不用啟動 NCQ !很多的文章都提到,關閉 NCQ 對於 Linux RAID 會有幫助!如果是單顆磁碟,那就一定要啟用 NCQ 比較好!# 找出磁碟的檔名之後,設定 # lsblk -ti # vim /root/bin/performance.sh # 先針對實體磁碟,(1)設定 16M 的預讀功能,(2)設定 deadline 佇列,(3)關閉 NCQ,(4)增加佇列數量 for hdd in sda sdb sbc sdd do echo 16384 > /sys/block/${hdd}/queue/read_ahead_kb echo deadline > /sys/block/${hdd}/queue/scheduler echo 1 > /sys/block/${hdd}/device/queue_depth echo 256 > /sys/block/${hdd}/queue/nr_requests done # 再針對 /dev/md126 進行調整 echo 32768 > /sys/block/md126/queue/read_ahead_kb echo 512 > /sys/block/${hdd}/queue/nr_requests # sh /root/bin/performance.sh
- 檔案系統優化:
當資料變成電子數據資訊後,傳輸到磁碟內的時候,主要是透過檔案系統來處理的。 檔案系統有一定的方式來轉換這個過程。但是,我們後端實際是使用 software RAID 來進行資料放置到磁碟的動作, software RAID 又有自己的資料放置方式與 chunk 的資料大小 (我們這個範例中,使用的是 chunk 64K 的格式)。 這當中如果給予的資料大小不一樣時,那在不同的界面就需要再透過一層轉換,這可能會造成些許效能的誤差。
因此,通常在格式化的時候,檔案系統都會針對是否具有 RAID 的資料來進行檔案系統的優化。 我們以 XFS 檔案系統搭配 RAID 來說明。
# df /vmdisk 檔案系統 1K-區段 已用 可用 已用% 掛載點 /dev/md126p4 862893404 34720 862858684 1% /vmdisk # xfs_info /dev/md126p4 meta-data=/dev/md126p4 isize=512 agcount=32, agsize=6744656 blks = sectsz=4096 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0 data = bsize=4096 blocks=215828736, imaxpct=25 = sunit=16 swidth=32 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=105385, version=2 = sectsz=4096 sunit=1 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0
以上面顯示的資料為例,在 /dev/md126p4 這個檔案系統內:
- 每一個格式化後的 block 容量為 4K (就是 bsize=4096);
- 而 chunk (或 stripe) 佔用的 block 數量 (那個 sunit 的數值) 為 16 個,因此在這個檔案系統中,預設的資料大小就是 16*4K = 64K!
- 而每次傳輸的資料,使用的資料頻寬為 switdh=32 個 block,也就是 32*4K = 128K 的資料頻寬。 也就是說,每次傳送出 128K 的資料,裡面使用了 2 個 sunit 的意思!
現在來看看既有的 software RAID 設定:
# cat /proc/mdstat Personalities : [raid10] md126 : active raid10 sda[3] sdb[2] sdc[1] sdd[0] 976768000 blocks super external:/md127/0 64K chunks 2 near-copies [4/4] [UUUU] md127 : inactive sdd[3](S) sdc[2](S) sda[1](S) sdb[0](S) 10336 blocks super external:imsm unused devices:
chunk 就是 64K,剛 XFS 格式相同!而因為我們使用 4 顆磁碟做成 RAID10,因此只有 2 顆磁碟在進行分散式寫入, 亦即是每顆磁碟可以記載 64K,所以總頻寬會是 64K*2 = 128K,也就是剛剛好 swidth 的資料量!
如果你的 XFS 顯示的資料與實際的 RAID 不相符的時候,最好進行重新格式化來處理!這樣資料的寫入會比較正常些! 那該如何處理?其實很簡單!我們的 /vmdisk 尚未使用,所以先卸載,之後重新格式化!格式化的時候,輸入的參數是:
- su=64K :因為 chunk 為 64K 的緣故
- sw=2 :因為 RAID10 共 4 顆,所以有兩顆分散寫入的意思。
最後再修改 /etc/fstab ,輸入最新的 UUID 資料即可!
# umount /vmdisk # mkfs.xfs -f -d su=64k,sw=2 /dev/md126p4 meta-data=/dev/md126p4 isize=512 agcount=8, agsize=262128 blks = sectsz=4096 attr=2, projid32bit=1 = crc=1 finobt=0, sparse=0 data = bsize=4096 blocks=2097024, imaxpct=25 = sunit=16 swidth=32 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=4096 sunit=1 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # blkid /dev/md126p4 /dev/md126p4: UUID="05c65eaa-6bf9-4d49-a877-51753e823d7c" TYPE="xfs" PARTUUID="653d4a10-7cde-4106-835c-d70ca8248f75" # vim /etc/fstab # mount -a
- CPU 與系統:先透過 CentOS 官方提供的效能調校服務 (tuned) 來處理預設的效能問題:
效能測試軟體
不是做了上述的設定,系統效能就一定會很好!不見得的!需要有數據佐證才行!所以,當然就得要實際來測試一下系統的效能才行! 每種效能有各自的測試軟體,而測試也得依據你的環境不同而進行個別的處置才行。底下我們介紹幾個常見的效能測試軟體,大家互相測試看看囉!
- 網路效能測試,使用 iperf3 軟體
網路測試當然就得要有 Server 與 Client 端了!不同的資料流向可能產生的效率並不一樣喔!我們建議可以簡單的使用 iperf3 這個軟體來測試 Server/client 兩端的網路傳輸喔!
- iperf3 軟體下載:每個同學各自前往底下的網站,下載所需要的軟體。因為我們使用的是 CentOS 7,因此直接下載 3.1.3 那個 64 位元的版本即可:
- 下載總頁面:https://iperf.fr/iperf-download.php
- 直接按下我:https://iperf.fr/download/fedora/iperf3-3.1.3-1.fc24.x86_64.rpm
# yum install ./iperf3-3.1.3-1.fc24.x86_64.rpm
- Server 端的執行:同學兩兩成對,一個當 Server 一個當 Client,這個部份是針對 Server 的同學實做!
# iperf3 -s & Server listening on 5201 # netstat -tlunp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp6 0 0 :::5201 :::* LISTEN 5944/iperf3 # iptables -I INPUT -p tcp --dport 5201 -j ACCEPT
- Client 端的執行:另一位同學取得 Server 的 IP 之後,就可以這樣進行測試:
# 流量從 client 傳向 server 的方向: # iperf3 -c 172.16.10.101 -t 10 -i 5 Connecting to host 172.16.10.101, port 5201 [ 4] local 172.16.60.100 port 59204 connected to 172.16.10.101 port 5201 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-5.00 sec 9.85 GBytes 16.9 Gbits/sec 2 2.82 MBytes [ 4] 5.00-10.00 sec 10.3 GBytes 17.7 Gbits/sec 0 2.96 MBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 20.1 GBytes 17.3 Gbits/sec 2 sender [ 4] 0.00-10.00 sec 20.1 GBytes 17.3 Gbits/sec receiver
相關的意義是:- -c Server_IP:使用 client 模式,連線到 Server 去;
- -t 10:僅偵測 10 秒鐘
- -i 5:每 5 秒鐘報告一次傳輸的資訊
# 流量從 server 傳向 client 的方向: # iperf3 -c 172.16.10.101 -t 10 -i 5 -R Connecting to host 172.16.10.101, port 5201 Reverse mode, remote host 172.16.10.101 is sending [ 4] local 172.16.60.100 port 59210 connected to 172.16.10.101 port 5201 [ ID] Interval Transfer Bandwidth [ 4] 0.00-5.00 sec 9.53 GBytes 16.4 Gbits/sec [ 4] 5.00-10.00 sec 9.04 GBytes 15.5 Gbits/sec - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 18.6 GBytes 16.0 Gbits/sec 0 sender [ 4] 0.00-10.00 sec 18.6 GBytes 16.0 Gbits/sec receiver
- iperf3 軟體下載:每個同學各自前往底下的網站,下載所需要的軟體。因為我們使用的是 CentOS 7,因此直接下載 3.1.3 那個 64 位元的版本即可:
- 使用 fio 執行磁碟 I/O 的測試方式:
磁碟的測試會比較困擾,因為不同的運作會有不一樣的設計方式!舉例來說,檔案系統通常使用隨機存取的模式,而大型檔案的讀寫, 通常卻是連續讀寫的方式!因此,測試的項目差異很大!無論如何,我們還是可以透過一個名為 fio 的測試軟體,來測試整體磁碟讀寫的效能!
- 安裝:fio 已經包含在 CentOS 官網資料中,所以直接 yum 即可!
# yum install fio # fio --help
- 執行隨機寫入的檔案測試,得先跑到 /vmdisk 底下喔!此外,因為我們的 chunk 設定為 64K,因此,
假定隨機寫入使用的 block 為 64K 喔!
# cd /vmdisk # fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite --bs=64k --direct=1 --size=1G --numjobs=1 --runtime=240 --group_reporting randwrite: (g=0): rw=randwrite, bs=(R) 64.0KiB-64.0KiB, (W) 64.0KiB-64.0KiB, (T) 64.0KiB-64.0KiB, ioengine=libaio, iodepth=1 fio-3.1 Starting 1 process randwrite: Laying out IO file (1 file / 1024MiB) Jobs: 1 (f=1): [w(1)][100.0%][r=0KiB/s,w=103MiB/s][r=0,w=1652 IOPS][eta 00m:00s] randwrite: (groupid=0, jobs=1): err= 0: pid=4240: Fri Jul 5 23:56:54 2019 write: IOPS=1668, BW=104MiB/s (109MB/s)(1024MiB/9821msec) slat (usec): min=19, max=138, avg=25.78, stdev= 5.76 clat (usec): min=380, max=10512, avg=567.89, stdev=214.54 lat (usec): min=402, max=10548, avg=594.74, stdev=214.87 clat percentiles (usec): | 1.00th=[ 408], 5.00th=[ 424], 10.00th=[ 433], 20.00th=[ 445], | 30.00th=[ 457], 40.00th=[ 469], 50.00th=[ 486], 60.00th=[ 570], | 70.00th=[ 676], 80.00th=[ 717], 90.00th=[ 766], 95.00th=[ 799], | 99.00th=[ 873], 99.50th=[ 906], 99.90th=[ 1004], 99.95th=[ 1549], | 99.99th=[10552] bw ( KiB/s): min=103040, max=112384, per=100.00%, avg=106884.11, stdev=2810.76, samples=19 iops : min= 1610, max= 1756, avg=1670.00, stdev=43.92, samples=19 lat (usec) : 500=54.00%, 750=33.37%, 1000=12.51% lat (msec) : 2=0.07%, 4=0.02%, 10=0.01%, 20=0.02% cpu : usr=1.45%, sys=4.78%, ctx=16387, majf=0, minf=27 IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% issued rwt: total=0,16384,0, short=0,0,0, dropped=0,0,0 latency : target=0, window=0, percentile=100.00%, depth=1 Run status group 0 (all jobs): WRITE: bw=104MiB/s (109MB/s), 104MiB/s-104MiB/s (109MB/s-109MB/s), io=1024MiB (1074MB), run=9821-9821msec Disk stats (read/write): dm-3: ios=0/16062, merge=0/0, ticks=0/8789, in_queue=8789, util=90.36%, aggrios=0/16385, aggrmerge=0/0, aggrticks=0/8939, aggrin_queue=8924, aggrutil=89.85% vda: ios=0/16385, merge=0/0, ticks=0/8939, in_queue=8924, util=89.85%
- 隨機讀寫:再來測試隨機讀寫的方法:
# fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=random_read_write.fio --bs=64k --iodepth=64 --size=512M --readwrite=randrw --rwmixread=75 test: (g=0): rw=randrw, bs=(R) 64.0KiB-64.0KiB, (W) 64.0KiB-64.0KiB, (T) 64.0KiB-64.0KiB, ioengine=libaio, iodepth=64 fio-3.1 Starting 1 process test: Laying out IO file (1 file / 512MiB) test: (groupid=0, jobs=1): err= 0: pid=4247: Fri Jul 5 23:59:11 2019 read: IOPS=18.7k, BW=1171MiB/s (1228MB/s)(382MiB/326msec) write: IOPS=6389, BW=399MiB/s (419MB/s)(130MiB/326msec) cpu : usr=8.62%, sys=46.46%, ctx=2085, majf=0, minf=22 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.2%, 32=0.4%, >=64=99.2% submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0% complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0% issued rwt: total=6109,2083,0, short=0,0,0, dropped=0,0,0 latency : target=0, window=0, percentile=100.00%, depth=64 Run status group 0 (all jobs): READ: bw=1171MiB/s (1228MB/s), 1171MiB/s-1171MiB/s (1228MB/s-1228MB/s), io=382MiB (400MB), run=326-326msec WRITE: bw=399MiB/s (419MB/s), 399MiB/s-399MiB/s (419MB/s-419MB/s), io=130MiB (137MB), run=326-326msec Disk stats (read/write): dm-3: ios=5091/1760, merge=0/0, ticks=12277/4376, in_queue=16704, util=72.31%, aggrios=6109/2083, aggrmerge=0/0, aggrticks=14927/5212, aggrin_queue=20138, aggrutil=71.74% vda: ios=6109/2083, merge=0/0, ticks=14927/5212, in_queue=20138, util=71.74%
更詳細的測試資料,可以參考文末的參考文獻喔!
- 安裝:fio 已經包含在 CentOS 官網資料中,所以直接 yum 即可!
特別的防火牆管理與跳板管理 (knockd, fail2ban)
你可能知道,sshd 是個很厲害的服務,可以讓我們遠端登入。但是為了避免被攻擊,所以我們可能都會將 port 22 只針對少部份來源做放行。 另外,某些單位可能從入口處就直接關閉 port 22 了!如此一來,你當然無法使用 ssh 登入系統了。那怎辦?
通常的作法,大多數都是透過 sshd_config 增加一個埠口,或者是透過 iptables 的 port mapping 功能,直接將某個 port number 轉到 port 22 上面。但是,如此一來,這個新開的 port ,舉例說, 2222 好了,就是在一直開啟的狀態,那,就可能會被一直攻擊啊! 畢竟網路上面的 port scan 軟體實在太多了。
這個時候,你有兩個可以做的動作!一個是透過 knockd 的服務,讓你的這個 port 只有在某個特別的狀態發生時, 才會主動的放行防火牆。另外一個則是透過 fail2ban 的功能,限制錯誤登入的次數與抵擋時間,都可以有效的避免被瘋狂的猜密碼!
- 讓你的 sshd 服務啟動一個額外的埠口:
一般的規劃,來自區域網路對你的 ssh 做連線時,預設還是全放行,然後透過 port 22 來連線,不必加上特別的埠口特徵。 但是如果來自於外部網路的連線,最好不要針對 port 22 啦!畢竟這個 port 22 實在很危險!很容易被攻擊! 所以,我們假設使用 port 2222 來作為外部連線的方式。這時,請讓你的 sshd 服務放行兩個埠口吧!
# vim /etc/ssh/sshd_config Port 22 Port 2222 # 上面這兩個設定值需要同時存在才行喔! # systemctl restart sshd # systemctl status sshd ● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled) Active: active (running) since 六 2019-07-06 22:05:35 CST; 14s ago Docs: man:sshd(8) man:sshd_config(5) Process: 23354 ExecStart=/usr/sbin/sshd $OPTIONS (code=exited, status=0/SUCCESS) Main PID: 23355 (sshd) CGroup: /system.slice/sshd.service └─23355 /usr/sbin/sshd 7月 06 22:05:35 station10-101.gocloud.vm systemd[1]: Starting OpenSSH server daemon... 7月 06 22:05:35 station10-101.gocloud.vm systemd[1]: PID file /var/run/sshd.pid not readable (yet?) after start. 7月 06 22:05:35 station10-101.gocloud.vm sshd[23355]: error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. 7月 06 22:05:35 station10-101.gocloud.vm sshd[23355]: error: Bind to port 2222 on :: failed: Permission denied. 7月 06 22:05:35 station10-101.gocloud.vm systemd[1]: Started OpenSSH server daemon. 7月 06 22:05:35 station10-101.gocloud.vm sshd[23355]: Server listening on 0.0.0.0 port 22. 7月 06 22:05:35 station10-101.gocloud.vm sshd[23355]: Server listening on :: port 22.
你會發現到 port 22 正常沒問題,但是 port 2222 會出現警示!雖然可能還是會放行 (因為我們使用了 permissive 的 SELinux type), 建議你還是加入這個 SELinux 的規則較佳:# semanage port -a -t ssh_port_t -p tcp 2222 # systemctl restart sshd # systemctl status sshd ● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled) Active: active (running) since 六 2019-07-06 22:09:15 CST; 3s ago Docs: man:sshd(8) man:sshd_config(5) Process: 23430 ExecStart=/usr/sbin/sshd $OPTIONS (code=exited, status=0/SUCCESS) Main PID: 23431 (sshd) CGroup: /system.slice/sshd.service └─23431 /usr/sbin/sshd 7月 06 22:09:15 station10-101.gocloud.vm systemd[1]: Starting OpenSSH server daemon... 7月 06 22:09:15 station10-101.gocloud.vm systemd[1]: PID file /var/run/sshd.pid not readable (yet?) after start. 7月 06 22:09:15 station10-101.gocloud.vm sshd[23431]: Server listening on 0.0.0.0 port 2222. 7月 06 22:09:15 station10-101.gocloud.vm sshd[23431]: Server listening on :: port 2222. 7月 06 22:09:15 station10-101.gocloud.vm sshd[23431]: Server listening on 0.0.0.0 port 22. 7月 06 22:09:15 station10-101.gocloud.vm systemd[1]: Started OpenSSH server daemon. 7月 06 22:09:15 station10-101.gocloud.vm sshd[23431]: Server listening on :: port 22. # netstat -tlunp | grep ssh tcp 0 0 0.0.0.0:2222 0.0.0.0:* LISTEN 23431/sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 23431/sshd tcp6 0 0 :::2222 :::* LISTEN 23431/sshd tcp6 0 0 :::22 :::* LISTEN 23431/sshd
這樣就將我們的 sshd 多放行一個埠口囉! - 使用 knockd 服務來不定時的啟動你的防火牆;
在上面的設定中,我們多了一個 port 2222 的 ssh 連線監聽埠口,那麼,需要針對整個 Internet 放行嘛? 個人建議是不要啦!畢竟真的很容易被攻擊!那麼,如果你需要連線時,該怎麼連線到 port 2222 呢?都沒有放行防火牆不是? 這個時候,你可以使用 knockd 這個服務來處理。
- 什麼是 knockd 呢?
其實 knockd 是用來動態支援防火牆 iptables 的模組,它的運作方式很簡單,就是載入 knockd 之後, 它會持續偵測 3 個 port,當用戶按照正確的順序去敲擊這三個 port 時, knockd 就會去放行某條防火牆規則! 而當經過一段時間之後,這個新增的防火牆規則就會被取消!有點像底下的模樣:
上圖中,在伺服器的環境中,knockd 會持續監視 port 1, 2, 3 這 3 個埠口,如果有用戶可以按照順序來敲擊這 3 個埠口時, knockd 會進行如下的動作:
如上圖,knockd 會針對用戶端的 IP 搭配 knockd 的設定,動態的將 iptables 的規則加入到防火牆的支援當中! 此時,用戶可以在規定的時間內 (大多在 10 分鐘內) 連線到 Server 當中喔!
如上圖,敲擊過後一段時間 (大約在 10 分鐘內), knockd 會主動的取消這一條新增的防火牆規則。 不過已經連線的用戶無須擔心,因為防火牆規則可以倚靠 ESTABLISHED 的規則來持續連線成功的! 只是如果斷線,那就會失去連線的能力,得要重新敲擊 knockd 才行喔!
- 開始安裝 knockd 啦!官網在底下,不過,建議直接前往 nux 的網站下載給 CentOS 7 安裝的 RPM 就好了!
- 官網 (有 32 位元 windows 下載軟體):http://www.zeroflux.org/projects/knock
- CentOS 可下載版:http://li.nux.ro/download/nux/dextop/el7/x86_64/
# wget http://li.nux.ro/download/nux/dextop/el7/x86_64/knock-server-0.7-2.el7.nux.x86_64.rpm # wget http://li.nux.ro/download/nux/dextop/el7/x86_64/knock-0.7-2.el7.nux.x86_64.rpm # yum install ./knock-* # rpm -ql knock-server /etc/knockd.conf <==設定檔所在處 /etc/rc.d/init.d/knockd <==服務啟動的腳本,舊的 systemV 的設定方式 /etc/sysconfig/knockd <==額外參數 /usr/sbin/knockd <==實際的執行檔! /usr/share/doc/knock-server-0.7 /usr/share/doc/knock-server-0.7/COPYING /usr/share/doc/knock-server-0.7/ChangeLog /usr/share/doc/knock-server-0.7/README.md /usr/share/doc/knock-server-0.7/TODO /usr/share/man/man1/knockd.1.gz
畢竟 knock 存在時間比較久,目前這個網友協助建立的套件,還是沿用 systemV 的設定,不是使用新的 systemd 的設定。 不過 CentOS 7 對兩者都有支援!還是可以運作無誤的!
- 針對 ssh 的 port 2222 進行放行的動作:
接下來,請修改 knockd 的設定檔,修改的內容也是挺單純的!大致上,就是修改成一個可以自己獨立存在的登錄檔, 然後修改一下我們的埠口序號即可:
# vim /etc/knockd.conf [options] UseSyslog logfile = /var/log/knockd.log [opencloseSSH] sequence = 2100:tcp,2200:udp,2300:tcp seq_timeout = 15 tcpflags = syn start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 2222 -j ACCEPT cmd_timeout = 30 stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 2222 -j ACCEPT # 參數的大致意義如下: # [options]: 與 knockd 環境有關的設定資料; # UseSyslog: 與 knockd 有關的登入資料使用 syslogd 放置到 /var/log/messages # [opencloseSSH] 開啟與關閉 SSH 防火牆的設定項目; # sequence: knockd 偵測的埠口與封包協定 (tcp/udp) # seq_timeout: 需要在幾『秒鐘』內,連續上面的埠口接觸 (sequence 之設定); # tcpflags: 來源封包所需帶有的封包標誌,一般來說, UDP 封包不會有 ack , # 所以上述的預設標籤與封包,其實是無法吻合的,所以需要修改。 # start_command: 若連續接觸所有的埠口,則 knockd 開始後續的指令; # stop_command: 若用戶端斷線了,那麼就執行後續的指令 # cmd_timeout: 若設定 stop_command 則需此設定,訂定開始與結束防火牆的時間。
- 開始執行 knockd 服務,同時未來開機也會自動啟動它:
# 立刻啟動: # systemctl start knockd # 開機就啟動 # systemctl enable knockd # systemctl status knockd ● knockd.service - SYSV: Knock is a port-knocking server/client. Loaded: loaded (/etc/rc.d/init.d/knockd; bad; vendor preset: disabled) Active: active (running) since 日 2019-07-07 00:21:46 CST; 14s ago Docs: man:systemd-sysv-generator(8) Main PID: 24800 (knockd) CGroup: /system.slice/knockd.service └─24800 /usr/sbin/knockd -d 7月 07 00:21:46 station10-101.gocloud.vm systemd[1]: Starting SYSV: Knock is a port-knocking server/client.... 7月 07 00:21:46 station10-101.gocloud.vm knockd[24800]: starting up, listening on eth0 7月 07 00:21:46 station10-101.gocloud.vm knockd[24796]: Starting knockd: [ OK ] 7月 07 00:21:46 station10-101.gocloud.vm systemd[1]: Started SYSV: Knock is a port-knocking server/client.. # LANG=C chkconfig --list knockd 0:off 1:off 2:on 3:on 4:on 5:on 6:off netconsole 0:off 1:off 2:off 3:off 4:off 5:off 6:off network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
這個時候伺服器端就已經處理好了!接下來就等著看看用戶端如何敲擊使用這個防火牆的小外掛囉! - Linux 用戶端敲擊伺服器的方案:
如果你的用戶端是 Linux 的話,使用剛剛的網址去下載非 knock-server 的那個 rpm 檔案,並且安裝即可。 那如果用戶端是 windows 呢?就得要重新跑到官網去抓正確的軟體了。先來看看 Linux 用戶端怎麼做吧!
# 在用戶端進行如下的動作: # wget http://li.nux.ro/download/nux/dextop/el7/x86_64/knock-0.7-2.el7.nux.x86_64.rpm # yum install ./knock-0.7-2.el7.nux.x86_64.rpm # knock -v 172.16.10.101 2100:tcp 2200:udp 2300:tcp hitting tcp 172.16.10.101:2100 hitting udp 172.16.10.101:2200 hitting tcp 172.16.10.101:2300 # 有的時候,上述的指令可能要多做幾次,這樣比較容易成功! # 來到 Server 端,查看一下防火牆有沒有增加一條規則呢? # iptables-save | grep 2222 -A INPUT -s 172.16.60.100/32 -p tcp -m tcp --dport 2222 -j ACCEPT # 回到用戶端,嘗試用 port 2222 登入一下 # ssh -p 2222 username@172.16.10.101
- Windows 端敲擊伺服器的方法:先前往底下的網站下載 windows 所需要的軟體:
- 官網 (有 32 位元 windows 下載軟體):http://www.zeroflux.org/projects/knock
- Windows 綠色軟體:http://www.zeroflux.org/proj/knock/files/knock-win32.zip
- 將下載的檔案,在 knock-win32\knock-win32-port\Release\ 裡面的 knock 檔案複製;
- 到 C:\>Windows\System32\ 底下,貼上這個檔案
- 打開 cmd 命令提示字元,並輸入『 knock --help 』查看可執行否?
- 在桌面上面,打開文字編輯器,輸入底下的文字:
knock -v 172.16.10.101 2100:tcp 2200:udp 2300:tcp pause
- 存檔成為 knock-to.bat ,記得副檔名是 .bat 喔!而且檔名不能只是 knock.bat,否則會產生無窮迴圈...
- 直接點兩下滑鼠敲擊這個檔案!就可以敲擊 Server 了!
- 接下來,使用 pietty 或 putty 等連線軟體來連線到 Server 即可!
如此一來,我們的 Server 在正常的情況下,就不會被莫名其妙的人所攻擊偵測到 port 2222 的放行, 而且還能夠在連續敲擊某些埠口之後,就能夠順利的開啟防火牆,這樣的跳板當然就會變得更加安全妥當囉!
- 什麼是 knockd 呢?
- 使用 fail2ban 讓你的服務有限制的放行錯誤行為:
通常人算不如天算,某些情況下,你的 ssh 還是可能被攻擊的!所以,如果能夠設定『當重複猜測密碼幾次都是失敗的, 那就將這個 IP 暫時丟進黑名單拒絕登入』時,你的系統將會更加的妥當安全。如何達成呢?就透過 fail2ban 吧! 這個 fail2ban 還挺有趣的!它不只能管 ssh 喔!還可以管理任何需要輸入密碼的服務哩!
- 安裝 fail2ban 吧:
# yum install epel-release # yum repolist Loaded plugins: fastestmirror, langpacks Loading mirror speeds from cached hostfile * base: ftp.twaren.net * epel: mirror01.idc.hinet.net * extras: ftp.twaren.net * updates: ftp.twaren.net repo id repo name status base/7/x86_64 CentOS-7 - Base 10,019 epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 13,283 extras/7/x86_64 CentOS-7 - Extras 419 updates/7/x86_64 CentOS-7 - Updates 2,231 repolist: 25,952 # yum-config-manager --disable epel # yum repolist Loaded plugins: fastestmirror, langpacks Loading mirror speeds from cached hostfile * base: ftp.twaren.net * extras: ftp.twaren.net * updates: ftp.twaren.net repo id repo name status base/7/x86_64 CentOS-7 - Base 10,019 extras/7/x86_64 CentOS-7 - Extras 419 updates/7/x86_64 CentOS-7 - Updates 2,231 repolist: 12,669 # 事實上, EPEL 並不是隨時都啟用啦!暫時關閉比較妥當! # yum --enablerepo=epel install fail2ban
- fail2ban 大部分的設定檔都在 /etc/fail2ban/ 目錄下,預設值都在 /etc/fail2ban/jail.conf 裡面,不過,這個檔案不要亂改!
官方文件是建議新增 jail.local 這個檔案,並將要修改的項目增加在裡頭就好。現在,我們就來針對幾個項目進行設定一下:
- 內部網路 127.0.0.0/8, 120.114.140.0/24, 120.114.141.0/24, 120.114.142.0/24 忽略限制
- 錯誤登入後的抵擋時間為 3600 秒
- 使用 iptables 不用 firewalld 服務
- 目前僅針對 sshd 作為限制,且同時針對 port 22, 2222 來設計
# vim /etc/fail2ban/jail.local [DEFAULT] ignoreip = 127.0.0.0/8 120.114.140.0/24 120.114.141.0/24 120.114.142.0/24 bantime = 3600 banaction = iptables-multiport [sshd] enabled = true port = ssh,2222 # systemctl start fail2ban # systemctl enable fail2ban # systemctl status fail2ban ● fail2ban.service - Fail2Ban Service Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; enabled; vendor preset: disabled) Active: active (running) since 日 2019-07-07 13:46:19 CST; 7s ago Docs: man:fail2ban(1) Main PID: 304 (fail2ban-server) CGroup: /system.slice/fail2ban.service └─304 /usr/bin/python2 -s /usr/bin/fail2ban-server -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid -x -b 7月 07 13:46:19 station10-101.gocloud.vm systemd[1]: Starting Fail2Ban Service... 7月 07 13:46:19 station10-101.gocloud.vm fail2ban-client[301]: 2019-07-07 13:46:19,623 fail2ban.server [302]: INFO Starting Fail2ban v0.9.7 7月 07 13:46:19 station10-101.gocloud.vm fail2ban-client[301]: 2019-07-07 13:46:19,623 fail2ban.server [302]: INFO Starting in daemon mode 7月 07 13:46:19 station10-101.gocloud.vm systemd[1]: Started Fail2Ban Service. # fail2ban-client status Status |- Number of jail: 1 `- Jail list: sshd # fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list:
就這樣,很簡單的就將我們的 sshd 服務設定了登入次數限制的防火牆機制!雖然還是很可能短時間被大量攻擊 (就是 10 分鐘內), 不過,至少總是一個限制的功能!
- 安裝 fail2ban 吧:
參考資料
- Software RAID tuning
- 磁碟本身的調整
- 效能測試軟體:
- port knock 軟體:
- 官網 (有 32 位元 windows 下載軟體):http://www.zeroflux.org/projects/knock
- Server 使用說明:https://netslovers.com/2018/02/28/port-knocking-server-securing-ssh-connection-centos-7/
- CentOS 可下載版:http://li.nux.ro/download/nux/dextop/el7/x86_64/
- 鳥哥的 knockd 舊文章:http://linux.vbird.org/linux_security/knockd.php
- fail2ban 的參考資料: