traceroute - 打印数据包跟踪到网络主机的路由
概要
traceroute [-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]
host [packet_len]
traceroute6 [options]
tcptraceroute [options]
lft [options]
描述
traceroute 跟踪从 IP 网络发送到给定主机的数据包所经过的路由。
它利用 IP 协议的生存时间 (TTL) 字段,并尝试从沿着到达主机路径上的每个网关中获取 ICMP TIME_EXCEEDED 响应。
traceroute6 等效于 traceroute -6
tcptraceroute 等效于 traceroute -T
lft,四层跟踪工具,执行 TCP 跟踪,类似于 traceroute -T,但尝试提供与原始的同类实现(也称为“lft”)的兼容性。
唯一的必需参数是目标主机名称或 IP 地址。可选的 packet_len 是探测数据包的总大小(IPv4 的默认值为 60 字节,IPv6 的默认值为 80 字节)。在某些情况下,可以忽略指定的尺寸,或增加到最小值。
此程序尝试通过启动具有小 TTL(生存时间)的探测数据包,然后侦听来自路径上网关的 ICMP“超时”回复,来跟踪 IP 数据包将遵循的到达某个 Internet 主机的路由。我们从 TTL 为 1 的探测开始,并每次增加 1,直到我们收到 ICMP“端口不可达”(或 TCP 重置),这意味着我们到达了“主机”,或者达到了最大值(默认为 30 跳)。默认情况下,每个 TTL 设置会发送三个探测,并打印一行,显示每个探测的 TTL、网关地址和往返时间。地址后可以根据请求打印其他信息。如果来自不同网关的探测回复,将打印每个响应系统的地址。如果在一定超时时间内没有响应,则为该探测打印一个“*”(星号)。
在行程时间之后,可以打印一些额外的注释:!H、!N 或 !P(主机、网络或协议不可达)、!S(源路由失败)、!F(需要分片)、!X(通信受管理方式禁止)、!V(主机优先级违规)、!C(优先级截止生效)或 !
我们不希望目标主机处理 UDP 探测数据包,因此目标端口设置为不太可能的值(您可以使用 -p 标志进行更改)。对于 ICMP 或 TCP traceroute,不存在此类问题(对于 TCP,我们使用半开放技术,可以防止我们的探测包被目标主机上的应用程序看到)。
在现代网络环境中,传统的 traceroute 方法并不总是适用,因为防火墙被广泛使用。此类防火墙会过滤“不太可能”的 UDP 端口,甚至 ICMP 回显。为了解决这个问题,实现了一些额外的 traceroute 方法(包括 tcp),请参见下面的可用方法列表。这些方法尝试使用特定的协议和源/目标端口,以绕过防火墙(让防火墙只将其视为允许类型的网络会话的开始)。
选项
--help 打印帮助信息并退出。
-4, -6 显式强制使用 IPv4 或 IPv6 traceroute。默认情况下,程序将尝试解析给定的名称,并自动选择适当的协议。如果解析主机名返回 IPv4 和 IPv6 地址,traceroute 将使用 IPv4。
-I, --icmp
使用 ICMP ECHO 作为探测。
-T, --tcp
使用 TCP SYN 作为探测。
-d, --debug
启用套接字级别调试(如果 Linux 内核支持)。
-F, --dont-fragment
不要分片探测数据包。(对于 IPv4,它还会设置 DF 位,该位告诉中间路由器不要远程分片)。
通过使用 packet_len 命令行参数更改探测数据包的大小,您可以手动获取有关各个网络跃点 MTU 的信息。--mtu 选项(参见下文)尝试自动执行此操作。
请注意,非分片功能(如 -F 或 --mtu)仅在 Linux 内核 6.22 及更高版本中有效。在此版本之前,IPv6 始终会被分片,IPv4 只能使用从路由缓存中发现的最终 MTU(这可能小于设备的实际 MTU)。
-f first_ttl, --first=first_ttl
指定从哪个 TTL 值开始。默认值为 1。
-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
指定 traceroute 将探测的最大跃点数(最大生存时间值)。默认值为 30。
-N squeries, --sim-queries=squeries
指定同时发送的探测数据包数量。并发发送多个探测数据包可以大大加快 traceroute 的速度。默认值为 16。 请注意,某些路由器和主机可以使用 ICMP 速率限制。在这种情况下,指定过大的数量可能会导致某些响应丢失。
-n 在显示 IP 地址时,不要尝试将其映射到主机名。
-p port, --port=port
对于 UDP 跟踪,指定 traceroute 将使用的目标端口(目标端口号将随着每个探测而递增)。 对于 ICMP 跟踪,指定初始 ICMP 序列值(每个探测也会递增)。 对于 TCP 和其他协议,仅指定要连接的(常量)目标端口。在使用 tcptraceroute 包装器时,-p 指定源端口。
-t tos, --tos=tos
对于 IPv4,设置服务类型 (TOS) 和优先级值。有用的值包括 16(低延迟)和 8(高吞吐量)。请注意,为了使用某些 TOS 优先级值,您必须是超级用户。 对于 IPv6,设置流量控制值。
-l flow_label, --flowlabel=flow_label
为 IPv6 数据包使用指定的 flow_label。
-w max[,here,near], --wait=max[,here,near]
确定等待探测响应的时间。
有三个(通常)浮点值,用逗号(或斜杠)分隔。Max 指定最大等待时间(以秒为单位,默认为 5.0),无论如何。
传统的 traceroute 实现始终等待整个 max 秒。但是,如果我们已经从同一跳或甚至从下一跳收到了某些响应,我们可以使用这些响应的往返时间作为提示来确定实际合理的等待时间。
可选的 here(默认为 3.0)指定一个因子,用于将已接收到的来自同一跳的响应的往返时间相乘。所得值将用作探测的超时时间,而不是(也不超过)max。可选的 near(默认为 10.0)指定一个类似的因子,用于来自下一跳的响应。 (在这种情况下,始终使用找到的第一个结果的时间)。
首先,我们查找同一跳(探测将从现在开始首先打印)。如果未找到,则查找下一跳。如果未找到,则使用 max。如果 here 和/或 near 具有零值,则跳过相应的计算。 如果仅指定 max,则始终将 here 和 near 设置为零(为了与早期版本兼容)。
-q nqueries, --queries=nqueries
设置每个跳的探测数据包数量。默认值为 3。
-r 绕过正常的路由表,并直接发送到附加网络上的主机。如果主机不在直接连接的网络上,则返回错误。
此选项可用于通过没有路由的主机 ping 本地主机。
-s source_addr, --source=source_addr
选择替代源地址。请注意,您必须选择其中一个接口的地址。默认情况下,使用传出接口的地址。
-z sendwait, --sendwait=sendwait
最小探测间隔时间(默认值为 0)。如果该值大于 10,则表示毫秒数;否则,表示秒数(允许使用浮点值)。当某些路由器对 ICMP 消息使用速率限制时,此选项很有用。
-e, --extensions
显示 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(所有四个字段都可能缺失)。
-A, --as-path-lookups
在路由注册表中执行 AS 路径查找,并在相应地址之后直接打印结果。
-V, --version
打印版本信息并退出。
以下是一些用于高级用途的附加选项(例如,替代跟踪方法等):
--sport=port
选择要使用的源端口。这意味着 -N 1 -w 5。通常,系统会选择源端口(如果适用)。
--fwmark=mark
设置传出数据包的防火墙标记(自 Linux 内核 2.6.25 以来)。
-M method, --module=name
使用指定的用于 traceroute 操作的方法。默认的传统 UDP 方法名称为 default,ICMP(-I)和 TCP(-T)的名称分别为 icmp 和 tcp。
可以通过 -O 传递特定于方法选项。大多数方法都有其简单的快捷方式(-I 意味着 -M icmp 等)。
-O option, --options=options
指定一些特定于方法选项。多个选项之间用逗号分隔(或在命令行中使用多个 -O)。每个方法可能有其自己特定的选项,或者可能根本没有选项。要打印可用选项的信息,请使用 -O help。
-U, --udp
使用 UDP 连接到特定目标端口进行 traceroute(而不是为每个探测增加端口)。默认端口为 53(dns)。
-UL 使用 UDPLITE 进行 traceroute(默认端口为 53)。
-D, --dccp
使用 DCCP 请求进行探测。
-P protocol, --protocol=protocol
使用指定协议的原始数据包进行 traceroute。默认协议为 253(rfc3692)。
--mtu 发现沿着跟踪路径的 MTU。这意味着 -F -N 1。新的 MTU 以 F=NUM 的形式打印在需要达到该 MTU 的跃点的第一个探测中。(实际上,相应的“需要分片”ICMP 消息通常由上一个跃点发送)。
请注意,某些路由器可能会缓存一次看到的信息,关于分片。因此,您可能会从更近的跃点接收到最终的 MTU。尝试通过 -t 指定不寻常的 TOS,这可能会有所帮助(然后它也可以在那里被缓存)。
有关更多信息,请参阅 -F 选项。
--back 打印反向跃点数,当它似乎与正向方向不同时。
此数字是根据以下假设猜测的:远程跃点发送的回复数据包的初始 TTL 设置为 64、128 或 255(这似乎是一种常见做法)。它以负值的形式打印,如下所示:-NUM。
可用方法列表
通常,必须通过 -M 名称选择特定的 traceroute 方法,但大多数方法都有其简单的命令行开关(如果存在,可以在方法名称后看到)。
default
传统的、古老 traceroute 方法。默认使用。
探测数据包是带有“不太可能”的目标端口的 udp 数据报。第一个探测的“不太可能”端口是 33434,然后每个后续探测的端口递增 1。由于这些端口预计未被使用,因此目标主机通常会返回“icmp unreachable port”作为最终响应。(没有人知道如果某个应用程序监听这些端口会发生什么)。
此方法允许非特权用户使用。
icmp -I
现在最常用的方法,它使用 icmp echo 数据包进行探测。 如果可以使用 ping(8) 命令 ping 目标主机,则 icmp traceroute 同样适用。
此方法可能允许非特权用户使用,从内核 3.0 开始(IPv4,对于 IPv6,从 11 开始,支持新的 dgram icmp(或“ping”)套接字。要允许此类套接字,系统管理员应提供 net/ipv4/ping_group_range sysctl 范围,以匹配用户的任意组。 选项:
raw 使用仅限 raw 套接字(传统方式)。 这种方式首先尝试(出于兼容性原因),然后作为回退使用新的 dgram icmp 套接字。
dgram 仅使用 dgram icmp 套接字。
tcp -T
一种众所周知的现代方法,旨在绕过防火墙。 使用恒定的目标端口(默认值为 80,http)。
如果在网络路径中存在某些过滤器,那么最有可能的是任何“不太可能”的 udp 端口(如默认方法)或甚至是 icmp 回显(如 icmp)都会被过滤,并且整个 traceroute 都会在防火墙处停止。要绕过网络过滤器,我们必须仅使用允许的协议/端口组合。如果我们跟踪一个邮件服务器,那么使用 -T -p 25 更有可能到达目标,即使 -I 无法到达。
此方法使用众所周知的“半开放技术”,可防止目标主机上的应用程序看到我们的探测。通常,会发送一个 tcp syn。对于未监听的端口,我们会收到 tcp reset,一切就完成了。对于正在监听的端口,我们会收到 tcp syn+ack,但通过发送 tcp reset 来回复(而不是预期的 tcp ack),这样远程 tcp 会话会在应用程序注意到之前被丢弃。
tcp 方法有几个选项:
syn,ack,fin,rst,psh,urg,ece,cwr
设置探测数据包中指定的 tcp 标志,可以组合使用。
flags=num
将 tcp 标头中的标志字段设置为 num。
ecn 发送带有 tcp 标志 ECE 和 CWR(用于显式拥塞通知,rfc3168)的 syn 数据包。
sack,timestamps,window_scaling
在传出的探测数据包中使用相应的 tcp 标头选项。
sysctl:使用当前的 sysctl(/proc/sys/net/*)设置,用于上述 TCP 标头选项和 ECN。
默认始终设置,除非另有指定。
fastopen:使用 fastopen TCP 选项(在 SYN 包中),仅用于初始 cookie 协商。
mss=[num]:使用 num 的值(或未更改)作为 maxseg TCP 标头选项(在 SYN 包中),并发现沿跟踪路径的限制。新的更改的 MSS 会在检测到的第一个探测中以 M=NUM 的形式打印一次。请注意,某些路由器可能会返回过短的原始片段作为超时消息,这使得检查不可能。此外,响应的顺序可能不同。所有这些都可能导致报告出现在较晚的位置(使用 -N 1 可以帮助确定顺序)。
info:打印最终 TCP 响应的 TCP 标志和支持的选项,以确定目标主机是否正在侦听端口以及其他有用的信息。支持的 TCP 选项是所有可以通过 -T -O 设置的选项,即 mss、sack、时间戳、窗口缩放和 fastopen,输出格式相似(mss 为一个值,其他选项仅表示存在)。
默认选项为 syn、sysctl。
tcpconn:TCP 方法的初始实现,简单地使用 connect(2) 调用,从而建立完整的 TCP 会话。不建议用于正常使用,因为目标应用程序始终会受到影响(并且可能会感到困惑)。
udp:-U
使用 UDP 数据报,带有固定的目标端口(默认 53,DNS)。 旨在绕过防火墙。
请注意,与 TCP 方法不同,目标主机上的相应应用程序始终会收到我们的探测(带有随机数据),并且大多数应用程序很容易被这些探测所迷惑。在大多数情况下,它不会响应我们的数据包,因此我们永远无法看到跟踪中的最终跳。幸运的是,似乎至少 DNS 服务器会以某种方式进行响应。
此方法允许非特权用户使用。
udplite:-UL
使用 UDPLite 数据报进行探测(带有固定的目标端口,默认 53)。
此方法允许非特权用户使用。 选项:
coverage=num:将 UDPLite 发送覆盖率设置为 num。
dccp:-D
使用 DCCP 请求数据包进行探测(rfc4340)。
此方法使用与 TCP 相同的方式,即“半开放技术”。默认目标端口为 3343。
选项:
service=num:将 DCCP 服务代码设置为 num(默认值为 1885957735)。
raw:-P proto
发送协议为 proto 的原始数据包。 不使用任何特定于协议的标头,仅使用 IP 标头。 意味着 -N 1 -w 5。 选项:
protocol=proto:使用 IP 协议 proto(默认值为 253)。
备注
为了加快速度,通常会同时发送多个探测。另一方面,这会产生“数据包风暴”,尤其是在响应方向上。路由器可能会限制 ICMP 响应的速率,并且可能会丢失一些响应。为了避免这种情况,请减少同时发送的探测数量,甚至将其设置为 1(就像最初的 traceroute 实现一样),即 -N 1。
最终(目标)主机可能会丢弃一些并发探测,甚至可能只响应最新的探测。这可能导致在最后一个跃点附近出现额外的“看起来已过期”的情况。我们使用一种智能算法来自动检测这种情况,但如果它在您的案例中无法提供帮助,请使用 -N 1。
为了获得更高的稳定性,您可以减慢程序的运行速度,使用 -z 选项,例如使用 -z 5,在探测之间进行半秒的暂停。
为了避免额外的等待,我们使用自适应算法来设置超时时间(请参阅 -w 选项以获取更多信息)。这可能会导致过早超时(尤其是在响应时间不一致时),并打印“*”而不是时间。在这种情况下,请通过指定带有所需超时时间的 -w 来关闭此算法(例如,-w 5)。
如果某些跃点对每种方法都没有任何响应,那么获得信息的最后机会是使用 ping -R 命令(IPv4,并且仅限于最近的 8 个跃点)。