Files
anubis-mirror/internal/honeypot/naive/naive.go
T
Xe Iaso ade8505b26 feat: first implementation of honeypot logic
This is a bit of an experiment, stick with me.

The core idea here is that badly written crawlers are that: badly
written. They look for anything that contains `<a href="whatever" />`
tags and will blindly use those values to recurse. This takes advantage
of that by hiding a link in a `<script>` tag like this:

```html
<script type="ignore"><a href="/bots-only">Don't click</a></script>
```

Browsers will ignore it because they have no handler for the "ignore"
script type.

This current draft is very unoptimized (it takes like 7 seconds to
generate a page on my tower), however switching spintax libraries will
make this much faster.

The hope is to make this pluggable with WebAssembly such that we force
administrators to choose a storage method. First we crawl before we
walk.

The AI involvement in this commit is limited to the spintax in
affirmations.txt, spintext.txt, and titles.txt. This generates a bunch
of "pseudoprofound bullshit" like the following:

> This Restoration to Balance & Alignment
>
> There's a moment when creators are being called to realize that the work
> can't be reduced to results, but about energy. We don't innovate products
> by pushing harder, we do it by holding the vision. Because momentum can't
> be forced, it unfolds over time when culture are moving in the same
> direction. We're being invited into a paradigm shift in how we think
> about innovation. [...]

This is intended to "look" like normal article text. As this is a first
draft, this sucks and will be improved upon.

Assisted-by: GLM 4.6, ChatGPT, GPT-OSS 120b
Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-12-15 18:27:42 -05:00

121 lines
2.7 KiB
Go

package naive
import (
_ "embed"
"log/slog"
"math/rand/v2"
"net/http"
"time"
"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"
)
//go:generate go tool github.com/a-h/templ/cmd/templ generate
// XXX(Xe): All of this was generated by ChatGPT, GLM 4.6, and GPT-OSS 120b. This is pseudoprofound bullshit in spintax[1] format so that the bullshit generator can emit plausibly human-authored text while being very computationally cheap.
//
// It feels somewhat poetic to use spammer technology in Anubis.
//
// [1]: https://outboundly.ai/blogs/what-is-spintax-and-how-to-use-it/
//
//go:embed spintext.txt
var spintext string
//go:embed titles.txt
var titles string
//go:embed affirmations.txt
var affirmations string
func New(st store.Interface, lg *slog.Logger) *Impl {
spin := gospin.New(nil)
return &Impl{
st: st,
infos: store.JSON[honeypot.Info]{Underlying: st, Prefix: "honeypot-infos"},
spin: spin,
lg: lg.With("component", "honeypot/naive"),
}
}
type Impl struct {
st store.Interface
infos store.JSON[honeypot.Info]
spin *gospin.Spinner
lg *slog.Logger
}
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()}
}
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()}
}
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 result
}
func (i *Impl) ServeHTTP(w http.ResponseWriter, r *http.Request) {
t0 := time.Now()
id := r.PathValue("id")
if id == "" {
id = uuid.NewString()
}
stage := r.PathValue("stage")
if stage == "init" {
i.lg.Debug("found new entrance point", "id", id, "userAgent", r.UserAgent(), "ip", r.Header.Get("X-Real-Ip"))
}
spins := i.makeSpins()
affirmations := i.makeAffirmations()
title := i.makeTitle()
var links []link
for _, affirmation := range affirmations {
links = append(links, link{
href: uuid.NewString(),
body: affirmation,
})
}
templ.Handler(
base(title, i.maze(spins, links)),
templ.WithStreaming(),
templ.WithStatus(http.StatusOK),
).ServeHTTP(w, r)
t1 := time.Since(t0)
honeypot.Timings.WithLabelValues("naive").Observe(float64(t1.Milliseconds()))
}
type link struct {
href string
body string
}