問題:用pptp搭建了linux平台的vpn伺服器,撥入後訪問內網ftp,下載檔案極慢;用其作網關上網,除了baidu外,大部分網站訪問速度極慢,幾乎無法訪問。 解決: 在pptp所在的linux服務的iptables的*filter表中加入 -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 原因分析
=====在斷開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向匹配了,資料自然就可以暢通無阻啦