netstat和tcp

使用 netstat

  netstat 命令是 linux 下一個很是有用的命令,顧名思義,其做用是查詢當前的網絡狀態。
  以最經常使用的查詢 TCP 鏈接狀態爲例,在 Shell 裏運行如下命令:linux

netstat -an | awk '/tcp/ {print $6}' | sort | uniq -c

  你會看到當前全部 TCP 鏈接的狀態計數:程序員

屏幕快照

  有更高追求的程序員,可能會想吧結果美化一下。好比,使用下面的命令:vim

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

  你會獲得以下的結果:服務器

屏幕快照

  上述兩個命令的結果不一樣,是由於我運行命令的時機不一樣,他們的意義是同樣的,僅僅只有格式的區別。cookie

分析 TCP 狀態

  這些狀態有什麼含義呢?咱們首先看一下 TCP 狀態轉換圖:網絡

TCP 狀態轉換圖

TCP 狀態轉換圖併發

  總結各狀態大體意義以下:socket

  CLOSED 初始狀態。
  LISTEN 服務端處於監聽狀態,能夠接受鏈接。
  SYN_SENT 客戶端鏈接併發送 SYN 報文,進入 SYN_SENT 狀態,等待服務端確認。
  SYN_RCVD 服務端接受到了 SYN 報文,當收到客戶端的 ACK 報文後,會進入到 ESTABLISHED 狀態。
  ESTABLISHED 鏈接已經創建,進入數據傳輸狀態。
  FIN_WAIT_1 創建鏈接後,其中一方請求終止鏈接,等待對方的 FIN 報文。
  FIN_WAIT_2 半鏈接,有一方要求關閉鏈接,但另外還告訴對方,我還有數據須要傳輸,稍後再關閉鏈接。
  TIME_WAIT 收到了對方的 FIN 報文,併發送出了 ACK 報文,2MSL 後便可回到 CLOSED 可用狀態。
  CLOSE_WAIT 等待關閉。
  CLOSING 當發送 FIN 報文後,並未收到對方的 ACK 報文,卻收到了 FIN 報文,表示雙方都正在關閉鏈接。
  LAST_ACK 被動關閉一方在發送 FIN 報文後,最後等待對方的 ACK 報文。tcp

  其中 SYN_RECVESTABLISHEDTIME_WAIT 是對咱們比較有意義的幾個狀態。優化

SYN_RECV

  表示正在等待處理的請求數。SYN_RECV 過多或居高不下,能夠理解爲服務器並不能及時處理全部的請求。這時要考慮進行效率優化,或增長更多的服務器;

ESTABLISHED

  表示正在進行數據傳輸的請求數。一般與在線人數和併發相關,能夠做爲服務器負載能力的一項指標。

TIME_WAIT

  表示處理完畢,等待超時結束的請求數。若 TIME_WAIT 過多,可調整內核參數進行優化,若仍無效,則需注意是否遭到了惡意攻擊。如有大量的 SYN_RECEIVEDTIME_WAITFIN_WAIT_1 等狀態存在,而 ESTABLISHED 不多,則可初步判斷存在 DDOS 攻擊。

關於 TIME_WAIT

  主動關閉的一方在發送最後一個 ACK 報文後,就會進入 TIME_WAIT 狀態,停留 2MSL(max segment lifetime)。

  TCP/IP 協議中如此設計,主要有兩個緣由:

  1. 防止上一次鏈接中的包,迷路後從新出現,影響新鏈接。 通過 2MSL,上一次鏈接中全部的重複包都會消失。

  2. 可靠的關閉 TCP 鏈接。 主動關閉方發送的最後一個 ACK(FIN) 報文,有可能丟失,這時被動方會從新發送 FIN 報文, 若是這時主動方處於 CLOSED 狀態 ,就會響應 RST 報文而不是 ACK 報文。因此主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED

  TIME_WAIT 並不會佔用太多資源,除非受到惡意攻擊。

優化 TIME_WAIT

  經過調整內核參數,能夠緩解 TIME_WAIT 過多的狀況。
  首先打開配置文件 vim /etc/sysctl.conf,修改如下配置:

# 表示開啓 SYN cookies。當出現 SYN 等待隊列溢出時,啓用 cookies 來處理,可防範少許 SYN 攻擊,默認爲 0,表示關閉;
net.ipv4.tcp_syncookies = 1

# 表示開啓重用。容許將 TIME-WAIT sockets 從新用於新的 TCP 鏈接,默認爲 0,表示關閉;
net.ipv4.tcp_tw_reuse = 1

# 表示開啓 TCP 鏈接中 TIME-WAIT sockets 的快速回收,默認爲 0,表示關閉;
net.ipv4.tcp_tw_recycle = 1

# 修改系統默認的 TIMEOUT 時間
net.ipv4.tcp_fin_timeout = 1

  而後執行以命令 /sbin/sysctl -p 讓參數生效。

相關文章
相關標籤/搜索