def lastor_redistr(client_coord, fp_to_bw, fp_to_coord, threshold): """ Redistributes LASTor guard probabilities. threshold = selection probability to fraction of the cost of the network contributed """ if threshold < 1: print("Error: threshold must be at least 1.") return None total_cost = 0 for fp, bw in fp_to_bw.items(): total_cost += relays.get_cost(bw) thresh = threshold / total_cost ratios = dict.fromkeys(fp_to_bw, 0) excess = 1 curr_fps = list(fp_to_coord.keys()) cnt = 1 while excess > 0: print(f'----- Round {cnt} -----') cnt += 1 if len(curr_fps) == 0: break curr_fp_to_coord = {fp: fp_to_coord[fp] for fp in curr_fps} curr_distr = lastor.compute_lt_selection_probs(client_coord, curr_fp_to_coord) print(f'sum distr (~1): {sum(curr_distr.values())}') norm = excess print(f'norm: {norm}') num_over = 0 excess = 0 for fp in list(curr_fps): cost = relays.get_cost(fp_to_bw[fp]) ratio = curr_distr[fp] / cost * norm ratios[fp] += ratio if ratios[fp] > thresh: excess += ((ratios[fp] - thresh) * cost) ratios[fp] = thresh curr_fps.remove(fp) num_over += 1 print(f'num over thresh: {num_over}') redistr = {} for fp, val in ratios.items(): prob = val * relays.get_cost(fp_to_bw[fp]) redistr[fp] = prob return redistr
def disp_targeted_split_table(num_relays, bw_resource): """ Prints table showing IP splitting effects on targeted attack against client in NYC (40.6943, -73.9249). Format: Relay # |relCost | vanilla prob | cumulative targ prob | coordinate """ print("Targeted IP splitting") client_coord = (40.6943, -73.9249) # emp_prob = 0 mal_coords_lst = [] fname = "attack_split_targ/malguardprobs.json" res = json.load(open(fname, 'r')) for coord, prob in res.items(): lat = float(coord[1:-1].split(',')[0]) lon = float(coord[1:-1].split(',')[1]) mal_coords_lst.append((lat, lon)) v_distr, v_prob = vanilla.compute_vanilla_guard_distr(guard_to_bw, bw_resource) for i in range(0, num_relays): cost = num_relays * relays.get_cost(bw_resource / num_relays) tot_cost = sum(guard_to_cost.values()) + cost rel_cost = cost / tot_cost # untargeted with 1 client in client_lst res = untargeted_prob([client_coord], mal_coords_lst[:i+1], bw_resource) print(f"{i+1} | relCost: {rel_cost} | VT prob: {v_prob} | targ LT prob: {res[0]} | {mal_coords_lst[i]}") return mal_coords_lst
def disp_untargeted_split_table(num_relays, bw_resource): """ Prints table showing IP splitting effects on untargeted attack. Format: Relay # |relCost | vanilla prob | avg untarg prob | max untarg prob with client coord | best mal coordinate """ print("Untargeted IP splitting") client_lst = json.load(open("../data/geoclients200.json")) mal_coords_lst = [] fname = "attack_split_untarg/malguardprobs.json" res = json.load(open(fname, 'r')) for coord, prob in res.items(): lat = float(coord[1:-1].split(',')[0]) lon = float(coord[1:-1].split(',')[1]) mal_coords_lst.append((lat, lon)) v_distr, v_prob = vanilla.compute_vanilla_guard_distr(guard_to_bw, bw_resource) for i in range(0, num_relays): cost = num_relays * relays.get_cost(bw_resource / num_relays) tot_cost = sum(guard_to_cost.values()) + cost rel_cost = cost / tot_cost res = untargeted_prob(client_lst, mal_coords_lst[:i+1], bw_resource) print(f"{i+1} | relCost: {rel_cost} | VT prob: {v_prob} | avg prob: {res[0]} | max prob: {res[2]} |{mal_coords_lst[i]}") return mal_coords_lst
def counterraptor_init_ratios(client_as, fp_to_bw, fp_to_as, fp_to_cost): """ Returns selection probability to cost ratio for client_as before applying redistribution algorithm to Counter-RAPTOR. """ client_to_all_res = json.load( open("../counterraptor/all_reachable_resilience.json")) client_to_guard_res = json.load( open("../counterraptor/cg_resilience.json")) alpha = 0.5 sample_size = 0.1 * len(fp_to_bw) total_cost = sum(fp_to_cost.values()) ratios = dict.fromkeys(fp_to_bw, 0) distr = counterraptor.compute_cr_selection_probs(client_as, fp_to_bw, fp_to_as, client_to_all_res, client_to_guard_res, alpha, sample_size) for fp, prob in distr.items(): cost = relays.get_cost(fp_to_bw[fp]) ratio = prob * total_cost / cost ratios[fp] = ratio return ratios
def disp_untargeted_split_table_avg(client_as_lst, best_as_untargeted, bw_resource, num_relays_lst): """ Prints table showing varying relays effect on untargeted attack (average success). """ v_guard_probs, v_prob = vanilla.compute_vanilla_guard_distr( guard_to_bw, bw_resource) for num_relays in num_relays_lst: sum_probs = 0 for client_as in client_as_lst: all_guard_probs, mal_guard_prob = cr.compute_cr_guard_distr( client_as, best_as_untargeted, client_to_all_res, client_to_guard_res, guard_to_bw, ip_to_as, num_relays, bw_resource, alpha, sample_size) sum_probs += mal_guard_prob mal_prob = sum_probs / len(client_as_lst) cost = num_relays * relays.get_cost(bw_resource / num_relays) tot_cost = sum(guard_to_cost.values()) + cost rel_cost = cost / tot_cost print( f"{num_relays} | relCost: {rel_cost} | VT prob: {v_prob} | utarg CR prob: {mal_prob} | AS{best_as_untargeted}" )
def disp_max_advantages(client_as_lst, bw_resources_lst, best_as_dict): """ Display maximum attacker advantage in untargeted attack compared to Vanilla Tor and relCost. """ for i in range(0, len(bw_resources_lst)): bw_resource = bw_resources_lst[i] v_guard_probs, v_prob = vanilla.compute_vanilla_guard_distr( guard_to_bw, bw_resource) rel_cost = relays.get_cost(bw_resource) / ( relays.get_cost(bw_resource) + sum(guard_to_cost.values())) best_as_untargeted = best_as_dict[str(bw_resource)] untargeted_prob_triple = untargeted_prob(client_as_lst, [best_as_untargeted], [bw_resource], pfi_instance) print(bw_resource) print("avg") print(untargeted_prob_triple[0] / v_prob) print(untargeted_prob_triple[0] / rel_cost) print("max") print(untargeted_prob_triple[2][1] / v_prob) print(untargeted_prob_triple[2][1] / rel_cost)
def lastor_init_ratios(client_coord, fp_to_bw, fp_to_coord, fp_to_cost): """ Returns selection probability to cost ratio for client_coord before applying redistribution algorithm to LASTor. """ total_cost = sum(fp_to_cost.values()) ratios = dict.fromkeys(fp_to_bw, 0) distr = lastor.compute_lt_selection_probs(client_coord, fp_to_coord) for fp, prob in distr.items(): cost = relays.get_cost(fp_to_bw[fp]) ratio = prob * total_cost / cost ratios[fp] = ratio return ratios
def denasa_init_ratios(client_as, fp_to_bw, fp_to_as, fp_to_cost): """ Returns selection probability to cost ratio for client_as before applying redistribution algorithm to DeNASA. """ total_cost = sum(fp_to_cost.values()) ratios = dict.fromkeys(fp_to_bw, 0) distr = denasa.compute_dn_selection_probs(client_as, fp_to_bw, fp_to_as, all_ases, pfi_instance) for fp, prob in distr.items(): cost = relays.get_cost(fp_to_bw[fp]) ratio = prob * total_cost / cost ratios[fp] = ratio return ratios
def disp_targeted_split_table(client_as, bw_resource, num_relays_lst): """ Prints table showing varying relays effect targeted attack. """ best_as = cr.compute_attack_as([client_as], client_to_all_res, client_to_guard_res, guard_to_bw, ip_to_as, sample_size) v_guard_probs, v_prob = vanilla.compute_vanilla_guard_distr( guard_to_bw, bw_resource) for num_relays in num_relays_lst: all_guard_probs, mal_prob = cr.compute_cr_guard_distr( client_as, best_as, client_to_all_res, client_to_guard_res, guard_to_bw, ip_to_as, num_relays, bw_resource, alpha, sample_size) cost = num_relays * relays.get_cost(bw_resource / num_relays) tot_cost = sum(guard_to_cost.values()) + cost rel_cost = cost / tot_cost print( f"{num_relays} | relCost: {rel_cost} | VT prob: {v_prob} | targ CR prob: {mal_prob} | AS{best_as}" )
def disp_untargeted_split_table_avg(client_as_lst, bw_resource, num_relays_lst): """ Prints table showing varying relays effect on untargeted attack (average success). Format: Relay # | relCost | vanilla prob | avg untarg prob | max untarg prob with client AS """ v_guard_probs, v_prob = vanilla.compute_vanilla_guard_distr( guard_to_bw, bw_resource) for num_relays in num_relays_lst: inDir = f"untarg{num_relays}" mal_guard_as_lst = [] for i in range(num_relays): fname = f"{inDir}/tempbeststate{i}.json" best_state = json.load(open(fname)) mal_guard_as_lst.append(best_state[1]) bw_per_guard = bw_resource / num_relays mal_guard_bw_lst = [bw_per_guard] * num_relays res_triple = untargeted_prob(client_as_lst, mal_guard_as_lst, mal_guard_bw_lst, pfi_instance) avg_prob = res_triple[0] hi_prob = res_triple[2] # tuple of (client AS, prob) cost = num_relays * relays.get_cost(bw_resource / num_relays) tot_cost = sum(guard_to_cost.values()) + cost rel_cost = cost / tot_cost print( f"{num_relays} | relCost: {rel_cost} | VT prob: {v_prob} | avg prob: {avg_prob} | max prob: {hi_prob}" )
sys.path.append('..') sys.path.append('../vanilla') import numpy as np import argparse import lastor as lt import vanilla import relays import json import pickle import operator import geopy.distance guard_to_bw = pickle.load(open("../guard_info/guard_to_bw.pickle", "rb")) guard_to_cost = {guard: relays.get_cost(bw) for guard, bw in guard_to_bw.items()} relay_ips = [ip.strip() for ip in open('../data/relay_ips.txt', 'r').readlines()] def make_prob_matrix(client_lst, mal_coord, bw_resources_lst): """ Returns a numpy matrix where every row corresponds to the bandwidth col_0: Vanilla Tor selection probability col_1: Untargeted LT average selection probability (across all clients) col_2: Untargeted LT lowest selection probability col_3: Untargeted LT highest selection probability client_lst: client coordinates mal_coord: malicious guard placement (single relay) bw_resources_lst: list of bandwidth resources """
ip_to_as = json.load(open("../guard_info/ip_to_as.json")) all_ases = [ asn.strip() for asn in open("../data/relay_ases.txt", 'r').readlines() ] guard_to_bw = pickle.load(open("../guard_info/guard_to_bw.pickle", "rb")) fp_to_bw = {g.fingerprint: bw for (g, bw) in guard_to_bw.items()} fp_to_as = { g.fingerprint: ip_to_as[g.address] for (g, bw) in guard_to_bw.items() } fp_to_coord = pickle.load(open("../guard_info/guard_fps_to_coord.pickle", "rb")) fp_to_cost = {fp: relays.get_cost(bw) for fp, bw in fp_to_bw.items()} def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--dump', action='store_true') return parser.parse_args() # -------------------------------------------------------------- def counterraptor_init_ratios(client_as, fp_to_bw, fp_to_as, fp_to_cost): """ Returns selection probability to cost ratio for client_as before applying redistribution algorithm to Counter-RAPTOR.
def counterraptor_redistr(client_as, fp_to_bw, fp_to_as, threshold): """ Redistributes Counter-RAPTOR guard probabilities. threshold = selection probability to fraction of the cost of the network contributed """ if threshold < 1: print("Error: threshold must be at least 1.") return None client_to_all_res = json.load( open("../counterraptor/all_reachable_resilience.json")) client_to_guard_res = json.load( open("../counterraptor/cg_resilience.json")) alpha = 0.5 sample_g = 0.1 total_cost = 0 for fp, bw in fp_to_bw.items(): total_cost += relays.get_cost(bw) thresh = threshold / total_cost ratios = dict.fromkeys(fp_to_bw, 0) excess = 1 curr_fps = list(fp_to_bw.keys()) cnt = 1 while excess > 0: print(f'----- Round {cnt} -----') cnt += 1 if len(curr_fps) == 0: break curr_fp_to_bw = {fp: fp_to_bw[fp] for fp in curr_fps} curr_fp_to_as = {fp: fp_to_as[fp] for fp in curr_fps} curr_distr = counterraptor.compute_cr_selection_probs( client_as, curr_fp_to_bw, curr_fp_to_as, client_to_all_res, client_to_guard_res, alpha, sample_g * len(curr_fp_to_bw)) print(f'sum distr (~1): {sum(curr_distr.values())}') norm = excess print(f'norm: {norm}') num_over = 0 excess = 0 for fp in list(curr_fps): cost = relays.get_cost(fp_to_bw[fp]) ratio = curr_distr[fp] / cost * norm ratios[fp] += ratio if ratios[fp] > thresh: excess += ((ratios[fp] - thresh) * cost) ratios[fp] = thresh curr_fps.remove(fp) num_over += 1 print(f'num over thresh: {num_over}') redistr = {} for fp, val in ratios.items(): prob = val * relays.get_cost(fp_to_bw[fp]) redistr[fp] = prob return redistr
import counterraptor as cr import vanilla import json import pickle import relays # ------- init info ------------------ client_to_all_res = json.load(open("all_reachable_resilience.json")) client_to_guard_res = json.load(open("cg_resilience.json")) client_as_lst = list(client_to_guard_res.keys()) ip_to_as = json.load(open("../guard_info/ip_to_as.json")) guard_to_bw = pickle.load(open("../guard_info/guard_to_bw.pickle", "rb")) guard_to_cost = { guard: relays.get_cost(bw) for guard, bw in guard_to_bw.items() } alpha = 0.5 sample_size = int(0.1 * len(guard_to_bw)) # g = 0.1 # ------------------------------------ def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("--target_as") return parser.parse_args()