相關學習資料html
tcp-ip詳解卷1:協議.pdf
目錄算法
0. 引言 1. 應用層 3. 傳輸層 4. 網絡層
0. 引言 數據庫
協議中的網絡字節序問題緩存
在學習協議格式以前,有一點必須明白,不然咱們在觀察抓包數據的時候可能會產生疑惑:安全
1. 協議格式中的字段排布,最高位在左邊,記爲0bit;最低位在右邊,記爲31 bit。 2. 4個字節的32bit值如下面的次序傳輸: 1) 首先是0~7bit 2) 其次8~15bit 3) 而後16~23bit 4) 最後是24~31bit 這種傳輸次序稱做"big endian字節序" 3. 因爲TCP/IP首部中全部的二進制整數在網絡中傳輸時都要求以這種次序,所以它又稱做"網絡字節序" 4. 以其餘形式存儲二進制整數的機器,如little endian格式,則必須在傳輸數據以前把首部轉換成網絡字節序
1. 應用層服務器
0x1: NTP網絡協議cookie
NTP有兩種不一樣類型的報文,一種是時鐘同步報文,另外一種是控制報文(用於網絡管理),NTP基於UDP報文進行傳輸,使用的UDP端口號爲123 網絡
1. 時鐘同步報文session
1. LI(Leap Indicator)(2 bits) 1) 值爲"11"時表示告警狀態,時鐘未被同步 2) 爲其餘值時NTP自己不作處理 2. VN(Version Number)(3 bits): 表示NTP的版本號,目前的最新版本爲3 3. Mode(3 bits): 表示NTP的工做模式。不一樣的值所表示的含義分別是: 1) 0: 未定義 2) 1: 主動對等體模式 3) 2: 表示被動對等體模式 4) 3: 表示客戶模式 5) 4: 表示服務器模式 6) 5: 表示廣播模式或組播模式 7) 6: 表示此報文爲NTP控制報文(MODE_CONTROL) 8) 7: 預留給內部使用(MODE_PRIVATE) 4. Stratum(8 bits): 系統時鐘的層數,取值範圍爲1~16,它定義了時鐘的準確度,這也代表了整個NTP的架構是一種層次型的架構 1) 層數爲1的時鐘準確度最高 2) 準確度從1到16依次遞減 3) 層數爲16的時鐘處於未同步狀態,不能做爲參考時鐘 5. Poll(8 bits): 輪詢時間,即兩個連續NTP報文之間的時間間隔 6. Precision(8 bits): 系統時鐘的精度 7. Root Delay(32 bits): 本地到主參考時鐘源的往返時間 8. Root Dispersion(32 bits): 系統時鐘相對於主參考時鐘的最大偏差 9. Reference Identifier(32 bits): 參考時鐘源的標識 10. Reference Timestamp(64 bits): 系統時鐘最後一次被設定或更新的時間 11. Originate Timestamp(64 bits): NTP請求報文離開發送端時發送端的本地時間 12. Receive Timestamp(64 bits): NTP請求報文到達接收端時接收端的本地時間 13. Transmit Timestamp(64 bits): 應答報文離開應答者時應答者的本地時間 14. Authenticator((optional)96 bits): 驗證信息
Relevant Link:架構
http://bjtime.cn/info/view.asp?id=270 http://www.rfc-editor.org/rfc/rfc958.txt http://wenku.baidu.com/view/4a7e73c308a1284ac85043a8.html http://wiki.wireshark.org/SampleCaptures http://qgjie456.blog.163.com/blog/static/354513672010821241599/ http://www.cnblogs.com/TianFang/archive/2011/12/20/2294603.html
2. 控制報文
控制報文和時鐘同步報文的區別僅僅在於"Mode"字段的區別,
1. 常規NTP時間同步報文 模式1~5 2. NTP控制報文 模式6,由ntpq使用 3. NTP mode 7 (MODE_PRIVATE) 由ntpdc查詢和控制工具使用
對於控制報文來講,"Mode"字段的值爲6
Relevant Link:
http://wiki.wireshark.org/NTP http://wiki.wireshark.org/SampleCaptures
0x2: DNS
1. DNS可使用UDP和TCP;DNS協議要求客戶端先使用UDP進行查詢,若響應數據超過512字節,則可再次使用TCP進行查詢獲得完整響應(我曾嘗試首次就用TCP查詢,結果是部分服務器不響應TCP三次握手,部分創建TCP鏈接成功但不響應DNS查詢) 2. DNS服務器使用的端口號爲53 3. 雖然DNS協議支持一次查詢多個域名,但大部分的DNS服務器的實現都不支持querycout > 1的狀況,會返回Format error錯誤;想要一次查詢多個,須要使用DNS擴展協議EDNS 4. DNS有兩種類型的報文,分別是查詢報文和響應報文,查詢報文和響應報文都包含相同的首部
1. 首部
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
各字段意義以下
1. 標識(16位): 客戶端每次查詢使用不一樣的標誌號。服務端在響應中重複這個標識號 2. 標誌(16位): 意義以下 3. QR(1位): 1) 0表示查詢報文 2) 1表示響應報文 4. OpenCode(4位): 定義查詢或響應的類型 1) 0: 標準 2) 1: 反向,即經過ip地址查詢域名相關信息 3) 2: 服務器狀態請求 5. AA(1位): 當值爲1時,表示名字服務器是權限服務器 6. TC(1位): 當值爲1時,表示響應已超過512字節並已截斷爲512字節 7. RD(1位): 當值爲1時,表示客戶端但願獲得遞歸回答。響應報文中重複這個值 8. RA(1位): 當值爲1時,表示可獲得遞歸響應。只能在響應報文中置位(值爲1) 9. 保留(3位): 保留字段,所有爲0 10. rCode(4位): 表示在響應中的差錯狀態。只有權限服務器才能作出這個判斷 1) 0: 無差錯 2) 1: 格式差錯 3) 2: 問題在域名服務器上 4) 3: 域參照問題 5) 4: 查詢類型不支持 6) 5: 在管理上被禁止 7) 6~15: 保留 11. 問題記錄數(16位): 問題部分的查詢記錄數 12. 回答記錄數(16位): 回答記錄數,在查詢報文中值爲0 13. 受權記錄數(16位): 回答記錄數,在查詢報文中值爲0 14. 附加記錄數(16位): 回答記錄數,在查詢報文中值爲0
2. 問題記錄格式
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / QNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
各字段意義以下
1. 查詢名字: 域名的可變長字段;其中計數字段指明每一節中的字符數。 2. 查詢類型(16位) 1) A = 1: 32位的IPv6地址 2) NS = 2: 名字服務器 3) CNAME = 5: 規範名稱 4) SOA = 6: 受權開始 5) WKS = 11: 熟知服務 6) PTR = 12: 指針 7) HINFO = 13: 主機信息 8) MX = 15: 郵件交換 9) AAAA = 28: IPv6地址 10) AXFR = 252: 請求傳送完整區文件 11) ANY = 255: 請求全部記錄 3. 查詢類別(16位): 定義使用DNS的特定協議 1) AN = 1: 由於特 2) CSNET = 2: CSNET網絡 3) CS = 3: COAS網絡 4) HS = 4: 由MIT開發的Hesoid服務器
3. 資源記錄格式
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
各字段意義以下
1. 域名(16位): 因爲響應包含查詢中完整的問題部分,爲不重複記錄域名;這裏使用問題記錄中域名的偏移量表示 2. 域類型(16位)與問題記錄的查詢類型字段相同 3. 域類別(16位): 與問題記錄的查詢類別字段相同 4. 生存時間(32位): 在該時間內,接收方能夠將次回答保存在告訴緩存中,單位爲秒 5. 資源數據長度(16位) 6. 資源數據(可變長): 值內容取決於類型字段的值,能夠是 1) 數值 2) 域名 3) 偏移指針 4) 字符串
Relevant Link:
http://my.oschina.net/simplefocus/blog/215310 https://technet.microsoft.com/zh-cn/library/dd197470(v=ws.10).aspx https://en.wikipedia.org/wiki/Domain_Name_System https://www.ietf.org/rfc/rfc1035.txt
0x3: UTP(uTorrent Transport Protocol)
BitTorrent協議支持基於TCP或UTP網絡協議進行數據傳輸,可是因爲TCP協議是有鏈接的,須要先進行握手。在進行數據傳輸的過程當中,每一個種子會佔有大量的TCP鏈接(沒對peer-to-peer都要佔用一對TCP鏈接),從而佔有大量的用戶帶寬。這給其餘須要高實時性的應用形成很大的網絡壓力。因而BitTorrent又支持UTP協議用來進行數據傳輸,這也是當前大部分BT下載客戶端所採用的實現方式。UTP(uTorrent Transport Protocol)是基於UDP網絡協議的,也就是無鏈接協議,採用這種協議進行數據交換,能夠很容易進行帶寬控制,不會形成網絡擁堵
0 4 8 16 24 32 +-------+-------+---------------+---------------+---------------+ | type | ver | extension | connection_id | +-------+-------+---------------+---------------+---------------+ | timestamp_microseconds | +---------------+---------------+---------------+---------------+ | timestamp_difference_microseconds | +---------------+---------------+---------------+---------------+ | wnd_size | +---------------+---------------+---------------+---------------+ | seq_nr | ack_nr | +---------------+---------------+---------------+---------------+
1. type: 數據包類型 1) 0--帶負載數據包,就是一般在鏈接創建後,上傳數據或下載數據的包 2) 1--鏈接結束數據包,結束一個鏈接 3) 2--數據迴應包,當一個peer收到一個帶負載數據包後,會回一個ACK包,來表示這個包已正確接收,有點相似於TCP的SYN的感受,可是這個是在UDP包的數據段作鏈接控制(基於UDP實現的僞ACK機制) 4) 3--重置鏈接 5) 4--開始一個鏈接 2. ver: 協議版本,一般爲1 3. extension: 擴展段,用於支持BEPs 4. connection_id: 鏈接id,同一個鏈接id的數據包屬於一個鏈接,通常每兩個peer之間會開兩個鏈接,一個用於發,一個用於收 5. timestamp_microseconds: 包的發送時間 6. timestamp_difference_microseconds: 對於當前鏈接,最近收到的包時間和當前要發送的包之間的時間間隔 7. wnd_size: 發送方當前剩餘窗口大小,用於進行速度和帶寬控制。BitTorrent協議中每個發出去的數據包,都要求接收方回一個ACK包。而一個peer的窗口大小是指當前發送出去,但尚未收到迴應的包的總大小,單位爲字節。每個peer都一個最大窗口值和一個窗口大小上限值。當wnd_size小於最小UTP包大小的時候,發送方會中止發送數據包,或調整每一個數據包的數據負載大小 8. seq_nr: 相對於一個鏈接,數據包的序列號,以一個包爲計數單位 9. ack_nr: 發送方最近接收到的包的序列號
Relevant Link:
http://www.bittorrent.org/beps/bep_0029.html
0x4: SSDP(Simple Service Discovery Protocol)
SSDP 簡單服務發現協議,是應用層協議,是構成UPnP(通用即插即用)技術的核心協議之一。它爲網絡客戶端(network client)提供了一種發現網絡服務(network services)的機制,採用基於通知和發現路由的多播方式實現
簡單服務發現協議提供了在局部網絡裏面發現設備的機制。控制點(也就是接受服務的客戶端)能夠經過使用簡單服務發現協議,根據本身的須要查詢在本身所在的局部網絡裏面提供特定服務的設備。設備(也就是提供服務的服務器端)也能夠經過使用簡單服務發現協議,向本身所在的局部網絡裏面的控制點聲明它的存在
1. 實現
簡單服務發現協議是在HTTPU和HTTPMU的基礎上實現的協議
1. 按照協議的規定,當一個控制點(客戶端)接入網絡的時候,它能夠向一個特定的多播地址的SSDP端口使用M-SEARCH方法發送"ssdp:discover"消息。當設備監聽到這個保留的多播地址上由控制點發送的消息的時候,設備會分析控制點請求的服務,若是自身提供了控制點請求的服務,設備將經過單播的方式直接響應控制點的請求 2. 相似的,當一個設備接入網絡的時候,它應當向一個特定的多播地址的SSDP端口使用NOTIFY方法發送"ssdp:alive"消息。控制點根據本身的策略,處理監聽到的消息。考慮到設備可能在沒有通知的狀況下中止服務或者從網絡上卸載,"ssdp:alive"消息必須在HTTP協議頭CACHE-CONTROL裏面指定超時值,設備必須在約定的超時值到達之前重發"ssdp:alive"消息。若是控制點在指定的超時值內沒有再次收到設備發送的"ssdp:alive"消息,控制點將認爲設備已經失效 3. 當一個設備計劃從網絡上卸載的時候,它也應當向一個特定的多播地址的SSDP端口使用NOTIFY方法發送"ssdp:byebye"消息。可是,即便沒有發送"ssdp:byebye"消息,控制點也會根據"ssdp:alive"消息指定的超時值,將超時而且沒有再次收到的"ssdp:alive"消息對應的設備認爲是失效的設備 4. 在IPv4環境,當須要使用多播方式傳送相關消息的時候,SSDP通常使用多播地址239.255.255.250和UDP端口號1900。根據互聯網地址指派機構的指派,SSDP在IPv6環境下使用多播地址FF0x::C,這裏的X根據scope的不一樣能夠有不一樣的取值
2. 協議內容解析
SSDP消息分爲設備查詢消息、設備通知消息兩種,一般狀況下,使用更多地是設備查詢消息
設備查詢消息
M-SEARCH * HTTP/1.1 HOST: 239.255.255.250:1900 MAN: "ssdp:discover" MX: 5 ST: ssdp:all 1. 其中第一行是消息頭,固定 2. HOST對應的是廣播地址和端口,239.255.255.250是默認SSDP廣播ip地址,1900是默認的SSDP端口 3. MAN後面的ssdp:discover爲固定 4. MX爲最長等待時間 5. ST: 查詢目標,它的值能夠是 1) upnp:rootdevice 僅搜索網絡中的根設備 2) uuid:device-UUID 查詢UUID標識的設備 3) urn:schemas-upnp-org:device:device-Type:version 查詢device-Type字段指定的設備類型,設備類型和版本由UPNP組織定義 4) ssdp:all
響應消息
在設備接收到查詢請求而且查詢類型(ST字段值)與此設備匹配時,設備必須向多播地址239.255.255.250:1900迴應響應消息。通常形如
HTTP/1.1 200 OK / NOTIFY * HTTP/1.1(設備通知的HTTP頭) CACHE-CONTROL: max-age = seconds until advertisement expires DATE: when reponse was generated EXT: LOCATION: URL for UPnP description for root device SERVER: OS/Version UPNP/1.0 product/version ST: search target //不經常使用的設備通知HTTP回包增長了下列的字段 NT 在此消息中,NT頭必須爲服務的服務類型。 NTS 表示通知消息的子類型,必須爲ssdp:alive或者ssdp:byebye USN 表示不一樣服務的統一服務名,它提供了一種標識出相同類型服務的能力
Relevant Link:
http://blog.csdn.net/lilypp/article/details/6631951
http://baike.baidu.com/link?url=GsvncL_i_vpV3cRwwYFBju3MgD6sVgDcFx-XqmyybypBXYMTeV5ExjnxoIS0YNWS5ervCdHOtoqqJWwzsL5H2q
http://www.tuicool.com/articles/nUjmMf
3. 傳輸層
0x1: ICMP Internet控制報文協議
儘管對於ICMP協議屬於網絡層仍是傳輸層有不少爭議,可是從學習協議的嚴謹性上來講,ICMP應該算是傳輸層協議,由於ICMP數據報須要被包裝在IP數據報的數據部分進行發送,因此ICMP也應該算是IP協議的一個上層協議。
ICMP屬於傳輸層協議。ICMP 的正式規範參見RFC 792 [Posterl 1981b]
和其餘大多數協議同樣,ICMP有不少種數據報類型,它們的協議格式也不盡相同,咱們按照類型的大分類來逐一學習
在ICMP數據報中,頭部的類型(8bit)、和代碼(8bit)字段決定了這個ICMP數據報的準確類型。類型和代碼各佔8bit,先決定類型,而後看代碼,它們共同決定了這個ICMP數據報的類型
Destination Unreachable Message(目的不可達)
1. 類型 類型碼爲3 2. 代碼 1) 0: 網絡不可達 2) 1: 主機不可達 3) 2: 協議不可達 4) 3: 端口不可達 5) 4: 須要進行分片但設置了不分片bit 6) 5: 源站路由失敗 7) 6: 目的網絡不認識 8) 7: 目的主機不認識 9) 8: 源主機被隔離(做廢不用) 10) 9: 目的網絡被強制禁止 11) 10: 目的主機被強制禁止 12) 11: 因爲服務類型TOS,網絡不可達 13) 12: 因爲服務類型TOS,主機不可達 14) 13: 因爲過濾,通訊被強制禁止 15) 14: 主機越權 16) 15: 優先權停止生效 3. 校驗和 4. 4字節的unused字段,置零 5. 原始IP數據報的頭部+64bit的數據部分
當發送一份ICMP差錯報文時,報文始終包含IP的首部和產生ICMP差錯報文的IP數據報的前8個字節(64bit)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協議(根據IP數據報首部中的
協議字段來判斷)和用戶進程(根據包含在IP數據報前8個字節中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯繫起來
Time Exceeded Message(超時)
1. 類型 類型碼爲11 2. 代碼 1) 0: 傳輸期間生存期爲0 2) 1: 在數據報組裝期間生存期爲0 3. 校驗和 4. 4字節的unused字段,置零 5. 原始IP數據報的頭部+64bit的數據部分 當發送一份ICMP差錯報文時,報文始終包含IP的首部和產生ICMP差錯報文的IP數據報的前8個字節(64bit)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協議(根據IP數據報首部中的
協議字段來判斷)和用戶進程(根據包含在IP數據報前8個字節中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯繫起來
Parameter Problem Message(參數錯誤)
1. 類型 類型碼爲12 2. 代碼 1) 0: 錯誤信息的指針 3. 校驗和 4. 4字節的unused字段,置零 5. 原始IP數據報的頭部+64bit的數據部分 當發送一份ICMP差錯報文時,報文始終包含IP的首部和產生ICMP差錯報文的IP數據報的前8個字節(64bit)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協議(根據IP數據報首部中的
協議字段來判斷)和用戶進程(根據包含在IP數據報前8個字節中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯繫起來
Source Quench Message(源站被抑制)
1. 類型 類型碼爲4 2. 代碼 1) 0: 源站被抑制 3. 校驗和 4. 4字節的unused字段,置零 5. 原始IP數據報的頭部+64bit的數據部分 當發送一份ICMP差錯報文時,報文始終包含IP的首部和產生ICMP差錯報文的IP數據報的前8個字節(64bit)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協議(根據IP數據報首部中的
協議字段來判斷)和用戶進程(根據包含在IP數據報前8個字節中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯繫起來
Redirect Message(重定向)
1. 類型 類型碼爲5 2. 代碼 1) 0: 對網絡重定向 2) 1: 對主機重定向 3) 2: 對服務類型和網絡重定向 4) 3: 對服務類型和主機重定向 3. 校驗和 4. Gateway Internet Address 指明重定向後的IP地址 5. 原始IP數據報的頭部+64bit的數據部分 當發送一份ICMP差錯報文時,報文始終包含IP的首部和產生ICMP差錯報文的IP數據報的前8個字節(64bit)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協議(根據IP數據報首部中的
協議字段來判斷)和用戶進程(根據包含在IP數據報前8個字節中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯繫起來
對於ICMP Redirect重定向數據報,咱們須要注意的,攻擊者能夠針對指定主機或者路由器發送ICMP Redirect數據報,來強制更新目標主機或路由器的"網關設置",從而劫持目標主機的原始流量。
http://insecure.org/sploits/arp.games.html
Echo or Echo Reply Message(ping)
1. 類型 1) 0: 回顯應答 2) 8: 回顯請求 2. 代碼 0 3. 校驗和 5. Identifier、Sequence Number 發送方用它們對每次的echo和reply進行匹配 6. 數據
Timestamp or Timestamp Reply Message(ICMP時間戳請求與應答)
ICMP時間戳請求容許系統向另外一個系統查詢當前的時間。返回的建議值是自午夜開始計算的毫秒數,協調的統一時間(Coordinated Universal Time, UTC)
1. 類型 1) 13: 發送時間戳 2) 14: 返回時間戳 2. 代碼 0 3. 校驗和 5. Identifier、Sequence Number 發送方用它們對每次的echo和reply進行匹配 6. Originate Timestamp 請求端填寫發起時間戳,而後發送報文 7. Receive Timestamp 應答系統收到請求報文時填寫接收時間戳 8. Transmit Timestamp 在 發送應答時填寫發送時間戳
0x2: TCP(Transmission Control Protocol)
1. TCP用於從應用程序到網絡的數據傳輸控制 2. TCP負責在數據傳送以前將它們分割爲IP包(面向應用層提供65535bytes的載荷空間,可是受限於下層網絡層IP協議的限制,須要根據MTU進行分包),而後在它們到達的時候將它們重組 3. TCP是面向鏈接的通訊協議,經過三次握手創建鏈接,通信完成時要拆除鏈接,因爲TCP是面向鏈接的因此只能用於端到端的通信 4. TCP提供的是一種可靠的數據流服務,採用"帶重傳的確定確認"技術來實現傳輸的可靠性。TCP還採用一種稱爲"滑動窗口"的方式進行流量控制,所謂窗口實際表示接收能力,用以限制發送方的發送速度 5. 若是IP數據包中有已經封好的TCP數據包,那麼IP將把它們向"上"傳送到TCP層。TCP將包排序並進行錯誤檢查,同時實現虛電路間的鏈接。TCP數據包中包括序號和確認,因此未按照順序收到的包能夠被排序,而損壞的包能夠被重傳 6. TCP將它的信息送到更高層的應用程序,例如Telnet的服務程序和客戶程序。應用程序輪流將信息送回TCP層,TCP層便將它們向下傳送到IP層,設備驅動程序和物理介質,最後到接收方 7. 面向鏈接的服務(例如Telnet、FTP、rlogin、X Windows和SMTP)須要高度的可靠性,因此它們使用了TCP。DNS在某些狀況下使用TCP(發送和接收域名數據庫),但使用UDP傳送有關單個主機的信息
1. TCP segment structure
Transmission Control Protocol accepts data from a data stream, divides it into chunks(根據MTU), and adds a TCP header creating a TCP segment. The TCP segment is then encapsulated into an Internet Protocol (IP) datagram, and exchanged with peers.
Processes transmit data by calling on the TCP and passing buffers of data as arguments. The TCP packages the data from these buffers into segments and calls on the internet module(例如IP) to transmit each segment to the destination TCP
A TCP segment consists of a segment header and a data section. The TCP header contains 10 mandatory fields, and an optional extension field (Options, pink background in table).
The data section follows the header. Its contents are the payload data carried for the application. The length of the data section is not specified in the TCP segment header. It can be calculated by subtracting the combined length of the TCP header and the encapsulating IP header from the total IP datagram length (specified in the IP header).
Offsets | Octet | 0 | 1 | 2 | 3 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Octet | Bit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
0 | 0 | Source port | Destination port | ||||||||||||||||||||||||||||||
4 | 32 | Sequence number | |||||||||||||||||||||||||||||||
8 | 64 | Acknowledgment number (if ACK set) | |||||||||||||||||||||||||||||||
12 | 96 | Data offset | Reserved 0 0 0 |
N S |
C W R |
E C E |
U R G |
A C K |
P S H |
R S T |
S Y N |
F I N |
Window Size | ||||||||||||||||||||
16 | 128 | Checksum | Urgent pointer (if URG set) | ||||||||||||||||||||||||||||||
20 ... |
160 ... |
Options (if data offset > 5. Padded at the end with "0" bytes if necessary.) ... |
1. Source port (16 bits): identifies the sending port 2. Destination port (16 bits): identifies the receiving port 3. Sequence number (32 bits): has a dual role: 1) If the SYN flag is set (1), then this is the initial sequence number. The sequence number of the actual first data byte and the acknowledged number in the corresponding ACK are then this sequence number plus 1. 2) If the SYN flag is clear (0), then this is the accumulated sequence number of the first data byte of this segment for the current session. 4. Acknowledgment number (32 bits) if the ACK flag is set then the value of this field is the next sequence number that the receiver is expecting. This acknowledges receipt of all prior bytes (if any). The first ACK sent by each end acknowledges the other end's initial sequence number itself, but no data. 5. Data offset (4 bits) specifies the size of the TCP header in 32-bit words. The minimum size header is 5 words and the maximum is 15 words thus giving the minimum size of 20 bytes and maximum of 60 bytes, allowing for up to 40 bytes of options in the header. This field gets its name from the fact that it is also the offset from the start of the TCP segment to the actual data. 6. Reserved (3 bits): for future use and should be set to zero 7. Flags (9 bits) (aka Control bits): contains 9 1-bit flags 1) NS (1 bit) – ECN-nonce concealment protection (experimental: see RFC 3540). 2) CWR (1 bit) – Congestion Window Reduced (CWR) flag is set by the sending host to indicate that it received a TCP segment with the ECE flag set and had responded in congestion control mechanism (added to header by RFC 3168). 3) ECE (1 bit) – ECN-Echo has a dual role, depending on the value of the SYN flag. It indicates: 3.1) If the SYN flag is set (1), that the TCP peer is ECN capable. 3.2) If the SYN flag is clear (0), that a packet with Congestion Experienced flag set (ECN=11) in IP header received during normal transmission (added to header by RFC 3168). This serves as an indication of network congestion (or impending congestion) to the TCP sender. 4) URG (1 bit) – indicates that the Urgent pointer field is significant 5) ACK (1 bit) – indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set. 6) PSH (1 bit) – Push function. Asks to push the buffered data to the receiving application. 7) RST (1 bit) – Reset the connection 8) SYN (1 bit) – Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear. 9) FIN (1 bit) – No more data from sender 8. Window size (16 bits) the size of the receive window, which specifies the number of window size units (by default, bytes) (beyond the segment identified by the sequence number in the acknowledgment field) that the sender of this segment is currently willing to receive (用於時間窗口流控制) 9. Checksum (16 bits): The 16-bit checksum field is used for error-checking of the header and data 10. Urgent pointer (16 bits): if the URG flag is set, then this 16-bit field is an offset from the sequence number indicating the last urgent data byte 11. Options (Variable 0–320 bits, divisible by 32) 12. Padding: The TCP header padding is used to ensure that the TCP header ends and data begins on a 32 bit boundary. The padding is composed of zeros.
2. Protocol operation
A TCP connection is managed by an operating system through a programming interface that represents the local end-point for communications, the Internet socket. During the lifetime of a TCP connection the local end-point undergoes a series of state changes
1. LISTEN: (server) represents waiting for a connection request from any remote TCP and port. 2. SYN-SENT: (client) represents waiting for a matching connection request after having sent a connection request. 3. SYN-RECEIVED: (server) represents waiting for a confirming connection request acknowledgment after having both received and sent a connection request. 4. ESTABLISHED: (both server and client) represents an open connection, data received can be delivered to the user. The normal state for the data transfer phase of the connection. 1) SYN: The active open is performed by the client sending a SYN to the server. The client sets the segment's sequence number to a random value A. 2) SYN-ACK: In response, the server replies with a SYN-ACK. The acknowledgment number is set to one more than the received sequence number i.e. A+1, and the sequence number that the server chooses for the packet is another random number, B. 3) ACK: Finally, the client sends an ACK back to the server. The sequence number is set to the received acknowledgement value i.e. A+1, and the acknowledgement number is set to one more than the received sequence number i.e. B+1. 5. FIN-WAIT-1: (both server and client) represents waiting for a connection termination request from the remote TCP, or an acknowledgment of the connection termination request previously sent. 6. FIN-WAIT-2: (both server and client) represents waiting for a connection termination request from the remote TCP. 7. CLOSE-WAIT: (both server and client) represents waiting for a connection termination request from the local user. 8. CLOSING: (both server and client) represents waiting for a connection termination request acknowledgment from the remote TCP. 9. LAST-ACK: (both server and client) represents waiting for an acknowledgment of the connection termination request previously sent to the remote TCP (which includes an acknowledgment of its connection termination request). 10. TIME-WAIT: (either server or client) represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request. [According to RFC 793 a connection can stay in TIME-WAIT for a maximum of four minutes known as two MSL (maximum segment lifetime).] 11. CLOSED: (both server and client) represents no connection state at all.
3. 糊塗窗口綜合症
當發送端應用進程產生數據很慢、或接收端應用進程處理接收緩衝區數據很慢,或兩者兼而有之;就會使應用進程間傳送的報文段很小,特別是有效載荷很小。 極端狀況下,有效載荷可能只有1個字節;而傳輸開銷有40字節(20字節的IP頭+20字節的TCP頭) 這種現象就叫糊塗窗口綜合症
1. 發送端求解 若是發送端爲產生數據很慢的應用程序服務(典型的有telnet應用),例如,一次產生一個字節。這個應用程序一次將一個字節的數據寫入發送端的TCP的緩存。若是發送端的TCP沒有特定的指令,它就產生只包括一個字節數據的報文段。結果有不少41字節的IP數據報就在互連網中傳來傳去。解決的方法是防止發送端的TCP逐個字節地發送數據。必須強迫發送端的TCP收集數據,而後用一個更大的數據塊來發送。發送端的TCP要等待多長時間呢?若是它等待過長,它就會使整個的過程產生較長的時延。若是它的等待時間不夠長,它就可能發送較小的報文段,因而,Nagle找到了一個很好的解決方法,發明了Nagle算法。而他選擇的等待時間是一個RTT,即下個ACK來到時 2. 接收端求解 接收端的TCP可能產生糊塗窗口綜合症,若是它爲消耗數據很慢的應用程序服務,例如,一次消耗一個字節。假定發送應用程序產生了1000字節的數據塊,但接收應用程序每次只吸取1字節的數據。再假定接收端的TCP的輸入緩存爲4000字節。發送端先發送第一個4000字節的數據。接收端將它存儲在其緩存中。如今緩存滿了。它通知窗口大小爲零,這表示發送端必須中止發送數據。接收應用程序從接收端的TCP的輸入緩存中讀取第一個字節的數據。在入緩存中如今有了1字節的空間。接收端的TCP宣佈其窗口大小爲1字節,這表示正渴望等待發送數據的發送端的TCP會把這個宣佈看成一個好消息,併發送只包括一個字節數據的報文段。這樣的過程一直繼續下去。一個字節的數據被消耗掉,而後發送只包含一個字節數據的報文段 對於這種糊塗窗口綜合症,即應用程序消耗數據比到達的慢,有兩種建議的解決方法 1) Clark解決方法: Clark解決方法是隻要有數據到達就發送確認,但宣佈的窗口大小爲零,直到或者緩存空間已能放入具備最大長度的報文段,或者緩存空間的一半已經空了。 2) 延遲確認ACK: 這表示當一個報文段到達時並不當即發送確認。接收端在確認收到的報文段以前一直等待,直到入緩存有足夠的空間爲止。延遲的確認防止了發送端的TCP滑動其窗口。當發送端的TCP發送完其數據後,它就停下來了。這樣就防止了這種症狀。遲延的確認還有另外一個優勢:它減小了通訊量。接收端不須要確認每個報文段。但它也有一個缺點,就是遲延的確認有可能迫使發送端重傳其未被確認的報文段。能夠用協議來平衡這個優勢和缺點,例如如今定義了確認的延遲不能超過500毫秒
4. nagle算法
TCP/IP協議中,不管發送多少數據,老是要在數據前面加上協議頭,同時,對方接收到數據,也須要發送ACK表示確認。爲了儘量的利用網絡帶寬,TCP老是但願儘量的發送足夠大的數據。(一個鏈接會設置MSS參數,所以,TCP/IP但願每次都可以以MSS尺寸的數據塊來發送數據)。Nagle算法就是爲了儘量發送大塊數據,避免網絡中充斥着許多小數據塊
Nagle算法的基本定義是任意時刻,最多隻能有一個未被確認的小段。 所謂"小段",指的是小於MSS尺寸的數據塊,所謂"未被確認",是指一個數據塊發送出去後,沒有收到對方發送的ACK確認該數據已收到
/source/net/ipv4/tcp_output.c
1. It is full sized. (provided by caller in %partial bool): 若是包長度達到MSS,則容許發送 2. Or it contains FIN. (already checked by caller): 若是該包含有FIN,則容許發送 3. Or TCP_CORK is not set, and TCP_NODELAY is set: 設置了TCP_NODELAY選項(意在禁止nagle),則容許發送 4. Or TCP_CORK is not set, and all sent packets are ACKed: 未設置TCP_CORK選項時,若全部發出去的小數據包(包長度小於MSS)均被確認,則容許發送 5. 上述條件都未知足,但發生了超時(通常設置延遲ACK,通常爲200ms),則當即發送
Nagle算法只容許一個未被ACK的包存在於網絡,它並無論包的大小,所以它事實上就是一個擴展的停-等協議,只不過它是基於包停-等的,而不是基於字節停-等的。Nagle算法徹底由TCP協議的ACK機制決定,這會帶來一些問題,好比若是對端ACK回覆很快的話,Nagle事實上不會拼接太多的數據包,雖然避免了網絡擁塞,網絡整體的利用率依然很低。另外,他是一個自適應的方法
Nagle算法是silly window syndrome(SWS)預防算法的一個半集,預防SWS不止nagle算法一個途徑。SWS算法預防發送少許的數據,Nagle算法是其在發送方的實現,而接收方要作的時不要通告緩衝空間的很小增加,不通知小窗口,除非緩衝區空間有顯著的增加。這裏顯著的增加定義爲徹底大小的段(MSS)或增加到大於最大窗口的一半
5. TCP握手交互Flag狀態機
在Linux的協議棧實現中,tcp_rcv_state_process函數負責處理了TCP鏈接/釋放的狀態機
/net/ipv4/tcp_input.c
int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, unsigned int len) { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); int queued = 0; tp->rx_opt.saw_tstamp = 0; switch (sk->sk_state) { case TCP_CLOSE: goto discard; case TCP_LISTEN: if (th->ack) return 1; if (th->rst) goto discard; if (th->syn) { if (th->fin) goto discard; if (icsk->icsk_af_ops->conn_request(sk, skb) < 0) return 1; /* Now we have several options: In theory there is * nothing else in the frame. KA9Q has an option to * send data with the syn, BSD accepts data with the * syn up to the [to be] advertised window and * Solaris 2.1 gives you a protocol error. For now * we just ignore it, that fits the spec precisely * and avoids incompatibilities. It would be nice in * future to drop through and process the data. * * Now that TTCP is starting to be used we ought to * queue this data. * But, this leaves one open to an easy denial of * service attack, and SYN cookies can't defend * against this problem. So, we drop the data * in the interest of security over speed unless * it's still in use. */ kfree_skb(skb); return 0; } goto discard; case TCP_SYN_SENT: queued = tcp_rcv_synsent_state_process(sk, skb, th, len); if (queued >= 0) return queued; /* Do step6 onward by hand. */ tcp_urg(sk, skb, th); __kfree_skb(skb); tcp_data_snd_check(sk); return 0; } if (!tcp_validate_incoming(sk, skb, th, 0)) return 0; /* step 5: check the ACK field */ if (th->ack) { int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) > 0; switch (sk->sk_state) { case TCP_SYN_RECV: if (acceptable) { tp->copied_seq = tp->rcv_nxt; smp_mb(); tcp_set_state(sk, TCP_ESTABLISHED); sk->sk_state_change(sk); /* Note, that this wakeup is only for marginal * crossed SYN case. Passively open sockets * are not waked up, because sk->sk_sleep == * NULL and sk->sk_socket == NULL. */ if (sk->sk_socket) sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); tp->snd_una = TCP_SKB_CB(skb)->ack_seq; tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); if (tp->rx_opt.tstamp_ok) tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; /* Make sure socket is routed, for * correct metrics. */ icsk->icsk_af_ops->rebuild_header(sk); tcp_init_metrics(sk); tcp_init_congestion_control(sk); /* Prevent spurious tcp_cwnd_restart() on * first data packet. */ tp->lsndtime = tcp_time_stamp; tcp_mtup_init(sk); tcp_initialize_rcv_mss(sk); tcp_init_buffer_space(sk); tcp_fast_path_on(tp); } else { return 1; } break; case TCP_FIN_WAIT1: if (tp->snd_una == tp->write_seq) { tcp_set_state(sk, TCP_FIN_WAIT2); sk->sk_shutdown |= SEND_SHUTDOWN; dst_confirm(__sk_dst_get(sk)); if (!sock_flag(sk, SOCK_DEAD)) /* Wake up lingering close() */ sk->sk_state_change(sk); else { int tmo; if (tp->linger2 < 0 || (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { tcp_done(sk); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); return 1; } tmo = tcp_fin_time(sk); if (tmo > TCP_TIMEWAIT_LEN) { inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); } else if (th->fin || sock_owned_by_user(sk)) { /* Bad case. We could lose such FIN otherwise. * It is not a big problem, but it looks confusing * and not so rare event. We still can lose it now, * if it spins in bh_lock_sock(), but it is really * marginal case. */ inet_csk_reset_keepalive_timer(sk, tmo); } else { tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto discard; } } } break; case TCP_CLOSING: if (tp->snd_una == tp->write_seq) { tcp_time_wait(sk, TCP_TIME_WAIT, 0); goto discard; } break; case TCP_LAST_ACK: if (tp->snd_una == tp->write_seq) { tcp_update_metrics(sk); tcp_done(sk); goto discard; } break; } } else goto discard; /* step 6: check the URG bit */ tcp_urg(sk, skb, th); /* step 7: process the segment text */ switch (sk->sk_state) { case TCP_CLOSE_WAIT: case TCP_CLOSING: case TCP_LAST_ACK: if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) break; case TCP_FIN_WAIT1: case TCP_FIN_WAIT2: /* RFC 793 says to queue data in these states, * RFC 1122 says we MUST send a reset. * BSD 4.4 also does reset. */ if (sk->sk_shutdown & RCV_SHUTDOWN) { if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); tcp_reset(sk); return 1; } } /* Fall through */ case TCP_ESTABLISHED: tcp_data_queue(sk, skb); queued = 1; break; } /* tcp_data could move socket to TIME-WAIT */ if (sk->sk_state != TCP_CLOSE) { tcp_data_snd_check(sk); tcp_ack_snd_check(sk); } if (!queued) { discard: __kfree_skb(skb); } return 0; } EXPORT_SYMBOL(tcp_rcv_state_process);
序列號和確認號
TCP會話的每一端都包含一個32位(bit)的序列號,該序列號被用來跟蹤該端發送的數據量。每個包中都包含序列號,在接收端則經過確認號用來通知發送端數據成功接收
包1: TCP會話的每一端的序列號(seqnumber)都從0開始,一樣的,確認號也從0開始(初始的本端不須要向誰確認),由於此時通話還未開始,沒有通話的另外一端須要確認 包2: 服務端響應客戶端的請求,響應中附帶序列號0(因爲這是服務端在該次TCP會話中發送的第一個包,因此序列號爲0,seqnumber = 0)和相對確認號1(代表服務端收到了客戶端發送的包1中的SYN)(acknumber = 1) //須要注意的是,儘管客戶端沒有發送任何有效數據,確認號仍是被加1,這是由於接收的包中包含SYN或FIN標誌位(並不會對有效數據的計數產生影響,由於含有SYN或FIN標誌位的包並不攜帶有效數據) 包3: 和包2中同樣,客戶端使用確認號1(seqnumber = 1)響應服務端的序列號0,同時響應中也包含了客戶端本身的序列號(因爲服務端發送的包中確認收到了客戶端發送的SYN,故客戶端的序列號由0變爲1) //此時,通訊的兩端的序列號都爲1,通訊兩端的序列號增1發生在全部TCP會話的創建過程當中 包4: 這是流中第一個攜帶有效數據的包(確切的說,是客戶端發送的HTTP請求),序列號依然爲1,由於到上個包爲止,尚未發送任何數據,確認號也保持1不變,由於客戶端沒有從服務端接收到任何數據 //須要注意的是,包中有效數據的長度爲725字節
0x6: 各個Flag觸發條件
RST
RST: (Reset the connection)用於復位因某種緣由引發出現的錯誤鏈接,也用來拒絕非法數據和請求。若是接收到RST位時候,一般發生了某些錯誤
1. 發送RST包關閉鏈接時,沒必要等緩衝區的包都發出去,直接就丟棄緩衝區中的包,發送RST 2. 而接收端收到RST包後,也沒必要發送ACK包來確認
系統會在如下幾個條件下發送RST包
1. 創建鏈接的SYN到達某端口,可是該端口上沒有正在監聽的服務 例如主機A向主機B發送一個SYN請求,表示想要鏈接主機B的40000端口,可是主機B上根本沒有打開40000這個端口,因而就向主機A發送了一個RST。這種狀況很常見。特別是服務器程序core dump以後重啓以前連續出現RST的狀況會常常發生 若是雲上ECS向某地區進行大量端口掃描,則該地區(例如武漢)可能會發送大量的RST包返回給雲ECS 2. TCP收到了一個根本不存在的鏈接上的分節 咱們知道,TCP在數據傳輸前,要經過三路握手(three-way handshake)創建鏈接,即鏈接創建起後,服務器和客戶端都有一個關於此鏈接的描述,具體形式表現爲套接口對,若是收到的某TCP分節,根據源 IP,源tcp port number,及目的IP,目的tcp port number在本地(指服務器或客戶端)找不到相應的套接口對,TCP則認爲在一個不存在的鏈接上收到了分節,說明此鏈接已錯,要求從新創建鏈接,因而發出了RST的TCP包 3. 請求超時。使用setsockopt的SO_RCVTIMEO選項設置recv的超時時間。接收數據超時時,會發送RST包 4. 提早關閉 5. 在一個已關閉的socket上收到數據: 客戶端在服務端已經關閉掉socket以後,仍然在發送數據。這時服務端會產生RST 1. 使用shutdown、close關閉套接字,發送的是FIN,不是RST 2. 套接字關閉前,使用sleep。對運行的程序Ctrl+C,會發送FIN,不是RST 3. 套接字關閉前,執行return、exit(0)、exit(1),會發送FIN、不是RST
其中,ACK是可能與SYN,FIN等同時使用的
1. 好比SYN和ACK可能同時爲1,它表示的就是創建鏈接以後的響應 2. 若是隻是單個的一個SYN,它表示的只是創建鏈接。TCP的幾回握手就是經過這樣的ACK表現出來的 3. 但SYN與FIN是不會同時爲1的,由於前者表示的是創建鏈接,然後者表示的是斷開鏈接 4. RST通常是在FIN以後纔會出現爲1的狀況,表示的是鏈接重置 5. 通常地 1) 當出現FIN包或RST包時,咱們便認爲客戶端與服務器端斷開了鏈接 2) 而當出現SYN和SYN + ACK包時,咱們認爲客戶端與服務器創建了一個鏈接 6. PSH爲1的狀況,通常只出如今DATA內容不爲0的包中,也就是說PSH爲1表示的是有真正的TCP數據包內容被傳遞
Relevant Link:
http://baike.baidu.com/view/7649.htm?fromtitle=tcp%2Fip&fromid=214077&type=syn http://www.w3school.com.cn/tcpip/tcpip_protocols.asp https://en.wikipedia.org/wiki/Transmission_Control_Protocol https://tools.ietf.org/html/rfc793 http://www.cnblogs.com/zhaoyl/archive/2012/09/20/2695799.html
http://www.oschina.net/question/234345_47411
http://www.mianfeiwendang.com/doc/0545169db5932b91fd62609b/2
http://blog.csdn.net/wudiyi815/article/details/8505726
http://blog.csdn.net/guowenyan001/article/details/11766929
http://baike.baidu.com/view/1044719.htm
http://my.oschina.net/costaxu/blog/127394
4. 網絡層
本章節介紹網絡層的各類協議、以及格式規範。
(這裏給一張網絡層整體架構圖,儘可能包含完整的網絡層協議)
0x1: IP 網際協議
IP是TCP/IP協議族中最爲核心的協議。RFC 791[Postel 1981a]是IP的正式規範文件: http://www.rfc-editor.org/rfc/rfc791.txt
1. 版本(4bit) 1) 版本號4: IPv4 2) 版本號6: IPv6 2. 首部長度(4bit) 首部佔32bit(4字節)字的數目(因此首部長度爲這個字段值*4),包括任何選項。普通IP數據報(沒有任何選擇項)字段的值是5(20字節) 3. 服務類型(TOS)(8bit) 1) 優先權子字段(3bit): 如今已被忽略 2) TOS子字段(4bit) 2.1) Bit 0: 最小時延 2.2) Bit 1: 最大吞吐量 2.3) Bit 2: 最高可靠性 2.4) Bit 3: 最小費用 3) 未用置0字段(1bit) 在單個IP數據報中,TOS子字段4bit中只能置其中1 bit。若是全部4bit均爲0,那麼就意味着是通常服務。RFC 1340、RFC 1349詳細地描述了TOS的特性: 1) Domain Name Service 1.1) UDP Query: 1000: 最小時延 1.2) TCP Query: 0000: 通常服務 1.3) Zone Transfer: 0100: 最大吞吐量 2) NNTP: 0001: 最小費用 3) ICMP 3.1) Errors: 0000: 通常服務 3.2) Requests: 0000: 通常服務 3.3) Responses: 0000: 通常服務 4) Any IGP: 0010: 最高可靠性 5) EGP: 0000: 通常服務 6) TELNET: 1000: 最小時延 Telnet要求最小的傳輸時延,由於人們主要用它們來傳輸少許的交互數據 7) FTP 7.1) Control: 1000: 最小時延 7.2) Data: 0100: 最大吞吐量 FTP文件傳輸則要求有最大的吞吐量 8) TFTP: 0100: 最大吞吐量 9) SMTP 9.1) Command phase: 1000: 最小時延 9.2) DATA phase: 0100: 最大吞吐量 10) BOOTP: 0000: 通常服務 對於IP數據報中的TOS字段,咱們須要明白的是: 如今大多數的TCP/IP實現都不支持TOS特性,可是在不少Unix系統上對它提供了設置。另外,路由協議如OSPF和IS-IS都能根據這些字段的值進
行路由決策。因此,研究TOS仍是頗有現實意義的 4. 總長度(16bit) 總長度字段是指整個IP數據報的長度(以字節爲單位)。利用總長度字段-首部長度字段,就能夠知道IP數據報中數據內容的起始位置和長度。因爲該字段長16比特,因此IP數據報最長可達65535
字節。當數據報被分片時,該字段的值也隨着變化(關於數據報分片,咱們以後會詳細學習) 總長度字段是IP首部中必要的內容,由於一些數據鏈路(如以太網)須要填充一些數據以達到最小長度。儘管以太網的最小幀長爲46字節,可是I P數據可能會更短(IP的頭部只有20字節,數據部
分能夠爲0)。若是沒有總長度字段,那麼IP層就不知道46字節中有多少是IP數據報的內容,有多少是padding的內容 5. 標識(16bit) 標識字段惟一地標識主機發送的每一份數據報。一般每發送一份報文它的值就會加1。在分片和重組時會使用到 6. 標誌(3bit) 1) Bit 0: 保留,必須置爲0 2) Bit 1: 2.1) 0: 能夠分組 2.2) 1: 不能夠分組 3) Bit 2: 3.1) 0: 已是最後一個分組了 3.2) 1: 還有更多分組 7. 片偏移(13bit) 當前分片在完整數據報中的偏移 8. 生存時間TTL(8bit) TTL(time-to-live)生存時間字段設置了數據報能夠通過的最多路由器數。它指定了數據報的生存時間。TTL的初始值由源主機設置(一般爲32或64),一旦通過一個處理它的路由器,它的值就
減去1。當該字段的值爲0時,數據報就被丟棄,併發送ICMP報文通知源主機。 9. 協議(8bit) 該IP數據包攜帶的的上層協議,這個字段的做用爲了實現"分用",所謂分用,即當目的主機收到一個以太網數據幀時,數據就開始從協議棧中由底向上升,同時去掉各層協議加上的報文首部。每
層協議盒都要去檢查報文首部中的協議標識,以肯定接收數據的上層協議。這個過程稱做分用(Demultiplexing) 10. 首部檢驗和(16bit) 首部檢驗和字段是根據"IP首部"計算的檢驗和碼(注意,只是首部),它不對首部後面的數據進行計算。 爲了計算一份數據報的IP檢驗和,首先把檢驗和字段置爲0。而後,對首部中每一個16bit進行二進制反碼求和(整個首部當作是由一串16bit的字組成),結果存在檢驗和字段中。當收到一份IP數
據報後,一樣對首部中每一個16bit進行二進制反碼的求和。因爲接收方在計算過程當中包含了發送方存在首部中的檢驗和,所以,若是首部在傳輸過程當中沒有發生任何差錯,那麼接收方計算的結果
應該爲全1。若是結果不是全1(即檢驗和錯誤),那麼I P就丟棄收到的數據報。可是不生成差錯報文,由上層去發現丟失的數據報並進行重傳 11. 源IP地址(32bit) 每一份IP數據報都包含源IP地址和目的I P地址,它們都是32 bit的值 12. 目的IP地址(32bit) 每一份IP數據報都包含源IP地址和目的I P地址,它們都是32 bit的值 13. 選項OPTION 選項數據報中的一個"可變長"、"可選信息"。 1) 安全和處理限制(用於軍事領域,詳細內容參見RFC 1108[Kent 1991]) 2) 記錄路徑(讓每一個路由器都記下它的IP地址) 3) 時間戳(讓每一個路由器都記下它的IP地址和時間) 4) 寬鬆的源站選路(loose source route)(爲數據報指定一系列必須通過的IP地址) http://en.wikipedia.org/wiki/Loose_Source_Routing 5) 嚴格的源站選路(strict source route)(與寬鬆的源站選路相似,可是要求只能通過指定的這些地址,不能通過其餘的地址)
可使用: loose: ping –j <hosts>、strict: ping –k <hosts>進行測試 14. Padding填充: 選項字段一直都是以32 bit做爲界限,在必要的時候插入值爲0的填充字節。這樣就保證IP首部始終是32bit的整數倍(這是首部長度字段所要求的,由於它是以2爲基底的) 14. 數據 IP數據包攜帶的上層數據
Copyright (c) 2014 LittleHann All rights reserved