diff options
| author | Aurelia <git@acuteaura.net> | 2025-04-25 13:59:55 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-25 11:59:55 +0000 |
| commit | a420db8b8a3597b56bcc6dc7d1fc5f5d7d932448 (patch) | |
| tree | a8962aafc94ffd192a23a912c01b73f574dcce6b /test/cmd | |
| parent | 5a4f68d384895b09c45d0c6ebb09b069603c363b (diff) | |
| download | anubis-a420db8b8a3597b56bcc6dc7d1fc5f5d7d932448.tar.xz anubis-a420db8b8a3597b56bcc6dc7d1fc5f5d7d932448.zip | |
feat: more elaborate XFF compute (#350)
* feat: more elaborate XFF compute
#328 followup
now featuring configuration and
defaults that shouldn't break most
setups.
fixes #344
* refactor: obvious condition eval order optimization
* feat: add StripLLU implementation
* chore: I'm sorry it's 7 AM
* test: add test environment for unix socket serving
Signed-off-by: Xe Iaso <me@xeiaso.net>
* test(unix-socket-xff): comment out the shell script more
Signed-off-by: Xe Iaso <me@xeiaso.net>
* fix(internal): fix logic bug in XFF computation, add tests
Signed-off-by: Xe Iaso <me@xeiaso.net>
* fix(internal): prevent panic in local testing
Signed-off-by: Xe Iaso <me@xeiaso.net>
* fix(internal): shuffle around return values to flow better
Signed-off-by: Xe Iaso <me@xeiaso.net>
---------
Signed-off-by: Xe Iaso <me@xeiaso.net>
Co-authored-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'test/cmd')
| -rw-r--r-- | test/cmd/relayd/main.go | 124 | ||||
| -rw-r--r-- | test/cmd/unixhttpd/main.go | 75 |
2 files changed, 199 insertions, 0 deletions
diff --git a/test/cmd/relayd/main.go b/test/cmd/relayd/main.go new file mode 100644 index 0000000..26700d7 --- /dev/null +++ b/test/cmd/relayd/main.go @@ -0,0 +1,124 @@ +package main + +import ( + "context" + "flag" + "log" + "log/slog" + "net" + "net/http" + "net/http/httputil" + "net/url" + "os" + "path/filepath" + "strings" + "time" + + "github.com/TecharoHQ/anubis/internal" + "github.com/facebookgo/flagenv" + "github.com/google/uuid" +) + +var ( + bind = flag.String("bind", ":3004", "port to listen on") + certDir = flag.String("cert-dir", "/xe/pki", "where to read mounted certificates from") + certFname = flag.String("cert-fname", "cert.pem", "certificate filename") + keyFname = flag.String("key-fname", "key.pem", "key filename") + proxyTo = flag.String("proxy-to", "http://localhost:5000", "where to reverse proxy to") + slogLevel = flag.String("slog-level", "info", "logging level") +) + +func main() { + flagenv.Parse() + flag.Parse() + + internal.InitSlog(*slogLevel) + + slog.Info("starting", + "bind", *bind, + "cert-dir", *certDir, + "cert-fname", *certFname, + "key-fname", *keyFname, + "proxy-to", *proxyTo, + ) + + cert := filepath.Join(*certDir, *certFname) + key := filepath.Join(*certDir, *keyFname) + + st, err := os.Stat(cert) + + if err != nil { + slog.Error("can't stat cert file", "certFname", cert) + os.Exit(1) + } + + lastModified := st.ModTime() + + go func(lm time.Time) { + t := time.NewTicker(time.Hour) + defer t.Stop() + + for range t.C { + st, err := os.Stat(cert) + if err != nil { + slog.Error("can't stat file", "fname", cert, "err", err) + continue + } + + if st.ModTime().After(lm) { + slog.Info("new cert detected", "oldTime", lm.Format(time.RFC3339), "newTime", st.ModTime().Format(time.RFC3339)) + os.Exit(0) + } + } + }(lastModified) + + u, err := url.Parse(*proxyTo) + if err != nil { + log.Fatal(err) + } + + h := httputil.NewSingleHostReverseProxy(u) + + if u.Scheme == "unix" { + slog.Info("using unix socket proxy") + + h = &httputil.ReverseProxy{ + Director: func(r *http.Request) { + r.URL.Scheme = "http" + r.URL.Host = r.Host + + r.Header.Set("X-Forwarded-Proto", "https") + r.Header.Set("X-Forwarded-Scheme", "https") + r.Header.Set("X-Request-Id", uuid.NewString()) + r.Header.Set("X-Scheme", "https") + + remoteHost, remotePort, err := net.SplitHostPort(r.Host) + if err == nil { + r.Header.Set("X-Forwarded-Host", remoteHost) + r.Header.Set("X-Forwarded-Port", remotePort) + } else { + r.Header.Set("X-Forwarded-Host", r.Host) + } + + host, _, err := net.SplitHostPort(r.RemoteAddr) + if err == nil { + r.Header.Set("X-Real-Ip", host) + } + }, + Transport: &http.Transport{ + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", strings.TrimPrefix(*proxyTo, "unix://")) + }, + }, + } + } + + log.Fatal( + http.ListenAndServeTLS( + *bind, + cert, + key, + h, + ), + ) +} diff --git a/test/cmd/unixhttpd/main.go b/test/cmd/unixhttpd/main.go new file mode 100644 index 0000000..a57c202 --- /dev/null +++ b/test/cmd/unixhttpd/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "flag" + "fmt" + "log" + "log/slog" + "net" + "net/http" + "os" + "path/filepath" + "strings" + + "github.com/TecharoHQ/anubis/internal" + "github.com/facebookgo/flagenv" +) + +var ( + dir = flag.String("dir", ".", "directory to serve") + slogLevel = flag.String("slog-level", "info", "logging level") + socketPath = flag.String("socket-path", "./unixhttpd.sock", "unix socket path to use") +) + +func init() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0])) + fmt.Fprintf(os.Stderr, " %s [--dir=.] [--socket-path=./unixhttpd.sock]\n\n", filepath.Base(os.Args[0])) + flag.PrintDefaults() + os.Exit(2) + } +} + +func main() { + flagenv.Parse() + flag.Parse() + + internal.InitSlog(*slogLevel) + + if *dir == "" && *socketPath == "" { + flag.Usage() + } + + slog.Info("starting up", "dir", *dir, "socketPath", *socketPath) + + os.Remove(*socketPath) + + mux := http.NewServeMux() + + mux.HandleFunc("/reqmeta", func(w http.ResponseWriter, r *http.Request) { + contains := strings.Contains(r.Header.Get("Accept"), "text/html") + + if contains { + w.Header().Add("Content-Type", "text/html") + fmt.Fprint(w, "<pre id=\"main\"><code>") + } + + r.Write(w) + + if contains { + fmt.Fprintln(w, "</pre></code>") + } + }) + + mux.Handle("/", http.FileServer(http.Dir(*dir))) + + server := http.Server{ + Handler: mux, + } + + unixListener, err := net.Listen("unix", *socketPath) + if err != nil { + panic(err) + } + log.Fatal(server.Serve(unixListener)) +} |
