multiprobe 0.1.0

Enterprise-grade multi-protocol network probing with Paris Traceroute, path analytics, MTU discovery, and TLS analysis
Documentation
# multiprobe

[![Crates.io](https://img.shields.io/crates/v/multiprobe.svg)](https://crates.io/crates/multiprobe)
[![Documentation](https://docs.rs/multiprobe/badge.svg)](https://docs.rs/multiprobe)
[![License](https://img.shields.io/crates/l/multiprobe.svg)](LICENSE)

Enterprise-grade multi-protocol network probing library for Rust with Paris Traceroute, path analytics, MTU discovery, bufferbloat detection, and TLS analysis.

## Why multiprobe?

- **Paris Traceroute** - First pure-Rust implementation of ECMP-aware traceroute
- **Comprehensive Analytics** - Jitter, MTU, bufferbloat, reordering in one crate
- **Protocol Differential Score** - Novel metric for cross-protocol path analysis
- **Production Ready** - 100+ tests, zero unsafe in public API

## Features

### Protocol Probes
| Probe | Description | Privileges |
|-------|-------------|------------|
| TCP | Connect probes with timing breakdown | None |
| UDP | Packet probes with response detection | None |
| ICMP | Echo requests with RTT measurement | CAP_NET_RAW |
| TLS | Handshake timing, cipher, version analysis | None |

### Path Discovery
| Feature | Description |
|---------|-------------|
| Traceroute | Standard hop-by-hop path discovery |
| Paris Traceroute | ECMP-aware traceroute (maintains flow consistency) |
| Multi-path Discovery | Find all paths through load balancers |
| Load Balancing Detection | Identify per-flow vs per-packet ECMP |

### Path Analytics
| Metric | Description |
|--------|-------------|
| Latency Stats | min/max/mean/median/p95/p99/jitter |
| Path MTU | Binary search MTU discovery |
| Bufferbloat | Latency degradation under load (A-F grading) |
| Packet Reordering | Out-of-order delivery detection |

### Classification
| Feature | Description |
|---------|-------------|
| Path Fingerprint | Stable hashes for path comparison |
| Protocol Differential Score | Cross-protocol behavior analysis |
| Network Behavior | ICMP filtering, asymmetric routing detection |

## Installation

```toml
[dependencies]
multiprobe = "0.1"
```

## Quick Start

```rust
use multiprobe::Probe;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), multiprobe::Error> {
    // TCP probe with timing
    let tcp = Probe::tcp("example.com", 443)
        .timeout(Duration::from_secs(5))
        .send().await?;
    
    println!("Success: {}", tcp.success);
    println!("Latency: {:.2}ms", tcp.timing.total_ms());
    
    Ok(())
}
```

## Multi-Protocol Analysis

```rust
use multiprobe::{Probe, Classifier};

let result = Probe::multi("example.com")
    .tcp(80)
    .tcp(443)
    .udp(53)
    .timeout(Duration::from_secs(5))
    .send().await?;

// Per-protocol results
for probe in &result.results {
    println!("{}: {} ({:.2}ms)", 
        probe.protocol,
        if probe.success { "OK" } else { "FAIL" },
        probe.timing.total_ms());
}

// Path classification
println!("Classification: {}", result.classify());

// Protocol Differential Score
let pds = Classifier::differential_score(&result.results);
println!("Consistency: {:.2}", pds.consistency);
println!("Behavior: {}", pds.interpret());

// Fingerprint
println!("Fingerprint: {}", Classifier::fingerprint(&result.results));
println!("Hash: {:016x}", Classifier::fingerprint_hash(&result.results));
```

## Paris Traceroute

Standard traceroute fails behind ECMP load balancers because it varies flow identifiers between probes. Paris Traceroute (Augustin et al., 2006) maintains constant flow IDs for consistent path discovery.

```rust
use multiprobe::{Probe, ParisMode, FlowId};

// Basic Paris Traceroute
let trace = Probe::paris("example.com")
    .max_hops(30)
    .timeout_per_hop(Duration::from_secs(2))
    .send().await?;

println!("Target: {} ({})", trace.target, trace.target_ip);
println!("Hops: {}", trace.hops.len());
println!("Reached: {}", trace.reached_destination);
println!("Load Balancing: {}", trace.load_balancing);

for hop in &trace.hops {
    let addr = hop.addr.map(|ip| ip.to_string())
        .unwrap_or_else(|| "*".to_string());
    println!("{:2}. {:15} {:.2}ms", 
        hop.ttl, addr, hop.rtt.as_secs_f64() * 1000.0);
}

// With custom flow ID
let trace = Probe::paris("example.com")
    .flow_id(FlowId::udp(33434, 33434))
    .mode(ParisMode::Udp)
    .detect_load_balancing(true)
    .send().await?;

// Discover multiple paths through load balancers
let paths = multiprobe::discover_paths("example.com", 6, &Default::default()).await?;
println!("Found {} distinct paths", paths.len());
```

## TLS Handshake Analysis

```rust
use multiprobe::Probe;

let tls = Probe::tls("example.com")
    .port(443)
    .timeout(Duration::from_secs(10))
    .send().await?;

if tls.success {
    println!("TLS Version: {}", tls.tls_version);
    println!("Cipher: {:?}", tls.cipher_suite);
    println!("HTTP/2: {}", tls.supports_http2());
    println!("Modern TLS: {}", tls.is_modern_tls());
    
    println!("\nTiming Breakdown:");
    println!("  DNS:   {:.2}ms", tls.timing.dns_ms());
    println!("  TCP:   {:.2}ms", tls.timing.tcp_ms());
    println!("  TLS:   {:.2}ms", tls.timing.tls_ms());
    println!("  Total: {:.2}ms", tls.timing.total_ms());
} else {
    println!("TLS failed: {:?}", tls.error);
}
```

## Latency Statistics

```rust
use multiprobe::Probe;

let stats = Probe::latency("example.com", 443)
    .samples(100)
    .interval(Duration::from_millis(100))
    .send().await?;

println!("Samples: {}/{}", stats.success_count, stats.sample_count);
println!("Loss: {:.1}%", stats.loss_rate * 100.0);
println!();
println!("Min:    {:.2}ms", stats.min_rtt.as_secs_f64() * 1000.0);
println!("Max:    {:.2}ms", stats.max_rtt.as_secs_f64() * 1000.0);
println!("Mean:   {:.2}ms", stats.mean_rtt.as_secs_f64() * 1000.0);
println!("Median: {:.2}ms", stats.median_rtt.as_secs_f64() * 1000.0);
println!("P95:    {:.2}ms", stats.p95_rtt.as_secs_f64() * 1000.0);
println!("P99:    {:.2}ms", stats.p99_rtt.as_secs_f64() * 1000.0);
println!("Jitter: {:.2}ms", stats.jitter.as_secs_f64() * 1000.0);
println!("StdDev: {:.2}ms", stats.std_dev.as_secs_f64() * 1000.0);

if stats.has_high_jitter() {
    println!("WARNING: High jitter detected!");
}
if stats.has_packet_loss() {
    println!("WARNING: Packet loss detected!");
}
```

## Path MTU Discovery

```rust
use multiprobe::Probe;

let mtu = Probe::mtu("example.com")
    .min_mtu(68)
    .max_mtu(1500)
    .timeout(Duration::from_secs(2))
    .send().await?;

println!("Path MTU: {} bytes", mtu.path_mtu);
println!("DF Honored: {}", mtu.df_honored);
println!("Frag Needed msgs: {}", mtu.frag_needed_count);
```

## Bufferbloat Detection

```rust
use multiprobe::Probe;

let bloat = Probe::bufferbloat("example.com")
    .port(443)
    .baseline_samples(10)
    .loaded_samples(10)
    .send().await?;

println!("Baseline: {:.2}ms", bloat.baseline_latency.as_secs_f64() * 1000.0);
println!("Under Load: {:.2}ms", bloat.loaded_latency.as_secs_f64() * 1000.0);
println!("Bloat Factor: {:.2}x", bloat.bloat_factor);
println!("Grade: {}", bloat.grade);  // A-F rating
println!("Detected: {}", bloat.detected);
```

## Path Classification

| Classification | Description |
|---------------|-------------|
| `Open` | All protocols succeed |
| `IcmpFiltered` | ICMP blocked, TCP/UDP pass |
| `TcpFiltered` | ICMP passes, TCP blocked |
| `SelectiveFirewall` | Some ports open, some closed |
| `Blocked` | All protocols fail |
| `NatDetected` | TTL variance indicates NAT |

## Protocol Differential Score

Quantifies behavioral differences across protocols:

```rust
use multiprobe::Classifier;

let pds = Classifier::differential_score(&results);

// Differentials (0.0 = identical, 1.0 = completely different)
println!("ICMP vs TCP: {:.2}", pds.icmp_tcp_diff);
println!("ICMP vs UDP: {:.2}", pds.icmp_udp_diff);
println!("TCP vs UDP:  {:.2}", pds.tcp_udp_diff);

// Consistency (1.0 = all protocols identical)
println!("Consistency: {:.2}", pds.consistency);

// Latency variance
println!("Latency Variance: {:.2}ms", pds.latency_variance_ms);

// Interpreted behavior
use multiprobe::NetworkBehavior;
match pds.interpret() {
    NetworkBehavior::Direct => println!("Direct path"),
    NetworkBehavior::IcmpFiltering => println!("ICMP filtering"),
    NetworkBehavior::ProtocolSpecificFiltering => println!("Protocol filtering"),
    NetworkBehavior::AsymmetricRouting => println!("Asymmetric routing"),
    NetworkBehavior::Unknown => println!("Unknown"),
}
```

## Load Balancing Detection

```rust
use multiprobe::LoadBalancingType;

let trace = Probe::paris("example.com")
    .detect_load_balancing(true)
    .send().await?;

match trace.load_balancing {
    LoadBalancingType::None => println!("No load balancing"),
    LoadBalancingType::PerFlow => println!("Per-flow ECMP"),
    LoadBalancingType::PerPacket => println!("Per-packet ECMP"),
    LoadBalancingType::Unknown => println!("Unknown"),
}
```

## Permissions

| Feature | Linux | macOS | Windows |
|---------|-------|-------|---------|
| TCP/UDP probes | None | None | None |
| TLS probes | None | None | None |
| Latency stats | None | None | None |
| ICMP ping | CAP_NET_RAW | root | Admin |
| Traceroute | CAP_NET_RAW | root | Admin |
| Paris Traceroute | CAP_NET_RAW | root | Admin |
| MTU Discovery | CAP_NET_RAW | root | Admin |

```bash
# Linux: Grant capability
sudo setcap cap_net_raw+ep ./your-binary

# macOS/Linux: Run with sudo
sudo ./your-binary
```

## API Reference

### Probe Builders

```rust
Probe::tcp(target, port)      // TCP connect probe
Probe::udp(target, port)      // UDP probe
Probe::icmp(target)           // ICMP ping
Probe::multi(target)          // Multi-protocol
Probe::traceroute(target)     // Standard traceroute
Probe::paris(target)          // Paris Traceroute
Probe::tls(target)            // TLS handshake
Probe::latency(target, port)  // Latency statistics
Probe::mtu(target)            // Path MTU discovery
Probe::bufferbloat(target)    // Bufferbloat detection
```

### Standalone Functions

```rust
multiprobe::paris_traceroute(target, &options)  // Paris trace
multiprobe::discover_paths(target, flows, &options)  // Multi-path
multiprobe::measure_latency(target, port, samples, interval)
multiprobe::discover_path_mtu(target, &options)
multiprobe::detect_bufferbloat(target, &options)
multiprobe::analyze_reordering(target, port, packets)
multiprobe::probe_tls(target, &options)
multiprobe::compare_tls(target1, target2, &options)
```

## References

- **Paris Traceroute**: Augustin et al., "Avoiding traceroute anomalies with Paris traceroute" (IMC 2006)
- **RFC 3550**: RTP jitter calculation
- **RFC 1191**: Path MTU Discovery
- **Bufferbloat**: Gettys & Nichols, "Bufferbloat: Dark Buffers in the Internet" (2012)

## License

MIT OR Apache-2.0