Last active
August 29, 2015 14:19
-
-
Save remohammadi/b3fe57e9314e8fa918bc to your computer and use it in GitHub Desktop.
Http Traceroute
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #! /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