Category: Hack

  • 使用FreeNAS替換ESXI

    在將我的MicroServer重裝為FreeNAS之後,我發現我其實並不需要Vmware ESXI,因為我需要的大部分功能,包括web伺服器,流量監控,PLEX,BT下載,都可以通過FreeBSD jail去實現,這完全是一個讓我感到驚喜的場面,只需要些許的點擊,少許的配置,就可以安裝很多應用程式上去,一直以來我都覺得jail是個很好的半虛擬化工具,但FreeBSD的目標受眾畢竟還是相對少很多。

    而不太常用的Windows,也可以透過FreeNAS帶有的虛擬化功能,創建一台虛擬機就可以。

    至此,所有我需要在ESXI上實現的功能,在FreeNAS中都完整的實現,數據也沒有丟失太多,只有一點點的數據丟失,算是運氣沒有那麼差。

    ZFS在很早之前我就有使用,但從未認真關注過,也並沒有使用到RAID特性,FreeNAS是基於ZFSFreeBSD的實現,在ZFS存儲池中,有以下一些基於RAID的概念需要了解:

    Stripe:與RAID0類似,硬碟條帶,至少需要一個硬碟,一個都不能壞;
    Mirror:與RAID1類似,硬碟鏡像,至少需要兩個硬碟,可以壞一個;
    RAIDZ1:與RAID5類似,一重奇偶校驗,至少需要三個硬碟,可以壞一個;
    RAIDZ2:與RAID6類似,雙重奇偶校驗,至少需要四個硬碟,可以壞兩個;
    RAIDZ3:ZFS特有的,三重奇偶校驗,至少需要五個硬碟,可以壞三個;

    Log(ZIL):高速寫緩存設備,至少需要一個專用設備,可以使用兩個,建議使用具有停電保護的SSD;
    Cache(L2ARC):高速讀緩存設備,需要至少一個專用設備,可以使用兩個,建議使用具有停電保護的SSD;
    Spare:熱備硬碟,當正在使用的硬碟發生故障後,Spare硬碟將馬上代替此故障盤,可以有多個。

    關於RAID級別的區別,這裡就不說了,網路上有很多解釋很詳細的文章,可以搜索,由於我的MicroServer是四盤位,所以容量最大化的最小安全設計應該是raidz1,但網路上有很多基於RAID5的恢復失敗案例,主因為同一批硬碟故障率接近,當一塊硬碟出現崩潰,RAID5在恢復過程中大量讀取數據,恢復速度又較慢,此時剩餘硬碟崩潰的可能性大大增加,更重要的是zfs存儲池一旦創建後,是不能修改的,硬碟數量既不能增加,也不能減少,只能更換為更大容量的硬碟,我思考了一下,將四塊硬碟設置為RAIDZ2,容量損失一半,安全增加數倍,兩塊硬碟同時損壞的可能性,幾乎沒有。

    高速讀寫緩存,是FreeNAS特有的功能,我用了兩塊PCIE轉NVME轉接卡,各安裝了一塊250G的NVME SSD,對讀寫進行緩存,效果嘛,我發現似乎因為目前我使用的是G網,而不是10G網,即使將MicroServer的兩個網路卡使用LACP聚合到交換機,我訪問NAS的讀速度,依然只能達到G網的峰值,也就是90M/s至109M/s之間的樣子,至於寫速度,同樣的文件,第一次寫入速度大約在60M/s至70M/s,第二次寫入速度會提升到90M/s至109M/s之間的樣子。

    寫入速度這麼低,那兩塊希捷的硬碟,一定是所謂的疊瓦,查了一下序列號和批號果然是,當時買硬碟的時候,慣性思考為隨著技術的進步,磁碟密度果然是越來越高,沒想到,這不但是技術的退步,而且明顯是廠商的貪婪,因為廠商並沒有對技術參數進行說明和公開,目前只有希捷沒有公開自己使用了疊瓦技術的硬碟,西部數據東芝都公開了自己使用了SMR技術的硬碟,當然,西部數據是被逼的,因為他們在應用於NAS的WD Red產品線上使用了不適合於NAS使用的SMR技術而被人揭露,這如果不能用廠商的貪婪來進行解釋,那麼實在是找不出來第二個解釋。

    但我寫入的速度需求並不大,沒有iscsi這樣的需求,NFS也大多用於讀取數據,所以這種退步並沒有表達得很明顯。

    於是我深深的懷疑,ESXI數據丟失,是因為疊瓦盤造成的,因為在SMR的機制中,當你刪除一個文件或者一部分文件後,磁碟會進行類似於SSD的trim操作,將磁碟遠端的數據複製到近端,如果你要進行一個複寫操作,這時候,磁碟的佔用會很容易達到100%,此時既無法讀取也無法寫入,問題在於,機械磁碟的trim效率遠遠低於SSD,於是就表現為,磁碟無響應,當磁碟無響應之後,在硬體RAID卡中,就可能會出現掉盤或者丟盤的現象,而我之前的Server上,是用了一塊LSI的RAID卡,把四塊硬碟做了RAID10陣列。

    這無疑是個隱患,我重新購買了東芝PMR硬碟,將希捷SMR硬碟挨個換掉,經過測試,我的數據在ZFS環境下,同樣的數據大小,希捷SMR硬碟數據重建時間為30到32小時,而東芝PMR硬碟,數據重建時間為5到6小時,SMR硬碟數據重建的時間是PMR硬碟數的5到6倍,在這5到6倍的時間中,很可能會有另外的硬碟損壞,那麼就很可能出現數據完全丟失的情況,從FreeNASnetdata plugin中也可以明顯看出兩種硬碟技術的讀寫曲線,SMR硬碟在重建時,寫入速率時高時低,寫入一段時間後,寫入速度會變為0,此時硬碟佔用為100%,經過dm-smr的trim操作後,重新恢復至一個較高的寫入速率,週而復始,而PMR硬碟在重建時,寫入速率穩定在90M/s到100M/s之間,沒有變為0的時候。

    在生產線上,關鍵業務一般不會採用重建的方式,當關鍵業務出現陣列降級,會將業務下線,然後用新的硬碟創建新的陣列,將數據從舊的陣列複製到新的陣列上,然後用新的陣列上線業務,這樣可以避免陣列重建過程中,大量的數據讀取使得舊硬碟溫度過高而導致陣列損毀。

    至此,終於將MicroServer的隱患消除,之前在ESXI上偶爾存在的lag現象也不復存在,一直以為是AMD的CPU性能不行,沒有想到,居然是被希捷的SMR硬碟坑了一道。

  • Blocking bad bots with PF

    網路上各類針對WordPress的攻擊很多,比較討厭的是來自於各大主機商的訪問,比如DigitaloceanOVHLinodeAliyun,但是,運行在這些主機商伺服器上的業務,通常和我們的網站並沒有什麼必需的聯繫,所以我們完全可以把他們都封鎖掉。

    封鎖他們的IP有很多種方式,最簡單的方式,就是通過CDN的訪問控制列表,在CDN上設置黑名單,然後你可以在Apache或者Nginx設置你的網站只允許CDN的IP訪問,這是你自己的白名單,這就可以確保你的網站不會被其他IP地址訪問,問題是,如果你有多個網站運行在同一個IP地址上,而你又不能為你所有的網站設置同樣的CDN或者同樣的訪問規則時,這個方法就變得不適用。

    第二種方式,你可以在Apache或者Nginx設置你的網站禁止特定IP訪問,無論是通過CDN送過來的IP還是直接訪問,均可以達到封鎖效果,問題是,這種方法需要消耗webserver軟體的性能,而且通常都會消耗掉不少的性能,有沒有更好一點的辦法呢?

    第三種方式,使用服務器上的防火牆,或者使用VPC防火牆,當你擁有一個數十台服務器的網絡時,你是必然會使用VPC的,否則安全管理會變得非常繁瑣,使用VPC的防火牆,在各大主機商是非常簡單的事情,點擊兩三下,輸入要封鎖的IP地址範圍,就可以了。

    那麼,如果我們想使用操作系統的防火牆呢?比如FreeBSD下的PF

    PF是一個久負盛名的軟體,來自於OpenBSD的packet filter,比較有名的應用大概就是pfsense,有商業化運營的硬體產品出售,但由開源軟體發展而來的商業軟體,在性能上和JuniperCisco比起來還是差了一大截,如果有硬體防火牆可用,當然優先的選擇是硬體防火牆。在FreeBSD上其實是有很多的防火牆軟體可以選擇,以前我常用ipfw,他的配置是一行一行按順序執行,很多次我都因為寫錯了某個地方然後就把自己鎖在了伺服器的外面,PF好像至今尚未出現過這樣的情形。

    一個典型的PF配置如下:

    if=”eth0″

    icmp_types = “echoreq”
    open_tcp = “{ 80,443}”
    open_udp = “{ 53}”

    set block-policy drop
    set skip on lo0
    set limit { states 10000, frags 5000 }
    set loginterface eth0
    set optimization normal
    set require-order yes
    set fingerprints “/etc/pf.os”
    set ruleset-optimization basic

    table persist file “/etc/pf.blocked.ip.conf”

    scrub in all

    block drop in log (all) quick on $if from to any
    block log all
    block in all
    block return all

    antispoof quick for $if

    pass in on $if proto tcp from any to any port $open_tcp keep state
    pass in on $if proto udp from any to any port $open_udp keep state

    pass out quick all keep state

    pass in on $if inet proto icmp all icmp-type $icmp_types keep state

    其中,涉及到封鎖IP地址的有兩行配置:

    table persist file “/etc/pf.blocked.ip.conf”

    block drop in log (all) quick on $if from to any

    第一行是定義一個object叫做blockedips,他的文檔類型是一個conf配置文檔。

    第二行則是拒絕這個配置文檔中所有的IP地址訪問$if這張網路卡。

    那麼這個conf文檔的配置格式為何呢?按照標準的IP地址格式就可以了,我把一些常見的惡意IP地址範圍都加了進去,主要是上面提到的主機商,很多黑客和惡意程式利用這些主機商來進行掃描和攻擊。

    #Aliyun

    8.208.0.0/16
    39.105.0.0/16
    47.91.0.0/16
    47.111.0.0/16
    47.112.0.0/16
    123.56.0.0/16
    123.57.0.0/16
    161.117.0.0/16
    182.92.0.0/16

    #Digitalocean

    45.55.0.0/16
    68.183.0.0/16
    104.248.0.0/16
    128.199.0.0/16
    138.68.0.0/16
    138.197.0.0/16
    139.59.0.0/16
    142.93.0.0/16
    146.185.0.0/16
    142.93.0.0/16
    146.185.0.0/16
    157.230.0.0/16
    157.245.0.0/16
    159.65.0.0/16
    159.89.0.0/16
    165.22.0.0/16
    165.227.0.0/16
    167.172.0.0/16
    178.62.0.0/16
    178.128.0.0/16
    178.186.0.0/16
    188.166.0.0/16
    185.85.0.0/16
    185.86.0.0/16
    190.202.0.0/16
    206.189.0.0/16
    217.182.0.0/16

    OVH

    5.135.0.0/16
    51.38.0.0/16
    51.68.0.0/16
    51.83.0.0/16
    51.254.0.0/16
    54.36.0.0/16
    54.37.0.0/16
    91.121.0.0/16
    137.74.0.0/16
    144.217.0.0/16
    147.135.0.0/16
    158.69.0.0/16
    192.99.0.0/16
    213.32.0.0/16

    Linode

    172.104.0.0/16

    Huawei 華為雲

    114.119.0.0/16

    Taobao 淘寶一搜

    42.120.0.0/16

    我一般都是直接封鎖B類地址範圍,Digitalocean的IP地址實在是太多了。

    其實原本還有很多中國的二三流搜索引擎,每天不停的惡意抓取,比如今日頭條,但是,由於中國從來都不按照國際規範分配IP地址,很多時候使用whois檢出的IP地址都只能劃歸到某一個省份,而不是某一個城市,甚至公司,這樣你就很難去把他封鎖掉,只能一個C類地址範圍加進去試試看。

    當然,在rc.conf中,我們應該預先定義好log的路徑和名稱,如下,我定義了一個pflog,放在/data/log目錄中:

    pf_enable=”YES”
    pf_rules=”/etc/pf.conf”
    pflog_enable=”YES”
    pflog_logfile=”/data/log/pflog”

    那麼,如何讀取這個日誌文檔呢?因為他並不是一個純文本文檔,我們不能用vi或者cat或者tail來閱讀他,我們必須使用tcpdump來查看這個日誌文件,查看的命令行格式如下:

    tcpdump -n -e -ttt -r /data/log/pflog

    執行之後,可以得到如下類似的輸出結果,這個輸出中,我的服務器IP地址是116.128.134.139:

    tcpdump -n -e -ttt -r /data/log/pflog
    reading from file /data/log/pflog, link-type PFLOG (OpenBSD pflog file)
    00:00:00.000000 rule 2/0(match): block in on eth0: 178.62.41.44 > 116.128.134.139: ICMP echo request, id 4282, seq 980, length 16
    01:38:36.513282 rule 2/0(match): block in on eth0: 217.182.193.13.56093 > 116.128.134.139.1500: Flags [S], seq 3677707474, win 1024, options [mss 536], length 0
    00:38:42.059567 rule 2/0(match): block in on eth0: 178.62.41.44 > 116.128.134.139: ICMP echo request, id 5933, seq 3298, length 16
    00:00:04.451304 rule 2/0(match): block in on eth0: 178.62.80.93 > 116.128.134.139: ICMP echo request, id 9026, seq 345, length 16
    01:16:14.250758 rule 2/0(match): block in on eth0: 178.62.106.84 > 116.128.134.139: ICMP echo request, id 5864, seq 1941, length 16
    00:15:17.692806 rule 2/0(match): block in on eth0: 178.62.78.199 > 116.128.134.139: ICMP echo request, id 30618, seq 1686, length 16
    05:04:34.023956 rule 2/0(match): block in on eth0: 178.62.78.199 > 116.128.134.139: ICMP echo request, id 3055, seq 465, length 16
    00:20:23.179962 rule 2/0(match): block in on eth0: 178.62.106.84 > 116.128.134.139: ICMP echo request, id 11035, seq 2333, length 16
    00:15:19.427828 rule 2/0(match): block in on eth0: 178.62.80.93 > 116.128.134.139: ICMP echo request, id 17857, seq 577, length 16
    01:06:00.483685 rule 2/0(match): block in on eth0: 178.62.109.7 > 116.128.134.139: ICMP echo request, id 10094, seq 4315, length 16
    00:10:12.073875 rule 2/0(match): block in on eth0: 178.62.41.44 > 116.128.134.139: ICMP echo request, id 14083, seq 420, length 16
    00:55:54.286830 rule 2/0(match): block in on eth0: 178.62.78.199 > 116.128.134.139: ICMP echo request, id 6287, seq 2726, length 16
    00:10:15.098226 rule 2/0(match): block in on eth0: 178.62.41.44 > 116.128.134.139: ICMP echo request, id 15544, seq 4722, length 16
    00:15:24.539292 rule 2/0(match): block in on eth0: 178.62.109.7 > 116.128.134.139: ICMP echo request, id 13960, seq 3050, length 16

    可以觀察到,這些惡意bots在發送spam之前,會使用多個不同的主機先ping一下看是否通暢,然後再發起惡意訪問,比如來自Digitalocean的178.62.0.0/16和138.197.0.0/16,就有很多的記錄,這些請求都被PF block掉了,不會到達webserver或是其他地方,甚至還有針對445端口進行掃描的Windows病毒蠕蟲。

    如果我們想要查看實時的日誌顯示,那麼我們可以用pflog0這個虛擬網卡,執行如下的命令行可以得到輸出,你看很快的,就進來了一條記錄:

    tcpdump -n -e -ttt -i pflog0

    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on pflog0, link-type PFLOG (OpenBSD pflog file), capture size 262144 bytes
    00:00:00.000000 rule 2/0(match): block in on eth0: 138.197.130.235 > 116.128.134.139: ICMP echo request, id 19068, seq 6044, length 16

    如果我們只希望查看某些IP地址或端口的記錄,應當如何使用呢?由於pflog使用的是tcpdump的二進制文檔格式,那麼tcpdump的任何命令都是適用的,幾個樣例如下:

    查看80端口的記錄:

    tcpdump -n -e -ttt -r /data/log/pflog port 80

    查看特定IP地址和端口的記錄:

    tcpdump -n -e -ttt -r /data/log/pflog port 80 and host 192.168.1.3

    你也可以把它套用到pflog0上:

    tcpdump -n -e -ttt -i pflog0 host 192.168.4.2

    甚至可以使用更複雜的命令來過濾,和硬體防火牆比起來, 操作略為複雜一些。

    tcpdump -n -e -ttt -i pflog0 inbound and action block and on eth0

    一些提示:

    ip – address family is IPv4.
    ip6 – address family is IPv6.
    on int – packet passed through the interface int.
    ifname int – same as on int.
    ruleset name – the ruleset/anchor that the packet was matched in.
    rulenum num – the filter rule that the packet matched was rule number num.
    action act – the action taken on the packet. Possible actions are pass and block.
    reason res – the reason that action was taken. Possible reasons are match, bad-offset, fragment, short, normalize, memory, bad-timestamp, congestion, ip-option, proto-cksum, state-mismatch, state-insert, state-limit, src-limit and synproxy.
    inbound – packet was inbound.
    outbound – packet was outbound.

    顯示防火牆當前的連結,也是一個常用的命令,如何使用呢?我們需要額外安裝一個pftop軟體,然後執行它。

    pkg install pftop

    pftop

    pfTop: Up State 1-26/26, View: default, Order: none, Cache: 10000 6:33:52

    PR DIR SRC DEST STATE AGE EXP PKTS BYTES
    tcp In 108.162.215.39:38588 116.128.134.139:80 FIN_WAIT_2:FIN_WAIT_2 00:03:23 00:00:07 15 1576
    tcp In 108.162.215.127:20290 116.128.134.139:80 FIN_WAIT_2:FIN_WAIT_2 00:02:29 00:01:01 15 1447
    tcp In 108.162.215.39:56092 116.128.134.139:80 TIME_WAIT:TIME_WAIT 00:02:23 00:01:07 17 2429
    tcp In 172.69.33.38:28072 116.128.134.139:80 ESTABLISHED:ESTABLISHED 00:01:30 23:59:46 10 1584
    tcp In 108.162.215.39:39160 116.128.134.139:80 ESTABLISHED:ESTABLISHED 00:01:23 23:59:37 10 1376
    tcp In 108.162.215.203:26782 116.128.134.139:80 ESTABLISHED:ESTABLISHED 00:01:21 23:59:40 10 1234

    pftop的這個輸出信息量其實並不大,甚至還不如iftop顯示的數據量多,但區別在於,pftop可以顯示出連結的狀態,連結處於CLOSED,ESTABLISHED,還是WAIT的狀態,當遭遇到攻擊的時候,半開連結作為判斷因素有那麼一點點的作用。

    對比一下Juniper SSG的輸出:

    ssg5-> get session | inc /80
    id 10597/s,vsys 0,flag 00000000/8000/1001/0000,policy 1,time 30, dip 2 module 0, di on if 11(nspflag 801a01):10.1.1.5/59689->54.39.179.91/8080,6,000c2997db20,sess token 3,vlan 0,tun 0,vsd 0,route 3,wsf 7 if 0(nspflag 10003a00):10.70.5.12/1427<-54.39.179.91/8080,6,000000000000,sess token 4,vlan 0,tun 0,vsd 0,route 11,wsf 6 id 10627/s,vsys 0,flag 00000000/8000/1001/0000,policy 1,time 30, dip 2 module 0, di on
    if 11(nspflag 801a01):10.1.1.105/51382->203.208.39.215/80,6,546009783576,sess token 3,vlan 0,tun 0,vsd 0,route 3,wsf 8
    if 0(nspflag 10003a00):10.70.5.12/3892<-203.208.39.215/80,6,000000000000,sess token 4,vlan 0,tun 0,vsd 0,route 11,wsf 6 id 10972/s,vsys 0,flag 00000000/8000/1001/0000,policy 1,time 26, dip 2 module 0, di on if 11(nspflag 801a01):10.1.1.138/49773->223.166.152.106/80,6,a860b62b6556,sess token 3,vlan 0,tun 0,vsd 0,route 3,wsf 7 if 0(nspflag 10003a00):10.70.5.12/3626<-223.166.152.106/80,6,000000000000,sess token 4,vlan 0,tun 0,vsd 0,route 11,wsf 6 id 11108/s,vsys 0,flag 00000000/8000/1001/0000,policy 1,time 23, dip 2 module 0, di on if 11(nspflag 801a01):10.1.1.138/53973->116.128.160.96/8080,6,a860b62b6556,sess token 3,vlan 0,tun 0,vsd 0,route 3,wsf 8

    對比一下Cisco ASA的輸出:

    F5ASA# sh conn | inc :80
    TCP outside 114.247.184.134:53018 inside 172.30.1.121:80, idle 0:09:20, bytes 0, flags UfB
    TCP outside 123.54.116.24:59970 inside 172.30.1.121:80, idle 0:16:06, bytes 0, flags UfB
    TCP outside 112.44.42.1:1193 inside 172.30.1.121:80, idle 0:16:10, bytes 0, flags UfB
    TCP outside 111.44.151.170:11348 inside 172.30.1.121:80, idle 0:36:34, bytes 0, flags UfB
    TCP outside 123.54.116.24:59480 inside 172.30.1.121:80, idle 0:42:03, bytes 0, flags UfB
    TCP outside 112.32.196.89:8609 inside 172.30.1.121:80, idle 0:56:14, bytes 0, flags UfB
    TCP outside 117.157.99.170:60380 inside 172.30.1.165:80, idle 0:00:02, bytes 7330, flags UIOB
    TCP outside 117.157.99.170:60379 inside 172.30.1.165:80, idle 0:00:02, bytes 7330, flags UIOB
    TCP outside 117.147.16.83:12041 inside 172.30.1.165:80, idle 0:00:00, bytes 30381, flags UIOB
    TCP outside 112.39.103.179:26126 inside 172.30.1.165:80, idle 0:00:03, bytes 6025, flags UIOB
    TCP outside 113.233.207.78:62067 inside 172.30.1.165:80, idle 0:00:03, bytes 81796, flags UIOB

  • 年年岁岁花相似,岁岁年年人不同

    Hi! Ken and everyone,
    Very glad to get your email.I’m still here in Pittsburgh, PA, USA.
    今天天气晴好,湛蓝的天空一尘不染.一路上,绿草如茵,鲜花怒放,小鸟,松鼠在树上,在脚下跑来跑去.使我不禁想起与同学们在一起的美好时光.
    匹 兹堡是一个拥有200多万人口的城市.有10余所高校.付老师所在的匹大有学生32000多人,很大部分来自世界各国.该校排名比较靠前,尤以医学技术著 称于世.与此比邻的卡耐基梅隆大学(彼此无围墙,仅数十米之遥)亦有数万学生.该校计算机技术与麻省理工学院齐名,并列美国高校榜首.
    各校报告会,讨论会等活动很多,我每天都去参加,觉得所获很大.活动组织者参与者都很友好,而且提供免费餐饮.
    很感谢同学们喜欢我的课,我回校后欢迎大家来听我的课.
    很喜欢收到你们的电邮.

    这是X老师还在M国的时候发的邮件,而现在,他和F老师之间却面临着这样一个不得不面对的抉择,不知道他又会怎样的伤心。