aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2025-01-18 18:23:23 -0500
committerXe Iaso <me@xeiaso.net>2025-01-18 18:23:23 -0500
commit2309654e616d934b87279c070697c559221717d1 (patch)
tree4f5354bf17cdeb0b3e7df634d041f9dea7e94814
parentbcc7c0d28e8c225c730b5574718aa7d963c1cdea (diff)
downloadx-2309654e616d934b87279c070697c559221717d1.tar.xz
x-2309654e616d934b87279c070697c559221717d1.zip
cmd/anubis: improve metrics
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--cmd/anubis/.gitignore1
-rw-r--r--cmd/anubis/anubis.env.default5
-rw-r--r--cmd/anubis/anubis@.service12
-rw-r--r--cmd/anubis/main.go22
-rw-r--r--cmd/anubis/yeetfile.js22
5 files changed, 60 insertions, 2 deletions
diff --git a/cmd/anubis/.gitignore b/cmd/anubis/.gitignore
new file mode 100644
index 0000000..8d5bedc
--- /dev/null
+++ b/cmd/anubis/.gitignore
@@ -0,0 +1 @@
+*.rpm \ No newline at end of file
diff --git a/cmd/anubis/anubis.env.default b/cmd/anubis/anubis.env.default
new file mode 100644
index 0000000..b72eddd
--- /dev/null
+++ b/cmd/anubis/anubis.env.default
@@ -0,0 +1,5 @@
+BIND=:8923
+DIFFICULTY=3
+METRICS_BIND=:9090
+SERVE_ROBOTS_TXT=0
+TARGET=http://localhost:3000 \ No newline at end of file
diff --git a/cmd/anubis/anubis@.service b/cmd/anubis/anubis@.service
new file mode 100644
index 0000000..102775f
--- /dev/null
+++ b/cmd/anubis/anubis@.service
@@ -0,0 +1,12 @@
+[Unit]
+Description="Anubis HTTP defense proxy (instance %i)"
+
+[Service]
+ExecStart=/usr/bin/anubis
+Restart=always
+RestartSec=30s
+EnvironmentFile=/etc/anubis/anubis-%i.env
+LimitNOFILE=infinity
+
+[Install]
+WantedBy=multi-user.target \ No newline at end of file
diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go
index 5c345e3..da4571c 100644
--- a/cmd/anubis/main.go
+++ b/cmd/anubis/main.go
@@ -12,6 +12,7 @@ import (
"fmt"
"log"
"log/slog"
+ "math"
mrand "math/rand"
"net/http"
"net/http/httputil"
@@ -24,6 +25,7 @@ import (
"github.com/golang-jwt/jwt/v5"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
"within.website/x/internal"
"within.website/x/xess"
)
@@ -38,6 +40,11 @@ var (
//go:embed static
static embed.FS
+ bypasses = promauto.NewCounter(prometheus.CounterOpts{
+ Name: "anubis_bypasses",
+ Help: "The total number of requests that bypassed challenge validation",
+ })
+
challengesIssued = promauto.NewCounter(prometheus.CounterOpts{
Name: "anubis_challenges_issued",
Help: "The total number of challenges issued",
@@ -56,7 +63,7 @@ var (
timeTaken = promauto.NewHistogram(prometheus.HistogramOpts{
Name: "anubis_time_taken",
Help: "The time taken for a browser to generate a response (milliseconds)",
- Buckets: prometheus.DefBuckets,
+ Buckets: prometheus.ExponentialBucketsRange(1, math.Pow(2, 18), 19),
})
)
@@ -94,12 +101,23 @@ func main() {
})
}
+ if *metricsBind != "" {
+ go metricsServer()
+ }
+
mux.HandleFunc("/", s.maybeReverseProxy)
- slog.Info("listening", "url", "http://localhost"+*bind)
+ slog.Info("listening", "url", "http://localhost"+*bind, "difficulty", *challengeDifficulty, "serveRobotsTXT", *robotsTxt, "target", *target)
log.Fatal(http.ListenAndServe(*bind, mux))
}
+func metricsServer() {
+ mux := http.NewServeMux()
+ mux.Handle("/metrics", promhttp.Handler())
+ slog.Debug("listening for metrics", "url", "http://localhost"+*metricsBind)
+ log.Fatal(http.ListenAndServe(*metricsBind, mux))
+}
+
func sha256sum(text string) (string, error) {
hash := sha256.New()
_, err := hash.Write([]byte(text))
diff --git a/cmd/anubis/yeetfile.js b/cmd/anubis/yeetfile.js
new file mode 100644
index 0000000..6f4096e
--- /dev/null
+++ b/cmd/anubis/yeetfile.js
@@ -0,0 +1,22 @@
+go.install();
+
+["amd64", "arm64"].forEach(goarch => rpm.build({
+ name: "anubis",
+ description: "Anubis weighs the souls of incoming HTTP requests and uses a sha256 proof-of-work challenge in order to protect upstream resources from scraper bots.",
+ homepage: "https://xeiaso.net/blog/2025/anubis",
+ license: "CC0",
+ goarch,
+
+ build: (out) => {
+ // install Anubis binary
+ go.build("-o", `${out}/usr/bin/anubis`);
+
+ // install systemd unit
+ yeet.run("mkdir", "-p", `${out}/usr/lib/systemd/system`);
+ yeet.run("cp", "anubis@.service", `${out}/usr/lib/systemd/system/anubis@.service`);
+
+ // install default config
+ yeet.run("mkdir", "-p", `${out}/etc/anubis`);
+ yeet.run("cp", "anubis.env.default", `${out}/etc/anubis/anubis-default.env`);
+ },
+})); \ No newline at end of file