diff options
| author | srdusr <[email protected]> | 2024-01-16 16:26:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-01-16 16:26:00 +0200 |
| commit | 1125afc47b9d6e68d95d0ffdbb74514f4618e624 (patch) | |
| tree | 63d5150b7dbc74685ebaec35ee0e74ec30c721d5 /cmd | |
| download | mitmux-1125afc47b9d6e68d95d0ffdbb74514f4618e624.tar.gz mitmux-1125afc47b9d6e68d95d0ffdbb74514f4618e624.zip | |
Scaffold mitmux: proxy daemon, CA generation, HTTP/CONNECT passthrough
Implements build-order step 1: headless proxy daemon (mitmuxd) with
plaintext HTTP passthrough and raw CONNECT tunneling, plus root CA
generation/persistence for later TLS interception. Verified live
against real HTTP and HTTPS requests through the proxy.
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/mitmuxd/main.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/cmd/mitmuxd/main.go b/cmd/mitmuxd/main.go new file mode 100644 index 0000000..400ca82 --- /dev/null +++ b/cmd/mitmuxd/main.go @@ -0,0 +1,62 @@ +// Command mitmuxd is the mitmux headless proxy daemon. It owns the +// listening socket and (in later build steps) the traffic database; a +// TUI or other client attaches separately without interrupting capture. +package main + +import ( + "context" + "flag" + "log" + "os" + "os/signal" + "syscall" + "time" + + "mitmux/internal/ca" + "mitmux/internal/proxy" +) + +func main() { + listen := flag.String("listen", "127.0.0.1:8080", "proxy listen address") + caDir := flag.String("ca-dir", "", "directory for CA cert/key (default: XDG config dir)") + flag.Parse() + + dir := *caDir + if dir == "" { + d, err := ca.Dir() + if err != nil { + log.Fatalf("resolve CA dir: %v", err) + } + dir = d + } + + root, err := ca.EnsureCA(dir) + if err != nil { + log.Fatalf("load CA: %v", err) + } + log.Printf("CA ready: %s", root.Cert.Subject.CommonName) + + srv := proxy.New(*listen) + + errCh := make(chan error, 1) + go func() { + errCh <- srv.ListenAndServe() + }() + + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) + + select { + case err := <-errCh: + if err != nil { + log.Fatalf("proxy: %v", err) + } + case sig := <-sigCh: + log.Printf("received %s, shutting down", sig) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); err != nil { + log.Fatalf("shutdown: %v", err) + } + } +} |