python中的TCP Traceroute

时间:2018-11-02 04:05:50

标签: python scapy traceroute

我正在编写一个Python脚本来执行“ TCP Traceroute”。我了解到scapy是执行此操作的有用库,但是我没有得到所需的结果。谁能帮我解决这个问题?我希望python脚本生成与命令行类似的结果。

我正在使用Linux,python 2.7和scapy 2.4。我不确定为什么所有跃点都显示相同的IP地址。

from scapy.layers.inet import traceroute

result, unans = traceroute('172.217.17.46', maxttl=30)
   for snd, rcv in result:
   print snd.ttl, rcv.src, snd.sent_time, rcv.time

运行此代码时,我得到以下结果:

1 10.0.2.2 1541113255.58 1541113255.6
2 172.217.17.46 1541113255.58 1541113255.72
3 172.217.17.46 1541113255.58 1541113255.72
4 172.217.17.46 1541113255.58 1541113255.72
5 172.217.17.46 1541113255.59 1541113255.73
6 172.217.17.46 1541113255.59 1541113255.73
7 172.217.17.46 1541113255.6 1541113255.74
8 172.217.17.46 1541113255.6 1541113255.74
9 172.217.17.46 1541113255.6 1541113255.74
10 172.217.17.46 1541113255.61 1541113255.75
11 172.217.17.46 1541113255.61 1541113255.75
12 172.217.17.46 1541113255.61 1541113255.75
13 172.217.17.46 1541113255.62 1541113255.76
14 172.217.17.46 1541113255.62 1541113255.76
15 172.217.17.46 1541113255.62 1541113255.76
16 172.217.17.46 1541113255.62 1541113255.77
17 172.217.17.46 1541113255.63 1541113255.77
18 172.217.17.46 1541113255.63 1541113255.77
19 172.217.17.46 1541113255.63 1541113255.77
20 172.217.17.46 1541113255.63 1541113255.77
21 172.217.17.46 1541113255.64 1541113255.78
22 172.217.17.46 1541113255.64 1541113255.78
23 172.217.17.46 1541113255.64 1541113255.78
24 172.217.17.46 1541113255.64 1541113255.78
25 172.217.17.46 1541113255.65 1541113255.79
26 172.217.17.46 1541113255.65 1541113255.79
27 172.217.17.46 1541113255.65 1541113255.79
28 172.217.17.46 1541113255.66 1541113255.8
29 172.217.17.46 1541113255.66 1541113255.8
30 172.217.17.46 1541113255.66 1541113255.8

我想获得与从命令行运行tcptraceroute时得到的结果相同的结果:tcptraceroute 172.217.17.46

命令行结果:

Selected device en0, address 192.168.86.24, port 49618 for outgoing packets
Tracing the path to 172.217.17.46 on TCP port 80 (http), 30 hops max
 1  192.168.86.1  2.848 ms  1.224 ms  1.330 ms
 2  96.120.101.53  10.423 ms  13.646 ms  12.221 ms
 3  po-115-rur102.bellevue.wa.seattle.comcast.net (68.87.205.245)  18.877 ms  18.818 ms  12.593 ms
 4  be-103-ar01.seattle.wa.seattle.comcast.net (69.139.164.77)  15.188 ms  14.272 ms  14.005 ms
 5  be-33650-cr01.seattle.wa.ibone.comcast.net (68.86.93.165)  14.547 ms  15.273 ms  19.750 ms
 6  be-10846-pe01.seattle.wa.ibone.comcast.net (68.86.86.90)  14.546 ms  14.266 ms  13.521 ms
 7  50.242.150.242  14.159 ms  15.791 ms  14.037 ms
 8  74.125.243.195  14.635 ms  22.377 ms  13.558 ms
 9  72.14.236.174  15.051 ms  27.454 ms  14.312 ms
 10  108.170.235.60  66.430 ms  69.762 ms  68.606 ms
 11  216.239.58.255  85.531 ms  84.354 ms  85.303 ms
 12  172.253.51.157  153.310 ms  154.710 ms  153.375 ms
 13  209.85.142.166  157.376 ms  166.552 ms  157.562 ms
 14  216.239.43.37  170.523 ms  168.040 ms  158.182 ms
 15  108.170.241.225  158.953 ms  161.418 ms  169.103 ms
 16  108.170.236.137  158.561 ms  161.635 ms  157.510 ms
 17  ams16s29-in-f46.1e100.net (172.217.17.46) [open]  165.981 ms  160.451 ms  166.120 ms

问题1:Scapy traceroute功能是否真的是TCP traceroute? Question2:我对scapy和traceroute是陌生的,代码中明显缺少什么吗?如果scapy不适合,我还可以使用其他库吗?我真的很感谢您的帮助和任何指导。

注意:我想对IPV6和IPV4都执行TCP跟踪路由。

1 个答案:

答案 0 :(得分:7)

scapy traceroute函数确实是TCP traceroute吗?

是的,它确实执行TCP跟踪路由(以及其他功能)。看看Scapy source-code

    @conf.commands.register
    def traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4 = None, filter=None, timeout=2, verbose=None, **kargs):
        """Instant TCP traceroute traceroute(target, [maxttl=30,] [dport=80,] [sport=80,] [verbose=conf.verb]) -> None"""
        if verbose is None:
            verbose = conf.verb
        if filter is None:
            # we only consider ICMP error packets and TCP packets with at
            # least the ACK flag set *and* either the SYN or the RST flag
            # set
            filter="(icmp and (icmp[0]=3 or icmp[0]=4 or icmp[0]=5 or icmp[0]=11 or icmp[0]=12)) or (tcp and (tcp[13] & 0x16 > 0x10))"
        if l4 is None:
            a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
                     timeout=timeout, filter=filter, verbose=verbose, **kargs)
        else:
            # this should always work
            filter="ip"
            a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/l4,
                     timeout=timeout, filter=filter, verbose=verbose, **kargs)
        a = TracerouteResult(a.res)
        if verbose:
            a.show()
        return a,b


我想对tcpipv6都执行ipv4跟踪路由

再次查看Scapy源代码,traceroot6可以完成这项工作:

def traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), 
                l4 = None, timeout=2, verbose=None, **kargs):
    """
    Instant TCP traceroute using IPv6 :
    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
    """
    if verbose is None:
        verbose = conf.verb

    if l4 is None:
        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
                 timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
    else:
        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
                 timeout=timeout, verbose=verbose, **kargs)
    a = TracerouteResult6(a.res)
    if verbose:
        a.display()
    return a,b

traceroute ipv6的示例代码:

from scapy.all import *

waypoint = "2001:301:0:8002:203:47ff:fea5:3085"
target = "2001:5f9:4:7:2e0:81ff:fe52:9a6b"
traceroute6(waypoint, minttl=10, maxttl=40, l4=IPv6ExtHdrRouting(addresses=[target])/ICMPv6EchoRequest(data=RandString(7)))


我不确定为什么所有跃点都显示相同的IP地址。

使用 DNS traceroute ,通过在traceroute()函数的l4参数中指定完整的数据包,您不会为所有跃点获得相同的IP地址

from scapy.all import *

target = ["172.217.17.46"]
result, unans = traceroute(target, l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="www.google.com")))


或者,您可以使用 TCP SYN traceroute 获得类似的结果:

from scapy.all import *

target = ["172.217.17.46"]
result, unans = sr(IP(dst=target, ttl=(1, 10)) / TCP(dport=53, flags="S"))
for snd, rcv in result:
  print(snd.ttl, rcv.src, snd.sent_time, rcv.time)


或者您可以创建 IP and UDP packets 来使用traceroute来实现Scapy,如下所示:

from scapy.all import *
hostname = "172.217.17.46"
for i in range(1, 28):
    pkt = IP(dst=hostname, ttl=i) / UDP(dport=33434)
    reply = sr1(pkt, verbose=0)
    if reply is None:
        break
    elif reply.type == 3:
        print("Done!", reply.src)
        break
    else:
        print("%d hops away: " % i, reply.src, reply.time)


如果Scapy不适合使用其他库吗?

  • 签出webb。我没有使用它,但是您可以像这样使用它:
import webb
webb.traceroute("www.google.com")
webb.traceroute("www.google.com",'file-name.txt')
  • 还有check out this tcptraceroute,作者是Thomas Guettler。

  • 或者Addy Yeow(Ayeowch)的此Multi-source traceroute with geolocation实现。
    除其他外,使用-j参数(JSON_FILE),它将以JSON文件格式列出源。

  • 或Christian Kreibich的this implementation。它可以将traceroute信息解析为一系列的跃点对象,每个跃点对象都包含一个或多个探测结果,同样是对象实例。同样,字符串格式会产生熟悉的traceroute输出。
    (为了使用Python 3,需要将cStringIO更改为from io import StringIO


没有 scapy (使用Windows控制台):

  

创建一个名为 output.py 的脚本,其中包含以下内容:

import sys
from subprocess import Popen

if len(sys.argv) < 2:
    print('Usage: output.py "command to watch"')
    sys.exit(1)

cmd_line = sys.argv[1:]

p = Popen(cmd_line)
p.communicate()[0]
  

示例用法: python output.py ping google.com

     

ping 的示例输出:

Pinging google.com [216.58.209.14] with 32 bytes of data:
Reply from 216.58.209.14: bytes=32 time=50ms TTL=56
Reply from 216.58.209.14: bytes=32 time=45ms TTL=56
Reply from 216.58.209.14: bytes=32 time=45ms TTL=56
Reply from 216.58.209.14: bytes=32 time=45ms TTL=56

Ping statistics for 216.58.209.14:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 45ms, Maximum = 50ms, Average = 46ms

  

用法示例: python output.py tracert google.com

     

tracert 的示例输出:

Tracing route to google.com [172.217.18.174]
over a maximum of 30 hops:

  1    <1 ms     1 ms     1 ms  192.168.0.1
  2     6 ms     8 ms     8 ms  xx.xx.xx.xx
  3     8 ms     8 ms     8 ms  [xx.xx.xxx.xxx]
  4    17 ms    16 ms    16 ms  be3549.ccr31.sof02.atlas.cogentco.com [154.54.59.138]
  5    18 ms    17 ms    20 ms  be3421.ccr51.beg03.atlas.cogentco.com [130.117.0.94]
  6    32 ms    31 ms    30 ms  be3464.ccr52.vie01.atlas.cogentco.com [154.54.59.189]
  7    39 ms    37 ms    44 ms  be3462.ccr22.muc03.atlas.cogentco.com [154.54.59.182]
  8    42 ms    48 ms    44 ms  be2960.ccr42.fra03.atlas.cogentco.com [154.54.36.253]
  9    44 ms    50 ms    50 ms  be3187.agr41.fra03.atlas.cogentco.com [130.117.1.117]
 10    43 ms    45 ms    46 ms  tata.fra03.atlas.cogentco.com [130.117.15.86]
 11    45 ms    45 ms    44 ms  72.14.196.162
 12    43 ms    41 ms    46 ms  108.170.251.129
 13    46 ms    46 ms    45 ms  74.125.37.167
 14    45 ms    52 ms    48 ms  fra15s29-in-f14.1e100.net [172.217.18.174]

如果您不希望解析名称,则可以使用tracert -d


对于OSXLinux以及Python 2.7,您可以使用此parser