lonca-net 0.2.1

A loopback HTTP CONNECT proxy that asks a gate about every connection
Documentation
  • Coverage
  • 76.92%
    30 out of 39 items documented1 out of 22 items with examples
  • Size
  • Source code size: 37.1 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 314.5 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 1s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • selcukgural/lonca
    1 0 6
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • selcukgural

lonca-net

A small network proxy for sandboxed commands, from Lonca and usable on its own.

A sandbox lets commands reach only this proxy, on loopback. Every connection (CONNECT host:port or an absolute http:// request) is put to a Gate, which decides whether it goes through. Loopback, private and link-local destinations are refused unless the gate allows them, and the proxy connects to the address it checked, so DNS cannot swap in a private address after the check. The proxy never looks inside TLS itself; a gate may serve a tunnel it let through (Gate::relay).

It has no dependencies and knows nothing about who uses it: the gate holds all the policy.

use std::sync::Arc;

use lonca_net::{Gate, Request, Verdict};

/// Lets a build fetch crates and nothing else.
struct CratesOnly;

impl Gate for CratesOnly {
    fn decide(&self, request: &Request<'_>) -> Verdict {
        match (request.host, request.port) {
            ("index.crates.io" | "static.crates.io", 443) => Verdict::allow(),
            _ => Verdict::deny("only crates.io"),
        }
    }
}

fn main() -> std::io::Result<()> {
    // Loopback only: `bind` refuses any other address.
    let listener = lonca_net::bind("127.0.0.1:0")?;
    let server = lonca_net::spawn(listener, Arc::new(CratesOnly))?;

    // The sandboxed command gets HTTPS_PROXY=http://<this address>.
    println!("proxy on {}", server.local_addr());

    // Closes the listener and cuts every open connection.
    server.stop();
    Ok(())
}

Gate::finished, Gate::carried and Gate::relay are told how each connection ended, see every byte relayed (and may cut it when a budget is spent), and may serve a tunnel themselves.

Its API has no stability promise yet, and its version moves with Lonca's workspace (every Lonca crate has the same version): pin an exact one.