diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a1c33f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +caddy \ No newline at end of file diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..7712b26 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,20 @@ + +{ + order anubis after encode + order redir after anubis +} + +:18888 { + request_header +X-Real-IP {remote_host} + request_header +X-Forwarded-For {remote_host} + + anubis + + handle / { + try_files {path} /index.html + file_server { + root web/ + browse + } + } +} diff --git a/caddy_anubis.go b/caddy_anubis.go index 9f3ba5c..a067d0d 100644 --- a/caddy_anubis.go +++ b/caddy_anubis.go @@ -1,120 +1,119 @@ package caddyanubis import ( - "fmt" - "io" + "log/slog" "net/http" - "os" "github.com/TecharoHQ/anubis" libanubis "github.com/TecharoHQ/anubis/lib" + "github.com/TecharoHQ/anubis/lib/policy" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp" + "go.uber.org/zap" ) func init() { - caddy.RegisterModule(Middleware{}) + caddy.RegisterModule(AnubisMiddleware{}) httpcaddyfile.RegisterHandlerDirective("anubis", parseCaddyfile) + httpcaddyfile.RegisterDirectiveOrder("anubis", httpcaddyfile.After, "templates") } -// Middleware implements an HTTP handler that writes the -// visitor's IP address to a file or stream. -type Middleware struct { - // The file or stream to write to. Can be "stdout" - // or "stderr". - Output string `json:"output,omitempty"` +type AnubisMiddleware struct { + Target *string `json:"target,omitempty"` + AnubisPolicy *policy.ParsedConfig + AnubisServer *libanubis.Server + Next caddyhttp.Handler - w io.Writer + logger *zap.Logger } // CaddyModule returns the Caddy module information. -func (Middleware) CaddyModule() caddy.ModuleInfo { +func (AnubisMiddleware) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "http.handlers.anubis", - New: func() caddy.Module { return new(Middleware) }, + New: func() caddy.Module { return new(AnubisMiddleware) }, } } // Provision implements caddy.Provisioner. -func (m *Middleware) Provision(ctx caddy.Context) error { - switch m.Output { - case "stdout": - m.w = os.Stdout - case "stderr": - m.w = os.Stderr - default: - return fmt.Errorf("an output stream is required") - } - return nil -} - -// Validate implements caddy.Validator. -func (m *Middleware) Validate() error { - if m.w == nil { - return fmt.Errorf("no writer") - } - return nil -} - -// ServeHTTP implements caddyhttp.MiddlewareHandler. -func (m Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { - m.w.Write([]byte(r.RemoteAddr)) +func (m *AnubisMiddleware) Provision(ctx caddy.Context) error { + m.logger = ctx.Logger().Named("anubis") + m.logger.Info("Anubis middleware provisioning") policy, err := libanubis.LoadPoliciesOrDefault("", anubis.DefaultDifficulty) if err != nil { return err } - errChan := make(chan error) - anubisServer, err := libanubis.New(libanubis.Options{ + m.AnubisPolicy = policy + + m.AnubisServer, err = libanubis.New(libanubis.Options{ Next: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - errChan <- next.ServeHTTP(w, r) + m.logger.Info("Anubis middleware calling next") + + if m.Target != nil { + http.Redirect(w, r, *m.Target, http.StatusTemporaryRedirect) + } else { + m.Next.ServeHTTP(w, r) + } }), - Policy: policy, + Policy: m.AnubisPolicy, ServeRobotsTXT: true, }) - if err != nil { return err } - anubisServer.ServeHTTP(w, r) + m.logger.Info("Anubis middleware provisioned") + return nil +} - for err := range errChan { - if err != nil { - return err - } - } +// Validate implements caddy.Validator. +func (m *AnubisMiddleware) Validate() error { + return nil +} + +// ServeHTTP implements caddyhttp.MiddlewareHandler. +func (m *AnubisMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { + m.logger.Info("Anubis middleware processing request") + slog.SetLogLoggerLevel(slog.LevelDebug) + m.logger.Info("Anubis middleware sending request") + m.Next = next + m.AnubisServer.ServeHTTP(w, r) return nil } // UnmarshalCaddyfile implements caddyfile.Unmarshaler. -func (m *Middleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { +func (m *AnubisMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { d.Next() // consume directive name // require an argument - if !d.NextArg() { - return d.ArgErr() + for nesting := d.Nesting(); d.NextBlock(nesting); { + switch d.Val() { + case "target": + if d.NextArg() { + val := d.Val() + m.Target = &val + } + } } - // store the argument - m.Output = d.Val() return nil } // parseCaddyfile unmarshals tokens from h into a new Middleware. func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) { - var m Middleware + var m AnubisMiddleware err := m.UnmarshalCaddyfile(h.Dispenser) - return m, err + return &m, err } // Interface guards var ( - _ caddy.Provisioner = (*Middleware)(nil) - _ caddy.Validator = (*Middleware)(nil) - _ caddyhttp.MiddlewareHandler = (*Middleware)(nil) - _ caddyfile.Unmarshaler = (*Middleware)(nil) + _ caddy.Provisioner = (*AnubisMiddleware)(nil) + _ caddy.Validator = (*AnubisMiddleware)(nil) + _ caddyhttp.MiddlewareHandler = (*AnubisMiddleware)(nil) + _ caddyfile.Unmarshaler = (*AnubisMiddleware)(nil) ) diff --git a/go.mod b/go.mod index 939df38..0bbe8cb 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,18 @@ module github.com/daegalus/caddy-anubis go 1.24.1 -replace github.com/TecharoHQ/anubis => ../anubis +require ( + github.com/caddyserver/caddy/v2 v2.9.1 + github.com/TecharoHQ/anubis v1.14.3-0.20250322224449-6156d3d7293a +) -require github.com/caddyserver/caddy/v2 v2.9.1 +require ( + github.com/a-h/templ v0.3.833 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a // indirect + github.com/yl2chen/cidranger v1.0.2 // indirect +) require ( dario.cat/mergo v1.0.1 // indirect @@ -14,7 +23,6 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/TecharoHQ/anubis v1.14.2 github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 86eb1b7..66bf568 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSC github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/TecharoHQ/anubis v1.14.3-0.20250322224449-6156d3d7293a h1:juchXqktszLfbOpuM1Oht32OOj5T+03qjeEfYBs+HLM= +github.com/TecharoHQ/anubis v1.14.3-0.20250322224449-6156d3d7293a/go.mod h1:xWCWbEh+wZ5W/Vv0BFpWIQH0MWsiwZgmV5IlKwXxmMs= github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU= github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..d55ea65 --- /dev/null +++ b/web/index.html @@ -0,0 +1,9 @@ + + + Home + + +

Welcome to the Home Page

+

Click here to go to the About Page

+ + \ No newline at end of file