| records | ||
| .gitignore | ||
| exp.py | ||
| exp_proxies.py | ||
| install-certs-arch.sh | ||
| install-certs-debian.sh | ||
| mkcacert.sh | ||
| mkcert.sh | ||
| mkcerts.sh | ||
| README.md | ||
| run.sh | ||
TLS power measure benchmark
Goal: measure the power overhead of adding TLS to a client or a server, on realistic loads.
Realistic load implies using a real-world client (such as a web browser on a low-end device) and server (such as a video streaming platform on a typical server).
Problem: realistic clients have complex behaviors that go beyond a simple OpenSSL example code, and modern browsers and website won't work without HTTPS.
Assumption: most of the load added by the security layers is decoupled from the application (in both web browsers and web servers).
Experiments:
1: (Client) <=[TLS]=> (Proxy 1) <-[plain]-> (Proxy 2) <-[plain]-> (Proxy 3) <=[TLS]=> (Server)
2: (Client) <=[TLS]=> (Proxy 1) <==[TLS]==> (Proxy 2) <-[plain]-> (Proxy 3) <=[TLS]=> (Server)
3: (Client) <=[TLS]=> (Proxy 1) <-[plain]-> (Proxy 2) <==[TLS]==> (Proxy 3) <=[TLS]=> (Server)
^measure^
Client and server are identical in all experiments. The only modification made to the client is to add a trusted certificate owned by Proxy 1.
Only Proxy 2 must be a dedicated machine. The other parties may be placed on the same machine.
Call E1, E2, E3 the energy measured for Proxy 2 in experiments 1, 2, 3.
E2-E1 is the energy used to operate the server's half of a TLS connection.
E3-E1 is the energy used to operate the client's half of a TLS connection.
Client:
- Web browser trusting a certificate owned by Proxy 1
Things to experiment
- Implementations
- OpenSSL 1.0.2
- OpenSSL 1.1.1
- OpenSSL 3.0
- OpenSSL 3.2
- OpenSSL 3.3
- OpenSSL 3.4
- OpenSSL 3.5
- OpenSSL 3.6
- WolfSSL
- GnuTLS
- NSS (used by Firefox) (?)
- opencryptoki (?)
- AWS-LC
- BoringSSL (Chrome, Android)
- LibreSSL
- SymCrypt (used by Windows) (install manually)
- Versions
- TLS 1.2
- TLS 1.3
- Features
- TLS
- Ciphers
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_CCM_SHA256
- TLS_AES_128_CCM_8_SHA256
- Key exchange groups
- secp256r1
- secp384r1
- secp521r1
- x25519
- x448
- ffdhe2048
- ffdhe3072
- ffdhe4096
- ffdhe6144
- ffdhe8192
- Signatures
- rsa_pkcs1_sha256
- rsa_pkcs1_sha384
- rsa_pkcs1_sha512
- ecdsa_secp256r1_sha256
- ecdsa_secp384r1_sha384
- ecdsa_secp521r1_sha512
- rsa_pss_rsae_sha256
- rsa_pss_rsae_sha384
- rsa_pss_rsae_sha512
- ed25519
- ed448
- rsa_pss_pss_sha256
- rsa_pss_pss_sha384
- rsa_pss_pss_sha512
- rsa_pkcs1_sha1
- ecdsa_sha1
- Ciphers
- X.509
- Signature algorithm
- RSA2048
- RSA3072
- RSA4096
- EC 256
- EC 384
- SCT
- TODO !!!
- Signature algorithm
- TLS
- Usages
- Video streaming
- Full-speed download
- Real-time video call
- Mostly text browsing
- With or without ads
Most of the implementations can be used through RusTLS.
However RusTLS clients won't enable to force TLS1.2 if 1.3 is available.
rpxy
Reverse-proxy utilisant RusTLS.
WolfSSL
git clone https://github.com/wolfSSL/wolfssl --depth 1
cd wolfssl
sh autogen.sh
./configure --enable-all --enable-all-crypto --disable-shared --prefix=/opt/wolfssl-rs/
make
sudo make install
self-signed cert
openssl req -x509 -newkey rsa:2048 -keyout /tmp/foo.home.key -subj "/CN=foo.home/C=AT/ST=Lyon/L=Lyon/O=MyOrg" -out /tmp/foo.home.crt -nodes -sha256 -addext "subjectAltName=DNS:foo.home"
Client
Automatize experiments using Selenium
Experiment management
- Manager tells P2 what shared libs and rpxy binary to load.
- Tell P1, P2, P3 what rpxy config to load.
- Start measures.
- Start Yocto (USB).
- Start
Ad-hoc proxy?
Features:
- Use RusTLS and any backend easily
- Listen to plain HTTP or TLS (1.2 or 1.3)
State of the art
- https://pub.h-brs.de/frontdoor/deliver/index/docId/4771/file/2019-ESP32-TLS-Power.pdf
- 2019
- TLS 1.2, 1.3
- ESP32
- WolfSSL
- https://www.semanticscholar.org/paper/Energy-Consumption-Framework-and-Analysis-of-on-Patterson-Buchanan/706736a29cef777e5dc50ba22b4788b2bfb4c6ef
- 2025
- RaspberryPi
- OpenSSL
- ML-KEM
- https://www.semanticscholar.org/paper/Energy-Profiling-and-Comparison-of-TLS-Protocols-Gatram-Reddy/9c061fe57a0008574b85919bc70fc803c6e66f06
- 2024
- RaspberryPi
- TLS PQ, TLS KEM, TLS
- https://www.semanticscholar.org/paper/Energy-Consumption-Evaluation-of-Post-Quantum-TLS-Tasopoulos-Dimopoulos/2ffc6d13349e2fa5f89aaf18e69ce2044ecef4fe
- 2023
- STM Nucleo
- WolfSSL
- TLS 1.3 PQ
- https://arxiv.org/pdf/2508.04583v2
- 2025
- TLS 1.3
- Nginx + Python requests
- https://github.com/MarcT0K/privacy-carbon-experiments
- https://davidtnaylor.com/CostOfTheS.pdf
- 2014
Sources
Notes
Install sa on p2:
sudo apt install acct
sudo chmod +s /sbin/sa
Override DNS in browser:
firefox -P tlsbench
In about:config, set devtools.chrome.enabled to true.
Set default DNS in settings.
In console:
const gOverride = Cc["@mozilla.org/network/native-dns-override;1"].getService(Ci.nsINativeDNSResolverOverride);
gOverride.clearOverrides();
var names = ["apple.com", "www.apple.com", "mzstatic.com", "youtube.com", "www.youtube.com", "i.ytimg.com", "fonts.gstatic.com", "www.google.com", "accounts.google.com", "yt3.ggpht.com", "www.gstatic.com"];
for(var i in names) {
gOverride.addIPOverride(names[i], "127.0.0.1");
}
Authorize rpxy to bind to ports 80 and 443:
sudo setcap CAP_NET_BIND_SERVICE=+eip netreplay
python exp.py make -c
python exp.py send
python exp.py update-certs # also do this command on p2
python exp.py run
On Debian, update-certs says 0 certs added even if it has actually updated some certs. This step is still needed.
Problems
Youtube gives 502 bad gateway.
- Works with bare curl. (not hiding we're a bot)
- We have same JA3 fingerprint as Firefox.
- HTTP request is intact.
- JA4 fingerprint different from Firefox but existing for some browsers.
Modèle d'expérience à revoir
- Le relai d'une vidéo streaming avec TLS prend max 3% d'un cœur sur le Pi3, soit pas beaucoup plus que le bruit.
- Il faudrait spammer avec plusieurs connexions pour voir un effet significatif.
- On peut spammer le streaming vidéo, mais pas le reste (antibots).
- On ne devrait pas spammer sur Renater...
- Il faut donc tout faire en local.
Solutions :
- Copier les sites en statique et les servir avec Apache. => OK pour des sites propres genre Wikipedia, WordPress (à voir pour la pub)
- Installer des instances => Peertube, WordPress
- Copier le trafic et le rejouer => risque de demander beaucoup de dev
Youtube
Youtube utilise des trucs aléatoires en RANDOM.googlevideo.com pour la vidéo. Cependant il y a quelques domaines utilisés qui ne changent pas, du moins sur un même navigateur avec la même vidéo et sur une courte période.
Avant d'enregistrer le trafic, il faut observer les domaines utilisés puis générer les certificats et les redirections en fonction.
TODO
- Partie serveur sans TLS de netreplay -> sans SNI, il faut parser le HTTP >.<
- exp.py: détecter la fin du replay
- yoctowatt
- mesures CPU, mémoire, bande passante sur p2
- CPU: paquet acct, commande
sa -m
- CPU: paquet acct, commande