Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: ability to set iface #58

Merged
merged 3 commits into from
Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions tracevis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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('--show-ifaces', action='store_true',
help="show the network interfaces (conf.route)")
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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("show_ifaces"):
show_conf_route()
exit()
if args.get("dns") or args.get("dnstcp"):
do_traceroute = True
name_prefix += "dns"
Expand Down Expand Up @@ -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"):
Expand Down
8 changes: 4 additions & 4 deletions utils/geolocate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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:
Expand Down Expand Up @@ -59,15 +59,15 @@ 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'
network_name = ''
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:
Expand Down
26 changes: 17 additions & 9 deletions utils/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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"
Expand All @@ -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(
Expand All @@ -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


Expand Down Expand Up @@ -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)
Expand All @@ -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 = []
Expand Down Expand Up @@ -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")
Expand Down