Трассировка TCP в питоне

Я пишу скрипт 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? Вопрос 2: Я новичок в scapy и traceroute. Есть ли что-то очевидное, что мне не хватает в коде? Есть ли другая библиотека, которую я могу использовать, если scapy не подходит? Я был бы очень признателен за помощь и любые указатели.

ПРИМЕЧАНИЕ: Я ХОЧУ ВЫПОЛНИТЬ МАРШРУТ TCP TRACE ДЛЯ IPV6 И IPV4.


person Hussain ali    schedule 02.11.2018    source источник


Ответы (1)


Действительно ли функция scapy traceroute выполняет трассировку TCP?

Да, она выполняет TCP traceroute (среди прочего). Взгляните на Scapy исходный код:

    @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


Я хочу выполнить tcp traceroute как для ipv6, так и для 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

Пример кода для трассировки 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, указав полный пакет в параметре l4 функции traceroute(), вы не получите одинаковые 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')
  • Кроме того, ознакомьтесь с этим tcptraceroute Томаса Геттлера.

  • Или эту реализацию трассировки с несколькими источниками и геолокацией от Эдди Йеоу (Ayeowch).
    Среди прочего, используя параметр -j (JSON_FILE), он будет отображать источники в формате файла JSON.

  • Или эта реализация от Christian Kreibich. Он может разбивать информацию о трассировке на ряд объектов переходов, каждый из которых состоит из одного или нескольких результатов проверки, а также экземпляров объекта. Кроме того, форматирование строк дает знакомые выходные данные 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, если не хотите разрешать имена.


Для OSX и Linux, а также с Python 2.7 вы можете использовать этот парсер.

person Panos Kal.    schedule 02.11.2018
comment
Пинг и трассировка не совсем одно и то же :/ - person Cukic0d; 02.11.2018
comment
У вас есть обновленный код на 2021 год, пожалуйста? Я не могу заставить ни один из ваших фрагментов кода работать на Python 3.8 в MacOS. - person Monty; 13.04.2021
comment
Это не проблема версии Python. Это скайп версия. Я только что протестировал свои фрагменты с использованием Python 3.7.7, 3.81 и отлично работает с scapy 2.4.3. Используя последнюю документацию scapy, их примеры не работают! - person Panos Kal.; 14.04.2021