Linux 之《荒島餘生》(五):網路篇
你想通過執行ping google.com來判斷網路連通性麼?我想你這是在侮辱方教授。本篇是《荒島餘生》系列第四篇,網路篇,但不會教你fq。其餘參見:
ofollow,noindex" target="_blank">Linux之《荒島餘生》(一)準備篇
Linux之《荒島餘生》(四)I/O篇看著kali linux上百個網路命令,我陷入了沉思。專業的網路命令實在是太多了,如果要羅列,上千個也是有的。個人不是滲透測試工作者,大部分功能只知皮毛。所以本文是非常淺顯的技術總結,僅聚焦工作中常用到的一些Linux命令。
由於 nio
的普及, ck10k
的問題已經成為過去式。現在隨便一臺伺服器,就可以支援數十萬級別的連線了。那麼我們來算一下,100萬的連線需要多少資源。
首先,每一個連線都是檔案控制代碼,所以需要檔案描述符數量支援才行,每一個socket記憶體佔用15k-20k之間,這樣,僅維護相應socket,就需要 20G
記憶體;而廣播一個1KB的訊息需要佔用的頻寬為 1000M
!
檢視當前系統的連線
如何看當前系統有多少連線呢?可以使用 netstat
結合 awk
進行統計。如下指令碼,統計了每一種狀態的tcp連線數量
# netstat -antp | awk '{a[$6]++}END{ for(x in a)print x,a[x]}' LISTEN 41 CLOSE_WAIT 24 ESTABLISHED 150 Foreign 1 TIME_WAIT 92
但如果你在一臺有上萬連線的伺服器上執行這個命令,你可能會等上很長時間。所以,我們有了第二代網路狀態統計工具: netstat
=> ss
(可別和那個越獄工具搞混了)。
# ss -s Total: 191 (kernel 220) TCP:5056 (estab 42, closed 5000, orphaned 3, synrecv 0, timewait 5000/0), ports 3469 ...
netstat
屬於 net-tools
工具集,而 ss
屬於 iproute
。其命令對應如下,是時候和net-tools說Bye了。
用途 | net-tools | iproute |
---|---|---|
統計 | ifconfig | ss |
地址 | netstat | ip addr |
路由 | route | ip route |
鄰居 | arp | ip neigh |
VPN | iptunnel | ip tunnel |
VLAN | vconfig | ip link |
組播 | ipmaddr | ip maddr |
ss命令
基本使用
我們按照使用場景來看下ss的用法。
檢視系統正在監聽的tcp連線
ss -atr ss -atn #僅ip
檢視系統中所有連線
ss -alt
檢視監聽444埠的程序pid
ss -ltp | grep 444
檢視程序555佔用了哪些埠
ss -ltp | grep 555
顯示所有udp連線
ss -u -a
檢視TCP sockets,使用-ta選項
檢視UDP sockets,使用-ua選項
檢視RAW sockets,使用-wa選項
檢視UNIX sockets,使用-xa選項
和某個ip的所有連線
ss dst 10.66.224.130 ss dst 10.66.224.130:http ss dst 10.66.224.130:smtp ss dst 10.66.224.130:443
顯示所有的http連線
ssdport = :http
檢視連線本機最多的前10個ip地址
netstat -antp | awk '{print $4}' | cut -d ':' -f1 | sort | uniq -c| sort -n -k1 -r | head -n 10
Recv-Q和Send-Q
注意ss的執行結果,我們說明一下Recv-Q和Send-Q。
這兩個值,在 LISTEN
和 ESTAB
狀態分別代表不同意義。一般,正常的應用程式這兩個值都應該為0(backlog除外)。數值越大,說明問題越嚴重。
LISTEN狀態
-
Recv-Q:代表建立的連線還有多少沒有被accept,比如Nginx接受新連線變的很慢
-
Send-Q:代表listen backlog值
ESTAB狀態
-
Recv-Q:核心中的資料還有多少(bytes)沒有被應用程式讀取,發生了一定程度的阻塞
-
Send-Q:代表核心中傳送佇列裡還有多少(bytes)資料沒有收到ack,對端的接收處理能力不強
檢視網路流量
檢視流量
有很多工具可以看網路流量,但我最喜歡sar。sar是linux上功能最全的監控軟體。如圖,使用 sar -n DEV 1
即可每秒重新整理一次網路流量。
當然,你也可以使用ifstat、nload、iptraf等命令檢視。然而資料來源,還是來自我們的/proc目錄
watch cat /proc/net/dev
檢視佔流量最大的IP
有時候我們發現網路頻寬佔用非常高,但我們無法判斷到底流量來自哪裡。這時候,iftop就可以幫上忙了。如圖,可以很容易的找出流量來自哪臺主機。
當你不確定內網的流量來源,比如有人在壓測,api呼叫不合理等,都可以通過這種方法找到他。
抓包
tcpdump
當我們需要判斷是否有流量,或者除錯一個難纏的netty應用問題,則可以通過抓包的方式去進行進一步的判斷。在Linux上,可以通過 tcpdump
命令抓取資料,然後使用 Wireshark
進行分析。
tcpdump -i eth0 -nn -s0 -v port 80
-
-i
指定網絡卡進行抓包 -
-n
和ss一樣,表示不解析域名 -
-nn
兩個n表示埠也是數字,否則解析成服務名 -
-s
設定抓包長度,0表示不限制 -
-v
抓包時顯示詳細輸出,-vv、-vvv依次更加詳細
1)加入 -A
選項將列印ascii , -X
列印hex碼。
tcpdump -A -s0 port 80
2)抓取特定ip的相關包
tcpdump -i eth0 host 10.10.1.1 tcpdump -i eth0 dst 10.10.1.20
3) -w
引數將抓取的包寫入到某個檔案中
tcpdump -i eth0 -s0 -w test.pcap
4)tcpdump支援表示式,還有更加複雜的例子,比如抓取系統中的get,post請求(非https)
tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:"
更多參見
https://hackertarget.com/tcpdump-examples/
抓取的資料,使用wireshark檢視即可。
http抓包
抓包工具將自身當作代理,能夠抓取你的瀏覽器到伺服器之間的通訊,並提供修改、重放、批量執行的功能。是發現問題,分析協議,攻擊站點的利器。常用的有以下三款:
-
Burpsuite (跨平臺)
-
Fiddle2 (Win)
-
Charles (Mac)
壞事要偷偷的幹哦。
流量複製
你可能需要使你的生產環境HTTP真實流量在開發環境或者預演環境重現,這樣就用到了流量複製功能。
有三個工具可供選擇,個人傾向於Gor。
-
Gor
-
TCPReplay
-
TCPCopy
連線數過多問題
根據TCP/IP介紹,socket大概包含10個連線狀態。我們平常工作中遇到的,除了針對SYN的拒絕服務攻擊,如果有異常,大概率是TIME_WAIT和CLOSE_WAIT的問題。
TIME_WAIT一般通過優化核心引數能夠解決;CLOSE_WAIT一般是由於程式編寫不合理造成的,更應該引起開發者注意。
TIME_WAIT
TIME_WAIT是主動關閉連線的一方保持的狀態,像nginx、爬蟲伺服器,經常發生大量處於time_wait狀態的連線。TCP一般在主動關閉連線後,會等待 2MS
,然後徹底關閉連線。由於HTTP使用了TCP協議,所以在這些頻繁開關連線的伺服器上,就積壓了非常多的TIME_WAIT狀態連線。
某些系統通過dmesg可以看到以下資訊。
__ratelimit: 2170 callbacks suppressed TCP: time wait bucket table overflow TCP: time wait bucket table overflow TCP: time wait bucket table overflow TCP: time wait bucket table overflow
通過ss -s命令檢視,可以看到timewait已經有2w個了。
ss -s Total: 174 (kernel 199) TCP:20047 (estab 32, closed 20000, orphaned 4, synrecv 0, timewait 20000/0), ports 10785
sysctl命令可以設定這些引數,如果想要重啟生效的話,加入/etc/sysctl.conf檔案中。
# 修改閾值 net.ipv4.tcp_max_tw_buckets = 50000 # 表示開啟TCP連線中TIME-WAIT sockets的快速回收 net.ipv4.tcp_tw_reuse = 1 #啟用timewait 快速回收。這個一定要開啟,預設是關閉的。 net.ipv4.tcp_tw_recycle= 1 # 修改系統預設的TIMEOUT時間,預設是60s net.ipv4.tcp_fin_timeout = 10
測試引數的話,可以使用 sysctl -w net.ipv4.tcp_tw_reuse = 1 這樣的命令。如果是寫入進檔案的,則使用sysctl -p生效。
CLOSE_WAIT
CLOSE_WAIT一般是由於對端主動關閉,而我方沒有正確處理的原因引起的。說白了,就是程式寫的有問題,屬於危害比較大的一種。
我們拿”csdn 諧音太郎”遇到的一個典型案例來說明。
程式碼是使用HttpClient的一個使用片段。在這段程式碼裡,通過呼叫in.close()來進行連線資源的清理。但可惜的是,程式碼中有一個判斷:非200狀態的連線直接返回null。在這種情況下, in
連賦值的機會都沒有,當然也就無法關閉,然後就發生了連線洩漏。
所以,HttpClient的正確關閉方式是使用其api: abort()
。
其他常用命令
應用軟體
# 斷點續傳下載檔案 wget -c $url # 下載整站 wget -r -p -np -k $url # 傳送網路連線(常用) curl -XGET $url # 傳輸檔案 scp sftp # 資料映象備份 rsync
檢測工具
# 連通性檢測 ping google.com # 到對端路由檢測 tracepath google.com # 域名檢測 dig google.com nslookup google.com # 網路掃描工具 nmap # 壓力測試 iperf # 全方位監控工具(好東西) nmon
配置工具
# 停止某個網絡卡 ifdown # 開啟某個網絡卡 ifup # 多功能管理工具 ethtool
壓力測試
wrk ab webbench http_load
多功能工具
# 遠端登入 telnet ssh nc # 防火牆 iptables -L
結尾
除了基本的工具,本文提到的很多網路命令,都不是預裝的,需要使用yum自行安裝。網路程式設計方面的學習,我覺得,讀一下《TCP/IP詳解 卷1:協議》這本書,然後寫幾個Netty應用就可以了。
NIO我們已經在I/O篇提起了,在此不再做詳細介紹。等你碰到所謂的拆包粘包問題,遇到心跳和限流問題,甚至遇到了流量整形問題,那麼證明你離一個專業的網路程式設計程式設計師越來越近了。