| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- 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,
- ),
- )
- }
|