開發事故--兩個小時,我的簡訊介面被呼叫了 4W 次

語言: CN / TW / HK

一早到公司,泡了杯茶,準備逛逛各種論壇,開啟我摸魚的一天。沒想到的是,在十點多樣子,中臺的專案負責人突然就找到了我,說今天一早我的專案呼叫了 4W 次的簡訊介面,頓時就覺得晴天霹靂!!!我感覺到了一口黑漆漆的大鍋朝我狂奔,與此同時,上級領導也發來訊息——儘快處理!

這裡簡單介紹下我專案的環境——就是寶塔的 lnmp,嘿嘿,當初覺得可方便了呢!不過現在只覺得 mmp,而且是單機,沒有叢集。然後簡訊介面也不是呼叫的公司的中臺服務,由中臺和簡訊服務商對接的。

好了,鍋已經來了,想辦法處理吧。首先需要定位問題,這 4W 的請求怎麼來的,是否是正常的使用者行為(肯定不正常,我皮一下)。

冷靜下來,我當時分析這種情況發生有四種:

1:自己腦子瓦特了,客戶端一個請求過來,我向服務商發起了多次呼叫

2:有大佬入侵了我的伺服器

3:因為中颱提供的簡訊服務是暴露在外網的,會不會是中臺那邊被攻擊了

4:有小可愛通過指令碼、爬蟲等惡意併發呼叫我的介面

問題定位

第一種情況

首先肯定要去看看自己擼的程式碼,有沒有 BUG,看看是不是業務程式碼的問題。但是對於一個獲取簡訊驗證碼的業務,不可能存在複雜設計在裡面,我的大概邏輯就如下列的虛擬碼:

phone = $_POST[ 'phone' ]
if (!preg_match( '/\d+/' ,$phone,$str)){
return false ;
}
res = smsSdk.sentPost(phone)
return res

不用考慮 DB,不用考慮第三方是否穩定,那麼業務程式碼沒問題,不存在一個請求會向服務商多次請求。

第二種情況

我直接 pass 了,伺服器安全這塊,我懂的真不多,如果是這種情況,我只能求警察叔叔幫忙了

第三種情況

因為這種併發的請求,儘管沒有涉及 db,不會有很高的 io 開銷,但是這麼大的請求過來,會造成頻繁的上下文切換,cpu 的使用率在某些時刻,肯定是存在不正常的飆升,恰好,寶塔上面有 cpu 的監控,看了一下,確實存在不正常的飆升

圖 1

從圖中可以看到,有幾個時間短,cpu 異常飆升,那我就基本排除第三種情況,只能是所有請求都是從我這邊的伺服器打到中臺的

第四種情況

因為 php 是一個 cgi 程式,所以需要用 nginx 把使用者的 http 請求反向代理,客戶端每一個請求過來,liunx 都會將請求轉給 nginx,然後由 nginx 反向代理到 php-fpm 這個 fastcgi 的程序管理器,明白了這一點,那就去找找 nginx 的日誌吧

因為是寶塔幫我安裝的 nginx,首先得需要確定配置檔案。nginx -V,看看有沒有指定配置檔案的路徑,結果沒有,那就找找二進位制執行指令碼的存放路徑,因為配置檔案會預設存放這個目錄

圖 2

上圖找到配置檔案,一般這種主配置檔案,都只會配置一些所有 work 程序都能用到的配置資訊,找到對 include vhost 的路徑,才能找到自己網站真正的配置資訊,一翻查詢,定位了 access.log 的位置

圖 3

好傢伙,已經這麼大了,現在日誌找到了,該分析了。

因為這個日誌太大了,如果直接在生產環境分析,IO 消耗會很大,所以我是把日誌下載下來弄到我本地中,然後我在本地搭了一個虛擬機器。

開始分析,先明確呼叫簡訊介面的 url ,我的介面 url 是 sentRegisterCode,然後採用的 awk 分析日誌,其目的,主要是分析出呼叫的簡訊介面的次數是否和中臺所反饋的消耗匹配

awk  '/sentRegisterCode/{split($4,a,"[:]");print a[1]}'  access.log|sort | uniq -c |sort -n -k 1 -r|head -n 10

上面這條語句,主要是統計出按照每個小時呼叫過簡訊介面的介面次數並按降序的方式顯示前十條資料,得到下面的結果

圖 4

可以看到,在一月 6 號的幾個時間點和圖 1 的 cpu 的使用率完美契合,而且呼叫的次數也和中臺說的 4W 次符合。所以我們需要進一步分析這 4W 請求是從哪裡來的。

awk  '/sentRegisterCode/{print $1}'  access.log|sort | uniq -c |sort -n -k 1 -r|head -n 10

這條我是看看 Ip 呼叫簡訊介面最多的前 10 條,得到結果如下:

圖 5

可以看到就這一個 Ip,就呼叫了 38511 次,所以這個人是真噁心,你說你要搞這個網站把,你代理都不弄一個,就裸奔

問題處理

問題找到了,就是有人惡意呼叫簡訊介面,針對這個問題,我找了兩個處理問題的方法,然後對簡訊介面的呼叫的日誌專門配置了。

第一種就是做了圖形的人機驗證,其實我知道,這種手段的效果微乎其微,真有爬蟲來噁心爬這個介面,網上各種打碼平臺,包括我們公司自己都訓練了一套打碼模型,但終歸是能防止一部分中來惡意呼叫。不過 VAPTCHA 這個驗證,我們公司爬蟲的大佬說目前市面上的打碼平臺還針對不了,後期我會對接這個。

第二種就是限流,只針對與呼叫簡訊介面的請求,我使用了 nginx 的 limit_req 模組,以 Ip 作為關鍵字,做了 5r/m 的限制。

然後就是監控了,因為之前的 ngxin 的 access.log 日誌都是預設的 combined 的模式,我首先針對於這個記錄的資訊做了一些更改,然後針對一些高頻訪問的 ip,就封掉。然後使用了 goaccess 工具實時對日誌請求統計分析

2022.01.10

https://m.zhipin.com/mpa/html/get/column?contentId=f7d06bdaa518c101qxBz2di7&identity=0&userId=6846059

版權申明:本文來源於網友收集或網友投稿,僅供學習交流之用,如果有侵權,請轉告版主或者留言,本公眾號立即刪除。