import socket
import traceback
import requests
# # socket de UDP
# udp_send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# # socket RAW de citire a răspunsurilor ICMP
# icmp_recv_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
# icmp_recv_socket.bind(('', 0))
# # setam timout in cazul in care socketul ICMP la apelul recvfrom nu primeste nimic in buffer
# icmp_recv_socket.settimeout(5)
# def traceroute(ip, port):
# setam TTL in headerul de IP pentru socketul de UDP
# for i in range(1, 30):
# TTL = i
# udp_send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, TTL)
# # trimite un mesaj UDP catre un tuplu (IP, port)
# udp_send_sock.sendto(b'salut', (ip, port))
# # asteapta un mesaj ICMP de tipul ICMP TTL exceeded messages
# # in cazul nostru nu verificăm tipul de mesaj ICMP
# # puteti verifica daca primul byte are valoarea Type == 11
# # https://tools.ietf.org/html/rfc792#page-5
# # https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Header
# addr = 'done!'
# try:
# data, addr = icmp_recv_socket.recvfrom(63535)
# except Exception as e:
# print("Socket timeout ", str(e))
# print(traceback.format_exc())
# print(addr)
# if addr[0] == ip:
# break
# return addr
# i = 0
# while i < 2:
# i += 1
# # setam TTL in headerul de IP pentru socketul de UDP
# TTL = i
# udp_send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, TTL)
# # trimite un mesaj UDP catre un tuplu (IP, port)
# udp_send_sock.sendto(b'salut', (ip, port))
# try:
# data, addr = icmp_recv_socket.recvfrom(63535)
# print(addr)
# except Exception as e:
# print("Socket timeout ", str(e))
# print(traceback.format_exc())
# continue
# if addr[0] == ip:
# break
# return addr
def traceroute(hostname):
address = socket.gethostbyname(hostname)
port = 33434
max_hops = 30
icmp = socket.getprotobyname('icmp')
udp = socket.getprotobyname('udp')
ttl = 1
while True:
recv_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, udp)
send_socket.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
recv_socket.bind(("", port))
send_socket.sendto(b'', (hostname, port))
curr_addr = None
curr_name = None
try:
_, curr_addr = recv_socket.recvfrom(512)
curr_addr = curr_addr[0]
try:
curr_name = socket.gethostbyaddr(curr_addr)[0]
except socket.error:
curr_name = curr_addr
except socket.error:
pass
finally:
send_socket.close()
recv_socket.close()
if curr_addr is not None:
curr_host = "%s (%s)" % (curr_name, curr_addr)
else:
curr_host = "*"
print("%d\t%s" % (ttl, curr_host))
ttl += 1
if curr_addr == address or ttl > max_hops:
break
return curr_addr
'''
Exercitiu hackney carriage (optional)!
e posibil ca ipinfo sa raspunda cu status code 429 Too Many Requests
cititi despre campul X-Forwarded-For din antetul HTTP
https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
si setati-l o valoare in asa fel incat
sa puteti trece peste sistemul care limiteaza numarul de cereri/zi
Alternativ, puteti folosi ip-api (documentatie: https://ip-api.com/docs/api:json).
Acesta permite trimiterea a 45 de query-uri de geolocare pe minut.
'''
# exemplu de request la IP info pentru a
# obtine informatii despre localizarea unui IP
fake_HTTP_header = {
'referer': 'https://ipinfo.io/',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36'
}
# informatiile despre ip-ul 193.226.51.6 pe ipinfo.io
# https://ipinfo.io/193.226.51.6 e echivalent cu
# raspuns = requests.get('https://ipinfo.io/widget/193.226.51.6', headers=fake_HTTP_header)
# print(raspuns.json())
#
# # pentru un IP rezervat retelei locale da bogon=True
# raspuns = requests.get('https://ipinfo.io/widget/10.0.0.1', headers=fake_HTTP_header)
# print(raspuns.json())
if __name__ == '__main__':
traceroute('google.com')