Category: Tech

  • Mac mini重建Fusion Drive

    原本BBC停播之後,我以為VOA也會跟著停播的,畢竟聽的人越來越少,關鍵是真實的聽眾數量無法進行統計,也就無法對下一年的預算做出規劃,今天偶然發現VOA的頻率居然還在廣播,於是找出收音機,從VOA的頻率上,傳來了清晰而又明亮數十年如一日的中央人民廣播電台。

    電磁波這種東西,只要頻率一樣就可以進行干擾,考場無法使用手機就是這樣子的原理,因為考場部署了和手機基地台相同頻率的干擾設備,你的手機會根據距離的遠近,優先選擇連結到干擾設備,而不會去連結正確的基地台,短波廣播的干擾原理類似,中央人民廣播電台數十年如一日的將自己的廣播頻率設置在BBCVOA相同的頻率,目的就是干擾短波收音機的接收,不讓民眾聽到他們的聲音,從物理距離來說中央人民廣播電台離我更近,VOA在日本的短波轉播站即使覆蓋到南方,信號強度也沒有辦法和財大氣粗的中央人民廣播電台相比。

    上次把Macmini的普通硬碟換成了SSD,拆過一次Fusion Drive,但是沒有把PCI-SSD和SSD做Fusion Drive,我以為128G的PCI硬碟,裝個系統什麼的,應該是夠了,但是我估計錯誤,PCI硬碟很快就裝滿到了120G,根據SSD的特性,是不能把他裝得太滿,再裝多一些,我估計這塊硬碟會掛點,所以我不得不重建了一次Fusion Drive。

    首先當然是備份,最好的備份方式,就是開啟Time Machine,用外置硬碟或者支持TimeMachine的網路存儲都沒問題,我這次使用的是我網路存儲上的備份,網路存儲備份的好處在於,你不用去管他什麼時候為你備份,一切都是自動的。

    當備份完成之後,我們就可以來進行磁碟重新分區的操作,從菜單重啓電腦,然後按住cmd+R,直到被咬過一口的白蘋果出現,當出現選擇菜單時,不要選擇任何一個。而是選擇最上面的終端Terminal,進入命令行介面,在terminal窗口中輸入diskutil resetFusion,然後按回車鍵。

    這時候,提示有兩塊硬碟,並且兩塊都是SSD, this is nonstandard but OK. 接下來我們輸入Yes,注意Y要大寫,就會開始對兩塊硬碟進行初始化分區,創建分區表的操作。注意!注意!注意!TimeMachine只會備份操作系統所在的那塊硬碟,如果你的第二塊硬碟上有數據,則需要手動備份,由於我的第二塊硬碟上沒有什麼重要的數據,這裏就沒有進行備份操作,當你確認後,你的兩塊硬碟都會被重新分區。

    創建FusionDrive的速度很快,大概一兩分鐘就好了,you should now install macOS.

    這裏可以選擇全新安裝,全新安裝的話,可以透過網路,下載最新的macOS鏡像,然後解壓縮,安裝,也可以透過外置硬碟或是網路存儲的TimeMachine備份來進行恢復,這裏我選擇Restore from Time Machine Backup

    繼續三兩個提示之後,選擇一下備份恢復的來源,這裏我選擇網路存儲,如果存儲是需要驗證的,那麼下一步會彈出對話框讓你鍵入用戶名和密碼,

    很顯然,在網路存儲上我們不止存放有一個備份副本,在不同的時間段,當你修改了文檔,移動了目錄,安裝了新的application,都會形成一個新的備份副本,這裏我選擇最近一次備份。

    選擇確認後,會彈出最後一個對話框,是否要erase disk,為什麼會有這個提示?我之前不是已經對硬碟重新分區了嗎?是的,但是程式並不知道啊,恢復備份在很多場景下都會發生,並不是只有這一個場景,當你的系統在正常運行,需要找回被誤刪的文檔時,這個提示就非常有必要了。

    接下來是比較漫長的恢復過程,90G的數據大概恢復了兩個小時,我應該把Wi-Fi斷開直接用有線網路傳輸也許會比較快。

    當恢復完成,電腦重啓後,熟悉的桌面和設置都還在那,一如既往,Application目錄裡面的app,會自動重新下載,和iPhone非常類似,當app重新下載完成後,就可以開始使用啦。

    可以看到,現在系統中只有一塊硬碟叫做Fusion Drive,從實際使用來看,第一次被copy或者move到這塊融合硬碟上的文件,會默認被放在速度較慢的2.5英寸SSD上,當你頻繁的打開它,或是你的程式頻繁的調用它,它才會被移到速度較快的PCI-SSD上去。

  • 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

  • How to Exclude a Word with grep

    grep命令在用於在文本數據中搜索定義的字符串,字符,單詞或正則表達式匹配的行和代碼片段時非常有用。 儘管grep的大多數用途是對語法匹配的數據進行排序,但是如果我們想用grep排除單詞或字符串怎麼辦? 用grep排除與在grep中查找匹配項是類似的,今天讓我們看看如何使用grep排除字符串匹配和單詞。

    grep是與操作系統無關的實用程序,因此您可以在Mac OS,Linux,Unix或任何其他使用grep的系統中使用排除。

    如何使用grep排除單個單詞

    排除具有字符串或語法匹配行數據最簡單方法是使用grep和-v。

    例如,假設我們使用cat在命令行中輸出文件,但是我們想排除所有包含“google”的行,那麼語法將如下所示:

    cat webserver.log | grep -v “google”

    輸出將是webserver.log文本中不包括與”google”匹配字符串的數據。

    也可以直接在文件上使用grep,並根據單詞或語法排除匹配,如下所示:

    grep -v “google” webserver.log

    如何使用grep排除多個字符串或單詞

    既然我們知道如何排除單個單詞,下一個明顯的問題是使用grep排除多個單詞。 這同樣簡單,並且有幾種不同的方法可以使用-v標誌和-e標誌來完成此操作。

    首先,以上述示例為例,在透過管道傳輸到grep的文件中使用cat,並排除與兩個單詞匹配的任何數據:“google”和“baidu”,如下所示:

    cat webserver.log | grep -v -e “google” -e “baidu”

    包含“ google”或“ baidu”的每一行將從打印結果中排除。

    您還可以像以前一樣直接在文件上使用grep

    grep -v -e “google” -e “baidu” webserver.log

    另一種方法是通過使用管道來分隔每個匹配項來用grep分隔要排除的內容,如下所示:

    grep -Ev “google|baidu” webserver.log

    如果在示例文本文件上測試了這些選項中的任何一個,無論採用哪種方法,輸出都是相同的,每個選項都會輸出排除了包含目標短語,語法,單詞或文本匹配項的數據。