mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-26 18:12:45 +00:00
fix(honeypot/naive): optimize hilariously
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
+11
-2
@@ -1,6 +1,7 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
@@ -13,6 +14,13 @@ import (
|
||||
"github.com/sebest/xff"
|
||||
)
|
||||
|
||||
type realIPKey struct{}
|
||||
|
||||
func RealIP(r *http.Request) (netip.Addr, bool) {
|
||||
result, ok := r.Context().Value(realIPKey{}).(netip.Addr)
|
||||
return result, ok
|
||||
}
|
||||
|
||||
// TODO: move into config
|
||||
type XFFComputePreferences struct {
|
||||
StripPrivate bool
|
||||
@@ -77,6 +85,9 @@ func RemoteXRealIP(useRemoteAddress bool, bindNetwork string, next http.Handler)
|
||||
panic(err) // this should never happen
|
||||
}
|
||||
r.Header.Set("X-Real-Ip", host)
|
||||
if addr, err := netip.ParseAddr(host); err == nil {
|
||||
r = r.WithContext(context.WithValue(r.Context(), realIPKey{}, addr))
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -129,8 +140,6 @@ func XForwardedForUpdate(stripPrivate bool, next http.Handler) http.Handler {
|
||||
} else {
|
||||
r.Header.Set("X-Forwarded-For", xffHeaderString)
|
||||
}
|
||||
|
||||
slog.Debug("updating X-Forwarded-For", "original", origXFFHeader, "new", xffHeaderString)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,16 +2,19 @@ package naive
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math/rand/v2"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/TecharoHQ/anubis/internal"
|
||||
"github.com/TecharoHQ/anubis/internal/honeypot"
|
||||
"github.com/TecharoHQ/anubis/lib/store"
|
||||
"github.com/a-h/templ"
|
||||
"github.com/google/uuid"
|
||||
"github.com/m1/gospin"
|
||||
"github.com/nikandfor/spintax"
|
||||
)
|
||||
|
||||
//go:generate go tool github.com/a-h/templ/cmd/templ generate
|
||||
@@ -31,52 +34,88 @@ var titles string
|
||||
//go:embed affirmations.txt
|
||||
var affirmations string
|
||||
|
||||
func New(st store.Interface, lg *slog.Logger) *Impl {
|
||||
spin := gospin.New(nil)
|
||||
func New(st store.Interface, lg *slog.Logger) (*Impl, error) {
|
||||
affirmation, err := spintax.Parse(affirmations)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't parse affirmations: %w", err)
|
||||
}
|
||||
|
||||
body, err := spintax.Parse(spintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't parse bodies: %w", err)
|
||||
}
|
||||
|
||||
title, err := spintax.Parse(titles)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't parse titles: %w", err)
|
||||
}
|
||||
|
||||
lg.Debug("initialized basic bullshit generator", "affirmations", affirmation.Count(), "bodies", body.Count(), "titles", title.Count())
|
||||
|
||||
return &Impl{
|
||||
st: st,
|
||||
infos: store.JSON[honeypot.Info]{Underlying: st, Prefix: "honeypot-infos"},
|
||||
spin: spin,
|
||||
lg: lg.With("component", "honeypot/naive"),
|
||||
}
|
||||
st: st,
|
||||
infos: store.JSON[honeypot.Info]{Underlying: st, Prefix: "honeypot-infos"},
|
||||
affirmation: affirmation,
|
||||
body: body,
|
||||
title: title,
|
||||
lg: lg.With("component", "honeypot/naive"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Impl struct {
|
||||
st store.Interface
|
||||
infos store.JSON[honeypot.Info]
|
||||
spin *gospin.Spinner
|
||||
lg *slog.Logger
|
||||
|
||||
affirmation, body, title spintax.Spintax
|
||||
}
|
||||
|
||||
func (i *Impl) makeAffirmations() []string {
|
||||
result, err := i.spin.SpinN(affirmations, rand.IntN(5)+1)
|
||||
if err != nil {
|
||||
i.lg.Debug("can't spin affirmations, using fallback", "err", err)
|
||||
return []string{uuid.NewString()}
|
||||
count := rand.IntN(5) + 1
|
||||
|
||||
var result []string
|
||||
for j := 0; j < count; j++ {
|
||||
result = append(result, i.affirmation.Spin())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (i *Impl) makeSpins() []string {
|
||||
result, err := i.spin.SpinN(spintext, rand.IntN(8)+8)
|
||||
if err != nil {
|
||||
i.lg.Debug("can't spin text, using fallback", "err", err)
|
||||
return []string{uuid.NewString()}
|
||||
count := rand.IntN(5) + 1
|
||||
|
||||
var result []string
|
||||
for j := 0; j < count; j++ {
|
||||
result = append(result, i.body.Spin())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (i *Impl) makeTitle() string {
|
||||
result, err := i.spin.Spin(titles)
|
||||
if err != nil {
|
||||
i.lg.Debug("can't spin titles, using fallback", "err", err)
|
||||
return uuid.NewString()
|
||||
}
|
||||
return i.title.Spin()
|
||||
}
|
||||
|
||||
return result
|
||||
func (i *Impl) clampIP(addr netip.Addr) netip.Prefix {
|
||||
fallback := netip.MustParsePrefix(addr.String() + "/32")
|
||||
switch {
|
||||
case addr.Is4() || addr.Is4In6():
|
||||
result, err := addr.Prefix(24)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
return result
|
||||
|
||||
case addr.Is6():
|
||||
result, err := addr.Prefix(48)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
return result
|
||||
|
||||
default:
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Impl) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -87,9 +126,45 @@ func (i *Impl) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
id = uuid.NewString()
|
||||
}
|
||||
|
||||
realIP, _ := internal.RealIP(r)
|
||||
if !realIP.IsValid() {
|
||||
i.lg.Error("the real IP is somehow invalid, bad middleware stack?")
|
||||
http.Error(w, "The cake is a lie", http.StatusTeapot)
|
||||
return
|
||||
}
|
||||
|
||||
network := i.clampIP(realIP)
|
||||
|
||||
stage := r.PathValue("stage")
|
||||
|
||||
var info honeypot.Info
|
||||
var err error
|
||||
|
||||
if stage == "init" {
|
||||
i.lg.Debug("found new entrance point", "id", id, "userAgent", r.UserAgent(), "ip", r.Header.Get("X-Real-Ip"))
|
||||
i.lg.Debug("found new entrance point", "id", id, "userAgent", r.UserAgent(), "clampedIP", network)
|
||||
|
||||
info = honeypot.Info{
|
||||
CreatedAt: time.Now(),
|
||||
UserAgent: r.UserAgent(),
|
||||
IPAddress: realIP.String(),
|
||||
HitCount: 1,
|
||||
}
|
||||
|
||||
i.infos.Set(r.Context(), network.String(), info, time.Hour)
|
||||
} else {
|
||||
info, err = i.infos.Get(r.Context(), network.String())
|
||||
if err != nil {
|
||||
info = honeypot.Info{
|
||||
CreatedAt: time.Now(),
|
||||
UserAgent: r.UserAgent(),
|
||||
IPAddress: realIP.String(),
|
||||
HitCount: 1,
|
||||
}
|
||||
i.infos.Set(r.Context(), network.String(), info, time.Hour)
|
||||
} else {
|
||||
info.HitCount++
|
||||
i.infos.Set(r.Context(), network.String(), info, time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
spins := i.makeSpins()
|
||||
|
||||
@@ -30,7 +30,7 @@ templ (i Impl) maze(body []string, links []link) {
|
||||
}
|
||||
<ul>
|
||||
for _, link := range links {
|
||||
<li><a href={ templ.SafeURL(fmt.Sprintf("./%s", link.href)) }></a>{ link.body }</li>
|
||||
<li><a href={ templ.SafeURL(fmt.Sprintf("./%s", link.href)) }>{ link.body }</a></li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
|
||||
Generated
+3
-3
@@ -131,20 +131,20 @@ func (i Impl) maze(body []string, links []link) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"></a>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(link.body)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `page.templ`, Line: 33, Col: 80}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `page.templ`, Line: 33, Col: 76}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</li>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</a></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user