誰是那些試圖透過SSH非法存取我的伺服器的人?來自哪個國家?

6 min

language: ja bn en es hi pt ru zh-cn zh-tw

大家好,我是無能。我公開了Vultr的FreeBSD伺服器,很好奇那些試圖透過SSH進行嘗試的人是誰,所以就查看了一下。順帶一提,FreeBSD會將「security run output」發送到我的網域,告訴我有哪些嘗試。

image
就是這種感覺。那麼,我們就用geoip來看看這些試圖進行嘗試的人的全球IP位址來自哪個國家吧。順帶一提,geoiplookup指令可以這樣安裝:

sudo pacman -S geoip  
  

指令是這個

$ geoiplookup IP位址  
GeoIP Country Edition: RU, Russian Federation  
  

使用bash進行文字格式化

那麼,首先將原始資料「security run output」的字串隨意地複製到我的ThinkPad上,然後進行格式化。

cat vultr | grep -oP "from.*port" | awk '{print $(NF-1)}' | sort | uniq > grepip  
  

在上述情況中,我們從名為vultr的「security run output」描述中,使用grep的-o選項匹配值,並使用-P選項的Perl正規表達式,提取從「from」字串到「port」字串的描述。
會變成像下面這樣的字串。

from IP位址 port  
  

此時不使用awk的原因是,如果以空格作為分隔符,當密碼錯誤或伺服器上不存在目標使用者時,錯誤輸出會有所不同,因此我提取了從「from」到「port」的整個字串以捕捉所有情況。接下來,我使用awk提取最後一個記錄中的IP位址,然後使用sort和uniq刪除重複的IP,並將結果寫入名為grepip的檔案中。然後,我們將使用bash對這些IP執行geoiplookup,並進行簡單的國家統計。

$ cat country.sh  
#!/bin/bash  
  
# IP位址的檔案  
INPUT="grepip"  
  
# 輸出檔案  
OUTPUT="countries.log"  
  
# 初始化  
> $OUTPUT  
  
# 對每個IP位址執行geoiplookup,取得國家資訊  
while IFS= read -r ip; do  
    geoiplookup "$ip" | awk -F: '{print $2}' >> $OUTPUT  
done < "$INPUT"  
  
# 統計並顯示國家資訊  
sort $OUTPUT | uniq -c | sort -tr  
  

這樣就賦予了執行權限。

chmod +x ./country.sh  
  

只需執行即可

$ ./country.sh  
      1  BE, Belgium  
      1  BG, Bulgaria  
      1  BR, Brazil  
      1  CH, Switzerland  
      1  HK, Hong Kong  
      1  HU, Hungary  
      1  IR, Iran, Islamic Republic of  
      1  IT, Italy  
      1  LT, Lithuania  
      1  MT, Malta  
      1  MX, Mexico  
      1  MY, Malaysia  
      1  NO, Norway  
      1  PA, Panama  
      1  PE, Peru  
      1  SE, Sweden  
      1  SK, Slovakia  
      1  TH, Thailand  
      1  TM, Turkmenistan  
      1  TZ, Tanzania, United Republic of  
      1  UZ, Uzbekistan  
      1  ZA, South Africa  
      2  RO, Romania  
      2  UA, Ukraine  
      3  PL, Poland  
      6  GB, United Kingdom  
      7  VN, Vietnam  
      8  CA, Canada  
      8  ID, Indonesia  
      9  RU, Russian Federation  
      9  SG, Singapore  
     10  FR, France  
     10  KR, Korea, Republic of  
     11  DE, Germany  
     11  NL, Netherlands  
     16  CN, China  
     18  IN, India  
     43  US, United States  
  

哦,原來如此...

使用Matplotlib清晰地顯示圖表

嗯,雖然在字串上可以理解,但當數量變多時會很難看,所以想用圖表顯示對吧?
此外,如果將其腳本化,也可以作為cron作業來生成。因此,我們將使用方便的Python函式庫Matplotlib來顯示圖表。安裝與程式碼:

pip install matplotlib  
  
cat AreYouFrom.py  
#!/usr/bin/python3  
  
import matplotlib.pyplot as plt  
import collections  
  
# 讀取檔案,按國家統計存取次數  
country_counts = collections.Counter()  
  
with open('countries.txt', 'r') as file:  
    for line in file:  
        # 取得國家資訊  
        country = line.strip().split(",")[1]  
        country_counts[country] += 1  
  
# 排序資料  
countries, counts = zip(*country_counts.most_common())  
  
# 建立圖表  
plt.figure(figsize=(10, 6))  
plt.bar(countries, counts, color='skyblue')  
plt.xlabel('Country')  
plt.ylabel('Accesses')  
plt.title('Accesses by Country')  
plt.xticks(rotation=90)  
plt.tight_layout()  
  
# 輸出為png圖片檔案  
plt.savefig('accesses.png')  
  

這樣就可以輸出圖表和圖片了。

chmod +x AreYouFrom.py  
  

(這檔名真像國中生英文啊!)

image

登登!看來來自美國的最多。

按嘗試SSH的埠號進行統計

那麼,我們來按嘗試存取的埠號進行調查。
這樣就只grep出了埠號。

cat vultr | grep -oP "port [123456789].*ssh2$" | grep -oP "[123456789].* "  
  

將其輸出為ports.txt。
然而,由於所有埠號都不同,所以在繪製圖表時,我們將它們分成不同的區塊。

$ cat AreYouPort.py  
#!/usr/bin/python3  
import matplotlib.pyplot as plt  
from collections import Counter  
  
# 從檔案讀取埠號  
with open('ports.txt', 'r') as file:  
    ports = [int(line.strip()) for line in file]  
  
# 計算埠號的頻率分佈  
counter = Counter(ports)  
  
blocks = {}  
for port, count in counter.items():  
    block = (port // 10000) * 10000  
    if block not in blocks:  
        blocks[block] = 0  
    blocks[block] += count  
  
# 建立圖表  
x = list(blocks.keys())  
y = list(blocks.values())  
  
plt.figure(figsize=(12, 6))  
plt.bar(x, y, width=6000, color='skyblue', edgecolor='black')  
plt.xlabel('Port Number')  
plt.ylabel('Frequency')  
plt.title('Port Numbers by Frequency')  
plt.xticks(x, [f'{i}-{i+9999}' for i in x], rotation=45)  
plt.grid(True, axis='y', linestyle='--', alpha=0.7)  
plt.tight_layout()  
  
# 儲存為PNG檔案  
plt.savefig('port_numbers.png')  
  

結果是....
image
為什麼會有這麼多嘗試使用不可能的30,000以上埠號呢...。那麼今天就到這裡。下次再見了。

Related Posts