diff --git a/crawler.py b/crawler.py index 60f42cc..ae690fd 100644 --- a/crawler.py +++ b/crawler.py @@ -120,6 +120,7 @@ if __name__ == "__main__": "1.3": 0, } } + combinations = {} f = open(sys.argv[2], "r") c = json.load(f) for domain in c: @@ -141,51 +142,69 @@ if __name__ == "__main__": pass #print("Not found:", line, r) + cert = "" if "cert_sig" not in domain_stats: - summary["cert"]["none"] += 1 + cert = "none" elif domain_stats["cert_sig"] == "ecdsa_secp256r1_sha256": - summary["cert"]["secp256r1"] += 1 + cert = "secp256r1" elif domain_stats["cert_sig"] == "ecdsa_secp384r1_sha384": - summary["cert"]["secp384r1"] += 1 + cert = "secp384r1" elif domain_stats["cert_sig"] == "ecdsa_secp521r1_sha512": - summary["cert"]["secp521r1"] += 1 + cert = "secp521r1" elif "rsa" in domain_stats["cert_sig"]: - summary["cert"]["rsa{}".format(domain_stats["cert_pk_size"])] += 1 + cert = "rsa{}".format(domain_stats["cert_pk_size"]) + if cert != "": + summary["cert"][cert] += 1 + cipher = "" if "cipher" not in domain_stats: - summary["cipher"]["none"] += 1 + cipher = "none" elif "AES_128" in domain_stats["cipher"] or "AES128" in domain_stats["cipher"]: - summary["cipher"]["aes128"] += 1 + cipher = "aes128" elif "AES_256" in domain_stats["cipher"] or "AES256" in domain_stats["cipher"]: - summary["cipher"]["aes256"] += 1 + cipher = "aes256" elif "CHACHA20" in domain_stats["cipher"]: - summary["cipher"]["chacha20"] += 1 + cipher = "chacha20" + if cipher != "": + summary["cipher"][cipher] += 1 + kx = "" if "kx" not in domain_stats: - summary["kx"]["none"] += 1 + kx = "none" elif domain_stats["kx"] == "X25519MLKEM768": - summary["kx"]["x25519mlkem768"] += 1 + kx = "x25519mlkem768" elif domain_stats["kx"] == "X25519, 253 bits": - summary["kx"]["x25519"] += 1 + kx = "x25519" elif domain_stats["kx"] == "DH, 2048 bits": - summary["kx"]["rsa2048"] += 1 + kx = "rsa2048" elif domain_stats["kx"] == "DH, 3072 bits": - summary["kx"]["rsa3072"] += 1 + kx = "rsa3072" elif domain_stats["kx"] == "DH, 4096 bits": - summary["kx"]["rsa4096"] += 1 + kx = "rsa4096" elif domain_stats["kx"] == "ECDH, prime256v1, 256 bits": - summary["kx"]["secp256r1"] += 1 + kx = "secp256r1" elif domain_stats["kx"] == "ECDH, secp384r1, 384 bits": - summary["kx"]["secp384r1"] += 1 + kx = "secp384r1" elif domain_stats["kx"] == "ECDH, secp521r1, 521 bits": - summary["kx"]["secp521r1"] += 1 + kx = "secp521r1" + if kx != "": + summary["kx"][kx] += 1 + protocol = "" if "protocol" not in domain_stats: - summary["version"]["none"] += 1 + protocol = "none" elif domain_stats["protocol"] == "TLSv1.3": - summary["version"]["1.3"] += 1 + protocol = "1.3" elif domain_stats["protocol"] == "TLSv1.2": - summary["version"]["1.2"] += 1 + protocol = "1.2" + if protocol != "": + summary["version"][protocol] += 1 + + combination = (protocol, cert, kx, cipher) + if combination in combinations: + combinations[combination] += 1 + else: + combinations[combination] = 1 #if "kx" in domain_stats and domain_stats["kx"] == "ECDH": # print(c[domain]) @@ -195,10 +214,15 @@ if __name__ == "__main__": print(f"{cat}:") for item in stats[cat]: print(" {}:\t{}".format(item, stats[cat][item])) - elif "-s" in sys.argv: # summary + if "-s" in sys.argv: # summary for cat in summary: print(f"{cat}:") for item in summary[cat]: print(" {}:\t{}".format(item, summary[cat][item])) + if "-c" in sys.argv: # combinations + combinations_list = [c for c in combinations] + combinations_list.sort(key=lambda c: combinations[c]) + for c in combinations_list: + print("{}\t{}".format(c, combinations[c])) else: print(stats) diff --git a/exp.py b/exp.py index b9f588d..803b776 100644 --- a/exp.py +++ b/exp.py @@ -87,7 +87,7 @@ CONFIGS = { True, ], "records": [ - #{ "filename": "wikipedia", "repeat": 10000, "time": 90 }, + { "filename": "wp2", "repeat": 10000, "time": 600 }, { "filename": "yt2-ads", "repeat": 10000, "time": 600 }, { "filename": "yt2-ublock", "repeat": 10000, "time": 600 }, ], @@ -107,6 +107,7 @@ CONFIGS = { "idle": "idle - - - - - - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 0 -", "notify_listen": ("0.0.0.0", 8090), "notify_addr": "192.168.3.1:8090", + "concurrency": "4", }, # i7-4790 -> core2 "core2": { @@ -189,11 +190,13 @@ CONFIGS = { "server", ], "tls": [ - False, + #False, True, ], "records": [ - { "filename": "wikipedia", "repeat": 1000 }, + { "filename": "wp2", "repeat": 10000, "time": 600 }, + { "filename": "yt2-ads", "repeat": 10000, "time": 600 }, + { "filename": "yt2-ublock", "repeat": 10000, "time": 600 }, ], "repo_dir": "/home/tuxmain/reps/tlsbench", "exp_dir": "/dev/shm/exp", @@ -281,7 +284,7 @@ CONFIGS = { "rapl": False, "sa": False, "listen_port": 8080, - "idle": "idle - - - - - - - - - 1772205368.593937 1772206568.6941307 1200.1001937389374 0 298843 2217803 5.53333333333333 0 -", + "idle": "idle - - - - - - - - - 1774429500.8909554 1774430100.9141996 600.0232441425323 0 222346 1105446 8.666666666666666 0 -", "notify_listen": ("0.0.0.0", 8090), "notify_addr": "TODO:8090", "ld_preload": { @@ -343,12 +346,12 @@ CERT_SIGN_ALGS = [ "rsa2048", "rsa3072", "rsa4096", # widely used ] IMPLS = [ - "aws-lc", # Amazon's crypto widely used in Rust stuff - "boring", # Google's fork of OpenSSL used in Chrome and Android + #"aws-lc", # Amazon's crypto widely used in Rust stuff + #"boring", # Google's fork of OpenSSL used in Chrome and Android #"graviola", # New crypto in Rust "openssl", # widely used #"openssl-static", - "ring", # used in most Rust stuff + #"ring", # used in most Rust stuff #"symcrypt", # Microsoft's crypto #"wolfcrypt" # used in embedded (won't build with rpxy for now) ] @@ -637,7 +640,10 @@ def run_netreplay_server(ssh, exp_dir, repo_dir, record, listen_addr, listen_por #print(cmdline) return ssh_run_bg(ssh, cmdline, env) -def run_netreplay_client(ssh, exp_dir, repo_dir, record, remote_addr, remote_port, tls, impl, certs_dir, only_record=None, ciphers=None, kexes=None, earlydata="0", debug=False, notify_addr=None, ld_preload=None, skip_verif=False): +def run_netreplay_client( + ssh, exp_dir, repo_dir, record, remote_addr, remote_port, tls, impl, certs_dir, + only_record=None, ciphers=None, kexes=None, earlydata="0", debug=False, notify_addr=None, ld_preload=None, skip_verif=False, concurrency=None +): if exp_dir[-1] != "/": exp_dir += "/" repo_dir = repo_dir.removesuffix("/") @@ -661,6 +667,8 @@ def run_netreplay_client(ssh, exp_dir, repo_dir, record, remote_addr, remote_por cmd += ["-n", notify_addr] if skip_verif: cmd.append("-s") + if concurrency != None: + cmd += ["--concurrency", concurrency] cmdline = " ".join(cmd) #print(cmdline) return ssh_run_bg(ssh, cmdline, env) @@ -876,6 +884,7 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False): debug=debug, notify_addr=config["notify_addr"], ld_preload=config["ld_preload"] if "ld_preload" in config else None, + concurrency=config.get("concurrency"), ) else: netreplay = run_netreplay_server( @@ -912,6 +921,7 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False): notify_addr=config["notify_addr"], ld_preload=config["ld_preload"] if "ld_preload" in config else None, skip_verif=True, + concurrency=config.get("concurrency"), ) prof_filename = "-" @@ -942,6 +952,8 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False): if rec_count == 0xffffffff: break if rec_count > session_count: + if rec_count - session_count > 1: + print("count", session_count, "->", rec_count) session_count = rec_count except Timeout: print("TIMEOUT: stop") @@ -962,6 +974,14 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False): ssh_run(ssh, "killall netreplay-"+impl) except invoke.exceptions.UnexpectedExit as e: pass + + # flush the UDP queue + signal.alarm(2) + try: + while True: + notify_socket.recv(4) + except Timeout: + pass # Measure CPU after (as it may update only after the process is killed) new_cpu = 0 diff --git a/makecerts.py b/makecerts.py index 894a586..28f5620 100644 --- a/makecerts.py +++ b/makecerts.py @@ -15,7 +15,8 @@ ALGS = [ "rsa4096" ] DOMAINS = [ - #"wikipedia.org", + "wikipedia.org", + "wikimedia.org", "youtube.com", "rr2---sn-gxo5uxg-jqbl.googlevideo.com",# main domain googlevideo.com returns certificate for google.com only "googleusercontent.com", diff --git a/plots.py b/plots.py index 80654fd..fdd25ff 100644 --- a/plots.py +++ b/plots.py @@ -72,6 +72,10 @@ def impl_title(impl): # Where gnuplot files, data files and images are output PLOTS_DIR = "/dev/shm/plots" +# Energy per byte on the network, in W/s +# Estimated at 0.06 kWh/GB by Aslan 2018 +WS_PER_BYTE = 0.06 * 1000 * 3600 / 1024**3 + def gnuplot_histogram(**kwargs): if "machine" in kwargs and kwargs["machine"] != None: kwargs["machine"] = ", " + kwargs["machine"] @@ -525,6 +529,7 @@ def make_summary(logs): n = float(log.get("n", "1000")) plain_results[plain_result_key(log)] = { "cpu": (float(log["cpu"]) - idle_val["cpu"] * float(log["time"])) / n, + "total_energy": float(log["Wh"]) * 3600 / n, "energy": (float(log["Wh"]) * 3600 - idle_val["energy"] * float(log["time"])) / n, "in": (float(log["bytes_in"]) - idle_val["in"] * float(log["time"])) / n, "out": (float(log["bytes_out"]) - idle_val["out"] * float(log["time"])) / n, @@ -533,23 +538,38 @@ def make_summary(logs): n = float(log.get("n", "1000")) results[result_key(log)] = { "cpu": (float(log["cpu"]) - idle_val["cpu"] * float(log["time"])) / n, + "total_energy": float(log["Wh"]) * 3600 / n, "energy": (float(log["Wh"]) * 3600 - idle_val["energy"] * float(log["time"])) / n, "in": (float(log["bytes_in"]) - idle_val["in"] * float(log["time"])) / n, "out": (float(log["bytes_out"]) - idle_val["out"] * float(log["time"])) / n, } - lines = [["key", "idle (W)", "no_tls (Ws/S)", "tls (Ws/S)", "tls_only (Ws/S)", "tls_in (1)", "tls_out (1)"]] + lines = [[ + "key", + "idle (W)", + "no_tls (Ws/S)", + "tls (Ws/S)", + "tls_min (Ws/S)", + #"tls_max (Ws/S)", + "tls_in (MB/S)", + "tls_out (MB/S)", + "tls_io (MB/S)", + "tls_net (Ws/S)", + ]] for k in results: r = results[k] p = plain_results[k[:3]] lines.append([ "/".join([str(i) for i in k]), - str(idle_val["energy"]), - str(p["energy"]), - str(r["energy"]), - str(r["energy"] - p["energy"]), - str((r["in"] - p["in"]) / r["in"]), - str((r["out"] - p["out"]) / r["out"]), + str(round(idle_val["energy"], 1)), + str(round(p["energy"], 1)), + str(round(r["energy"], 1)), + str(round(r["energy"] - p["energy"], 1)) + " (" + str(round((r["energy"] - p["energy"])/r["energy"]*100, 1)) + "%)", + #str(round(r["total_energy"] - p["total_energy"], 1)), + str(round((r["in"] - p["in"])/1024**2, 2)) + " (" + str(round((r["in"] - p["in"])/r["in"]*100, 1)) + "%)", + str(round((r["out"] - p["out"])/1024**2, 2)) + " (" + str(round((r["out"] - p["out"])/r["out"]*100, 1)) + "%)", + str(round((r["in"] + r["out"] - p["in"] - p["out"])/1024**2, 2)) + " (" + str(round((r["in"] + r["out"] - p["in"] - p["out"])/(r["in"] + r["out"])*100, 1)) + "%)", + str(round(r["energy"] - p["energy"] + (r["out"] + r["in"] - p["out"] - p["in"]) * WS_PER_BYTE, 2)), ]) print(tabulate(lines))