Skip to content

Instantly share code, notes, and snippets.

@remohammadi
Last active August 29, 2015 14:19
Show Gist options
  • Select an option

  • Save remohammadi/b3fe57e9314e8fa918bc to your computer and use it in GitHub Desktop.

Select an option

Save remohammadi/b3fe57e9314e8fa918bc to your computer and use it in GitHub Desktop.
Http Traceroute
#! /usr/bin/env python
import sys
import time
from scapy.all import *
# thanks to http://jvns.ca/blog/2013/10/31/day-20-scapy-and-traceroute/
if len(sys.argv) < 2:
print "Usage: %s example.org" % sys.argv[0]
sys.exit(1)
HOSTNAME = sys.argv[1]
REQUEST = """GET / HTTP/1.1
Host: %s
""" % HOSTNAME
SRC_PORTS = [33434, 50000, 55000, 55123, 55321, 58765, 59012, 59999, 60000]
print " # state http node ip (time/sample size) ping node ip (time/sample size)"
for i in range(1, 28):
http_pkts = IP(dst=HOSTNAME, ttl=i) / TCP(sport=SRC_PORTS, dport=80) / REQUEST
ans, unans = sr(http_pkts, verbose=0, timeout=2, retry=2)
if len(ans) == 0:
# No reply =(
print("%2d: No reply" % i)
continue
ans_dic = {}
for pkt_pair in ans:
s = pkt_pair[1].src
ans_dic[s] = ans_dic.get(s, [])
ans_dic[s].append(pkt_pair)
most_visited_ip = None
for ip, pkts in ans_dic.items():
if (not most_visited_ip) or (len(pkts) > ans_dic[most_visited_ip]):
most_visited_ip = ip
sorted_http_ans = sorted(ans_dic[most_visited_ip], key=lambda pkt_pair: (pkt_pair[1].time - pkt_pair[0].time))
if len(sorted_http_ans) == 1:
http_time = 1000 * (sorted_http_ans[0][1].time - sorted_http_ans[0][0].time)
elif len(sorted_http_ans) == 2:
http_time = sorted_http_ans[0][1].time - sorted_http_ans[0][0].time
http_time += sorted_http_ans[1][1].time - sorted_http_ans[1][0].time
http_time *= 500
else:
sample_ans = sorted_http_ans[1:-1]
http_time = sum([(pkt_pair[1].time - pkt_pair[0].time) for pkt_pair in sample_ans])
http_time = http_time * 1000 / len(sample_ans)
msg = "hops away" if isinstance(sorted_http_ans[0][1].payload, ICMP) else "Done!"
# Try to get the ping time of the same node of which we have http time
ping_pkts = IP(dst=HOSTNAME, ttl=i) / UDP(sport=SRC_PORTS, dport=33434)
ans, unans = sr(ping_pkts, verbose=0, timeout=2, retry=2)
ans_dic = {}
for pkt_pair in ans:
s = pkt_pair[1].src
ans_dic[s] = ans_dic.get(s, [])
ans_dic[s].append(pkt_pair)
if most_visited_ip in ans_dic:
ping_ip = most_visited_ip
ping_ans = ans_dic[ping_ip]
else:
ping_ip = None
for ip, pkts in ans_dic.items():
if (not ping_ip) or (len(pkts) > ans_dic[ping_ip]):
ping_ip = ip
ping_msg = None
sorted_ping_ans = sorted(ping_ans, key=lambda pkt_pair: (pkt_pair[1].time - pkt_pair[0].time))
if len(sorted_ping_ans) == 0:
ping_msg = "No ping reply"
elif len(sorted_ping_ans) == 1:
ping_time = 1000 * (sorted_ping_ans[0][1].time - sorted_ping_ans[0][0].time)
elif len(sorted_ping_ans) == 2:
ping_time = sorted_ping_ans[0][1].time - sorted_ping_ans[0][0].time
ping_time += sorted_ping_ans[1][1].time - sorted_ping_ans[1][0].time
ping_time *= 500
else:
sample_ans = sorted_ping_ans[1:-1]
ping_time = sum([(pkt_pair[1].time - pkt_pair[0].time) for pkt_pair in sample_ans])
ping_time = ping_time * 1000 / len(sample_ans)
if not ping_msg:
ping_msg = "ping: %15s (%6.1fms/%2d)" % (ping_ip, ping_time, len(sorted_ping_ans))
print("%2d: %9s %15s (%6.1fms/%2d) - %s" % (
i, msg, most_visited_ip, http_time, len(sorted_http_ans), ping_msg))
if not isinstance(sorted_http_ans[0][1].payload, ICMP):
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment