建立好的pptpd服務測試連線外網很慢時,只需在iptables加入以下規則就可以正常了

-I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356

或是

/sbin/iptables -I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356

/etc/init.d/iptables save 存檔

為何會有這樣的原因如下

=====在斷開vpn連結的情況下:
在windowsXP下用ping -f -l XXXXXX 192.168.0.1一步一步測試(XXXXXXX為MTU大小,可以從1500開始,逐漸減小,知道可以ping通)
我們可以得到可以ping通的MTU最大為1426;
=====在連接vpn的前提下
在windowsXP下用ping -f -l XXXXXX 192.168.0.1一步一步測試(XXXXXXX為MTU大小,可以從1500開始,逐漸減小,知道可以ping通)
我們可以得到可以ping通的MTU最大為1372; 超過這個數則不能通,
====撥通vpn,在伺服器上用netstat –i查看介面,得到
Iface   MTU Met    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0   1500   0 102528561      0      0      0 194391413      0      0      0 BRU
eth1   1500   0 519820535    954 11553    924 208798037      0      0      0 BRU
lo    16436   0   151062      0      0      0   151062      0      0      0 LRU
ppp0   1396   0       19      0      0      0        8      0      0      0 OPRU

可知ppp的最大mtu為1396,當然,對應的mss應為(mtu-20位元組的IP頭部+20位元組的TCP 頭部=)1356 【小知識1】電腦網路中的MSS:
MSS: Maximum Segment Size 最大分段大小
MSS最大傳輸大小的縮寫,是TCP協議裡面的一個概念。
MSS就是TCP資料包每次能夠傳輸的最大資料分段。為了達到最佳的傳輸效能,TCP協議在建立連接的時候通常要協商雙方的MSS值,這個值TCP協議在 實現的時候往往用MTU值代替(需要減去IP資料包包頭的大小20Bytes和TCP資料段的包頭20Bytes)所以往往MSS為1460。通訊雙方會 根據雙方提供的MSS值得最小值確定為這次連接的最大MSS值。

【小知識2】mtu是網路傳輸最大報文包。
mss是網路傳輸資料最大值。
mss加包頭數據就等於mtu.
簡單說拿TCP包做例子。
報文傳輸1400位元組的資料的話,那麼mss就是1400,再加上20位元組IP包頭,20位元組tcp包頭,那麼mtu就是1400+20+20.
當然傳輸的時候其他的協議還要加些包頭在前面,總之mtu就是總的最後發出去的報文大小。mss就是你需要發出去的資料大小。 【小知識3】http://www.cnpaf.net/Class/TCPANDIP/200511/9898.html 假設PC建立了到SERVER的HTTP連接,PC希望從SERVER下載一個大的網頁。SERVER接收到PC的請求後開始發送大網頁檔,其IP的 DF位置1,不允許分片,IP報文長度為1500位元組。到達VPN閘道2的外網口(乙太)後,VPN閘道2發現其長度超過了1500個位元組,於是將其丟 棄,並給SERVER發回一個目的地址不可達的ICMP資訊,同時指出“MTU of next hop: 1500”。PC接收到該消息後,又按照1500位元組對外發送,又被丟棄,於是就形成了迴圈,無法通訊。
根據上述的分析,很容易得到如下解決方式,在VPN閘道2的出介面設置MTU為1500-4-20=1476,這樣VPN閘道2返回ICMP不可達消息時 將給出”MTU of next hop: 1476”。SERVER將以1476作為自己的最大MTU對外發送,到達VPN閘道1,封裝GRE和外層IP頭後就不會超過1500而順利發到對端。 -I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356 因為mss是在TCP連接建立開始時,通過帶有syn標誌的IP資料包進行傳輸的,所以我們在iptables裡面規定,在轉發資料時,只要發現產生於 ppt*的帶有 syn標誌資料包時,將其mss設定為1356位元組,這樣就與ppp0介面的路徑MTU向匹配了,資料自然就可以暢通無阻啦。 (注,vpn撥入一個,則建立一個ppt*的虛擬裝置,這個可以再linux上用ifcpnfig看到,第一個為ppt1,第二個為ppt2……)
參考: 1、http://fanqiang.chinaunix.net/app/other/2005-09-13/3655.shtml 2、http://technet.microsoft.com/zh-cn/library/cc768084(en-us).aspx 3、這是一個比較複雜的問題。首先,發現問題的過程是這樣的:使用一台WinXP的電腦(簡稱主機A)連接公司的VPN成功後,訪問內網的一個基於 B/S的CRM系統(簡稱主機B)時,發現首頁可以顯示(頁面比較簡單,包含的資料量較小),輸入帳號密碼登陸後,發現只能顯示頁面頂部的一點點內容,而 下面大部分內容無法顯示。而換一台Win2000的電腦登陸,內容就可以完全顯示出來。登陸到Linux VPN主機上,利用tcpdump對資料傳輸過程進行抓包分析,發現:每當B向A傳輸大於1396位元組的資料時,VPN主機就會回饋B如下資訊 10.87.0.200:VPN主機的內網網卡的IP位址
10.87.200.1:主機A的IP位址
10.87.200.6:主機B通過VPN獲取的IP地址
21:54:21.953848 IP 10.87.0.200 > 10.100.0.100: icmp 556: 10.100.0.203 unreachable -
need to frag (mtu 1396)
可以看到VPN主機向提供web服務的主機B返回了一個ICMP不可達的差錯報文。其含義是VPN主機收到了一個需要分片才能通過的資料包,而這個資料包在其IP頭部又設置了不能分片(DF)的標誌。所以該資料包不能通過VPN主機。
根據TCP/IP協定,在建立TCP連接時,傳輸雙方都要指明自己的mss(最大報文長度)大小,然後選取雙方之中最小的那個mss,以避免在隨後的資料 傳送過程中出現資料包分片傳輸的情況。通過抓包分析,主機B的mss為1460位元組,主機A的mss為1357位元組。兩者取小所以雙方協商的結果確定 mss為1357位元組,也就是說以後進行TCP資料傳輸時,資料包的最大傳輸單元MTU不能超過1397(mss+20位元組的IP頭部+20位元組的TCP 頭部),同時在IP頭部設置了不能分片(DF)的標誌。
然後在VPN主機上執行netstat –i,觀察各個網路介面的路徑MTU值為多少。觀察結果如下:
Iface MTU
eth0 1500 //外網網卡介面
eth1 1500 //內網網卡介面
lo 16436 //本機回環介面
ppp0 1396 //WinXP VPN接入通道介面
可以看到ppp0介面的路徑MTU為1396位元組,也就是說如果一個資料包想要通過這個介面的話,一定不能大於1396位元組,如果大於這個值,會出現兩種結果:
1、如果這個資料包的IP頭部沒有設置不能分片(DF)的標誌,那麼VPN主機就把這個資料包分片,使其資料包大小小於1396位元組,然後允許其通過。
2、反之,如果這個資料包的IP頭部設置不能分片(DF)的標誌,那麼VPN主機就會返回一個ICMP不可達的差錯報文。同時丟棄這個資料包。
問題就出在這裡,主機A和主機B協商的mss為1357位元組,也就是說其TCP資料包的MTU為1397,而ppp0允許的路徑MTU卻為1396,主機 A的MTU居然大於ppp0的路徑MTU!當主機B向主機A發送了一個1397位元組的資料包時,自然不能通過ppp0介面了。回到發現問題的那個情況,首 頁之所以能夠顯示成功,是因為首頁包含的資料較小,傳輸時只需要一個沒有超過1396位元組的IP資料包就可以了,所以能夠顯示出來,而登陸成功後的頁面包 含的資料較大,需要分為多個IP資料包進行傳輸。這裡可以假設一下,開頭的一個IP資料包因為沒有超過1396位元組因而通過,而隨後的IP資料包因為其大 小為1397位元組,超過了路徑MTU,所以不予通過。反映到頁面,就是登陸頁面下面的大部分內容無法顯示了。
我們再來看看用安裝了Win2000主機C連接VPN又是什麼狀況呢?通過抓包發現,主機C提出的mss為1360(可以推算出其MTU為1400),而 執行netstat –i,發現此時的ppp0的MTU為1496,路徑MTU大於主機C的MTU,這個結果是正常的。
大家一定會問,何主機B提出的MTU小於路徑MTU,這個問題只能問問微軟了,我查了一些英文資料,說這是WinXP本身系統的一個問題。
知道了問題的原理,那讓我們來看看如何進行解決吧。解決方法很簡單,就是借助iptalbes,設定主機B進行協商時提出的mss為1356。即在 iptables裡面加入一條規則: iptables -A FORWARD -p tcp --syn -s 10.87.200.0/31 -j TCPMSS --set-mss 1356   因為mss是在TCP連接建立開始時,通過帶有syn標誌的IP資料包進行傳輸的,所以我們在iptables裡面規定,在轉發資料時,只要發現帶有 syn標誌並且源位址為主機B的IP資料包時,將其mss設定為1356位元組,這樣就與ppp0介面的路徑MTU向匹配了,資料自然就可以暢通無阻啦。 因為mss是在TCP連接建立開始時,通過帶有syn標誌的IP資料包進行傳輸的,所以我們在iptables裡面規定,在轉發資料時,只要發現帶有 syn標誌並且源位址為主機B的IP資料包時,將其mss設定為1356位元組,這樣就與ppp0介面的路徑MTU向匹配了,資料自然就可以暢通無阻啦

By tony

自由軟體愛好者~喜歡不斷的思考各種問題,有新的事物都會想去學習嘗試 做實驗並熱衷研究 沒有所謂頂天的技術 只有謙虛及不斷的學習 精進專業,本站主要以分享系統及網路相關知識、資源而建立。 Github http://stnet253.github.io

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料