tcpdump抓包命令:
root#tcpdump -I eth0 -s 80 -w /tmp/tcpdump.cap
注:其中80表示,只抓每個包的前80個字節。
抓包時就篩選自己需要的包:
Wireshark抓包前Capture→Options,在Capture Filter中輸入“host 10.10.100.10”,然后再抓。
tcpdump抓包對應的命令:
root#tcpdump -I eth0 host 10.10.100.10 -w /tmp/tcpdump.cap
小技巧:
ping<IP> -n 1 -l 1
這樣抓包看到的,Data位為1,當請求方出口IP為PAT地址時,便於定位測試ping包是否可達。
過濾表達式:
- 根據IP和端口:過濾“IP為10.10.100.10且TCP端口為445”,則輸入“ip.addr eq 10.10.100.10 && tcp.port eq 445”
- 根據協議過濾:NFS共享掛在失敗,查看portmap和mount兩個協議,則輸入“portmap || mount”
- 數據包跟蹤:選中感興趣的包,選擇Follow TCP/UDP Stream。
- 鼠標幫助過濾:選中感興趣的包,右鍵Prepare a Filter→Selected可以自動生成過濾表達式。如果選擇Apply as Filter→Selected則此表達式還會自動執行。
Wireshark自動分析:
- 單擊Analyze→Expert Information可以看到不同級別的提示,如重傳統計,連接建立和重置統計
- 單擊Statistics→Service Response Time選定協議名稱,可以得到響應時間統計。
- 單擊Statistics→TCP Stream Graph
- 單擊Statistics→TCP Stream Graph可以生成統計圖
- 單擊Statistics→I/O Graphs可以看到統計信息,如平均流量等等:
- 通過“Ctrl+F”搜索關鍵字:選string按鈕,然后輸入error搜索:
NFS協議的抓包分析:
客戶端訪問NFS服務器的portmap端口(tcp111),詢問NFS進程的端口號,默認NFS的端口號時2049,客戶端再訪問TCP2049,mount掛載動作時file handle動作。
另外NFS創建文件時,是認UID的,同一個UID號再另一台機器上看到的用戶就會不一樣了。
NFS協議的細節動作:
NFS時多個READ-CALL連續發出,和window的CIFS不同,CIFS時一個一個來的。
NFS進入文件夾的動作時ACCESS-CALL,查找是LOOKUP-CALL,創建是CREATE-CALL,寫入是WRITE-CALL,寫完了提交時COMMIT-CALL(COMMIT確認了才算數據真正寫好),看看文件屬性是GETATTR-CALL
async和sync的寫方式,async時多個WRITE-Call同時發出,sync時一個一個WRITE-Call執行(commit對sync無意義),分辨方法時看WRITE-CALL上的UNSTABLE和FILE_SYNC標志,前者是async,后者表示sync。
有人mount時跟上noac參數,讀寫性能很差,是因為noac會強制寫操作為sync參數,讀操作時頻繁GETATTR,導致性能受影響。
MTU的交互:
TCP在三次握手過程中就會告知對方自己的MSS(Maximum Segment Size),MSS加上TCP頭(20)和IP頭(20)的長度就是MTU。
強制nslookup使用tcp協議:
root#nslookup
>set vc
TCP三次握手:
第一個數據段的Seq為1,長度1448,所以數據段2的Seq號就是1449,數據段2長度為1448,數據段3的Seq號為2897。接收方發送的ACK號其實就等於發送方的Seq加上長度,接收方以此來判斷少了哪些包,要求重傳。
我們之所以在Wireshark上看到Seq=0,是因為Wireshark啟用了Relative Sequence Number,可以在“Edit→Preferences→protocals→TCP”里設置。
Windows滑動窗口:
ACK的數據包中有win=1460或者win=2920之類的,表示接收方一次可以接收一個或兩個MSS,兩個就是發送方可以一次發兩個包來等對方確認。
如果接收方處理速度跟不上接收數據的速度,緩存就會滿了,從而導致接收窗口為0,發送方就會將自己的發送窗口限制為0,如下圖。
發送窗口決定一次能發多少字節,而MSS決定這些字節分幾個包發完。
發送方一次發N個包,接收方有時候收到很多包時,只要回復最后一個就能確認它收到了所有N個包。
歷史插曲:
TCP剛發明,接收窗口被定義為65535字節,TCP包頭只給接收窗口值留了16bit,無法突破65535的,RFC1323中三次握手時,把自己的Window Scale信息告知對方,由於Window Scale放在TCP頭之外的Option中,不用改TCP頭設計,Window Scale作用向對方聲明一個Shift count,我們把它做成2的指數,乘以TCP包頭中定義的接收窗口,得到真正的TCP接收窗口。
如下圖,5856就是183乘以32。
TCP慢速啟動:
剛開始是連續翻倍增加每一次發送MSS的數量,到一定數量后開始逐漸+1遞增。
RTO是收不到確認,等待一段時間后再發,從發原始包到重發的時間。
遇到擁塞重傳后,從1開始重新慢啟動,臨界值設定為上次擁塞時的一半。
快速重傳:
接收方收到的Seq比期望的大時,所以它沒收到一個包就Ack一次期望的Seq號,發送方收到3個或以上重復ACK時,就意識到相應的包已經丟了,從而重傳。為什么要規定3個Dup Ack呢,為了在很大程度上避免因亂序而觸發重傳。
擁塞避免階段收到快速重傳,臨界窗口應該設為發生擁塞時還沒被確認的數據量的一半,然后將擁塞窗口設置為臨界窗口值加3個MSS,繼續保留在擁塞避免階段,這個過程被稱為快速恢復。如下:
TCP延遲確認:
如果收到一個包之后暫時沒有什么數據需要發送對方,那就延遲一段時間(在windows默認為200ms),假如這段時間恰好有數據要發送,那確認信息就隨數據一同發出。
微軟KB328890提供關閉延遲確認的步驟。
Nagle算法:
在發出的數據沒有被確認之前,假如又有小數據生成,那就把小數據收集起來,湊滿一個MSS或者等收到確認后再發送。
UDP協議的優勢:
- UDP凈荷高。
- 沒有Seq和Ack,不建立連接,效率高
UDP協議的劣勢:
- 沒有MTU的概念,網絡層分片導致性能占用。
- 沒有重傳機制,應用層決定丟包處理。
- 分片機制容易遭受攻擊。
CIFS:
CIFS使用TCP的445端口。支持SMB,SMB2,SMB3(其中SMB2普遍)
客戶端把自己所有支持版本告知服務器端,服務器端挑出回復自己支持的最高版本。
CIFS的session身份驗證方式有Kerberos和NTLM。
Session Setup后客戶端打開共享路徑,操作稱為Tree Connect,服務器返回的Tree ID,客戶端利用這個ID去訪問目錄和文件。Tree Connect不檢查權限,即使無權限客戶也能得到,檢查權限的工作由Create操作完成。Create操作是涉及新建,打開,讀取等動作。
常見問題:
- 如果對文件夾禁止用戶訪問,但是下面一個文件允許訪問,則用戶無法打開對應目錄,但是能直接打開那個文件。
- Windows的備份是Create請求中“Backup Intent”設1,讀取為0,服務器可以根據這個字段來根據備份和讀取權限來決定是否准許訪問。
- Access Mask是“讀寫”,Share Access Mask是“讀”,如果有人讀寫,另一個人請求讀寫就會收到“Sharing Violation”錯誤。
- CIFS來解決緩存數據一致性,采用Oplock(機會鎖),有Exclusive(允許讀寫緩存),Batch(允許所有操作緩存)和Level2(允許讀緩存)三種形式。
(1)windows xp的SMB是一去一回,windows 7是多發多收,所以在網絡質量不好的地方,差距挺大。
(2)Windows Explorer從CIFS上復制文件比Robcopy和EMCopy慢,是因為它是單線程的。
(3)CIFS共享中,復制一個文件粘貼到同一個目錄是把內容復制到客戶端內存,再從客戶端內存寫到服務器上,,而粘貼到客戶端本地硬盤當然會比它快。SMB3才改進了這點,實現服務器端本地復制。
(4)剪切粘貼非常快是因為只是一個“rename”操作。
(5)SMB2沒有SMB協議這么啰嗦,所以讀性能提高很多。
SMB3(Win8和10和2012)改進了復制粘貼在網絡上跑兩次的問題,是運用給客戶端一個Token,客戶端利用Token給服務器發寫請求實現的。
SMB3還實現了雙網卡在CIFS層的負載均衡,一個SMB3 Session的諸多TCP分攤在兩塊網卡上,即使網卡癱了一塊,SMB3連接還能存在。
SMB3還把文件鎖之類的信息存在硬盤上,當雙機頭的架構中,主機頭掛了,備機頭起來便能獲得此信息,從而提供無縫服務。
DNS相關:
A記錄:域名解析到IP
PTR記錄:IP地址解析到域名(nslookup 跟上IP)
SRV記錄:查找域控
CNAME記錄:別名
DNS的放大攻擊:偽造DNS請求包的源IP,大量發送請求包,那個IP就會收到完全不對稱般大量的DNS響應包。
FTP主動模式:客戶端通過21端口連接服務器,但是數據傳輸是由服務器從20端口主動連接客戶端協商好的隨機高端口。
FTP被動模式:數據傳輸時,也是由客戶端發起連接的。
根據密鑰解密https流量:
Edit→Preferences→Protocols→SSL→RSA keys list,然后按照IP,Port,Protocol,Private Key格式填寫RSA keys list一行
Kerberos認證原理:
原始版本:
A用hash把密碼轉成一把密鑰Kclt,用kclt把當前時間戳加密生成一個字符串“時間戳Kclt”,把“時間戳kclt”和帳號A的信息,以及一段隨機字符串發給KDC組成身份認證請求AS_REQ。KDC收到AS_REQ后,讀到帳號A的信息,調出密碼,在用hash轉換成Kclt解開“時間戳Kclt”,能解開就表明請求是帳號A生成的。
選用時間戳是為了防范黑客的重放攻擊,用時間戳,只要NTP是同步的,時間間隔相差太大就認為是重放攻擊。
KDC在用Kclt加密隨機字符串,帳號A拿到回復后能否解出就能判斷KDC的真假。
以上過程中雙方都沒有向對方發送密碼,即便一方是假的也不會泄密。
但是有問題就是每次認證都要調出密碼執行hash解密,對KDC的性能要求太大。
改進版本:
KDC生成兩把一樣的密鑰Kclt-Kdc,把密碼hash成Kkdc,然后用它加密那把委托給A的密鑰,委托密鑰稱為TGT,KDC只需記住自己的Kkdc,就能解開委托給帳號的TGT,從而獲得與該帳號之間的密鑰,KDC的負擔大大降低。KDC回復給A的AS_REP需要包含TGT,“(Kclt-kdc,時間戳,隨機字符串)Kclt”
A收到AS-REP后利用Kclt機密“(Kclt-kdc,時間戳,隨機字符串)Kclt”,判斷KDC真實性,把Kclt-kdc和TGT保存備用。
賬號A請KDC幫忙認證資源B:
A將TGT,帳號A信息,時間戳,要訪問的B的資源發給KDC,這個請求叫TGS-REQ。
TGS_REQ=TGT,{帳號A信息,時間戳}Kclt-kdc,資源B相關信息
KDC收到TGS-REQ后,用Kkdc解密TGT得到Kclt-kdc,再用Kclt-kdc解密A的信息和時間戳驗證身份,確認A為真。
KDC生成兩把相同的密鑰給A和B使用,稱為Kclt-srv,其中一把密鑰給A,另一把委托A給B,Kerberos把B的密碼hash成Ksrv,然后用它加密委托給A轉交B的Kclt-srv,只能B能解開這條Ticket。
Ticket={帳號A的信息,Kclt-srv}Ksrv
TGS_REP={Kclt-srv}Kclt-kdc,Ticket
賬號A收到TGS_REP后,用Kclt-kdc解開{Kclt-srv}Kclt-kdc,得到Kclt-srv,Ticket發給B,以后多次訪問B都可用這個Ticket,不用每次向KDC申請,降低KDC負擔。
帳號A和帳號B互相認證:
帳號A給B發送“{帳號A的信息,時間戳}”Kclt-srv,以及上一步收到的Ticket,請求稱為AP_REQ。
AP_REQ=“{帳號A的信息,時間戳}Kclt-srv”,Ticket
B能用Ksrv解開Ticket得到Kclt-srv,用Kclt-srv解開“{帳號A的信息,時間戳}Kclt-srv”,B就能確認A為真,回復AP_REP來證明自己也是真的。
AP_REP={時間戳}Kclt-srv
帳號A利用Kclt-srv解密AP-REP,通過得到時間戳來判斷對方是否為真。
Wireshark解密查看必須Edit→Preferences→Protocols→KRB5,keytab file輸入key的路徑才能解密。
客戶可以用\\IP地址 訪問,但是用域名就不行:
用IP是NTLM身份認證的,用域名則是Kerberos認證的,機制不一樣,注意時鍾,NTLM不會因為懷疑重放攻擊拒絕訪問。
SACK機制(Selective Ack):
如果一個包丟了,接收方發現了,那這個包后續的包也要重傳,因為無法確定是否也丟失,但是接收方雖然知道丟了哪些包沒法告知發送發,RFC2018中給出了方案,SACK啟用的情況下,接收方能告訴發送方,它只需要重發的那個包,可以減少大量不必要的重傳。