﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-淋雨的博客-随笔分类-Network</title><link>http://www.cppblog.com/inkcpp/category/18631.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 16 May 2012 23:09:58 GMT</lastBuildDate><pubDate>Wed, 16 May 2012 23:09:58 GMT</pubDate><ttl>60</ttl><item><title>pptp搭建的vpn代理上网很慢 </title><link>http://www.cppblog.com/inkcpp/archive/2012/05/02/173463.html</link><dc:creator>淋雨的感觉</dc:creator><author>淋雨的感觉</author><pubDate>Wed, 02 May 2012 05:45:00 GMT</pubDate><guid>http://www.cppblog.com/inkcpp/archive/2012/05/02/173463.html</guid><wfw:comment>http://www.cppblog.com/inkcpp/comments/173463.html</wfw:comment><comments>http://www.cppblog.com/inkcpp/archive/2012/05/02/173463.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/inkcpp/comments/commentRss/173463.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/inkcpp/services/trackbacks/173463.html</trackback:ping><description><![CDATA[<span style="color: #836c74; font-family: Arial; font-size: 12px; letter-spacing: 1px; line-height: 20px; background-color: #ffffff; ">转贴自：</span><a href="http://blog.chinaunix.net/u/16464/showart.php?id=1923564" style="color: #836c74; font-size: 12px; font-family: Verdana, Arial, Helvetica, sans-serif; text-decoration: none; line-height: 20px; letter-spacing: 1px; background-color: #ffffff; ">http://blog.chinaunix.net/u/16464/showart.php?id=1923564<br /></a><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">题:用pptp搭建了linux平台的vpn服务器，拨入后访问内网ftp，下载文件极慢；用其作网关上网，除了baidu外，大部分网站访问速度极慢，几乎无法访问。</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">解决: 在pptp所在的linux服务的iptables的*filter表中加入</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">-I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356<br style="line-height: normal; " />或者在命令提示符运行<br style="line-height: normal; " />/sbin/iptables -I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">原因分析&nbsp;<br style="line-height: normal; " />=====在断开vpn链接的情况下：<br style="line-height: normal; " />在windowsXP下用ping -f -l XXXXXX 192.168.0.1一步一步测试（XXXXXXX为MTU大小，可以从1500开始，逐渐减小，知道可以ping通）<br style="line-height: normal; " />我们可以得到可以ping通的MTU最大为1426；<br style="line-height: normal; " />=====在连接vpn的前提下<br style="line-height: normal; " />在windowsXP下用ping -f -l XXXXXX 192.168.0.1一步一步测试（XXXXXXX为MTU大小，可以从1500开始，逐渐减小，知道可以ping通）<br style="line-height: normal; " />我们可以得到可以ping通的MTU最大为1372；</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">超过这个数则不能通，<br style="line-height: normal; " />====拨通vpn，在服务器上用netstat &#8211;i查看接口，得到<br style="line-height: normal; " />Iface&nbsp;&nbsp; MTU Met&nbsp;&nbsp;&nbsp; RX-OK RX-ERR RX-DRP RX-OVR&nbsp;&nbsp;&nbsp; TX-OK TX-ERR TX-DRP TX-OVR Flg<br style="line-height: normal; " />eth0&nbsp;&nbsp; 1500&nbsp;&nbsp; 0 102528561&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 194391413&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 BRU<br style="line-height: normal; " />eth1&nbsp;&nbsp; 1500&nbsp;&nbsp; 0 519820535&nbsp;&nbsp;&nbsp; 954 11553&nbsp;&nbsp;&nbsp; 924 208798037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 BRU<br style="line-height: normal; " />lo&nbsp;&nbsp;&nbsp; 16436&nbsp;&nbsp; 0&nbsp;&nbsp; 151062&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; 151062&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 LRU<br style="line-height: normal; " />ppp0&nbsp;&nbsp; 1396&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0 OPRU</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">可知ppp的最大mtu为1396，当然，对应的mss应为（mtu-20字节的IP头部+20字节的TCP 头部=）1356</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">【小知识1】计算机网络中的MSS：<br style="line-height: normal; " />MSS: Maximum Segment Size 最大分段大小<br style="line-height: normal; " />MSS最大传输大小的缩写，是TCP协议里面的一个概念。<br style="line-height: normal; " />MSS就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能，TCP协议在建立连接的时候通常要协商双方的MSS值，这个值TCP协议在实现的时候往往用MTU值代替（需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes）所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; "><br style="line-height: normal; " />【小知识2】mtu是网络传输最大报文包。&nbsp;<br style="line-height: normal; " />mss是网络传输数据最大值。&nbsp;<br style="line-height: normal; " />mss加包头数据就等于mtu.&nbsp;<br style="line-height: normal; " />简单说拿TCP包做例子。&nbsp;<br style="line-height: normal; " />报文传输1400字节的数据的话，那么mss就是1400，再加上20字节IP包头，20字节tcp包头，那么mtu就是1400+20+20.&nbsp;<br style="line-height: normal; " />当然传输的时候其他的协议还要加些包头在前面，总之mtu就是总的最后发出去的报文大小。mss就是你需要发出去的数据大小。</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">【小知识3】<a href="http://www.cnpaf.net/Class/TCPANDIP/200511/9898.html" style="color: #836c74; font-family: Verdana, Arial, Helvetica, sans-serif; text-decoration: none; ">http://www.cnpaf.net/Class/TCPANDIP/200511/9898.html</a></div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">假设PC建立了到SERVER的HTTP连接，PC希望从SERVER下载一个大的网页。SERVER接收到PC的请求后开始发送大网页文件，其IP的DF位置1，不允许分片，IP报文长度为1500字节。到达VPN网关2的外网口（以太）后，VPN网关2发现其长度超过了1500个字节，于是将其丢弃，并给SERVER发回一个目的地址不可达的ICMP信息，同时指出&#8220;MTU of next hop: 1500&#8221;。PC接收到该消息后，又按照1500字节对外发送，又被丢弃，于是就形成了循环，无法通讯。<br style="line-height: normal; " />根据上述的分析，很容易得到如下解决方式，在VPN网关2的出接口设置MTU为1500－4－20＝1476，这样VPN网关2返回ICMP不可达消息时将给出&#8221;MTU of next hop: 1476&#8221;。SERVER将以1476作为自己的最大MTU对外发送，到达VPN网关1，封装GRE和外层IP头后就不会超过1500而顺利发到对端。</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">-I FORWARD -p tcp --syn -i ppp+ -j TCPMSS --set-mss 1356</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">因为mss是在TCP连接建立开始时，通过带有syn标志的IP数据包进行传输的，所以我们在iptables里面规定，在转发数据时，只要发现产生于ppt*的带有 syn标志数据包时，将其mss设定为1356字节，这样就与ppp0接口的路径MTU向匹配了，数据自然就可以畅通无阻啦。</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">（注，vpn拨入一个，则建立一个ppt*的虚拟设备，这个可以再linux上用ifcpnfig看到，第一个为ppt1，第二个为ppt2&#8230;&#8230;）</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; "><br style="line-height: normal; " />参考：</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">1、<a href="http://fanqiang.chinaunix.net/app/other/2005-09-13/3655.shtml" style="color: #836c74; font-family: Verdana, Arial, Helvetica, sans-serif; text-decoration: none; ">http://fanqiang.chinaunix.net/app/other/2005-09-13/3655.shtml</a></div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">2、<a href="http://technet.microsoft.com/zh-cn/library/cc768084(en-us).aspx" style="color: #836c74; font-family: Verdana, Arial, Helvetica, sans-serif; text-decoration: none; ">http://technet.microsoft.com/zh-cn/library/cc768084(en-us).aspx</a></div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">3、这是一个比较复杂的问题。首先，发现问题的过程是这样的：使用一台WinXP的电脑（简称主机A）连接公司的VPN成功后，访问内网的一个基于 B/S的CRM系统（简称主机B）时，发现首页可以显示（页面比较简单，包含的数据量较小），输入账号密码登陆后，发现只能显示页面顶部的一点点内容，而下面大部分内容无法显示。而换一台Win2000的电脑登陆，内容就可以完全显示出来。登陆到Linux VPN主机上，利用tcpdump对数据传输过程进行抓包分析，发现：每当B向A传输大于1396字节的数据时，VPN主机就会反馈B如下信息&nbsp;<br style="line-height: normal; " />注意：&nbsp;<br style="line-height: normal; " />10.87.0.200：VPN主机的内网网卡的IP地址&nbsp;<br style="line-height: normal; " />10.87.200.1：主机A的IP地址&nbsp;<br style="line-height: normal; " />10.87.200.6：主机B通过VPN获取的IP地址&nbsp;<br style="line-height: normal; " />21:54:21.953848 IP 10.87.0.200 &gt; 10.100.0.100: icmp 556: 10.100.0.203 unreachable -&nbsp;<br style="line-height: normal; " />need to frag (mtu 1396)&nbsp;<br style="line-height: normal; " />可以看到VPN主机向提供web服务的主机B返回了一个ICMP不可达的差错报文。其含义是VPN主机收到了一个需要分片才能通过的数据包，而这个数据包在其IP头部又设置了不能分片（DF）的标志。所以该数据包不能通过VPN主机。&nbsp;<br style="line-height: normal; " />根据TCP/IP协议，在建立TCP连接时，传输双方都要指明自己的mss（最大报文长度）大小，然后选取双方之中最小的那个mss，以避免在随后的数据传送过程中出现数据包分片传输的情况。通过抓包分析，主机B的mss为1460字节，主机A的mss为1357字节。两者取小所以双方协商的结果确定 mss为1357字节，也就是说以后进行TCP数据传输时，数据包的最大传输单元MTU不能超过1397（mss+20字节的IP头部+20字节的TCP 头部），同时在IP头部设置了不能分片（DF）的标志。&nbsp;<br style="line-height: normal; " />然后在VPN主机上执行netstat &#8211;i，观察各个网络接口的路径MTU值为多少。观察结果如下：&nbsp;<br style="line-height: normal; " />Iface MTU&nbsp;<br style="line-height: normal; " />eth0 1500 //外网网卡接口&nbsp;<br style="line-height: normal; " />eth1 1500 //内网网卡接口&nbsp;<br style="line-height: normal; " />lo 16436 //本机回环接口&nbsp;<br style="line-height: normal; " />ppp0 1396 //WinXP VPN接入通道接口&nbsp;<br style="line-height: normal; " />可以看到ppp0接口的路径MTU为1396字节，也就是说如果一个数据包想要通过这个接口的话，一定不能大于1396字节，如果大于这个值，会出现两种结果：<br style="line-height: normal; " />1、如果这个数据包的IP头部没有设置不能分片（DF）的标志，那么VPN主机就把这个数据包分片，使其数据包大小小于1396字节，然后允许其通过。&nbsp;<br style="line-height: normal; " />2、反之，如果这个数据包的IP头部设置不能分片（DF）的标志，那么VPN主机就会返回一个ICMP不可达的差错报文。同时丢弃这个数据包。&nbsp;<br style="line-height: normal; " />问题就出在这里，主机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，所以不予通过。反映到页面，就是登陆页面下面的大部分内容无法显示了。&nbsp;<br style="line-height: normal; " />我们再来看看用安装了Win2000主机C连接VPN又是什么状况呢？通过抓包发现，主机C提出的mss为1360（可以推算出其MTU为1400），而执行netstat &#8211;i，发现此时的ppp0的MTU为1496，路径MTU大于主机C的MTU，这个结果是正常的。&nbsp;<br style="line-height: normal; " />大家一定会问，何主机B提出的MTU小于路径MTU，这个问题只能问问微软了，我查了一些英文资料，说这是WinXP本身系统的一个问题。&nbsp;<br style="line-height: normal; " />知道了问题的原理，那让我们来看看如何进行解决吧。解决方法很简单，就是借助iptalbes，设定主机B进行协商时提出的mss为1356。即在iptables里面加入一条规则：&nbsp;<br style="line-height: normal; " />代码&nbsp;<br style="line-height: normal; " />iptables -A FORWARD -p tcp --syn -s 10.87.200.0/31 -j TCPMSS --set-mss 1356&nbsp;&nbsp;</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">因为mss是在TCP连接建立开始时，通过带有syn标志的IP数据包进行传输的，所以我们在iptables里面规定，在转发数据时，只要发现带有 syn标志并且源地址为主机B的IP数据包时，将其mss设定为1356字节，这样就与ppp0接口的路径MTU向匹配了，数据自然就可以畅通无阻啦。</div><div style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; ">因为mss是在TCP连接建立开始时，通过带有syn标志的IP数据包进行传输的，所以我们在iptables里面规定，在转发数据时，只要发现带有 syn标志并且源地址为主机B的IP数据包时，将其mss设定为1356字节，这样就与ppp0接口的路径MTU向匹配了，数据自然就可以畅通无阻啦。</div><img src ="http://www.cppblog.com/inkcpp/aggbug/173463.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/inkcpp/" target="_blank">淋雨的感觉</a> 2012-05-02 13:45 <a href="http://www.cppblog.com/inkcpp/archive/2012/05/02/173463.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>