0-RTT
This commit is contained in:
parent
f5145f80ea
commit
c9dc2a306e
8 changed files with 230 additions and 134 deletions
296
exp.py
296
exp.py
|
|
@ -2,6 +2,31 @@
|
|||
import os, sys, subprocess
|
||||
|
||||
CONFIGS = {
|
||||
"debug": {
|
||||
"experiments": [
|
||||
"zrtt",
|
||||
],
|
||||
"setups": [
|
||||
#"none-local",
|
||||
"client-local",
|
||||
#"server-local",
|
||||
],
|
||||
"records": [
|
||||
{ "filename": "youtube", "repeat": 1 },
|
||||
],
|
||||
"repodir": "/home/tuxmain/reps/tlsbench",
|
||||
"expdir": "/dev/shm/exp",
|
||||
"log_backup_dir": "/home/tuxmain",
|
||||
"p2_hostname": "localhost",
|
||||
"p2_addr": "127.0.0.1",
|
||||
"p2_repodir": "/home/tuxmain/reps/tlsbench",
|
||||
"wattmeter": False,
|
||||
"perf": False,
|
||||
"perf_dir": "/home/tuxmain/.cache/exp",
|
||||
"p3_suffix": ".localhost",
|
||||
"p3_port_plain": 8080,
|
||||
"p3_port_tls": 8443,
|
||||
},
|
||||
# i7-4790 local
|
||||
"local": {
|
||||
"experiments": [
|
||||
|
|
@ -33,9 +58,10 @@ CONFIGS = {
|
|||
# i7-4790 -> pi3
|
||||
"pi3": {
|
||||
"experiments": [
|
||||
#"impl-cipher-ver",
|
||||
"impl-cipher-ver",
|
||||
"impl-cert-ver",
|
||||
#"impl-kex-ver",
|
||||
"impl-kex-ver",
|
||||
"zrtt"
|
||||
],
|
||||
"setups": [
|
||||
"none",
|
||||
|
|
@ -43,7 +69,7 @@ CONFIGS = {
|
|||
"server",
|
||||
],
|
||||
"records": [
|
||||
{ "filename": "youtube", "repeat": 100 },
|
||||
{ "filename": "youtube", "repeat": 1 },
|
||||
],
|
||||
"repodir": "/home/tuxmain/reps/tlsbench",
|
||||
"expdir": "/dev/shm/exp",
|
||||
|
|
@ -58,7 +84,7 @@ CONFIGS = {
|
|||
"p3_suffix": "",
|
||||
"p3_port_plain": 80,
|
||||
"p3_port_tls": 443,
|
||||
"idle": "idle - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 -",
|
||||
"idle": "idle - - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 -",
|
||||
},
|
||||
"pi3-local": {
|
||||
"experiments": [
|
||||
|
|
@ -116,7 +142,7 @@ CONFIGS = {
|
|||
"p3_suffix": "",
|
||||
"p3_port_plain": 80,
|
||||
"p3_port_tls": 443,
|
||||
"idle": "idle - - - - - - 600.0001013278961 0.0 735 4942 1.7759999999999962 -",
|
||||
"idle": "idle - - - - - - - 600.0001013278961 0.0 735 4942 1.7759999999999962 -",
|
||||
},
|
||||
"core2-local": {
|
||||
"experiments": [
|
||||
|
|
@ -147,6 +173,9 @@ CONFIGS = {
|
|||
},
|
||||
}
|
||||
|
||||
# Wildcard subdomains are used only for certificates.
|
||||
# This is useful for recording, because some domains may be unknown at that time.
|
||||
# Proxy config ignores them so individual subdomains must be added as well for replaying.
|
||||
DOMAINS_ = [
|
||||
# Apple
|
||||
"apple.com", "www.apple.com", "graffiti-tags.apple.com", "securemetrics.apple.com",
|
||||
|
|
@ -154,13 +183,38 @@ DOMAINS_ = [
|
|||
"mzstatic.com", "is1-ssl.mzstatic.com",
|
||||
# Youtube video
|
||||
"youtube.com", "www.youtube.com",
|
||||
"*.ytimg.com",
|
||||
"i.ytimg.com",
|
||||
"i1.ytimg.com",
|
||||
"i9.ytimg.com",
|
||||
"fonts.gstatic.com", "www.gstatic.com",
|
||||
"www.google.com", "accounts.google.com",
|
||||
"yt3.ggpht.com",
|
||||
"rr1---sn-gxo5uxg-jqbl.googlevideo.com",
|
||||
"rr2---sn-gxo5uxg-jqbl.googlevideo.com",
|
||||
"rr4---sn-q4fl6nds.googlevideo.com",
|
||||
"*.googlevideo.com",
|
||||
"rr3---sn-gx1v2vax-atne.googlevideo.com",
|
||||
"rr4---sn-hgn7yn7l.googlevideo.com",
|
||||
"rr3---sn-gx1v2vax-atne.googlevideo.com",
|
||||
"rr2---sn-gx1v2vax-atne.googlevideo.com",
|
||||
"rr1---sn-hgn7yn7l.googlevideo.com",
|
||||
"rr4---sn-hgn7yn76.googlevideo.com",
|
||||
"rr3---sn-hgn7rn7r.googlevideo.com",
|
||||
"rr1---sn-hgn7rn7y.googlevideo.com",
|
||||
"rr1---sn-hgn7rnee.googlevideo.com",
|
||||
"rr2---sn-aigl6ney.googlevideo.com",
|
||||
"rr3---sn-q4fzenee.googlevideo.com",
|
||||
"googleads.g.doubleclick.net",
|
||||
"static.doubleclick.net",
|
||||
"ad.doubleclick.net",
|
||||
"yt3.googleusercontent.com",
|
||||
"suggestqueries-clients6.youtube.com",
|
||||
"pagead2.googlesyndication.com",
|
||||
"tpc.googlesyndication.com",
|
||||
"encrypted-tbn0.gstatic.com",
|
||||
"encrypted-tbn1.gstatic.com",
|
||||
"encrypted-tbn2.gstatic.com",
|
||||
"encrypted-tbn3.gstatic.com",
|
||||
"fonts.googleapis.com",
|
||||
"consent.youtube.com",
|
||||
# Amazon
|
||||
"amazon.com", "www.amazon.com",
|
||||
# Wikipedia article
|
||||
|
|
@ -182,7 +236,7 @@ IMPLS = [
|
|||
"boring", # Google's fork of OpenSSL used in Chrome and Android
|
||||
"openssl", # widely used
|
||||
"ring", # used in most Rust stuff
|
||||
"symcrypt", # Microsoft's crypto
|
||||
#"symcrypt", # Microsoft's crypto
|
||||
#"wolfcrypt" # used in embedded (won't build with rpxy for now)
|
||||
]
|
||||
# Symmetric ciphers
|
||||
|
|
@ -223,6 +277,7 @@ EXPERIMENTS = {
|
|||
],
|
||||
"kexes": ["X25519"],
|
||||
"cert": ["prime256v1"],
|
||||
"earlydata": ["0"],
|
||||
},
|
||||
# Compare signatures among implementations and TLS versions
|
||||
"impl-cert-ver": {
|
||||
|
|
@ -239,6 +294,7 @@ EXPERIMENTS = {
|
|||
"rsa3072",
|
||||
"rsa4096",
|
||||
],
|
||||
"earlydata": ["0"],
|
||||
},
|
||||
# Compare key exchange groups among implementations and TLS versions
|
||||
"impl-kex-ver": {
|
||||
|
|
@ -256,6 +312,25 @@ EXPERIMENTS = {
|
|||
"MLKEM768",
|
||||
],
|
||||
"cert": ["prime256v1"],
|
||||
"earlydata": ["0"],
|
||||
},
|
||||
# Compare 0-RTT with no early data
|
||||
"zrtt": {
|
||||
"impls": [
|
||||
"aws_lc",
|
||||
#"ring"
|
||||
],
|
||||
"ciphers": [
|
||||
"AES_128_GCM_SHA256",
|
||||
#"AES_256_GCM_SHA384",
|
||||
#"CHACHA20_POLY1305_SHA256",
|
||||
#"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
#"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
#"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
],
|
||||
"kexes": ["X25519"],
|
||||
"cert": ["prime256v1"],
|
||||
"earlydata": ["0", "1"],
|
||||
},
|
||||
"debug": {
|
||||
"impls": IMPLS,
|
||||
|
|
@ -265,6 +340,7 @@ EXPERIMENTS = {
|
|||
],
|
||||
"kexes": ["X25519"],
|
||||
"cert": ["prime256v1"],
|
||||
"earlydata": ["0"],
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -283,15 +359,6 @@ for domain in DOMAINS_:
|
|||
if not domain in DOMAINS:
|
||||
DOMAINS.append(domain)
|
||||
|
||||
# JS to redirect the target domains to local (bypass DNS without altering system's config or webpages or packets)
|
||||
SCRIPT_FIREFOX_HOSTS = """const gOverride = Cc["@mozilla.org/network/native-dns-override;1"].getService(Ci.nsINativeDNSResolverOverride);
|
||||
gOverride.clearOverrides();
|
||||
var names = """+str(DOMAINS)+""";
|
||||
for(var i in names) {
|
||||
gOverride.addIPOverride(names[i], "127.0.0.1");
|
||||
}
|
||||
"""
|
||||
|
||||
for config in CONFIGS:
|
||||
CONFIGS[config]["name"] = config
|
||||
|
||||
|
|
@ -502,6 +569,8 @@ def make_rpxy_config(outdir, domains, cryptodir, config_name, p3_suffix, p3_port
|
|||
f = open(outdir+config_name+".toml", "w")
|
||||
f.write("listen_port = {}\nlisten_port_tls = {}\n".format(rpxy_config["listen_http"], rpxy_config["listen_https"]))
|
||||
for domain in domains:
|
||||
if "*" in domain:
|
||||
continue
|
||||
app = domain.replace(".", "_")
|
||||
root = get_domain_root(domain)
|
||||
f.write(rpxy_config["app"].format(
|
||||
|
|
@ -545,16 +614,18 @@ def choose_impl(expdir, p, impl):
|
|||
expdir += "/"
|
||||
os.symlink(os.getcwd()+"/rpxy_rustls_"+impl, expdir+str(p)+"_rpxy", False)
|
||||
|
||||
def run_netreplay(expdir, repodir, record, p2_addr, p2_port, listen_port, tls_mode, only_record=None, ciphers=None, kexes=None):
|
||||
def run_netreplay(expdir, repodir, record, p2_addr, p2_port, listen_port, tls_mode, only_record=None, ciphers=None, kexes=None, earlydata="0"):
|
||||
if expdir[-1] != "/":
|
||||
expdir += "/"
|
||||
repodir = repodir.removesuffix("/")
|
||||
env = {"RUST_LOG": "warning"}
|
||||
env = {"RUST_LOG": "warning", "EARLYDATA": earlydata}
|
||||
if ciphers:
|
||||
env["CIPHERS"] = ciphers
|
||||
if kexes:
|
||||
env["KEXES"] = kexes
|
||||
cmd = [repodir+"/netreplay", repodir+"/records/"+record["filename"], "play", p2_addr, str(p2_port), str(listen_port), expdir+"current_certs", tls_mode, "-r", str(record["repeat"])]
|
||||
cmd = [repodir+"/netreplay", repodir+"/records/"+record["filename"], "play", p2_addr, str(p2_port), str(listen_port), expdir+"current_certs", tls_mode, "-r", str(record["repeat"]),
|
||||
#"--record", "21"
|
||||
]
|
||||
if only_record != None:
|
||||
cmd += ["--record", only_record]
|
||||
print(" ".join(cmd))
|
||||
|
|
@ -631,7 +702,7 @@ def run_exp(config, only_record=None, idle=False):
|
|||
logfile_name = "log-"+timestr
|
||||
logfile_path = expdir+"/"+logfile_name
|
||||
logfile = open(logfile_path, "w")
|
||||
logfile.write("exp impl alg kex cipher setup record time cpu bytes_in bytes_out Wh prof\n")
|
||||
logfile.write("exp impl alg kex cipher ed setup record time cpu bytes_in bytes_out Wh prof\n")
|
||||
logfile.close()
|
||||
|
||||
perf_dir = ""
|
||||
|
|
@ -664,7 +735,7 @@ def run_exp(config, only_record=None, idle=False):
|
|||
while True:
|
||||
try:
|
||||
with open(logfile_path, "a") as logfile:
|
||||
logfile.write(f"idle - - - - - - {time_diff} {rpxy_cpu_diff} {p2_bytes_in_diff} {p2_bytes_out_diff} {energy_diff} -\n")
|
||||
logfile.write(f"idle - - - - - - - {time_diff} {rpxy_cpu_diff} {p2_bytes_in_diff} {p2_bytes_out_diff} {energy_diff} -\n")
|
||||
logfile.close()
|
||||
break
|
||||
except Exception as e:
|
||||
|
|
@ -692,54 +763,73 @@ def run_exp(config, only_record=None, idle=False):
|
|||
ssh_run(ssh, f"python {p2_path}/exp.py cert {config_name} {alg}")
|
||||
for kex in exp["kexes"]:
|
||||
for cipher in exp["ciphers"]:
|
||||
if not alg_filter(kex, alg, cipher, impl):
|
||||
continue
|
||||
for setup in config["setups"]:
|
||||
if SETUPS[setup]["tls_invariant"] and not first_set:
|
||||
for earlydata in exp["earlydata"]:
|
||||
if not alg_filter(kex, alg, cipher, impl):
|
||||
continue
|
||||
setupdir = expdir+"setups/"+setup
|
||||
for record in config["records"]:
|
||||
print(f"EXPERIMENT {expname}: {impl} {alg} {kex} {cipher} {setup}")
|
||||
p2_rpxy_config = SETUPS[setup]["rpxy_config"]
|
||||
vars = {"CIPHERS": cipher, "KEXES": kex, "RUST_LOG": "warning"}
|
||||
cmd = f"{p2_path}/rpxy_rustls_{impl} --config {expdir}/configs/{p2_rpxy_config}.toml --log-dir /dev/shm"
|
||||
#cmd = f"{p2_path}/rpxy_rustls_{impl} --config {expdir}/configs/{p2_rpxy_config}.toml"
|
||||
ssh_run_bg(ssh, cmd, env=vars)
|
||||
time.sleep(1)
|
||||
for setup in config["setups"]:
|
||||
if SETUPS[setup]["tls_invariant"] and not first_set:
|
||||
continue
|
||||
setupdir = expdir+"setups/"+setup
|
||||
for record in config["records"]:
|
||||
print(f"EXPERIMENT {expname}: {impl} {alg} {kex} {cipher} ED={earlydata} {setup}")
|
||||
p2_rpxy_config = SETUPS[setup]["rpxy_config"]
|
||||
vars = {"CIPHERS": cipher, "KEXES": kex, "RUST_LOG": "warning", "EARLYDATA": earlydata}
|
||||
cmd = f"{p2_path}/rpxy_rustls_{impl} --config {expdir}/configs/{p2_rpxy_config}.toml --log-dir /dev/shm"
|
||||
#cmd = f"{p2_path}/rpxy_rustls_{impl} --config {expdir}/configs/{p2_rpxy_config}.toml"
|
||||
ssh_run_bg(ssh, cmd, env=vars)
|
||||
time.sleep(1)
|
||||
|
||||
prof_filename = "-"
|
||||
if config["perf"]:
|
||||
prof_filename = f"{perf_dir}/perf-{timestr}-{run_id}.data"
|
||||
rpxy_pid = ssh_run(ssh, f"pidof rpxy_rustls_{impl}").removesuffix("\n")
|
||||
ssh_run_bg(ssh, f"perf record -F 997 --call-graph dwarf,64000 -g -o {prof_filename} -p {rpxy_pid}")
|
||||
|
||||
run_id += 1
|
||||
|
||||
rpxy_cpu = get_cpu_stat(ssh)
|
||||
p2_bytes_in, p2_bytes_out = get_net_stat(ssh)
|
||||
energy = 0
|
||||
if config["wattmeter"]:
|
||||
energy = wattmeter.get_meter()
|
||||
|
||||
start = time.time()
|
||||
netreplay = run_netreplay(
|
||||
config["expdir"],
|
||||
config["repodir"],
|
||||
record,
|
||||
config["p2_addr"],
|
||||
SETUPS[setup]["p2_port"],
|
||||
SETUPS[setup]["listen_port"],
|
||||
SETUPS[setup]["netreplay_tls_mode"],
|
||||
only_record=only_record,
|
||||
ciphers=cipher,
|
||||
kexes=kex
|
||||
)
|
||||
|
||||
# TODO detect when netreplay has finished
|
||||
try:
|
||||
netreplay.wait()
|
||||
except KeyboardInterrupt:
|
||||
netreplay.kill()
|
||||
prof_filename = "-"
|
||||
if config["perf"]:
|
||||
prof_filename = f"{perf_dir}/perf-{timestr}-{run_id}.data"
|
||||
rpxy_pid = ssh_run(ssh, f"pidof rpxy_rustls_{impl}").removesuffix("\n")
|
||||
ssh_run_bg(ssh, f"perf record -F 997 --call-graph dwarf,64000 -g -o {prof_filename} -p {rpxy_pid}")
|
||||
|
||||
run_id += 1
|
||||
|
||||
rpxy_cpu = get_cpu_stat(ssh)
|
||||
p2_bytes_in, p2_bytes_out = get_net_stat(ssh)
|
||||
energy = 0
|
||||
if config["wattmeter"]:
|
||||
energy = wattmeter.get_meter()
|
||||
|
||||
start = time.time()
|
||||
netreplay = run_netreplay(
|
||||
config["expdir"],
|
||||
config["repodir"],
|
||||
record,
|
||||
config["p2_addr"],
|
||||
SETUPS[setup]["p2_port"],
|
||||
SETUPS[setup]["listen_port"],
|
||||
SETUPS[setup]["netreplay_tls_mode"],
|
||||
only_record=only_record,
|
||||
ciphers=cipher,
|
||||
kexes=kex,
|
||||
earlydata=earlydata,
|
||||
)
|
||||
|
||||
# TODO detect when netreplay has finished
|
||||
try:
|
||||
netreplay.wait()
|
||||
except KeyboardInterrupt:
|
||||
netreplay.kill()
|
||||
try:
|
||||
ssh_run(ssh, f"killall rpxy_rustls_{impl}")
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
try:
|
||||
ssh_run(ssh, f"killall dtach")
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
exit(0)
|
||||
|
||||
#time.sleep(30)
|
||||
#sh("killall netreplay")
|
||||
try:
|
||||
#ssh_run(ssh, f"rm /dev/shm/access.log /dev/shm/rpxy.log")
|
||||
pass
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
try:
|
||||
ssh_run(ssh, f"killall rpxy_rustls_{impl}")
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
|
|
@ -748,47 +838,30 @@ def run_exp(config, only_record=None, idle=False):
|
|||
ssh_run(ssh, f"killall dtach")
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
exit(0)
|
||||
|
||||
#time.sleep(30)
|
||||
#sh("killall netreplay")
|
||||
try:
|
||||
#ssh_run(ssh, f"rm /dev/shm/access.log /dev/shm/rpxy.log")
|
||||
pass
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
try:
|
||||
ssh_run(ssh, f"killall rpxy_rustls_{impl}")
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
try:
|
||||
ssh_run(ssh, f"killall dtach")
|
||||
except invoke.exceptions.UnexpectedExit as e:
|
||||
pass
|
||||
end = time.time()
|
||||
|
||||
new_energy = 0
|
||||
if config["wattmeter"]:
|
||||
new_energy = wattmeter.get_meter()
|
||||
new_p2_bytes_in, new_p2_bytes_out = get_net_stat(ssh)
|
||||
new_rpxy_cpu = get_cpu_stat(ssh)
|
||||
record_filename = record["filename"]
|
||||
rpxy_cpu_diff = new_rpxy_cpu - rpxy_cpu
|
||||
p2_bytes_in_diff = new_p2_bytes_in - p2_bytes_in
|
||||
p2_bytes_out_diff = new_p2_bytes_out - p2_bytes_out
|
||||
energy_diff = new_energy - energy
|
||||
time_diff = end - start
|
||||
while True:
|
||||
try:
|
||||
with open(logfile_path, "a") as logfile:
|
||||
logfile.write(f"{expname} {impl} {alg} {kex} {cipher} {setup} {record_filename} {time_diff} {rpxy_cpu_diff} {p2_bytes_in_diff} {p2_bytes_out_diff} {energy_diff} {prof_filename}\n")
|
||||
logfile.close()
|
||||
break
|
||||
except Exception as e:
|
||||
print("Can't open log file:", e)
|
||||
time.sleep(1)
|
||||
sh(f"cp {logfile_path} {log_backup_dir}/{logfile_name}")
|
||||
first_set = False
|
||||
end = time.time()
|
||||
|
||||
new_energy = 0
|
||||
if config["wattmeter"]:
|
||||
new_energy = wattmeter.get_meter()
|
||||
new_p2_bytes_in, new_p2_bytes_out = get_net_stat(ssh)
|
||||
new_rpxy_cpu = get_cpu_stat(ssh)
|
||||
record_filename = record["filename"]
|
||||
rpxy_cpu_diff = new_rpxy_cpu - rpxy_cpu
|
||||
p2_bytes_in_diff = new_p2_bytes_in - p2_bytes_in
|
||||
p2_bytes_out_diff = new_p2_bytes_out - p2_bytes_out
|
||||
energy_diff = new_energy - energy
|
||||
time_diff = end - start
|
||||
while True:
|
||||
try:
|
||||
with open(logfile_path, "a") as logfile:
|
||||
logfile.write(f"{expname} {impl} {alg} {kex} {cipher} {earlydata} {setup} {record_filename} {time_diff} {rpxy_cpu_diff} {p2_bytes_in_diff} {p2_bytes_out_diff} {energy_diff} {prof_filename}\n")
|
||||
logfile.close()
|
||||
break
|
||||
except Exception as e:
|
||||
print("Can't open log file:", e)
|
||||
time.sleep(1)
|
||||
sh(f"cp {logfile_path} {log_backup_dir}/{logfile_name}")
|
||||
first_set = False
|
||||
if config["wattmeter"]:
|
||||
YAPI.FreeAPI()
|
||||
|
||||
|
|
@ -841,7 +914,6 @@ if __name__ == "__main__":
|
|||
send <config> Send configs and certs to p2
|
||||
update-certs <config> Update system's certs
|
||||
run <config> Run experiment
|
||||
script Print Firefox script to override DNS
|
||||
|
||||
Make options:
|
||||
-c Make CA cert (otherwise use already existing one)
|
||||
|
|
@ -907,8 +979,6 @@ Run options:
|
|||
from yoctopuce.yocto_power import *
|
||||
|
||||
run_exp(config, only_record=getargv("--record", None), idle="--idle" in sys.argv)
|
||||
elif opt == "script":
|
||||
print(SCRIPT_FIREFOX_HOSTS)
|
||||
else:
|
||||
print("Unknown command, use help for help")
|
||||
exit(1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue