必須牢記
網絡狀態
狀態 |
說明 |
LISTEN | 首先服務器需要打開一個socket進行監聽,監聽來自遠方TCP端口的連接請求 |
SYN_SENT | 表示主動連接,客戶端能通過應用程序調用connect()函數進行active open。於是客戶端TCP發送一個SYN以請求建立一個連接,之后狀態為SYN_SEND,表示已發送一個SYN到服務器端,等待SYN 1+ACK 0響應。 |
SYN_RECV | 服務器端收到客戶端的SYN 1+ACK 0,然后狀態變為SYN_RECV。表示服務器收到了客戶端發來的SYN,然后自己也響應了給客戶端一個SYN 1+ACK 1,然后等待客戶端確認。 這時候客戶端過來的連接(屬於半連接狀態)被放在一個SYN隊列里面,SYN泛洪***也是這樣的,就是服務器響應了SYN+ACK之后,客戶端就不在發送ACK了,然后繼續發送SYN,直到把服務器的最大連接數量耗盡。 半連接隊列長度是由內核參數tcp_max_syn_backlog來決定的。 |
ESTABLISHED | 代表一個打開的連接,客戶端收到服務器發送的SYN 1+ACK 1,就變為這個狀態,然后向服務器發送ACK,如果服務器收到這個ACK,那么它也變為這個狀態。這個狀態就是表示連接以及建立,正在或即將傳輸數據。服務器收到ACK以后就會把半連接從上面提到的SYN隊列中刪除,然后放到ACCEPT隊列中,這時這個半連接的狀態就變成了ESTABLISHED。 |
FIN_WAIT1 | 主動關閉端(可以是服務器也可以是客戶端)應用程序調用了close,於是其TCP發出FIN主動關閉請求,也就是四次斷開的第一次,之后就進入了FIN_WAIT1狀態,等待遠程主機的ACK請求。 |
CLOSE_WAIT | 被動關閉端(可以是服務器有可以是客戶端)收到了對方發來的FIN后,進入該狀態,然后發出ACK+1以回應FIN請求(它的接收也作為文件結束符傳遞給上層應用程序)。這個狀態實際上是說客戶端告訴服務器我沒有請求或者數據要發送了,等待看看服務器或者說是進程還有沒有數據要發送,如果有則繼續發送,如果沒有的話,就發送反向關閉指令。 如果服務器大量連接是這個狀態就要去查看程序,很有可能是程序設計的問題。 |
FIN_WAIT2 | 主動關閉端收到ACK+1后,就進入的FIN_WAIT2狀態,也就等服務器是否還有數據發來,如果服務器沒有數據了,那么服務器就發送的反向關閉指令。也就是反向關閉連接指令FIN1+ACK1。實際上是告訴客戶端我的數據發送完了,可以關閉連接了。 |
LAST_ACK | 被動關閉端,發送反向結束連接請求FIN 1+ACK 1,然后進入LAST_ACK狀態,等待主動關閉端發送ACK。 |
TIME_WAIT | 主動關閉端收到FIN 1 +ACK 1后,並進入TIME_WAIT狀態,然后發送ACK+1,等待一段時間(2MSL)以確保服務器收到了ACK+1,然后自己進入CLOSED狀態。這個階段主要是客戶端為了再次確認一下服務器是否可以關閉連接,因為網絡畢竟是不可靠的。 對於服務器有大量TIME_WAIT這個問題通常調整sysctl來解決。 |
CLOSING | 比較少見,表示等待遠程TCP對連接中斷的確認。 |
CLOSED | 被動關閉端在收到ACK包以后,就進入closed狀態,連接結束。 |
三次握手
四次斷開
為什么TIME_WAIT要等2MSL時長?
服務器發送FIN給客戶端,之后自己進入LAST_ACK階段,客戶端收到FIN之后會發送ACK並進入TIMW_WAIT階段,如果服務器沒有收到客戶端最后的ACK,那么它將會重發FIN,所以一個包的最大生存時間就是1MSL,客戶端等2倍就是為了防止這種情況發生,這樣就有時間來接收服務器重發的FIN信號。
古老的netstat命令
說它古老是因為它的確很古老目前已經被ss命令所替換,雖然在目前的CetnOS中還可以使用,但是它執行效率比ss命令要低。
參數和輸出說明
不加任何參數將會輸出2部分內容:
-
Active Internet connections 活動的internet連接,包含TCP和UDP。
-
Active UNIX domain sockets 活動UNIX本地套接字連接
參數 | 說明 |
-a | 顯示所有選項 |
-t | 僅顯示TCP相關選項 |
-u | 僅顯示UDP相關選項 |
-n | 盡量不顯示名稱,而用數字代替,比如主機名換成IP顯示 |
-l | 僅列出在Listen監聽的服務狀態 |
-p | 顯示建立相關網絡的程序名和進程號,也就是本機哪個進程開啟的這個網絡鏈接 |
-r | 顯示路由表,作用和 route -n一樣 |
-e | 顯示擴展信息 |
-s | 按不同協議輸出統計信息,因為協議不同,所以輸出的統計選項也不同 |
-c | 每隔固定時間刷新 |
# 這里只顯示了TCP的連接信息
netstat -anetp
列 |
說明 |
Proto | 協議 |
Recv-Q | 數據已經接收到本地套接字,但是還有多少沒有被程序取走的字節,從2.6.18內核開始這里包含了半連接隊列數據也就是對方發過來的SYN請求數據 |
Send-Q | 遠程主機未確認的字節數,從2.6.18內核開始這里包含了半連接隊列數據也就是服務器發送了SYN+ACK的數據量。 |
Local Address | 套接字在本地IP地址和端口 |
Foreign Address | 套接字遠程的IP地址,也就是客戶端或者上層代理的IP和端口 |
State | 網絡連接狀態 |
User | 運行該進程的賬戶,也就是該服務器網絡套接字屬於誰 |
Inode | |
PID/Progam name | 服務器端監聽或者處理該端口請求的程序 |
常用命令組合
# 查看當前正在監聽的TCP端口有哪些 netstat -alnt # 查看當前所有TCP端口的狀態 netstat -nat # 查看當前所有的TCP端口狀態並列出進程ID netstat -natp # 查看特定進程的網絡連接狀態 netstat -natp | grep PID
查看源IP中處於TIME_WAIT狀態數量最多的前20名IP
netstat -nat | grep TIME_WAIT | awk '{print $5}' | sort | uniq -c | sort -rn | head -n 20
# sort排序,默認正向排序
# uniq -c 取出重復項 -c 統計個數
# sort -rn 再次排序反向,同時以數字進行,默認是純文本
# head -n 20 顯示前20個
查看訪問80端口最多的前20個IP,其實道理和上面的類似
netstat -natp | grep 8080 | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -rn | head -n 20
查看連接狀態統計信息
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
查看已經建立連接和正在監聽的,你想查看其它狀態也是類似的
netstat -natl | egrep "ESTABLISHED|LISTEN"
查看指定端口且狀態為ESTABLISHED的連接數量
# grep -i 表示忽略大小寫 est 表示 ESTABLISHED
netstat -nlap | grep -i est | grep -i 2181 | wc -l
SS命令
參數 | 說明 |
-a | 顯示所有選項 |
-t | 僅顯示TCP相關選項 |
-u | 僅顯示UDP相關選項 |
-n | 盡量不顯示名稱,而用數字代替,比如主機名換成IP顯示 |
-l | 僅列出在Listen監聽的服務狀態 |
-p | 顯示建立相關網絡的程序名和進程號,也就是本機哪個進程開啟的這個網絡鏈接 |
-s | 顯示連接狀態統計信息 |
-r | 解析服務的名稱,ssh變成22這種。端口名稱和端口號的解析,IP和機器名的解析 |
-x | 顯示UNIX套接字 |
-m | 顯示套接字內存使用 |
-e | 顯示擴展信息 |
其實可以看到這里很多參數和netstat相似,所以使用也很方便,我們這里直接通過場景來說明
統計當前連接狀態信息
ss -s
顯示TCP或者UDP連接信息
# 加a就是所有的tcp連接信息
ss -at
查看所有TCP打開的端口
顯示連接到指定目標端口所有的連接,這里的目的或者源相對於本機來說,下面的命令含義是本機連接遠程443或者80的
ss -nt '( dst :443 or dst :80 )'
顯示所有源端口或目的端口是ssh
ss -at '( dport = :ssh or sport = :ssh )'
查看所有連接到本機22端口的連接
ss -nt sport = :ssh
顯示所有TCP建立連接的
ss -t4 state established
# 可用狀態 time-wait syn-sent syn-recv fin-wait-1 fin-wait-2 time-wait last-ack connected closed close-wait
說明
在ss命令和netstat命令都有下面的字段但是其含義不同
即使在ss命令中不同場景其含義也不同
如果State是LISTEN狀態:這里的含義就是上面說的Recv-Q是當前全連接隊列使用量;Send-Q是當前對應進程SOCKET套接字最大blacklog的數量,也就是全連接隊列最大長度
如果State不是LISTEN狀態:
Recv-Q:數據已經接收到本地緩存,還有多少沒有被程序取走,單位bytes
Send-Q:要發送的數據有多少還在本地緩沖區遠程主機未確認,如果不是0可能是本地發送數據過快或者對方接收數據過慢,單位bytes
其他網絡監控命令
iftop
# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 需要設置源
yum -y install iftop
# 安裝完執行下面的命令
iftop -nP
=> 代表發送 <= 代表接收
最右邊rates的三列數字,表示2秒、10秒和40秒的平均流量
cum表示從運行iftop開始到目前時間的總流量,peak流量峰值
TX:表示發送總量
RX:表示接收總量
TOTAL:表示全部總量
注意:在顯示過程中按下列鍵可以切換模式
T:是否顯示每個連接的總流量
B:分別顯示2秒、10秒和40秒的平均流量
P:暫停顯示/繼續顯示
nethogs
# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 需要設置源 yum -y install nethogs # 安裝完執行下面的命令
nethogs
當運行時按:
q:退出
s:對SENT列進行排序
r:對REVEIVE進行排序
m:切換顯示單位