12 stable releases
Uses new Rust 2024
| 2.2.2 | Sep 12, 2025 |
|---|---|
| 2.1.0 | Feb 2, 2025 |
| 2.0.1 | Oct 24, 2024 |
| 1.1.3 | Aug 31, 2024 |
| 0.0.0 | Mar 3, 2023 |
#73 in Network programming
22,736 downloads per month
Used in 11 crates
(7 directly)
225KB
4K
SLoC
Maybenot 🤔
Maybenot is a framework for traffic analysis defenses that hide patterns in encrypted communication. Its goal is to increase the uncertainty of network attackers, hence its logo 🤔 - the thinking face emoji (U+1F914).
Consider encrypted communication protocols such as QUIC, TLS, Tor, and WireGuard. While the connections are encrypted, patterns in the encrypted communication may still leak information about the communicated plaintext. Maybenot is a framework for creating defenses that hide such patterns.
Design
An instance of Maybenot repeatedly takes as input one or more events describing the encrypted traffic going over an encrypted channel. It produces as output zero or more scheduled actions, such as to send padding traffic or to block outgoing traffic. One or more state machines determine what actions to take based on events. State machines have a lightweight runtime and are subject to limits on the amount of padding and blocking they can schedule.
Integration with an encrypted communication protocol is done by reporting events and executing scheduled actions. Maybenot does not specify the specific async runtime or how to keep time for ease of integration.
Example usage
use crate::{Framework, Machine, TriggerAction, TriggerEvent};
use std::{str::FromStr, time::Instant};
// deserialize a machine, this is a "no-op" machine that does nothing
let s = "02eNpjYEAHjOgCAAA0AAI=";
let m = vec![Machine::from_str(s).unwrap()];
// create framework instance
let mut f = Framework::new(&m, 0.0, 0.0, Instant::now(), rand::rng()).unwrap();
loop {
// collect one or more events
let events = [TriggerEvent::NormalSent];
// trigger events, schedule actions, at most one per machine
for action in f.trigger_events(&events, Instant::now()) {
match action {
TriggerAction::Cancel {
machine: MachineId,
timer: Timer,
} => {
// cancel the specified timer (action, machine, or both) for the
// machine in question, if any
}
TriggerAction::SendPadding {
timeout: Duration,
bypass: bool,
replace: bool,
machine: MachineId,
} => {
// schedule padding to be sent after timeout
}
TriggerAction::BlockOutgoing {
timeout: Duration,
duration: Duration,
bypass: bool,
replace: bool,
machine: MachineId,
} => {
// block outgoing traffic for the specified duration after timeout
}
TriggerAction::UpdateTimer {
duration: Duration,
replace: bool,
machine: MachineId,
} => {
// update the internal timer for the machine in question
}
}
}
}
More details
Please see the Maybenot workspace root on GitHub for further details and associated tooling.
Contributing
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as MIT or Apache-2.0, without any additional terms or conditions.
Origin
Maybenot is based on the Circuit Padding Framework of Tor by Perry and Kadianakis from 2019, which is a generalization of the WTF-PAD Website Fingerprinting Defense design by Juarez et al. from 2016, which in turn is based on the concept of Adaptive Padding by Shmatikov and Wang from 2006.
Sponsorship
Made possible with support from Mullvad VPN, the Swedish Internet Foundation, and the Knowledge Foundation of Sweden.
Dependencies
~2.8–4MB
~80K SLoC