首先你需要1台偵測主機,能夠執行Linux,有網路。我大約有24台偵測主機,除了2台實體主機在我家,其他都是從世界各地租來(或免費申請)的VPS;這些主機的記憶體、儲存空間大小各有不同,以下列出我的偵測主機各類硬體資源的最小值,只要大於最小值,應該就可以用來偵測。
1、記憶體:最小的是128MB;
2、儲存空間:最小的是2GB,就是放在我家裡的那兩台,因為主機原本沒有硬碟,我把系統安裝在2GB的USB隨身碟上;
3、網路速度:不必多快,我最慢的一台是位於香港的VPS,網速10Mbps;
4、IP位址:你的偵測主機必須要有獨立的IPv4位址才行。
假設你有台電腦(或VM也成),有128MB記憶體,2GB的硬碟,10Mbps的網路頻寬,有獨立的IPv4位址,偵測主機的硬體環境就解決了。
我說一下在台灣要如何建構網路環境好了,這可能是大家會面臨的問題。去年9月前,我在台灣是沒有偵測主機的,因為台灣的公有雲或VPS太貴了(相對來說);那時我在家是用4G上網,沒有固網,所以也不會有獨立的IPv4位址。
去年10月發現第四台的網路實在太便宜了,我裝了cable;後來就想到何不用這網路偵測殭屍電腦?我向cable業者申請了一個固定IP,直接指到我裝好的偵測主機,結果沒問題,可以用。
通常固網(不管是cable或光世代之類)都是給8個浮動IP,或1個固定IP搭配7個浮動IP,我心想那浮動IP能偵測嗎?我又弄了1台主機;由於我的cable數據機是路由器,也取得一個IPv4的浮動IP,我就將第2台主機設為cable數據機的DMZ主機(有些路由器的類似設定是exposed server),結果也行。
我現在的問題是,那可以把業者給的8個浮動IP都用來偵測嗎?我現在想到的解決方案是:
1、我不可能搞8台電腦來做(電也是要錢的好嗎?),勢必要導入虛擬化環境。我買了台J1900主機,4GB記憶體,64GB的儲存空間,應該能切出8台偵測用的VM。
2、8台VM的網路介面要有各自獨立的MAC位址。然後如果是光世代之類的網路,就每個VM各自用pppoe撥接取得IP位址;如果是cable之類的,就各自用DHCP取得IP。可能有1台VM要用路由器取得的IP來偵測。
以上方案不知行不行?由於以前沒自己切過VM,所以目前在摸索Proxmox的階段。如果有人先試出來,麻煩告訴我是否行得通。
待續。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
據我觀察,Mobile01網站主機至少有兩個對外的網路服務:
1、HTTP(TCP port 80):沒做什麼特別的處理,就是將連線重導(redirect)到HTTPS。
2、HTTPS(TCP port 443):就是我們看到的Mobile01網站。
此外應該還有只對內部工作人員開放的SSH服務;在此我假設SSH被移到TCP port 2020(因為今年是公元2020年)。所以該主機在對外IP(假設是W.X.Y.Z)上會開放3個網路服務,佔用80、443、2020等3個埠號。
請以root身分安裝HAProxy:
apt-get install haproxy
安裝完畢後,HAProxy已經啟動,但我們還須修改其設定檔(我習慣用vi):
vi /etc/haproxy/haproxy.cfg
在設定檔結尾處加入以下設定:
frontend fr_tcp上面有4行bind設定,跳過了主機原本使用的3個埠號,涵蓋其他埠號1到10000之間的9997個埠號。log-format指定了須留存的幾種資料,意義如下:
mode tcp
bind W.X.Y.Z:1-79
bind W.X.Y.Z:81-442
bind W.X.Y.Z:444-2019
bind W.X.Y.Z:2021-10000
log-format %ci:%cp\ =>\ %fi:%fp\ [%t]
default_backend bk_tcp
backend bk_tcp
mode tcp
server www-2 127.0.0.1:2020
%ci:來源 IP
%cp:來源 IP 的 TCP 網路埠號
%fi:接受連線的偵測主機 IP
%fp:偵測主機接受連線的 TCP 網路埠號
%t:連線日期與時間
bk_tcp定義了HAProxy要將外界連線轉接到內部的後端伺服器資訊。在偵測初期,有無後端伺服器似乎不重要,因為是否被掃描到是由機率決定;但有後端伺服器的話,駭客會覺得此處有網路服務,存在入侵的機會,而找更多殭屍電腦來試探,偵測的效果會更好。
至此HAProxy的設定已修改完成,接下來要讓新設定生效;執行以下指令重新啟動rsyslog與HAProxy:
service rsyslog restart
service haproxy restart
此時執行ss -ln | grep tcp | grep W.X.Y.Z | wc這個指令(統計對外IP W.X.Y.Z上,等待連線的TCP埠號總數)應該會得到非常接近或剛好就是10000的結果,代表HAProxy已經依照設定,在埠號1到10000間的TCP port等待連線。
說明一下ss -ln | grep tcp | grep W.X.Y.Z | wc這個指令:
1、ss指令檢視系統內的網路連線狀況(以前我都是用"netstat","ss"對我是新指令);"ss -ln"列出系統內等待連線(處於"LISTEN"狀態,所以用"l"功能選項)的網路埠號(numeric,所以用"n"功能選項)。
2、grep會將標準輸入(stdin)讀取的資料進行過濾;"grep tcp"代表帶有字串"tcp"的輸入資料會被再次輸出,其他資料則被丟棄,而"grep W.X.Y.Z"代表帶有字串"W.X.Y.Z"(對外IP)的輸入資料會被再次輸出,其他資料則被丟棄。所以經過兩個grep的處理,剩下的資料就是同時有"tcp"與"W.X.Y.Z"的資料。
3、wc(word count)會讀取標準輸入(stdin)的資料,當資料讀光時,輸出總共有多少行資料、多少空格分開的字(word)、及多少字元。
重新啟動後,過一段時間應該就會有外界連線進來;連線記錄在/var/log/haproxy.log內,留存類似以下記錄:
2019-06-16T03:48:46.282268+00:00 testvm haproxy[9544]: A.B.C.D:56670 => E.F.G.H:10006 [16/Jun/2019:03:48:46.281]
這筆記錄顯示在2019年6月16日3點48分左右,位於 IP 位址 A.B.C.D 的連網裝置,經由其 TCP port 56670,主動連線到位於 IP 位址 E.F.G.H 的偵測主機的 TCP port 10006。此處記錄到的來源 IP,A.B.C.D ,就是殭屍電腦的 IP,而它掃描的 TCP網路埠號就是10006。
下次說明如何設定後端伺服器。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
frontend fr_tcp其實有4行bind設定,不過這裡只列出1行來協助說明。我定義的frontend設定fr_tcp會在TCP port 1到10000間(須排除少數原已使用的埠號)等待連線;一旦有連線進來,預設的後端伺服器(default_backend)是bk_tcp。而bk_tcp則指示HAProxy應該將外界連線導向給位在IP 127.0.0.1的TCP port 2020。
...
bind W.X.Y.Z:2021-10000
...
default_backend bk_tcp
backend bk_tcp
...
server www-2 127.0.0.1:2020
IP 127.0.0.1是一個特殊的IP,代表系統自身,它有個名稱叫loopback address;所有送到這個IP的資料都會被自己收到。這個IP與實體線路無關;就算系統沒有可用的對外連線(沒接網路線、也沒有無線網路),loopback還是可以運作,它的目的是要測試整個網路軟體層(network software stack)是沒問題的。
上次的偵測機制中,我並未設定要在IP 127.0.0.1的TCP port 2020執行的網路服務;這個情況下HAProxy還是可以偵測到一些隨機掃描的殭屍電腦。就好比停一輛車在停車場中,竊車集團的人員會隨機來拉車門;沒設定HAProxy的後端伺服器,就像一輛門拉不開的車,我還是知道隨機拉車門的人是有問題的。
車門拉不開,一切就此結束;如果車門能拉開呢?後續會有什麼差異?竊車集團最終要把車開走,所以是不是要找有技術的人來發動?看是要把電線短接,還是要電子啟動,這都要找更多人來處理;這樣是不是可以找出更多竊車集團的成員?
用同樣的道理來思考,如果我們在IP 127.0.0.1的TCP port 2020提供一個活的連線,對掃描的殭屍電腦來說,這個服務是活的,給它一個“搞不好可以從這裡入侵進去”的感覺,就可以吸引駭客在此投注更多資源;這有兩個好處:
1、偵測到更多殭屍電腦;
2、此處消耗駭客的資源,就可減少駭客對其他系統的攻擊或入侵行為。
我用過兩種方式設定後端伺服器,一種是無法登入的SSH服務,另一種則只是單純消耗殭屍電腦時間的網路服務;明天說說這兩種不同的設定方式。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
1、SSH的原始設定檔是/etc/ssh/sshd_config,以root權限先複製一份方便修改:
cp /etc/ssh/sshd_config /etc/ssh/sshd_config_fake
2、編輯/etc/ssh/sshd_config_fake,將有關設定改成以下所示:
Port 2020在前面haproxy的設定檔中,後端伺服器的socket是在IP 127.0.0.1的TCP port 2020,所以此處sshd的Port與ListenAddress就依此設定。“DenyUsers *”指示SSH伺服器不接受任何登入帳號;“LoginGraceTime 10”則是設為在成功連線後,若未在10秒鐘內成功登入系統,SSH伺服器就會自動斷線。
ListenAddress 127.0.0.1
LoginGraceTime 10
DenyUsers *
3、啟動這個無法登入系統的SSH服務:
/usr/sbin/sshd -f /etc/ssh/sshd_config_fake
我自己透過tail -f /var/log/haproxy.log指令(即時顯示haproxy的記錄資料)觀察,在增加後端伺服器一段時日後,等偵測到的活動比較頻繁後,如果停掉後端伺服器,haproxy輸出記錄就會變少;如果再次啟動後端伺服器,haproxy輸出記錄又會逐漸增多。
下次再說明第二種後端伺服器。
順帶說明一下,127.0.0.1這個IP是系統內的IP位址,外部主機是不能連到其他主機的127.0.0.1。比方說你家有兩台主機,IP分別是192.168.1.10與192.168.1.11,第二台主機(192.168.1.11)是無法連到第一台主機(192.168.1.10)的127.0.0.1。這個特性被用來進行一些資安上的設定,比方說我知道某個網路服務有軟體弱點,不能對外開放,但我的某些應用卻又須使用這個服務,就可將這個有弱點的服務設定在IP 127.0.0.1上提供服務,這樣就只有同一台主機執行的其他軟體能連線,又不至於被駭客藉此入侵系統。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
1、每當有外界連線,SSH就會產生(fork)一個新的process;每個process都需要自己的記憶體空間,直到連線結束才會釋出。如果大量連線湧入,SSH有可能耗盡所有記憶體,導致系統不穩定或效能問題。
2、第一種後端伺服器其實是我當初用的fake SSH,會留存連線相關資訊,以便後續通報。現在所有外界連線都經由HAProxy首先接收,所以並不需要fake SSH的連線記錄;這些記錄反而會佔用大量儲存空間,必須定期刪除,否則可能耗盡儲存空間,衍生其他問題。
第一個問題其實可經由HAProxy的設定解決;HAProxy設定後端伺服器時,可同時指定最高連線數,例如:
server www-2 127.0.0.1:9504 maxconn 8
結尾的“maxconn 8”,就是設定HAProxy同一時間最多轉接8個外界連線至後端伺服器。如果這時外界還有連線進來,HAProxy會先接受連線,但不進行轉接,等於先在HAProxy那裡等著;等後端伺服器結束先前轉接的連線時,HAProxy才會將等待中的外界連線轉接到後端伺服器。
第二個問題其實只要改rsyslog的設定檔就能解決,也不是太難。
第二種後端伺服器是我用Tcl(Tool Command Language)寫的。首先必須先安裝Tcl:
apt-get install tcl
後端伺服器的script如下(假設存放在junkd.tcl):
proc connDrop {sock} {要清楚解釋script如何運作其實有點難,我只能簡單說一下:
after 100
close $sock
after cancel [list close $sock]
}
proc connAccept {sock addr port} {
fconfigure $sock -buffering line
after 10000 [list close $sock]
fileevent $sock readable [list connDrop $sock]
}
socket -server connAccept -myaddr 127.0.0.1 9504
vwait forever
1、請看倒數第2行。在IP 127.0.0.1,TCP port 9504處("-myaddr 127.0.0.1 9504")啟動後端伺服器("socket -server");當外界連線進來時,呼叫程序connAccept(參數:connAccept)。
2、請看proc connAccept的定義。呼叫connAccept時,Tcl會提供3個參數:連線對應的socket、來源IP(addr)、來源TCP埠號(port)。由於此服務位於IP 127.0.0.1,只有內部程序才能連接,所以來源IP(應該也是127.0.0.1)與來源TCP埠號都沒有留存的必要。當connAccept被呼叫,10秒鐘後會自動結束("after 10000 [list close $sock]";10000的單位是毫秒,也就是千分之一秒)。如果socket有可讀取的資料("fileevent $sock readable"),則呼叫程序connDrop。
3、proc connDrop的主要工作是:等待0.1秒("after 100")後結束連線("close $sock"),所以每秒最多處理10次連線;我用延遲回應的方式控制junkd.tcl每秒的處理次數(同時連線數8乘以每個連線每秒可處理10次=80),避免HAProxy記錄太多資料,耗盡儲存空間。
script其他太細微的部分我就不解釋了。啟動junkd.tcl的指令為:
nohup nice tclsh junkd.tcl > /dev/null 2>&1 &
主要執行的指令是"tclsh junkd.tcl";前("nohup")後("> /dev/null 2>&1 &")是將此程序移到背景執行,"nice"則是降低此程序的執行優先權,避免在資源不足時與其他程序搶CPU。
Tcl處理網路連線並不產生新process,也不留存任何連線資訊,所以不會有fake SSH的那兩個問題。
後端伺服器就說明到此;下次談談別的。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
第一件事。依照前面我介紹的方法安裝HAProxy,其實系統會每天自動輪替產生(rotate)新的記錄檔(在/var/log/路徑下的haproxy.log);預設會保留52個記錄檔,最新的記錄檔名是haproxy.log,前一天則為haproxy.log.1,再往前則遞增結尾的數字並以gzip壓縮,例如haproxy.log.2.gz。
不過Debian系統預設的每日例行作業輪替時間是6點25分,這樣記錄檔會有兩天的記錄混在一起(前一天6:25以後的資料與第二天6:25之前的資料),資料處理會比較麻煩;這可以透過修改crontab的每日例行作業輪替時間來解決。以root身份編輯/etc/crontab,找到以下這一行:
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )把開頭的兩個數字改成0:
0 0 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )儲存檔案;之後haproxy的記錄檔就會是每天一個檔案。
第二件事。我在#13所列的一筆偵測記錄
2019-06-16T03:48:46.282268+00:00 testvm haproxy[9544]: A.B.C.D:56670 => E.F.G.H:10006 [16/Jun/2019:03:48:46.281]記錄開頭的日期時間並非系統預設的如下格式(只有月、日、時間,無年份):
Mar 4 16:26:34 debian systemd[1]: Reloading.英文月份並不好處理。要改成#13的那種記錄時間,可以root身份編輯/etc/rsyslog.conf,將下列設定:
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat前頭加上“#”,如下:
# $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat並下指令重新啟動rsyslog:
service rsyslog restart即可。
以下說明統計殭屍電腦IP的指令。先列出記錄樣本:
2019-06-16T03:48:46.282268+00:00 testvm haproxy[9544]: A.B.C.D:56670 => E.F.G.H:10006 [16/Jun/2019:03:48:46.281]殭屍電腦的IP,A.B.C.D是以空白隔開的第4個欄位,後面緊接著一個“:"與來源TCP埠號。我現在要產生一個檔案,每行資料包含一個殭屍電腦IP(在第2個欄位)與其嘗試的連線次數(在第1個欄位);欄位間以空白隔開,並以連線次數遞減的方式來進行資料排序。所需指令如下:
grep ' => ' /var/log/haproxy.log | grep '^2019-06-16' | awk '{ print $4; }' | sed -e 's/:.*$//' | sort | uniq -c | sort -nr > /tmp/tmp1.txt各指令使用UNIX的pipe功能進行串連;“|”左邊指令的標準輸出資料會成為“|”右邊指令的標準輸入資料。以下逐個指令進行說明:
1、第1個grep指令:輸出/var/log/haproxy.log內,帶有‘ => '字串(一共4個字元,前後有空格)的資料記錄;
2、第2個grep指令:讀取標準輸入資料,輸出以字串'2019-06-16'開頭("^"代表一行資料的開頭)的資料記錄。如果記錄有’2019-06-16'的字串,但不是在開頭出現,則不會被輸出;
3、awk指令:讀取標準輸入資料,輸出以空白隔開的第4個欄位(即記錄樣本的"A.B.C.D:56670");
4、sed指令:讀取標準輸入資料,刪除冒號及其後字元(即記錄樣本的":56670")後輸出(即記錄樣本的"A.B.C.D",殭屍電腦IP);
5、第1個sort指令:讀取標準輸入資料(殭屍電腦IP),排序後(相同的IP會在一起)輸出;
6、uniq指令:讀取標準輸入資料(殭屍電腦IP),統計相同資料的出現次數(殭屍電腦IP連線次數),輸出出現次數與原始資料(殭屍電腦IP);
7、第2個sort指令:讀取標準輸入資料,依照第1個欄位(殭屍電腦IP連線次數)的數值(選項"n")以遞減排序(選項"r")後輸出到/tmp/tmp1.txt。
統計偵測到多少個殭屍電腦IP的指令:
wc -l /tmp/tmp1.txt只列出殭屍電腦IP清單的指令:
awk '{ print $2; }' /tmp/tmp1.txt
今天就寫到這裡。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
如果有人想照我的法子來偵測殭屍電腦,可是擔心建置時遇到不知如何解決的問題,我可以從旁協助。不過你要先準備好一台乾淨的Debian Linux主機,並具有一個對外IP;如果你的Linux主機是放在家裡,經由IP分享器連上Internet,這或許也可以,不過具體如何做,要看分享器是否提供DMZ或exposed server的設定功能,不見得一定成。
我建議的處理方式是這樣。你用SSH登入Linux主機,然後利用類似線上語音會議(非視訊會議)的方式分享你的SSH畫面;在看得到你下指令與輸出畫面的狀況下,經由語音交談,我們合作在你的主機建置偵測機制,並共同解決中間遇到的問題。整個過程如果順利,希望不會超過30分鐘。
目前我想到的線上語音會議服務是roundee.io;老實說我也剛開始了解這個服務。基本上它不須安裝軟體,只要用Chrome瀏覽器開啟會議室的URL即可,且可多人(至多6人)與會;它也提供online chat的功能,在修改設定時應該用得上。
如果有興趣找我從旁協助,就發私訊過來,並說明:
1、你對Linux的熟悉度(可分為:會登入系統、會編輯檔案、會啟動/停止系統服務等幾個階段;從沒用過Linux的人請先自行裝一台Linux再説);
2、Linux主機的Debian版本與系統資源(記憶體大小、硬碟大小)等;
3、Linux主機的連網方式。
這部分就先這樣,其他問題遇到再說。
未來我會繼續說明如何進行殭屍電腦通報。
美軍連茂伊島野火都不救,還指望他來臺海千里送人頭嗎?
關閉廣告