在检查网络时,traceroute是我们常用的网络诊断工具。traceroute利用IP协议的生存时间(time to live,TTL)字段,并试图从通往主机的路径上的每个网关引出ICMP TIME_EXCEEDED响应。通过跟踪从IP网络传输到给定主机的路由数据包,将路由数据包跟踪打印到网络主机,使得用户可以查看IP报文从源端到达目的端所经过的三层设备,从而检查网络连接是否可用
traceroute的用法如下:
traceroute host [packet_len]
[-46dFITUnreAV] [-f first_ttl] [-g gate,...]
[-i device] [-m max_ttl] [-p port] [-s src_addr]
[-q nqueries] [-N squeries] [-t tos]
[-l flow_label] [-w waittimes] [-z sendwait] [-UL] [-D]
[-P proto] [--sport=port] [-M method] [-O mod_options]
[--mtu] [--back]
traceroute6 [options]
tcptraceroute [options]
lft [options]
其中,traceroute6相当于traceroute -6,tcptraceroute相当于traceroute -T。lft,即Layer Four Traceroute,四层跟踪路由,执行TCP跟踪路由,类似于Traceroute -T,但试图提供与原始此类实现(也称为“lft”)的兼容性。
traceroute唯一必需的参数是目标主机的域名或IP地址。可选的packet_length是探测数据包的总大小(IPv4默认为60字节,IPv6默认为80字节)。在某些情况下,可以忽略指定的大小,也可以将其增加到最小值。 该程序试图通过启动具有较小TTL(生存时间)的探测数据包,然后监听来自网关的ICMP“超时”回复,来跟踪IP数据包将到达某个互联网主机的路由。我们从TTL为1开始探测,然后逐个增加,直到我们收到ICMP“端口不可达”(或TCP重置),这意味着我们到达了“主机”,或者达到了最大值(默认为30跳)。在每个TTL设置下发送三个探测(默认情况下),并打印一行,显示TTL、网关地址和每个探测的往返时间。如果需要,可以在地址后面添加其他信息。如果探测响应来自不同的网关,则将打印每个响应系统的地址。如果在特定超时内没有响应,则会为该探测器打印一个“*”(星号)。探测结束后,可以打印一些额外的注释:!H、!N或者!P(主机、网络或协议无法访问)、!S(源路由失败)、!F(需要分片)、!X(通信被管理禁止)、!V(主机优先级违规)、!C(优先级截止生效),或!(ICMP不可达代码)。如果几乎所有探测都导致某种不可达,则 traceroute 将放弃并退出。我们不希望目标主机处理UDP探测数据包,因此目标端口被设置为一个不太可能的值(您可以用-p标志更改它)。ICMP或TCP跟踪路由没有这样的问题(对于TCP,我们使用半开放技术,这可以防止我们的探测被目标主机上的应用程序监测到)。 在现代网络环境中,由于防火墙的广泛使用,传统的跟踪路由方法并不总是适用。这种防火墙过滤“不太可能”的UDP端口,甚至ICMP回显。为了解决这个问题,实现了一些额外的跟踪路由方法(包括TCP),请参阅下面的可用方法列表。这些方法试图使用特定的协议和源/目的端口,以绕过防火墙(被防火墙视为允许的网络会话类型的开始)。
OPTIONS选项
明确强制IPv4或IPv6跟踪路由。默认情况下,程序将尝试解析给定的域名,并自动选择适当的协议。如果解析主机名同时返回IPv4和IPv6地址,则traceroute将使用IPv4。 不要对探测数据包进行分片。(对于IPv4,它还设置了DF位,这告诉中间路由器也不要远程分片)。通过packet_len命令行参数改变探测数据包的大小,您可以手动获取有关单个网络跳的MTU的信息。--mtu选项(见下文)尝试自动执行此操作。请注意,禁止分片功能(如-F或--mtu)仅在Linux内核2.6.22中正常工作。在此版本之前,IPv6总是分片的,IPv4只能使用已发现的最终MTU(来自路由缓存),这可能小于设备的实际MTU。-f first_ttl, --first=first_ttl
-g gateway, --gateway=gateway
告诉traceroute向传出数据包添加一个IP源路由选项,该选项告诉网络通过指定网关路由数据包(出于安全原因,大多数路由器已禁用源路由)。一般来说,允许使用多个网关(逗号分隔)。对于IPv6,允许num、addr、addr等形式,其中num是路由报文头类型(默认为类型2)。请注意,类型0路由报文头现在已弃用(rfc5095)。-i interface, --interface=interface
指定traceroute应通过其发送数据包的接口。默认情况下,根据路由表选择接口。-m max_ttl, --max-hops=max_ttl
指定跟踪路由将探测的最大跳数(最大生存时间值)。默认值为30。-N squeries, --sim-queries=squeries
指定同时发送的探测数据包的数量。同时发送多个探测器可以大大加快跟踪路由。默认值为16。请注意,一些路由器和主机可以使用ICMP速率限制。在这种情况下,指定太大的数字可能会导致一些响应丢失。对于UDP跟踪,指定跟踪路由将使用的目标端口基础(目标端口号将随每次探测而递增)。 对于ICMP跟踪,指定初始ICMP序列值(也随每次探测而递增)。对于TCP和其他协议,只指定要连接的(固定)目标端口。使用tcptracoute包装器时,-p指定源端口。对于IPv4,设置服务类型(Type of Service,TOS)和优先级值。有用的值是16(低延迟)和8(高吞吐量)。请注意,要使用某些TOS优先级值,您必须是超级用户。-l flow_label, --flowlabel=flow_label
-w max[,here,near], --wait=max[,here,near]
通常有三个浮点值,用逗号(或斜线)分隔。Max指定在任何情况下等待的最长时间(以秒为单位,默认值为5.0)。 传统的traceroute实现总是等待任何探测的最大秒数。但是,如果我们已经有来自同一跳甚至下一跳的一些回复,我们可以使用此类回复的往返时间作为提示,以确定实际合理的等待时间。此处的可选项(默认值为3.0)指定了一个系数,用于乘以已从同一跳接收到的响应的往返时间。结果值用作探测的超时值,而不是(但不超过)最大值。可选的near(默认值10.0)为下一跳的响应指定了一个类似的因子。(在这两种情况下都使用第一个发现结果的时间)。首先,我们寻找相同的调数(从现在开始将首先打印的探测)。如果什么也没找到,那就找下一跳。如果未找到任何内容,请使用最大值。如果此处和/或附近的值为零,则跳过相应的计算。如果只指定了max(为了与以前的版本兼容),则此处和附近始终设置为零。-q nqueries, --queries=nqueries
绕过正常的路由表,直接发送到连接网络上的主机。如果主机不在直接连接的网络上,则返回错误。此选项可用于通过没有路由的接口ping本地主机。-s source_addr, --source=source_addr
选择一个备选源地址。请注意,您必须选择其中一个接口的地址。默认情况下,使用传出接口的地址。-z sendwait, --sendwait=sendwait
探测之间的最小时间间隔(默认值0)。如果该值大于10,则指定以毫秒为单位的数字,否则指定秒数(也允许浮点值)。当某些路由器对ICMP消息使用速率限制时很有用。显示ICMP扩展(rfc4884)。一般形式是CLASS/TYPE:后面是十六进制转储。MPLS(rfc4950)显示为解析形式:MPLS:L= label,E=exp_use,S= stack_bottom,T=TTL(更多对象用/分隔)。接口信息(rfc5837)也显示为解析后的形式:{INC|SUB|OUT|NXT}:index,IP_addr,“name”,mtu=mtu(所有四个字段都可能缺失)。 在路由注册表中执行AS路径查找,并在相应地址后直接打印结果。选择要使用的源端口。隐含-N 1 -w 5。通常,源端口(如适用)由系统选择。设置传出数据包的防火墙标记(从Linux内核2.6.25开始)。使用指定的方法进行traceroute操作。默认的传统UDP方法名为Default,ICMP(-I)和TCP(-T)分别名为icmp和tcp。特定于方法的选项可以通过-O传递。大多数方法都有简单的快捷方式(-I表示-M icmp等)。-O option, --options=options
指定一些特定于方法的选项。几个选项用逗号分隔(或在cmdline上使用几个-O)。每种方法可能都有自己的特定选项,或者许多方法根本没有。要打印有关可用选项的信息,请使用-O help。使用UDP到特定的目标端口进行跟踪路由(而不是为每个探测器增加端口)。默认端口为53(DNS)。 使用UDPLITE进行跟踪路由(默认端口为53)。使用DCCP(Datagram Congestion Control Protocol,数据包拥塞控制协议)请求进行探测。-P protocol, --protocol=protocol
使用指定协议的原始数据包进行跟踪路由。默认协议为253(rfc3692)。沿着被追踪的路径发现MTU。暗示-F -N 1。在需要达到新MTU的跳的第一个探测时,以F=NUM的形式打印一次新MTU。(实际上,相应的“需要分片”ICMP消息通常是由前一跳发送的)。请注意,一些路由器可能会缓存一次看到的分片信息。因此,您可以通过更近的调数获得最终的MTU。尝试通过-t指定一个不寻常的TOS,这可能有助于一次尝试(然后它也可以被缓存在那里)。当向后跳数与向前跳数不同时,打印出来。这个数字是在假设远程跳发送初始TTL设置为64、128或255的回复数据包的情况下猜测的(这似乎是一种常见的做法)。它以“-NUM”的形式打印为负数。
可用方法列表
一般来说,特定的traceroute方法可能必须按【-M name】选择,但大多数方法都有简单的cmdline开关(如果存在,您可以在方法名称后面看到它们)。探测数据包是具有所谓“不太可能”目标端口的UDP数据包。第一个探测的“不太可能”端口是33434,然后对于每个下一个探测,它都会递增1。由于这些端口预计不会被使用,目标主机通常会返回“icmp unreach port”作为最终响应。(不过,没有人知道当一些应用程序监听这些端口时会发生什么)。目前最常用的方法是使用icmp echo报文进行探测。如果您可以ping(8)目标主机,则icmp跟踪路由也适用。 自内核 3.0(IPv4,IPv6为自3.11起)以来,此方法可能允许非特权用户使用,它支持新的 dgram icmp(或“ping”)套接字。要允许此类套接字,系统管理员应提供 net/ipv4/ping_group_range sysctl 范围以匹配用户的任何组。raw:仅使用原始套接字(传统方式)。默认情况下,首先尝试这种方式(出于兼容性原因),然后使用新的dgram icmp套接字作为后备。众所周知的现代方法,旨在绕过防火墙。使用固定的目标端口(默认为80,HTTP)。如果网络路径中存在一些过滤器,那么很可能任何“不太可能”的UDP端口(如默认方法)甚至icmp echo(如icmp)都会被过滤,整个跟踪路由将只在这样的防火墙处停止。要绕过网络过滤器,我们必须只使用允许的协议/端口组合。如果我们追踪一些东西,比如邮件服务器,那么更有可能的是-T -p 25可以到达它,即使-I不能。 此方法使用众所周知的“半开放技术”,它完全阻止目标主机上的应用程序看到我们的探测器。通常,会发送一个tcp syn。对于未监听的端口,我们收到tcp reset,一切都完成了。对于主动监听端口,我们接收tcp syn+ack,但通过tcp reset(而不是预期的tcp ack)进行应答,这样即使应用程序没有注意到,远程tcp会话也会被丢弃。syn,ack,fin,rst,psh,urg,ece,cwr:为探测数据包设置指定的tcp标志,可以任意组合。flags=num:将tcp报文头中的标志字段精确设置为num。ecn:发送带有tcp标志ECE和CWR的syn数据包(用于显式拥塞通知,rfc3168)。sack,timestamps,window_scaling:在传出探测数据包中使用相应的TCP报文头选项。sysctl:对上面的TCP报文头选项和ECN使用当前的sysctl(/proc/sys/net/*)设置。如果没有其他指定,则始终默认设置。fastopen:使用fastopen tcp选项(当使用syn时),仅用于初始cookie协商。mss=[num]:将num的值(或不变)用于maxseg tcp报文头选项(当使用syn时),并发现其在被追踪路径上的限制情况。新更改的mss以M=NUM的形式在检测到它的第一个探测上打印一次。注意,一些路由器可能会在超时消息中返回太短的原始片段,导致无法进行检查。除此之外,响应可能会以不同的顺序出现。所有这些都可能导致报告的后续位置(使用-N 1可以帮助确定顺序)。 info:当到达目标主机时,打印最终 tcp 回复的 tcp 标志和支持选项。允许确定应用程序是否监听端口和其他有用的东西。支持的 tcp 选项都是可以通过 -T -O 设置的,即 mss、sack、timestamps、window_scaling 和 fastopen,输出格式相似(mss 为一个值,其他的只是存在)。tcp方法的初始实现,简单地使用connect(2)调用,它可以完全打开tcp会话。正常不建议使用,因为目标应用程序总是会受到影响(并且可能会被混淆)。使用具有固定目标端口(默认53,DNS)的udp数据包。也打算绕过防火墙。请注意,与TCP方法不同,目标主机上的相应应用程序总是会收到我们的探测(带有随机数据),并且大多数应用程序很容易被它们混淆。然而,在大多数情况下,它不会对我们的数据包做出响应,因此我们永远不会在跟踪中看到最后一跳。(幸运的是,似乎至少DNS服务器会回复一些愤怒的内容)。使用udplite数据包进行探测(具有固定的目标端口,默认为53)。选项:coverage=num,将udplite发送覆盖率设置为num。使用DCCP请求数据包进行探测(rfc4340)。此方法使用与TCP相同的“半开放技术”。默认目标端口为33434。选项:service=num,将DCCP服务代码设置为num(默认值为1885957735)。发送协议原型的原始数据包。不使用特定于协议的报头,只使用IP报头。默认表示:-N 1 -w 5。选项:protocol=proto,使用IP协议原型(默认253)。为了加快工作速度,通常会同时发送多个探测。另一方面,它造成了“报文风暴”,尤其是在回复方向。路由器可以限制ICMP响应的速率,一些回复可能会丢失。为了避免这种情况,减少同时探测的数量,甚至将其设置为1(如初始traceroute实现中那样),即-N 1最终(目标)主机可以丢弃一些同时进行的探测,甚至可能只响应最新的探测。这可能会导致在最后一跳附近出现额外的“看起来过期”的跳数。我们使用智能算法来自动检测这种情况,但如果它对你的情况没有帮助,也可以使用-N 1。 为了获得更大的稳定性,您可以通过-z选项减慢程序的工作速度,例如在探测之间使用-z 0.5暂停半秒。为了避免额外的等待,我们使用自适应算法超时(有关更多信息,请参阅-w选项)。它可能会导致过早到期(特别是在响应时间有时不同的情况下),并打印“*”而不是时间。在这种情况下,通过仅指定所需超时的-w(例如-w 5)来关闭此算法。如果某些跃点对每种方法都没有报告任何信息,那么获得信息的最后机会是使用ping -R命令(IPv4,仅适用于最近的8个跃点)。相关命令:ping(8), ping6(8), tcpdump(8), netstat(8)