MTU: Maxitum Transmission Unit 傳輸單元最大值
MSS: Maxitum Segment Size 最大分段大小
PPPoE: PPP Over Ethernet(在乙太網路上承載PPP協議)
[分析過程]
先說說這MTU傳輸單元最大值,這個傳輸單元最大值實際上和鏈路層協議有著密切的關係,讓我們先仔細回憶一下EthernetII幀的結構DMAC+SMAC+Type+Data+CRC
由於乙太網路傳輸電氣方面的限制,每個乙太網路幀都有最小的大小64bytes最大不能超過1518bytes,對於小於或者大於這個限制的乙太網路幀我們都可以視之為錯誤的資料幀,一般的乙太網路轉寄裝置會丟棄這些資料幀。
(註:小於64Bytes的資料幀一般是由於乙太網路衝突產生的“片段”或者線路幹擾或者壞的乙太網路介面產生的,對於大於1518Bytes的資料幀我們一般把它叫做Giant幀,這種一般是由於線路幹擾或者壞的乙太網路口產生)
由於乙太網路EthernetII最大的資料幀是1518Bytes這樣,刨去乙太網路幀的幀頭(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和幀尾CRC校正部分4Bytes(這個部門有時候大家也把它叫做FCS),那麼剩下承載上層協議的地方也就是Data域最大就只能有1500Bytes這個值我們就把它稱之為MTU。這個就是網路層協議非常關心的地方,因為網路層協議比如IP協議會根據這個值來決定是否把上層傳下來的資料進行分區。就好比一個盒子沒法裝下一大塊麵包,我們需要把麵包切成片,裝在多個盒子裡面一樣的道理。
當兩台遠程PC互聯的時候,它們的資料需要穿過很多的路由器和各種各樣的網路媒介才能到達對端,網路中不同媒介的MTU各不相同,就好比一長段的水管,由不同粗細的水管組成(MTU不同 )通過這段水管最大水量就要由中間最細的水管決定。
對於網路層的上層協議而言(我們以TCP/IP協議族為例)它們對水管粗細不在意它們認為這個是網路層的事情。網路層IP協議會檢查每個從上層協議下來的資料包的大小,並根據本機MTU的大小決定是否作“分區”處理。分區最大的壞處就是
降低了傳輸效能,本來一次可以搞定的事情,分成多次搞定,所以在網路層更高一層(就是傳輸層)的實現中往往會對此加以注意!有些高層因為某些原因就會要求我這個麵包不能切片,我要完整地麵包,所以會在IP資料包包頭裡面加上一
個標籤:DF(Donot Fragment)。這樣當這個IP資料包在一大段網路(水管裡面)傳輸的時候,如果遇到MTU小於IP資料包的情況,轉寄裝置就會根據要求丟棄這個資料包。然後返回一個錯誤資訊給寄件者。這樣往往會造成某些通訊上的問題,不過幸運的是大部分網路鏈路都是MTU1500或者大於1500。
對於UDP協議而言,這個協議本身是不需連線的協議,對資料包的到達順序以及是否正確到達不甚關心,所以一般UDP應用對分區沒有特殊要求。
對於TCP協議而言就不一樣了,這個協議是連線導向的協議,對於TCP協議而言它非常在意資料包的到達順序以及是否傳輸中有錯誤發生。所以有些TCP應用對分區有要求---不能分區(DF)。
花開兩朵,各表一枝,說完MTU的故事我們該講講今天的第二個豬腳---PPPoE所謂PPPoE就是在乙太網路上面跑PPP協議,有人奇怪了,PPP協議和Ethernet不都是鏈路層協議嗎?怎麼一個鏈路層跑到另外一個鏈路層上面去了,難道升級成網路層協議了不成。其實這是個誤區:就是某層協議只能承載更上一層協議。
為什麼會產生這種奇怪的需求呢?這是因為隨著寬頻接入(這種寬頻接入一般為Cable Modem或者xDSL或者乙太網路的接入)由於乙太網路缺乏認證計費機制而傳統電訊廠商是通過PPP協議來對撥號等接入服務進行認證計費的,所以就出了這麼一個怪胎:PPPoE。(有關PPPoE的詳細介紹參見V大以及本站其他成員的一些介紹文章,我就不囉裡囉唆的了)
PPPoE帶來了好處,也帶來了一些壞處,比如:二次封裝耗費資源,降低了傳輸效能等等,這些壞處俺也不多說了,最大的壞處就是PPPoE導致MTU變小了乙太網路的MTU是1500,再減去PPP的包頭包尾的開銷(8Bytes),就變成1492。
如果兩台主機之間的某段網路使用了PPPoE那麼就會導致某些不能分區的應用無法通訊。
這個時候就需要我們調整一下主機的MTU,通過降低主機的MTU,這樣我們就能夠順利地進行通訊了。
當然對於TCP應用而言還有另外的解決方案。
馬上請出今天第三位豬腳:MSS。
MSS最大傳輸大小的縮寫,是TCP協議裡面的一個概念。
MSS就是TCP資料包每次能夠傳輸的最大資料分段。為了達到最佳的傳輸效能TCP協議在建立串連的時候通常要協商雙方的MSS值,這個值TCP協議在實現的時候往往用MTU值代替(需要減去IP資料包包頭的大小20Bytes和TCP資料區段的包頭20Bytes)所以往往MSS為1460。通訊雙方會根據雙方提供的MSS值得最小值確定為這次串連的最大MSS值。
介紹完這三位豬腳s
我們回過頭來看前言裡面的那個問題,我們試想一下,如果我們在中間路由器上把每次TCP串連的最大MSS進行調整這樣使得通過PPPoE鏈路的最大MSS值加上資料包頭包尾不會超過PPPoE的MTU大小1492這樣就不會造成無法通訊的問題.所以上面的問題可以通過ip tcp adjust-mss 1452來解決。
當然問題也可以通過修改PC機的MTU來解決。
[後記]
Cisco的TCP Adjust MSS Feature:
The TCP MSS Adjustment feature enables the configuration of the
maximum segment size (MSS) for transient packets that traverse a router,
specifically TCP segments in the SYN bit set, when Point to Point Protocol
over Ethernet (PPPoE) is being used in the network. PPPoE truncates the
Ethernet maximum transmission unit (MTU) 1492, and if the effective MTU
on the hosts (PCs) is not changed, the router in between the host and the
server can terminate the TCP sessions. The ip tcp adjust-mss command
specifies the MSS value on the intermediate router of the SYN packets to
avoid truncation.
一、TCP MSS 的原理
PC1(192.168.0.1)―――Router――――Internet―――-www server(238.135.1.1)
建立tcp串連的兩端在三向交握時會協商tcp mss大小,具體如下:
pc1發出syn報文,其中option選項填充的mss欄位一般為1460,同樣www server收到syn報文後,會發送syn+ack報文應答,option選項填充的mss欄位也為1460;協商雙方會比較syn和syn+ack報文中mss欄位大小,選擇較小的mss作為發送tcp分區的大小。通過比較,協商雙方的tcp mss都是1460。
對於涉及mpls l3vpn、pppoe+nat、ipsec、l2tp、gre等組網,通常由於報文太大需要分區,一般可以通過設定tcp mss解決。
針對上例說明tcp mss如何?
假設在路由器內網口配置tcp mss 1200
路由器收到www server的syn+ack報文時會修改option選項中的mss欄位為1200,然後再轉寄給PC1,PC1收到報文後認為對端的tcp mss為1200,這樣PC1發送資料(已經協商完了)給www server時會以1200作為分區大小;但路由器修改tcp mss為1200的操作www server是不知道的,因此www server還會以1460作為分區大小發送報文。
假設再路由器外網口配置tcp mss 1200
路由器收到PC1的syn報文時會修改option選項中的mss欄位為1200,然後再轉寄給www server,同樣www server發送資料給PC1時會以1200作為分區大小;同樣PC1不知道路由器修改tcp mss為1200,因為PC1還會以1460作為分區大小發送報文。
因此在實現雙向大包傳輸時需要在內外網同時修改tcp mss
綜上所述:在路由器介面上配置的tcp mss命令僅對出介面方向的syn報文和syn+ack報文有效,對於入介面方向的syn和syn+ack報文無效。
二、TCP MSS 與大包通訊的關係
使用者在使用路由器訪問Internet時,經常會反饋不能訪問網頁(或部分網頁)以及使用Outlook收發郵件(這些應用是基於TCP或UDP的),但進行Ping包時沒有問題,這時候檢查配置時也沒有錯誤。出現這種情況的時候,多半是因為在裝置上進行了NAT應用,同時裝置對報文進行了分區操作。
IP報文裡是有五元組的,但報文要進行分區時,只有第一片報文帶有IP的五元組資訊(源目的ip位址,源目的連接埠號碼,協議號),後續的分區不會保留TCP/UDP報文所有的標識資訊,如連接埠號碼資訊等,這種情況下,如果裝置又實現了NAT轉換操作(NAT轉換過程中,會隨機地做埠轉換),並且應用又是基於TCP/UDP的,這就導致報文不能正確組包,會出現上述的問題現象。
TCP/IP串連時建立的過程中會協商很多參數的,其中TCP MSS參數就是用於協商TCP報文大小的,如果協商出來的TCP MSS的參數值小於裝置的MTU的值時,TCP報文在裝置上就不會被分區,否則就會出現報文分區並導致上述現象的發生,因此,為了避免上述情況的發生,一定要保證協商的TCP MSS參數小於裝置的MTU的值。為此,Quidway路由器上有一個設定TCP MSS值的命令,如果配置了這條命令,路由器裝置在建立TCP/IP串連的過程中就按照這個配置的值來修改協商報文中關於TCP MSS的值,在同對端協商的過程中也就能夠協商出這個值來,如果不配置這條命令,路由器裝置就不會修改報文中的這個值(有時對端裝置發送過來的協商報文中的這個值會很大,如8000)。一般來說,預設或配置的MTU的值一般在1500左右,將TCP
MSS的值裝置為小於1500就可以,如1400或1024等。
如果TCP MSS值設定的過小,報文數量明顯增多又導致效率下降,特別是沒有配置NAT應用的情況下,限制TCP報文大小更沒有必要,由於應用情況比較複雜,設定預設的TCP MSS的值也不是特別合適(裝置會在建立串連時均要修改TCP MSS的值),因此,還是在應用中加以注意比較好,思科裝置也是有這個配置命令的
MTU: Maxitum Transmission Unit 傳輸單元最大值
MSS: Maxitum Segment Size 最大分段大小
MSS最大傳輸大小的縮寫,是TCP協議裡面的一個概念。
MSS就是TCP資料包每次能夠傳輸的最大資料分段。為了達到最佳的傳輸效能TCP協議在建立串連的時候通常要協商雙方的MSS值,這個值TCP協議在實現的時候往往用MTU值代替(需要減去IP資料包包頭的大小20Bytes和TCP資料區段的包頭20Bytes), 通訊雙方會根據雙方提供的MSS值得最小值確定為這次串連的最大MSS值。
而一般乙太網路MTU都為1500, 所以在乙太網路中, 往往TCP MSS為1460。
協商TCP MSS大小具體過程如下:
TCP client發出SYN報文,其中option選項填充的MSS欄位一般為(MTU-IP頭大小-TCP頭大小),同樣TCP server收到SYN報文後,會發送SYN+ACK報文應答,option選項填充的mss欄位也為(MTU-IP頭大小-TCP頭大小);協商雙方會比較SYN和SYN+ACK報文中MSS欄位大小,選擇較小的MSS作為發送TCP分區的大小。
對於涉及PPPOE+NAT、IPsec、L2TP、GRE等組網,通常由於報文太大需要分區,這樣會降低傳輸速率; 所以選擇一個合適的MSS對傳輸資料來說比較重要. linux中一般可以通過netfilter iptables設定TCP MSS來解決。
iptables -A FORWARD -p tcp- -tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
這條規則的目的就是改變TCP MSS以適應PMTU(Path MTU)
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN- j TCPMSS --set-mss 128
設定MSS為128