云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

CDN_阿里云服务器学生价_评分榜

小七 141 0

路径MTU发现在实践中的应用

上周,我们使用IP隧道(主要是在IPv4上隧道IPv6)的极少数用户无法访问我们的服务,因为网络更改破坏了我们服务器上的"路径MTU发现"。在本文中,我将解释MTU发现是什么路径,我们如何破坏它,如何修复它,以及我们使用的开源代码。通过Flickr首先是分裂当因特网上的主机要发送一些数据时,它必须知道如何将数据分成包。尤其是,它需要知道数据包的最大大小。主机可以发送的数据包的最大大小称为最大传输单位:MTU。MTU越长,性能越好,但可靠性越差。这是因为丢失的数据包意味着要重新传输更多的数据,而且因特网上的许多路由器不能传送很长的数据包。互联网之父们认为这个问题可以在IP层通过IP碎片来解决。不幸的是,IP碎片化有严重的缺点,在实践中是可以避免的。不要将钻头碎片化为了解决碎片问题,IP层在每个IP包上都包含一个"不要分段"位。它禁止路径上的任何路由器执行分段。那么,如果路由器不能传送数据包,也不能对其进行碎片化,它会怎么做呢?就在那时,乐趣开始了。根据RFC1191:当路由器无法转发数据报,因为它超过设置下一跳网络的MTU及其不分段位,则路由器需要返回ICMP目标无法到达的消息到数据报的源,代码指示"需要碎片和数据框集"。所以路由器必须发送ICMP类型3代码4消息。如果您想看到一种类型:tcpdump-s0-p-ni eth0'icmp和icmp[0]==3和icmp[1]==4'这个ICMP消息应该被传递到发起主机,而发起主机又应该调整该特定连接的MTU设置。这种机制称为路径MTU发现。理论上讲,这很好,但不幸的是,在传送ICMP数据包时,很多事情都会出错。最常见的问题是由错误配置的防火墙丢弃ICMP包引起的。通过Flickr另一个黑洞路由器丢弃数据包,但由于某种原因不能传递相关的ICMP消息的情况称为ICMP黑洞。当这种情况发生时,整个连接都被卡住了。发送端不断地尝试重新发送丢失的数据包,而接收端只确认接收到的小数据包。这个问题一般有三种解决办法。1) 减少客户端的MTU。当网络栈打开一个TCP/IP连接时,它在SYN包中提示它的MTU。这称为MSS-TCP选项。您可以在tcpdump中看到它,例如在我的主机上(注意"mss 1460"):$sudo tcpdump-s0-p-ni eth0'(ip和ip[20+13]&tcp syn!=0)'10: 24:13.920656 IP 192.168.97.138.55991>212.77.100.83.23:标志[S],序列号711738977,win 29200,选项[mss 1460,sackOK,TS val 6279040 ecr 0,nop,wscale 7],长度0如果你知道你在隧道后面,你可以考虑建议你的操作系统减少广告的mtu。在Linux中,它很简单(注意advmss 1400):$ip路由更改默认通过advmss 1400$sudo tcpdump-s0-p-ni eth0'(ip和ip[20+13]&tcp syn!=0)'10: 25:48.791956 IP 192.168.97.138.55992>212.77.100.83.23:标志[S],序列号389206299,win 28000,选项[mss 1400,sackOK,TS val 6302758 ecr 0,nop,wscale 7],长度02) 将服务器端所有连接的MTU降低到最小值。在服务器端这是一个很难解决的问题。一个服务器可能会遇到具有许多不同MTU的客户机,如果不能依赖路径MTU发现,那么就有了真正的问题。一种常用的解决方法是减少所有传出数据包的MTU。所有IPv6主机所需的最小MTU为1280,这是公平的。不幸的是,IPv4的值是576字节。另一方面,RFC4821建议假设最小MTU为1024是"足够安全的"。要更改MTU设置,可以键入:ip-f inet6路由替换mtu 1280(作为补充说明,您可以使用advmss代替。mtu设置更强大,适用于所有数据包,而不仅仅是TCP。而advmss只影响TCP层上给出的路径MTU提示。)不过,强制减小数据包大小并不是一个最佳解决方案。3) 启用智能MTU黑洞检测。RFC4821提出了一种检测ICMP黑洞的机制,并尝试对路径MTU进行智能调整。要在Linux上启用此功能,请键入:echo 1>/proc/sys/net/ipv4/tcp\u mtu探测echo 1024>/proc/sys/net/ipv4/tcp\u base_mss第二个设置将discovery中使用的起始MSS从512字节的可怜默认值提升到RFC4821建议的1024字节。CloudFlare架构为了了解上周发生的事情,首先我们需要绕道讨论一下我们的架构。在CloudFlare,我们使用BGP有两种方式。我们在外部使用它,即组织互联网的BGP,以及内部服务器之间的BGP。BGP的内部使用允许我们跨服务器获得高可用性。如果一台机器出现故障,BGP路由器会注意到并自动将流量推送到另一台服务器。我们已经使用了很长一段时间了,但是上周随着我们增加了内部BGP负载平衡,它在我们的网络中的使用也增加了。负载平衡机制被称为ECMP:等成本多路径路由。从配置的角度来看,变化很小,只需要将BGP指标调整为相等的值,启用ECMP的路由器完成其余的工作。但是有了ECMP,路由器必须有点智能。它无法实现真正的负载平衡,因为来自一个TCP连接的数据包可能会在错误的服务器上结束。相反,在ECMP中,路由器从从每个数据包中提取的通常元组中计算一个哈希值:对于TCP,它散列一个元组(src-ip,src-port,dst-ip,dst-port)并使用此哈希选择目标服务器。这保证了来自一个"流"的数据包将始终命中同一个服务器。ECMP不喜欢ICMPECMP确实会在会话中将TCP包转发到适当的服务器。不幸的是,它没有ICMP的专门知识,它只进行散列(src-ip,dst-ip)。其中源IP很可能是Internet上路由器的IP。在实践中,这有时会导致将ICMP数据包传递到与处理TCP连接的服务器不同的服务器。我们的案子就是这样。临时固定一些通过IPv6隧道访问CloudFlare的用户报告了这个问题。它们受到了影响,因为几乎每一个隧道IPv6都有一个减少的MTU。作为临时解决方案,我们将所有IPv6路径的MTU降低到1280(解决方案称为#2)。许多其他提供商也有同样的问题,他们在IPv6上使用这个技巧,而且从不发送大于1280字节的IPv6数据包。不管是好是坏,这个问题在IPv4上并不那么普遍。使用IPv4隧道的人越来越少,而路径MTU问题也得到了很好的理解。作为IPv4的临时修复,我们部署了RFC4821路径MTU发现(上面第3节提到的解决方案)。我们的解决方案:PMTUD与此同时,我们正在研究一个全面可靠的解决方案,恢复真正的mtu。其思想是将icmpmtu消息广播到所有服务器。这样,我们就可以保证ICMP消息将到达处理特定流的相关服务器,而不管ECMP路由器决定将其转发到哪里。我们很乐意为我们的小型"Path MTU Daemon"打开源代码,它可以完成以下工作:https://github.com/cloudflare/pmtud摘要在使用ECMP进行内部路由的网络中,正确地传递路径MTU-ICMP消息是一个非常困难的问题。尽管仍有很多需要改进的地方,但我们很高兴地报告:像许多其他公司一样,我们已经将IPv6上的MTU降低到安全级别值为1280。我们会考虑用它来提高性能一旦我们更加确信我们的其他解决方案有意的。我们推出PMTUD是为了确保ICMP的路径MTU消息在我们的数据中心中的"正确"路由。我们正在为IPv4启用linuxrfc4821路径MTU发现,它应该有助于解决真正的ICMP黑洞。觉得这篇文章有趣吗?加入我们的团队,包括我们在伦敦的精英办公室。我们一直在寻找有才华的开发人员和网络工程师!附录为了模拟黑洞,我们使用了iptables规则:iptables-I输入-s-m长度--长度1400:1500-j下降下面是模拟MTU ICMP消息的Scapy片段:#!/usr/bin/python从所有人进口*def回调(pkt):pkt2=IP(dst=pkt[IP].src)/ICMP(类型=3,代码=4,未使用=1280)/str(pkt[IP])[:28]pkt2.show()发送(pkt2)如果"名称"='"主视图":嗅探(prn=回调,存储=0,filter="ip和src及更大的1400")