Skip to content

ZZ0R0/RUP

Repository files navigation

RUP — a Burp-like intercepting proxy as a desktop app

RUP is a desktop application (Tauri 2 + TypeScript UI, Rust backend) that reproduces the core of a Burp-style workflow: spin up a local HTTPS MITM proxy, auto-launch a Chromium instance pinned to it, capture and replay requests, and incrementally map a target (crawl + light fuzz). The proxy backend wraps hudsucker and rustls, issues per-host leaf certificates from a local CA, and streams every intercepted exchange to the UI over the Tauri event bus.

Backend UI Proto License

⚠️ Authorized use only

RUP is a MITM proxy: it breaks TLS end-to-end guarantees for any client configured to trust its CA. Use it only against systems and targets you own or are explicitly authorized to test (pentest engagement, bug bounty in-scope, CTF, lab). Keep the CA private key secure and remove the CA from trust stores when you're done.


Architecture

flowchart LR
    subgraph App["RUP desktop app (Tauri 2)"]
        UI["TypeScript UI<br/>history · replay · site map"]
        subgraph Backend["Rust backend"]
            CMD["Tauri commands<br/>start_proxy · launch_chromium · replay_request · mapper_*"]
            CORE["burp_core<br/>lossless HTTP model (ordered headers, raw start line)"]
            PROXY["burp_proxy<br/>hudsucker + rcgen CA + rustls upstream + Chromium launcher"]
            MAP["burp_mapper<br/>job queue · crawl HTML · fuzz common paths · per-origin profiles"]
            CMD --- CORE --- PROXY --- MAP
        end
        UI <-->|"Tauri events: proxy:message · mapper:update · debug:proxy"| Backend
    end

    CHROME["Chromium<br/>dedicated profile + NSS trust store<br/>--proxy-server, --disable-quic"]
    ORIGIN[(Origin server)]

    CHROME -->|"HTTP/1.1 · HTTP/2 over TCP"| PROXY
    PROXY -->|"per-host leaf cert signed by local CA"| CHROME
    PROXY -->|"rustls (aws-lc-rs, webpki roots)"| ORIGIN
    MAP -.->|crawl / fuzz requests| ORIGIN
Loading
  • QUIC is disabled in Chromium so all traffic stays on the TCP proxy path. HTTP/2 is supported; HTTP/3 is not proxied.
  • Every intercepted request emits a Message to the UI (proxy:message). Responses currently pass through — extend handle_response to capture bodies.

Key features

  • Transparent HTTP/1.1 and HTTP/2 interception
  • On-the-fly leaf certificate issuance from your local CA (rcgen)
  • Chromium launcher with dedicated profile and NSS trust store
  • Lossless request parsing and serialization (ordered headers, raw start line)
  • Request replay
  • Basic site mapper: seed → crawl links → fuzz common paths
  • Tauri events streaming to the UI

Repository layout

src-tauri/
  Cargo.toml
  src/
    main.rs                # Tauri app entry, commands, event wiring
    lib.rs                 # Example Tauri command (greet)
  crates/
    burp_core/             # Data model and lossless HTTP parse utilities
    burp_proxy/            # Hudsucker wrapper, CA loading, Chromium launcher
    burp_mapper/           # Crawler + light fuzzer + profiles

Crates

  • burp_core Data structures: Request, Response, Message, HeaderList, HttpVersion. Utilities: lossless parsing of request/status lines and headers.

  • burp_proxy

    • Hudsucker proxy with:

      • CA: RcgenAuthority from ca.pem + ca.key.pem
      • Upstream TLS: rustls using webpki roots (aws-lc-rs provider)
      • HttpHandler that emits Message on every request
    • Chromium launcher:

      • sets HOME to the chosen profile directory
      • uses --user-data-dir, --proxy-server, --disable-quic
      • verifies NSS DB and CA import
  • burp_mapper

    • Async manager with a job queue and per-origin concurrency
    • Seed URLs, crawl HTML, fuzz common endpoints
    • Emits MapperEvent on discoveries
    • Optional per-origin profiles (headers, cookies)

Proxy details

CA and TLS interception

  • Files expected in the profile directory:

    • ca.key.pem — CA private key (PKCS#8 or SEC1; SEC1 is auto-converted)
    • ca.pem — self-signed CA certificate (X.509) with CA basic constraints
    • .pki/nssdb/cert9.db — NSS database that trusts the CA
  • RUP loads the CA into RcgenAuthority. Hudsucker issues per-origin leaf certs on demand.

  • Upstream TLS uses rustls with webpki roots (aws-lc-rs crypto provider).

Chromium launcher

  • Sets HOME and --user-data-dir to the same profile directory to force the NSS trust store used by that profile.
  • Uses --proxy-server=http=HOST:PORT;https=HOST:PORT and --proxy-bypass-list=<-loopback>.
  • Uses --disable-quic to avoid HTTP/3.

Setup

0) Prerequisites

  • Rust stable, Node 18+
  • Tauri 2 toolchain
  • libnss3-tools (certutil) for NSS DB
  • openssl or any tool able to generate a CA
  • Chromium or Chrome installed and discoverable in PATH (chromium, chromium-browser, google-chrome-stable, etc.)

1) Create a profile directory

PROFILE="$HOME/.local/share/rup"
mkdir -p "$PROFILE/.pki/nssdb"

2) Generate a CA

Example with OpenSSL:

cd "$PROFILE"
openssl genrsa -out ca.key.pem 4096
openssl req -x509 -new -nodes -key ca.key.pem -sha256 -days 3650 \
  -subj "/CN=BurpCloneCA" \
  -out ca.pem \
  -addext "basicConstraints=critical,CA:true,pathlen:1" \
  -addext "keyUsage=critical,keyCertSign,cRLSign" \
  -addext "subjectKeyIdentifier=hash" \
  -addext "authorityKeyIdentifier=keyid,issuer"

3) Initialize NSS database and import the CA

# Create an empty NSS DB (uses sql: driver)
certutil -N -d "sql:$PROFILE/.pki/nssdb" --empty-password

# Import the CA as a trusted issuer for TLS
certutil -A -d "sql:$PROFILE/.pki/nssdb" -n "BurpCloneCA" -t "C,," -i "$PROFILE/ca.pem"

# Verify
certutil -L -d "sql:$PROFILE/.pki/nssdb"

You should see BurpCloneCA listed.


Build and run

From the repo root:

# install deps
npm i

# dev run
npm run tauri dev

The app exposes Tauri commands to:

  • start the proxy: start_proxy(bind: "127.0.0.1:8080", auto_launch: bool)
  • launch Chromium bound to the proxy: launch_chromium(bind: "127.0.0.1:8080")
  • replay a request: replay_request(Request)
  • mapper control: mapper_enqueue_seed, mapper_enqueue_discovered, mapper_set_profile

In the UI, call window.__TAURI__.invoke("<command>", args).


Runtime events to the UI

  • proxy:messageMessage Emitted for every intercepted request.

  • mapper:updateMapperEvent Emitted for every discovered URL with status and content type.

  • debug:proxyString Optional debug lines from the proxy layer.


Data model snapshot (burp_core)

  • Request { id, method, url, version, headers: HeaderList, body, timings, annotations, raw_request_line }
  • Response { id, version, status, reason, headers, body, timings, annotations, raw_status_line }
  • Message { id, request, response: Option<Response>, created_at, scope }
  • HeaderList preserves header order and original casing.

Lossless helpers:

  • parse_request_line(&str) -> (Method, target, HttpVersion)
  • parse_status_line(&str) -> (HttpVersion, status, reason)
  • parse_header_lines_lossless(&[&str]) -> HeaderList
  • build_url_from_parts(scheme, host, port, path_q) -> Url

Mapper usage (burp_mapper)

Programmatic facade exposed in Tauri:

  • mapper_set_profile(SiteProfile) Default headers and cookie hints per origin.

  • mapper_enqueue_seed(url: String) Starts exploration.

  • mapper_enqueue_discovered(url: String) Manually add URLs.

Events:

  • mapper:update with MapperEvent { origin, url, status, content_type, discovered_by, when }.

Heuristics:

  • Extract links from HTML (a[href], link[href], script[src], img[src], form[action])
  • Fuzz small wordlist for directories and sibling files
  • Limited redirects and body sizes

Replay

replay_request(Request) -> Response Rebuilds a Reqwest request with original method, URL, and headers, then returns a Response object with headers and body. Cookies and auth flows are not persisted automatically. Adjust as needed.


Troubleshooting

  • Chromium cannot connect or shows certificate errors

    • Ensure BurpCloneCA appears in certutil -L -d "sql:$PROFILE/.pki/nssdb".
    • Verify HOME is set to the profile dir and --user-data-dir points to the same path.
    • Ensure --disable-quic is applied.
    • Check that the proxy bind address is reachable and not blocked by firewall.
  • Pages like Wikipedia or YouTube do not load

    • These enforce HSTS and strict TLS. The CA must be trusted by the active profile. Double-check NSS import and that Chromium launched with that profile.
    • Confirm traffic is HTTP/1.1 or HTTP/2 over TCP, not QUIC.
  • certutil: command not found

    • Install libnss3-tools (Debian/Ubuntu) or the equivalent for your distro.
  • Build error about with_rustls_client

    • Hudsucker ≥0.24 uses .with_rustls_connector(provider) instead. The code already uses this.
  • Proxy starts but nothing appears in the UI

    • Ensure the UI subscribes to proxy:message and mapper:update.
    • Confirm start_proxy was invoked with the expected bind address.

Extending

  • Capture and store full responses in handle_response.
  • Interception rules and modification hooks.
  • Persistent project storage and search.
  • Larger fuzz wordlists and smarter scheduling.
  • WebSocket handling and HTTP/2 push.

Security and legality

See the callout at the top: authorized targets only, protect the CA private key, remove the CA from trust stores when finished.

Status

Working desktop app. Request interception + replay + a basic site mapper; response-body capture, interception/modification rules, and persistent project storage are the obvious next steps (see TODO.md and Extending above).

License

MIT


Part of my work — more at zz0r0.fr.

About

Burp-like intercepting MITM proxy as a Tauri desktop app (Rust + TypeScript) on top of hudsucker — TLS interception, Chromium launcher, request replay, light crawler/fuzzer.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors