From 1d30fcd57e5a9cf079474baf8d673380ad166afa Mon Sep 17 00:00:00 2001 From: xhdix Date: Wed, 1 Jun 2022 02:22:58 +0300 Subject: [PATCH 1/3] feat: ability to set iface --- tracevis.py | 26 ++++++++++++++++++++++++-- utils/geolocate.py | 8 ++++---- utils/trace.py | 26 +++++++++++++++++--------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/tracevis.py b/tracevis.py index 104fbc5..af4ba7a 100755 --- a/tracevis.py +++ b/tracevis.py @@ -24,6 +24,11 @@ OS_NAME = platform.system() +def show_conf_route(): + from scapy.all import conf + print(conf.route) + + def dump_args_to_file(file, args, packet_info): args_without_config_arg = args.copy() if 'config_file' in args_without_config_arg: @@ -121,6 +126,10 @@ def get_args(): - 'new' : to change source port, sequence number, etc in each request (default) - 'new,rexmit' : to begin with the 'new' option in each of the three steps for all destinations and then rexmit""" ) + parser.add_argument('--iface', type=str, + help="set the target network interface") + parser.add_argument('--interfaces', action='store_true', + help="see the network interfaces (conf.route)") if len(sys.argv) == 1: parser.print_help() sys.exit(1) @@ -158,6 +167,7 @@ def main(args): edge_lable = "backttl" trace_retransmission = False trace_with_retransmission = False + iface = None output_dir = os.getenv('TRACEVIS_OUTPUT_DIR', DEFAULT_OUTPUT_DIR) if not os.path.exists(output_dir): os.mkdir(output_dir) @@ -190,14 +200,26 @@ def main(args): if args.get("paris"): trace_with_retransmission = True if args.get("options"): - # this argument will be changed or removed before v1.0.0 trace_options = args["options"].replace(' ', '').split(',') if "new" in trace_options and "rexmit" in trace_options: + print("Notice: this argument will be changed or removed before v1.0.0") + print("use --paris intead") trace_with_retransmission = True elif "rexmit" in trace_options: + print("Notice: this argument will be changed or removed before v1.0.0") + print("use --rexmit intead") trace_retransmission = True else: pass # "new" is default + if args.get("iface"): + if args["iface"] == "": + show_conf_route() + exit() + else: + iface = args["iface"] + if args.get("interfaces"): + show_conf_route() + exit() if args.get("dns") or args.get("dnstcp"): do_traceroute = True name_prefix += "dns" @@ -245,7 +267,7 @@ def main(args): continue_to_max_ttl=continue_to_max_ttl, do_tcph1=do_tcph1, do_tcph2=do_tcph2, trace_retransmission=trace_retransmission, - trace_with_retransmission=trace_with_retransmission) + trace_with_retransmission=trace_with_retransmission, iface=iface) if no_internet: attach_jscss = True if args.get("ripe"): diff --git a/utils/geolocate.py b/utils/geolocate.py index 4a2abb4..c65cfe0 100644 --- a/utils/geolocate.py +++ b/utils/geolocate.py @@ -15,7 +15,7 @@ OS_NAME = platform.system() -def nslookup(): +def nslookup(user_iface=None): # there is no timeout in getaddrinfo(), so we have to do it ourselves # Raw packets bypasses the firewall so it may not work as intended in some cases dns_request = IP( @@ -24,7 +24,7 @@ def nslookup(): rd=1, id=RandShort(), qd=DNSQR(qname="speed.cloudflare.com")) try: request_and_answers, _ = sr( - dns_request, verbose=0, timeout=1) + dns_request, iface=user_iface, verbose=0, timeout=1) except: return False if request_and_answers is not None and len(request_and_answers) != 0: @@ -59,7 +59,7 @@ def get_meta_json(): os.seteuid(usereuid) -def get_meta(): +def get_meta(user_iface=None): no_internet = True public_ip = '127.1.2.7' # we should know that what we are going to clean network_asn = 'AS0' @@ -67,7 +67,7 @@ def get_meta(): country_code = '' city = '' print("· - · · · detecting IP, ASN, country, etc · - · · · ") - if not nslookup(): + if not nslookup(user_iface): return no_internet, public_ip, network_asn, network_name, country_code, city user_meta = get_meta_json() if user_meta is not None: diff --git a/utils/trace.py b/utils/trace.py index 6a5cff6..60ea981 100755 --- a/utils/trace.py +++ b/utils/trace.py @@ -23,6 +23,7 @@ LOCALHOST = '127.0.0.1' SLEEP_TIME = 1 have_2_packet = False +user_iface=None measurement_data = [[], []] OS_NAME = platform.system() @@ -153,6 +154,7 @@ def get_new_timestamp(): def send_packet_with_tcphandshake(this_request, timeout): + global user_iface timestamp_start, new_timestamp = get_new_timestamp() ip_address = this_request[IP].dst destination_port = this_request[TCP].dport @@ -169,7 +171,7 @@ def send_packet_with_tcphandshake(this_request, timeout): sport=source_port, dport=destination_port, seq=RandInt(), flags="S", options=syn_tcp_options) tcp_handshake_timeout = timeout + max_repeat - ans, unans = sr(send_syn, verbose=0, timeout=tcp_handshake_timeout) + ans, unans = sr(send_syn, iface=user_iface, verbose=0, timeout=tcp_handshake_timeout) if len(ans) == 0: print("Warning: No response to SYN packet yet") max_repeat += 1 @@ -190,7 +192,7 @@ def send_packet_with_tcphandshake(this_request, timeout): dst=ip_address, id=(ans[0][0][IP].id + 1), flags="DF")/TCP( sport=source_port, dport=destination_port, seq=ans[0][1][TCP].ack, ack=ans[0][1][TCP].seq + 1, flags="A", options=ack_tcp_options) - send(send_ack, verbose=0) + send(send_ack, iface=user_iface, verbose=0) send_data = this_request del(send_data[IP].src) send_data[IP].id = ans[0][0][IP].id + 2 @@ -203,7 +205,7 @@ def send_packet_with_tcphandshake(this_request, timeout): del(send_data[IP].len) del(send_data[IP].chksum) request_and_answers, unanswered = sr( - send_data, verbose=0, timeout=timeout, multi=True) + send_data, iface=user_iface, verbose=0, timeout=timeout, multi=True) # send_fin = send_ack.copy() # todo: xhdix # send_fin[IP].id=ans[0][0][IP].id + 1 # send_fin[TCP].flags = "FA" @@ -216,6 +218,7 @@ def send_packet_with_tcphandshake(this_request, timeout): def send_single_packet(this_request, timeout): + global user_iface this_request[IP].id = RandShort() if this_request.haslayer(TCP): this_request[TCP].sport = utils.ephemeral_port.ephemeral_port_reserve( @@ -236,19 +239,20 @@ def send_single_packet(this_request, timeout): del(this_request[IP].len) del(this_request[IP].chksum) request_and_answers, unanswered = sr( - this_request, verbose=0, timeout=timeout) + this_request, iface=user_iface, verbose=0, timeout=timeout) return request_and_answers, unanswered def retransmission_single_packet(this_request, timeout, is_data_packet): + global user_iface this_request[IP].id += 1 del(this_request[IP].chksum) if is_data_packet: request_and_answers, unanswered = sr( - this_request, verbose=0, timeout=timeout, multi=True) + this_request, iface=user_iface, verbose=0, timeout=timeout, multi=True) else: request_and_answers, unanswered = sr( - this_request, verbose=0, timeout=timeout) + this_request, iface=user_iface, verbose=0, timeout=timeout) return request_and_answers, unanswered @@ -428,11 +432,12 @@ def generate_packets_for_each_ip(request_packets, request_ips, do_tcphandshake): def check_for_permission(): + global user_iface try: this_request = IP( dst=LOCALHOST, ttl=0)/TCP( sport=0, dport=53)/DNS() - sr1(this_request, verbose=0, timeout=0) + sr1(this_request, iface=user_iface, verbose=0, timeout=0) except OSError: print("Error: Unable to send a packet with unprivileged user. Please run as root/admin.") sys.exit(1) @@ -445,8 +450,11 @@ def trace_route( annotation_1: str = "", annotation_2: str = "", continue_to_max_ttl: bool = False, do_tcph1: bool = False, do_tcph2: bool = False, - trace_retransmission: bool = False, trace_with_retransmission: bool = False + trace_retransmission: bool = False, + trace_with_retransmission: bool = False, iface=None ): + global user_iface + user_iface=iface check_for_permission() measurement_name = "" request_packets = [] @@ -500,7 +508,7 @@ def trace_route( paris_id = repeat_requests elif trace_retransmission: paris_id = -1 - no_internet, public_ip, network_asn, network_name, country_code, city = utils.geolocate.get_meta() + no_internet, public_ip, network_asn, network_name, country_code, city = utils.geolocate.get_meta(user_iface) if name_prefix != "": measurement_name = name_prefix + '-' + network_asn + "-tracevis-" + \ datetime.utcnow().strftime("%Y%m%d-%H%M") From 200546965010c2e493874c86dd3c2b4099b1f57c Mon Sep 17 00:00:00 2001 From: xhdix Date: Wed, 1 Jun 2022 18:35:30 +0300 Subject: [PATCH 2/3] change showing the interfaces argument --- tracevis.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tracevis.py b/tracevis.py index af4ba7a..3836354 100755 --- a/tracevis.py +++ b/tracevis.py @@ -128,8 +128,8 @@ def get_args(): ) parser.add_argument('--iface', type=str, help="set the target network interface") - parser.add_argument('--interfaces', action='store_true', - help="see the network interfaces (conf.route)") + parser.add_argument('--show-interfaces', action='store_true', + help="show the network interfaces (conf.route)") if len(sys.argv) == 1: parser.print_help() sys.exit(1) @@ -217,7 +217,7 @@ def main(args): exit() else: iface = args["iface"] - if args.get("interfaces"): + if args.get("show_interfaces"): show_conf_route() exit() if args.get("dns") or args.get("dnstcp"): From 6c413c2072a770aafcc3daabadf7aedd2c32ff35 Mon Sep 17 00:00:00 2001 From: xhdix Date: Wed, 1 Jun 2022 18:38:19 +0300 Subject: [PATCH 3/3] change showing the interfaces argument 2 --- tracevis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracevis.py b/tracevis.py index 3836354..68d9358 100755 --- a/tracevis.py +++ b/tracevis.py @@ -128,7 +128,7 @@ def get_args(): ) parser.add_argument('--iface', type=str, help="set the target network interface") - parser.add_argument('--show-interfaces', action='store_true', + parser.add_argument('--show-ifaces', action='store_true', help="show the network interfaces (conf.route)") if len(sys.argv) == 1: parser.print_help() @@ -217,7 +217,7 @@ def main(args): exit() else: iface = args["iface"] - if args.get("show_interfaces"): + if args.get("show_ifaces"): show_conf_route() exit() if args.get("dns") or args.get("dnstcp"):