Clean readme, replace Arcs with leaked Boxes
This commit is contained in:
parent
ad2c0909b4
commit
a95efd9ed8
4 changed files with 19 additions and 35 deletions
|
|
@ -27,12 +27,13 @@ rustls-symcrypt = { version = "0.2.1", optional = true, features = ["chacha", "x
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
default = [
|
||||||
"aws-lc",
|
"aws-lc",# Change this to the wanted cryptographic backend (list below)
|
||||||
#"record",
|
"record",# It may be needed to remove the record feature when building with openssl
|
||||||
]
|
]
|
||||||
|
|
||||||
record = ["sslrelay"]
|
record = ["sslrelay"]
|
||||||
|
|
||||||
|
# Available cryptographic backends
|
||||||
aws-lc = ["tokio-rustls/aws-lc-rs", "rustls-post-quantum", "rustls-post-quantum/aws-lc-rs-unstable", "aws-lc-rs"]
|
aws-lc = ["tokio-rustls/aws-lc-rs", "rustls-post-quantum", "rustls-post-quantum/aws-lc-rs-unstable", "aws-lc-rs"]
|
||||||
boring = ["boring-rustls-provider"]
|
boring = ["boring-rustls-provider"]
|
||||||
graviola = ["rustls-graviola"]
|
graviola = ["rustls-graviola"]
|
||||||
|
|
|
||||||
22
README.md
22
README.md
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
This program has two modes:
|
This program has two modes:
|
||||||
* recording proxy: relays trafic with or without TLS and record requests and responses in clear. It is a TLS termination thus a certificate is needed.
|
* recording proxy: relays trafic with or without TLS and record requests and responses in clear. It is a TLS termination thus a certificate is needed.
|
||||||
* trafic replay: run a client that sends the recorded requests, and a server that responds with the corresponding recorded responses. A proxy can be placed in between. The proxy can even alter the plain data, because the server uses hash distance to identify the requests.
|
* trafic replay: run a client that sends the recorded requests, and a server that responds with the corresponding recorded responses. Responses are replaced with the same amount of random bytes for performance.
|
||||||
|
|
||||||
It has been tested with HTTP trafic only. Other protocols which are not request/response (or even websocket) may not be recorded properly.
|
|
||||||
|
|
||||||
It relies on the server name extension in TLS (SNI). Requests without server name may not be recorded.
|
It relies on the server name extension in TLS (SNI). Requests without server name may not be recorded.
|
||||||
|
|
||||||
|
|
@ -12,27 +10,21 @@ For experimental purpose. Do not use on an open network where security matters.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
[Install Rust nightly.](https://rustup.rs)
|
||||||
|
|
||||||
|
Choose a cryptographic backend in `Cargo.toml`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
RUSTFLAGS="--cfg tokio_unstable" cargo build --release
|
cargo build --release
|
||||||
```
|
```
|
||||||
|
|
||||||
## Record file format
|
|
||||||
|
|
||||||
The record file is a list of records. Each record follows this format:
|
|
||||||
* [1 byte] direction: ASCII 'C' for client-to-server, 'S' for server-to-client
|
|
||||||
* [8 bytes] connection id, big endian
|
|
||||||
* [1 byte] server name length
|
|
||||||
* server name (TLS's SNI or HTTP's Host)
|
|
||||||
* [8 bytes] data length, big endian
|
|
||||||
* data
|
|
||||||
|
|
||||||
## SSLKEYLOGFILE
|
## SSLKEYLOGFILE
|
||||||
|
|
||||||
The `SSLKEYLOGFILE` environment variable can be set to a file path to which the connection secrets will be exported, enabling decrypting the traffic in Wireshark.
|
The `SSLKEYLOGFILE` environment variable can be set to a file path to which the connection secrets will be exported, enabling decrypting the traffic in Wireshark.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
GNU AGPL v3, CopyLeft 2025 Pascal Engélibert [(why copyleft?)](https://txmn.tk/blog/why-copyleft/)
|
GNU AGPL v3, CopyLeft 2025-2026 Pascal Engélibert [(why copyleft?)](https://txmn.tk/blog/why-copyleft/)
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
|
||||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
||||||
|
|
|
||||||
|
|
@ -102,25 +102,24 @@ pub async fn play(
|
||||||
) {
|
) {
|
||||||
// Semaphore used to limit the number of concurrent clients.
|
// Semaphore used to limit the number of concurrent clients.
|
||||||
// Its handle is released when the task panics.
|
// Its handle is released when the task panics.
|
||||||
let limiter = Arc::new(Semaphore::new(concurrency));
|
let limiter: &'static _ = Box::leak(Box::new(Semaphore::new(concurrency)));
|
||||||
let counter = Arc::new(AtomicU32::new(0));
|
let counter: &'static _ = Box::leak(Box::new(AtomicU32::new(0)));
|
||||||
let running = Arc::new(Mutex::new(HashSet::new()));
|
let running: &'static _ = Box::leak(Box::new(Mutex::new(HashSet::new())));
|
||||||
let total = records.len() * repeat as usize;
|
let total = records.len() * repeat as usize;
|
||||||
let connect_to = connect_to.to_socket_addrs().unwrap().next().unwrap();
|
let connect_to = connect_to.to_socket_addrs().unwrap().next().unwrap();
|
||||||
|
|
||||||
let dummy_bytes = Arc::new(vec![0x42u8; 16 * 1024 * 1024]);
|
let dummy_bytes: &'static _ = Box::leak(Box::new(vec![0x42u8; 16 * 1024 * 1024]));
|
||||||
|
|
||||||
let notify_socket = notify_addr.map(|notify_addr| {
|
let notify_socket = notify_addr.map(|notify_addr| {
|
||||||
let socket = std::net::UdpSocket::bind("0.0.0.0:48567").unwrap();
|
let socket = std::net::UdpSocket::bind("0.0.0.0:48567").unwrap();
|
||||||
socket.connect(notify_addr).unwrap();
|
socket.connect(notify_addr).unwrap();
|
||||||
Arc::new(socket)
|
let socket: &'static _ = Box::leak(Box::new(socket));
|
||||||
|
socket
|
||||||
});
|
});
|
||||||
|
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||||
|
|
||||||
tokio::spawn({
|
tokio::spawn({
|
||||||
let running = running.clone();
|
|
||||||
let counter = counter.clone();
|
|
||||||
async move {
|
async move {
|
||||||
let mut last_count = 0;
|
let mut last_count = 0;
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -197,11 +196,7 @@ pub async fn play(
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
for (conn_id, (server_name, records)) in records.iter() {
|
for (conn_id, (server_name, records)) in records.iter() {
|
||||||
let connector = TlsConnector::from(config.clone());
|
let connector = TlsConnector::from(config.clone());
|
||||||
let counter = counter.clone();
|
|
||||||
let limiter = limiter.clone();
|
|
||||||
let running = running.clone();
|
|
||||||
let dummy_bytes = dummy_bytes.clone();
|
let dummy_bytes = dummy_bytes.clone();
|
||||||
let notify_socket = notify_socket.clone();
|
|
||||||
handles.push(tokio::spawn(async move {
|
handles.push(tokio::spawn(async move {
|
||||||
let mut running_guard = running.lock().await;
|
let mut running_guard = running.lock().await;
|
||||||
running_guard.insert(*conn_id);
|
running_guard.insert(*conn_id);
|
||||||
|
|
@ -294,11 +289,7 @@ pub async fn play(
|
||||||
for _i in 0..repeat {
|
for _i in 0..repeat {
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
for (conn_id, (_server_name, records)) in records.iter() {
|
for (conn_id, (_server_name, records)) in records.iter() {
|
||||||
let counter = counter.clone();
|
|
||||||
let limiter = limiter.clone();
|
|
||||||
let running = running.clone();
|
|
||||||
let dummy_bytes = dummy_bytes.clone();
|
let dummy_bytes = dummy_bytes.clone();
|
||||||
let notify_socket = notify_socket.clone();
|
|
||||||
handles.push(tokio::spawn(async move {
|
handles.push(tokio::spawn(async move {
|
||||||
let mut running_guard = running.lock().await;
|
let mut running_guard = running.lock().await;
|
||||||
running_guard.insert(*conn_id);
|
running_guard.insert(*conn_id);
|
||||||
|
|
@ -366,7 +357,7 @@ pub async fn play(
|
||||||
println!("Client: {} / {}", cnt, total);
|
println!("Client: {} / {}", cnt, total);
|
||||||
}
|
}
|
||||||
drop(limiter);
|
drop(limiter);
|
||||||
if let Some(notify_socket) = ¬ify_socket {
|
if let Some(notify_socket) = notify_socket {
|
||||||
notify_socket.send(&cnt.to_be_bytes()).unwrap();
|
notify_socket.send(&cnt.to_be_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
let mut running_guard = running.lock().await;
|
let mut running_guard = running.lock().await;
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ pub async fn play(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let response_map = Arc::new(response_map);
|
let response_map: &'static _ = Box::leak(Box::new(response_map));
|
||||||
let dummy_bytes = Arc::new(vec![0x42u8; 16 * 1024 * 1024]);
|
let dummy_bytes: &'static _ = Box::leak(Box::new(vec![0x42u8; 16 * 1024 * 1024]));
|
||||||
|
|
||||||
if use_tls {
|
if use_tls {
|
||||||
let mut resolver = ResolvesServerCertUsingSni::new();
|
let mut resolver = ResolvesServerCertUsingSni::new();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue