From 6156d3d7293a1757725b1d36a89a61ede1ffe850 Mon Sep 17 00:00:00 2001 From: Yulian Kuncheff <670212+daegalus@users.noreply.github.com> Date: Sat, 22 Mar 2025 23:44:49 +0100 Subject: Refactor and split out things into cmd and lib (#77) * Refactor anubis to split business logic into a lib, and cmd to just be direct usage. * Post-rebase fixes. * Update changelog, remove unnecessary one. * lib: refactor this This is mostly based on my personal preferences for how Go code should be laid out. I'm not sold on the package name "lib" (I'd call it anubis but that would stutter), but people are probably gonna import it as libanubis so it's likely fine. Packages have been "flattened" to centralize implementation with area of concern. This goes against the Java-esque style that many people like, but I think this helps make things simple. Most notably: the dnsbl client (which is a hack) is an internal package until it's made more generic. Then it can be made external. I also fixed the logic such that `go generate` works and rebased on main. * internal/test: run tests iff npx exists and DONT_USE_NETWORK is not set Signed-off-by: Xe Iaso * internal/test: install deps Signed-off-by: Xe Iaso * .github/workflows: verbose go tests? Signed-off-by: Xe Iaso * internal/test: sleep 2 Signed-off-by: Xe Iaso * internal/test: nix this test so CI works Signed-off-by: Xe Iaso * internal/test: warmup per browser? Signed-off-by: Xe Iaso * internal/test: disable for now :( Signed-off-by: Xe Iaso * lib/anubis: do not apply bot rules if address check fails Closes #83 --------- Signed-off-by: Xe Iaso Co-authored-by: Xe Iaso --- cmd/anubis/CHANGELOG.md | 5 - cmd/anubis/botPolicies.json | 398 --------------- cmd/anubis/decaymap.go | 87 ---- cmd/anubis/decaymap_test.go | 31 -- cmd/anubis/index.templ | 217 -------- cmd/anubis/index_templ.go | 225 --------- cmd/anubis/internal/config/config.go | 162 ------ cmd/anubis/internal/config/config_test.go | 248 --------- .../internal/config/testdata/bad/badregexes.json | 14 - .../internal/config/testdata/bad/invalid.json | 5 - .../internal/config/testdata/bad/nobots.json | 1 - .../config/testdata/good/allow_everyone.json | 12 - .../config/testdata/good/challengemozilla.json | 9 - .../config/testdata/good/everything_blocked.json | 10 - cmd/anubis/internal/dnsbl/dnsbl.go | 95 ---- cmd/anubis/internal/dnsbl/dnsbl_test.go | 61 --- .../internal/dnsbl/droneblresponse_string.go | 54 -- cmd/anubis/js/main.mjs | 89 ---- cmd/anubis/js/proof-of-work-slow.mjs | 63 --- cmd/anubis/js/proof-of-work.mjs | 93 ---- cmd/anubis/js/video.mjs | 16 - cmd/anubis/main.go | 558 ++------------------- cmd/anubis/policy.go | 212 -------- cmd/anubis/policy_test.go | 65 --- cmd/anubis/static/img/happy.webp | Bin 59250 -> 0 bytes cmd/anubis/static/img/pensive.webp | Bin 49148 -> 0 bytes cmd/anubis/static/img/sad.webp | Bin 50802 -> 0 bytes cmd/anubis/static/js/main.mjs | 2 - cmd/anubis/static/js/main.mjs.br | Bin 1216 -> 0 bytes cmd/anubis/static/js/main.mjs.gz | Bin 1451 -> 0 bytes cmd/anubis/static/js/main.mjs.map | 7 - cmd/anubis/static/js/main.mjs.zst | Bin 1430 -> 0 bytes cmd/anubis/static/robots.txt | 47 -- cmd/anubis/static/testdata/black.mp4 | Bin 1667 -> 0 bytes 34 files changed, 50 insertions(+), 2736 deletions(-) delete mode 100644 cmd/anubis/CHANGELOG.md delete mode 100644 cmd/anubis/botPolicies.json delete mode 100644 cmd/anubis/decaymap.go delete mode 100644 cmd/anubis/decaymap_test.go delete mode 100644 cmd/anubis/index.templ delete mode 100644 cmd/anubis/index_templ.go delete mode 100644 cmd/anubis/internal/config/config.go delete mode 100644 cmd/anubis/internal/config/config_test.go delete mode 100644 cmd/anubis/internal/config/testdata/bad/badregexes.json delete mode 100644 cmd/anubis/internal/config/testdata/bad/invalid.json delete mode 100644 cmd/anubis/internal/config/testdata/bad/nobots.json delete mode 100644 cmd/anubis/internal/config/testdata/good/allow_everyone.json delete mode 100644 cmd/anubis/internal/config/testdata/good/challengemozilla.json delete mode 100644 cmd/anubis/internal/config/testdata/good/everything_blocked.json delete mode 100644 cmd/anubis/internal/dnsbl/dnsbl.go delete mode 100644 cmd/anubis/internal/dnsbl/dnsbl_test.go delete mode 100644 cmd/anubis/internal/dnsbl/droneblresponse_string.go delete mode 100644 cmd/anubis/js/main.mjs delete mode 100644 cmd/anubis/js/proof-of-work-slow.mjs delete mode 100644 cmd/anubis/js/proof-of-work.mjs delete mode 100644 cmd/anubis/js/video.mjs delete mode 100644 cmd/anubis/policy.go delete mode 100644 cmd/anubis/policy_test.go delete mode 100644 cmd/anubis/static/img/happy.webp delete mode 100644 cmd/anubis/static/img/pensive.webp delete mode 100644 cmd/anubis/static/img/sad.webp delete mode 100644 cmd/anubis/static/js/main.mjs delete mode 100644 cmd/anubis/static/js/main.mjs.br delete mode 100644 cmd/anubis/static/js/main.mjs.gz delete mode 100644 cmd/anubis/static/js/main.mjs.map delete mode 100644 cmd/anubis/static/js/main.mjs.zst delete mode 100644 cmd/anubis/static/robots.txt delete mode 100644 cmd/anubis/static/testdata/black.mp4 (limited to 'cmd') diff --git a/cmd/anubis/CHANGELOG.md b/cmd/anubis/CHANGELOG.md deleted file mode 100644 index 612bec1..0000000 --- a/cmd/anubis/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# CHANGELOG - -## 2025-01-24 - -- Added support for custom bot policy documentation, allowing administrators to change how Anubis works to meet their needs. diff --git a/cmd/anubis/botPolicies.json b/cmd/anubis/botPolicies.json deleted file mode 100644 index 0e33706..0000000 --- a/cmd/anubis/botPolicies.json +++ /dev/null @@ -1,398 +0,0 @@ -{ - "bots": [ - { - "name": "amazonbot", - "user_agent_regex": "Amazonbot", - "action": "DENY" - }, - { - "name": "googlebot", - "user_agent_regex": "\\+http\\://www\\.google\\.com/bot\\.html", - "action": "ALLOW", - "remote_addresses": [ - "2001:4860:4801:10::/64", - "2001:4860:4801:11::/64", - "2001:4860:4801:12::/64", - "2001:4860:4801:13::/64", - "2001:4860:4801:14::/64", - "2001:4860:4801:15::/64", - "2001:4860:4801:16::/64", - "2001:4860:4801:17::/64", - "2001:4860:4801:18::/64", - "2001:4860:4801:19::/64", - "2001:4860:4801:1a::/64", - "2001:4860:4801:1b::/64", - "2001:4860:4801:1c::/64", - "2001:4860:4801:1d::/64", - "2001:4860:4801:1e::/64", - "2001:4860:4801:1f::/64", - "2001:4860:4801:20::/64", - "2001:4860:4801:21::/64", - "2001:4860:4801:22::/64", - "2001:4860:4801:23::/64", - "2001:4860:4801:24::/64", - "2001:4860:4801:25::/64", - "2001:4860:4801:26::/64", - "2001:4860:4801:27::/64", - "2001:4860:4801:28::/64", - "2001:4860:4801:29::/64", - "2001:4860:4801:2::/64", - "2001:4860:4801:2a::/64", - "2001:4860:4801:2b::/64", - "2001:4860:4801:2c::/64", - "2001:4860:4801:2d::/64", - "2001:4860:4801:2e::/64", - "2001:4860:4801:2f::/64", - "2001:4860:4801:31::/64", - "2001:4860:4801:32::/64", - "2001:4860:4801:33::/64", - "2001:4860:4801:34::/64", - "2001:4860:4801:35::/64", - "2001:4860:4801:36::/64", - "2001:4860:4801:37::/64", - "2001:4860:4801:38::/64", - "2001:4860:4801:39::/64", - "2001:4860:4801:3a::/64", - "2001:4860:4801:3b::/64", - "2001:4860:4801:3c::/64", - "2001:4860:4801:3d::/64", - "2001:4860:4801:3e::/64", - "2001:4860:4801:40::/64", - "2001:4860:4801:41::/64", - "2001:4860:4801:42::/64", - "2001:4860:4801:43::/64", - "2001:4860:4801:44::/64", - "2001:4860:4801:45::/64", - "2001:4860:4801:46::/64", - "2001:4860:4801:47::/64", - "2001:4860:4801:48::/64", - "2001:4860:4801:49::/64", - "2001:4860:4801:4a::/64", - "2001:4860:4801:4b::/64", - "2001:4860:4801:4c::/64", - "2001:4860:4801:50::/64", - "2001:4860:4801:51::/64", - "2001:4860:4801:52::/64", - "2001:4860:4801:53::/64", - "2001:4860:4801:54::/64", - "2001:4860:4801:55::/64", - "2001:4860:4801:56::/64", - "2001:4860:4801:60::/64", - "2001:4860:4801:61::/64", - "2001:4860:4801:62::/64", - "2001:4860:4801:63::/64", - "2001:4860:4801:64::/64", - "2001:4860:4801:65::/64", - "2001:4860:4801:66::/64", - "2001:4860:4801:67::/64", - "2001:4860:4801:68::/64", - "2001:4860:4801:69::/64", - "2001:4860:4801:6a::/64", - "2001:4860:4801:6b::/64", - "2001:4860:4801:6c::/64", - "2001:4860:4801:6d::/64", - "2001:4860:4801:6e::/64", - "2001:4860:4801:6f::/64", - "2001:4860:4801:70::/64", - "2001:4860:4801:71::/64", - "2001:4860:4801:72::/64", - "2001:4860:4801:73::/64", - "2001:4860:4801:74::/64", - "2001:4860:4801:75::/64", - "2001:4860:4801:76::/64", - "2001:4860:4801:77::/64", - "2001:4860:4801:78::/64", - "2001:4860:4801:79::/64", - "2001:4860:4801:80::/64", - "2001:4860:4801:81::/64", - "2001:4860:4801:82::/64", - "2001:4860:4801:83::/64", - "2001:4860:4801:84::/64", - "2001:4860:4801:85::/64", - "2001:4860:4801:86::/64", - "2001:4860:4801:87::/64", - "2001:4860:4801:88::/64", - "2001:4860:4801:90::/64", - "2001:4860:4801:91::/64", - "2001:4860:4801:92::/64", - "2001:4860:4801:93::/64", - "2001:4860:4801:94::/64", - "2001:4860:4801:95::/64", - "2001:4860:4801:96::/64", - "2001:4860:4801:a0::/64", - "2001:4860:4801:a1::/64", - "2001:4860:4801:a2::/64", - "2001:4860:4801:a3::/64", - "2001:4860:4801:a4::/64", - "2001:4860:4801:a5::/64", - "2001:4860:4801:c::/64", - "2001:4860:4801:f::/64", - "192.178.5.0/27", - "192.178.6.0/27", - "192.178.6.128/27", - "192.178.6.160/27", - "192.178.6.192/27", - "192.178.6.32/27", - "192.178.6.64/27", - "192.178.6.96/27", - "34.100.182.96/28", - "34.101.50.144/28", - "34.118.254.0/28", - "34.118.66.0/28", - "34.126.178.96/28", - "34.146.150.144/28", - "34.147.110.144/28", - "34.151.74.144/28", - "34.152.50.64/28", - "34.154.114.144/28", - "34.155.98.32/28", - "34.165.18.176/28", - "34.175.160.64/28", - "34.176.130.16/28", - "34.22.85.0/27", - "34.64.82.64/28", - "34.65.242.112/28", - "34.80.50.80/28", - "34.88.194.0/28", - "34.89.10.80/28", - "34.89.198.80/28", - "34.96.162.48/28", - "35.247.243.240/28", - "66.249.64.0/27", - "66.249.64.128/27", - "66.249.64.160/27", - "66.249.64.224/27", - "66.249.64.32/27", - "66.249.64.64/27", - "66.249.64.96/27", - "66.249.65.0/27", - "66.249.65.128/27", - "66.249.65.160/27", - "66.249.65.192/27", - "66.249.65.224/27", - "66.249.65.32/27", - "66.249.65.64/27", - "66.249.65.96/27", - "66.249.66.0/27", - "66.249.66.128/27", - "66.249.66.160/27", - "66.249.66.192/27", - "66.249.66.224/27", - "66.249.66.32/27", - "66.249.66.64/27", - "66.249.66.96/27", - "66.249.68.0/27", - "66.249.68.128/27", - "66.249.68.32/27", - "66.249.68.64/27", - "66.249.68.96/27", - "66.249.69.0/27", - "66.249.69.128/27", - "66.249.69.160/27", - "66.249.69.192/27", - "66.249.69.224/27", - "66.249.69.32/27", - "66.249.69.64/27", - "66.249.69.96/27", - "66.249.70.0/27", - "66.249.70.128/27", - "66.249.70.160/27", - "66.249.70.192/27", - "66.249.70.224/27", - "66.249.70.32/27", - "66.249.70.64/27", - "66.249.70.96/27", - "66.249.71.0/27", - "66.249.71.128/27", - "66.249.71.160/27", - "66.249.71.192/27", - "66.249.71.224/27", - "66.249.71.32/27", - "66.249.71.64/27", - "66.249.71.96/27", - "66.249.72.0/27", - "66.249.72.128/27", - "66.249.72.160/27", - "66.249.72.192/27", - "66.249.72.224/27", - "66.249.72.32/27", - "66.249.72.64/27", - "66.249.72.96/27", - "66.249.73.0/27", - "66.249.73.128/27", - "66.249.73.160/27", - "66.249.73.192/27", - "66.249.73.224/27", - "66.249.73.32/27", - "66.249.73.64/27", - "66.249.73.96/27", - "66.249.74.0/27", - "66.249.74.128/27", - "66.249.74.160/27", - "66.249.74.192/27", - "66.249.74.32/27", - "66.249.74.64/27", - "66.249.74.96/27", - "66.249.75.0/27", - "66.249.75.128/27", - "66.249.75.160/27", - "66.249.75.192/27", - "66.249.75.224/27", - "66.249.75.32/27", - "66.249.75.64/27", - "66.249.75.96/27", - "66.249.76.0/27", - "66.249.76.128/27", - "66.249.76.160/27", - "66.249.76.192/27", - "66.249.76.224/27", - "66.249.76.32/27", - "66.249.76.64/27", - "66.249.76.96/27", - "66.249.77.0/27", - "66.249.77.128/27", - "66.249.77.160/27", - "66.249.77.192/27", - "66.249.77.224/27", - "66.249.77.32/27", - "66.249.77.64/27", - "66.249.77.96/27", - "66.249.78.0/27", - "66.249.78.32/27", - "66.249.79.0/27", - "66.249.79.128/27", - "66.249.79.160/27", - "66.249.79.192/27", - "66.249.79.224/27", - "66.249.79.32/27", - "66.249.79.64/27", - "66.249.79.96/27" - ] - }, - { - "name": "bingbot", - "user_agent_regex": "\\+http\\://www\\.bing\\.com/bingbot\\.htm", - "action": "ALLOW", - "remote_addresses": [ - "157.55.39.0/24", - "207.46.13.0/24", - "40.77.167.0/24", - "13.66.139.0/24", - "13.66.144.0/24", - "52.167.144.0/24", - "13.67.10.16/28", - "13.69.66.240/28", - "13.71.172.224/28", - "139.217.52.0/28", - "191.233.204.224/28", - "20.36.108.32/28", - "20.43.120.16/28", - "40.79.131.208/28", - "40.79.186.176/28", - "52.231.148.0/28", - "20.79.107.240/28", - "51.105.67.0/28", - "20.125.163.80/28", - "40.77.188.0/22", - "65.55.210.0/24", - "199.30.24.0/23", - "40.77.202.0/24", - "40.77.139.0/25", - "20.74.197.0/28", - "20.15.133.160/27", - "40.77.177.0/24", - "40.77.178.0/23" - ] - }, - { - "name": "qwantbot", - "user_agent_regex": "\\+https\\://help\\.qwant\\.com/bot/", - "action": "ALLOW", - "remote_addresses": [ - "91.242.162.0/24" - ] - }, - { - "name": "kagibot", - "user_agent_regex": "\\+https\\://kagi\\.com/bot", - "action": "ALLOW", - "remote_addresses": [ - "216.18.205.234/32", - "35.212.27.76/32", - "104.254.65.50/32", - "209.151.156.194/32" - ] - }, - { - "name": "marginalia", - "user_agent_regex": "search\\.marginalia\\.nu", - "action": "ALLOW", - "remote_addresses": [ - "193.183.0.162/31", - "193.183.0.164/30", - "193.183.0.168/30", - "193.183.0.172/31", - "193.183.0.174/32" - ] - }, - { - "name": "mojeekbot", - "user_agent_regex": "http\\://www\\.mojeek\\.com/bot\\.html", - "action": "ALLOW", - "remote_addresses": [ - "5.102.173.71/32" - ] - }, - { - "name": "us-artificial-intelligence-scraper", - "user_agent_regex": "\\+https\\://github\\.com/US-Artificial-Intelligence/scraper", - "action": "DENY" - }, - { - "name": "well-known", - "path_regex": "^/.well-known/.*$", - "action": "ALLOW" - }, - { - "name": "favicon", - "path_regex": "^/favicon.ico$", - "action": "ALLOW" - }, - { - "name": "robots-txt", - "path_regex": "^/robots.txt$", - "action": "ALLOW" - }, - { - "name": "lightpanda", - "user_agent_regex": "^Lightpanda/.*$", - "action": "DENY" - }, - { - "name": "headless-chrome", - "user_agent_regex": "HeadlessChrome", - "action": "DENY" - }, - { - "name": "headless-chromium", - "user_agent_regex": "HeadlessChromium", - "action": "DENY" - }, - { - "name": "generic-bot-catchall", - "user_agent_regex": "(?i:bot|crawler)", - "action": "CHALLENGE", - "challenge": { - "difficulty": 16, - "report_as": 4, - "algorithm": "slow" - } - }, - { - "name": "generic-browser", - "user_agent_regex": "Mozilla", - "action": "CHALLENGE" - } - ], - "dnsbl": true -} diff --git a/cmd/anubis/decaymap.go b/cmd/anubis/decaymap.go deleted file mode 100644 index dcd2952..0000000 --- a/cmd/anubis/decaymap.go +++ /dev/null @@ -1,87 +0,0 @@ -package main - -import ( - "sync" - "time" -) - -func zilch[T any]() T { - var zero T - return zero -} - -// DecayMap is a lazy key->value map. It's a wrapper around a map and a mutex. If values exceed their time-to-live, they are pruned at Get time. -type DecayMap[K comparable, V any] struct { - data map[K]decayMapEntry[V] - lock sync.RWMutex -} - -type decayMapEntry[V any] struct { - Value V - expiry time.Time -} - -// NewDecayMap creates a new DecayMap of key type K and value type V. -// -// Key types must be comparable to work with maps. -func NewDecayMap[K comparable, V any]() *DecayMap[K, V] { - return &DecayMap[K, V]{ - data: make(map[K]decayMapEntry[V]), - } -} - -// expire forcibly expires a key by setting its time-to-live one second in the past. -func (m *DecayMap[K, V]) expire(key K) bool { - m.lock.RLock() - val, ok := m.data[key] - m.lock.RUnlock() - - if !ok { - return false - } - - m.lock.Lock() - val.expiry = time.Now().Add(-1 * time.Second) - m.data[key] = val - m.lock.Unlock() - - return true -} - -// Get gets a value from the DecayMap by key. -// -// If a value has expired, forcibly delete it if it was not updated. -func (m *DecayMap[K, V]) Get(key K) (V, bool) { - m.lock.RLock() - value, ok := m.data[key] - m.lock.RUnlock() - - if !ok { - return zilch[V](), false - } - - if time.Now().After(value.expiry) { - m.lock.Lock() - // Since previously reading m.data[key], the value may have been updated. - // Delete the entry only if the expiry time is still the same. - if m.data[key].expiry == value.expiry { - delete(m.data, key) - } - m.lock.Unlock() - - return zilch[V](), false - } - - return value.Value, true -} - -// Set sets a key value pair in the map. -func (m *DecayMap[K, V]) Set(key K, value V, ttl time.Duration) { - m.lock.Lock() - defer m.lock.Unlock() - - m.data[key] = decayMapEntry[V]{ - Value: value, - expiry: time.Now().Add(ttl), - } -} diff --git a/cmd/anubis/decaymap_test.go b/cmd/anubis/decaymap_test.go deleted file mode 100644 index 73e0626..0000000 --- a/cmd/anubis/decaymap_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "testing" - "time" -) - -func TestDecayMap(t *testing.T) { - dm := NewDecayMap[string, string]() - - dm.Set("test", "hi", 5*time.Minute) - - val, ok := dm.Get("test") - if !ok { - t.Error("somehow the test key was not set") - } - - if val != "hi" { - t.Errorf("wanted value %q, got: %q", "hi", val) - } - - ok = dm.expire("test") - if !ok { - t.Error("somehow could not force-expire the test key") - } - - _, ok = dm.Get("test") - if ok { - t.Error("got value even though it was supposed to be expired") - } -} diff --git a/cmd/anubis/index.templ b/cmd/anubis/index.templ deleted file mode 100644 index 79ae005..0000000 --- a/cmd/anubis/index.templ +++ /dev/null @@ -1,217 +0,0 @@ -package main - -import ( - "github.com/TecharoHQ/anubis" - "github.com/TecharoHQ/anubis/xess" -) - -templ base(title string, body templ.Component) { - - - - { title } - - - - @templ.JSONScript("anubis_version", anubis.Version) - - -
-
-

{ title }

-
- @body -
-
-

- Protected by Anubis from Techaro. Made with ❤️ in 🇨🇦. -

-
-
-
- - -} - -templ index() { -
- Loading...

-
Why am I seeing this?

You are seeing this because the administrator of this website has set up Anubis to protect the server against the scourge of AI companies aggressively scraping websites. This can and does cause downtime for the websites, which makes their resources inaccessible for everyone.

Anubis is a compromise. Anubis uses a Proof-of-Work scheme in the vein of Hashcash, a proposed proof-of-work scheme for reducing email spam. The idea is that at individual scales the additional load is ignorable, but at mass scraper levels it adds up and makes scraping much more expensive.

Ultimately, this is a hack whose real purpose is to give a \"good enough\" placeholder solution so that more time can be spent on fingerprinting and identifying headless browsers (EG: via how they do font rendering) so that the challenge proof of work page doesn't need to be presented to users that are much more likely to be legitimate.

Please note that Anubis requires the use of modern JavaScript features that plugins like JShelter will disable. Please disable JShelter or other such plugins for this domain.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -func errorPage(message string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var9 := templ.GetChildren(ctx) - if templ_7745c5c3_Var9 == nil { - templ_7745c5c3_Var9 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(message) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 213, Col: 14} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, ".

Go home

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/cmd/anubis/internal/config/config.go b/cmd/anubis/internal/config/config.go deleted file mode 100644 index 56975af..0000000 --- a/cmd/anubis/internal/config/config.go +++ /dev/null @@ -1,162 +0,0 @@ -package config - -import ( - "errors" - "fmt" - "net" - "regexp" -) - -type Rule string - -const ( - RuleUnknown Rule = "" - RuleAllow Rule = "ALLOW" - RuleDeny Rule = "DENY" - RuleChallenge Rule = "CHALLENGE" -) - -type Algorithm string - -const ( - AlgorithmUnknown Algorithm = "" - AlgorithmFast Algorithm = "fast" - AlgorithmSlow Algorithm = "slow" -) - -type Bot struct { - Name string `json:"name"` - UserAgentRegex *string `json:"user_agent_regex"` - PathRegex *string `json:"path_regex"` - Action Rule `json:"action"` - RemoteAddr []string `json:"remote_addresses"` - Challenge *ChallengeRules `json:"challenge,omitempty"` -} - -var ( - ErrNoBotRulesDefined = errors.New("config: must define at least one (1) bot rule") - ErrBotMustHaveName = errors.New("config.Bot: must set name") - ErrBotMustHaveUserAgentOrPath = errors.New("config.Bot: must set either user_agent_regex, path_regex, or remote_addresses") - ErrBotMustHaveUserAgentOrPathNotBoth = errors.New("config.Bot: must set either user_agent_regex, path_regex, and not both") - ErrUnknownAction = errors.New("config.Bot: unknown action") - ErrInvalidUserAgentRegex = errors.New("config.Bot: invalid user agent regex") - ErrInvalidPathRegex = errors.New("config.Bot: invalid path regex") - ErrInvalidCIDR = errors.New("config.Bot: invalid CIDR") -) - -func (b Bot) Valid() error { - var errs []error - - if b.Name == "" { - errs = append(errs, ErrBotMustHaveName) - } - - if b.UserAgentRegex == nil && b.PathRegex == nil && (b.RemoteAddr == nil || len(b.RemoteAddr) == 0) { - errs = append(errs, ErrBotMustHaveUserAgentOrPath) - } - - if b.UserAgentRegex != nil && b.PathRegex != nil { - errs = append(errs, ErrBotMustHaveUserAgentOrPathNotBoth) - } - - if b.UserAgentRegex != nil { - if _, err := regexp.Compile(*b.UserAgentRegex); err != nil { - errs = append(errs, ErrInvalidUserAgentRegex, err) - } - } - - if b.PathRegex != nil { - if _, err := regexp.Compile(*b.PathRegex); err != nil { - errs = append(errs, ErrInvalidPathRegex, err) - } - } - - if b.RemoteAddr != nil && len(b.RemoteAddr) > 0 { - for _, cidr := range b.RemoteAddr { - if _, _, err := net.ParseCIDR(cidr); err != nil { - errs = append(errs, ErrInvalidCIDR, err) - } - } - } - - switch b.Action { - case RuleAllow, RuleChallenge, RuleDeny: - // okay - default: - errs = append(errs, fmt.Errorf("%w: %q", ErrUnknownAction, b.Action)) - } - - if b.Action == RuleChallenge && b.Challenge != nil { - if err := b.Challenge.Valid(); err != nil { - errs = append(errs, err) - } - } - - if len(errs) != 0 { - return fmt.Errorf("config: bot entry for %q is not valid:\n%w", b.Name, errors.Join(errs...)) - } - - return nil -} - -type ChallengeRules struct { - Difficulty int `json:"difficulty"` - ReportAs int `json:"report_as"` - Algorithm Algorithm `json:"algorithm"` -} - -var ( - ErrChallengeRuleHasWrongAlgorithm = errors.New("config.Bot.ChallengeRules: algorithm is invalid") - ErrChallengeDifficultyTooLow = errors.New("config.Bot.ChallengeRules: difficulty is too low (must be >= 1)") - ErrChallengeDifficultyTooHigh = errors.New("config.Bot.ChallengeRules: difficulty is too high (must be <= 64)") -) - -func (cr ChallengeRules) Valid() error { - var errs []error - - if cr.Difficulty < 1 { - errs = append(errs, fmt.Errorf("%w, got: %d", ErrChallengeDifficultyTooLow, cr.Difficulty)) - } - - if cr.Difficulty > 64 { - errs = append(errs, fmt.Errorf("%w, got: %d", ErrChallengeDifficultyTooHigh, cr.Difficulty)) - } - - switch cr.Algorithm { - case AlgorithmFast, AlgorithmSlow, AlgorithmUnknown: - // do nothing, it's all good - default: - errs = append(errs, fmt.Errorf("%w: %q", ErrChallengeRuleHasWrongAlgorithm, cr.Algorithm)) - } - - if len(errs) != 0 { - return fmt.Errorf("config: challenge rules entry is not valid:\n%w", errors.Join(errs...)) - } - - return nil -} - -type Config struct { - Bots []Bot `json:"bots"` - DNSBL bool `json:"dnsbl"` -} - -func (c Config) Valid() error { - var errs []error - - if len(c.Bots) == 0 { - errs = append(errs, ErrNoBotRulesDefined) - } - - for _, b := range c.Bots { - if err := b.Valid(); err != nil { - errs = append(errs, err) - } - } - - if len(errs) != 0 { - return fmt.Errorf("config is not valid:\n%w", errors.Join(errs...)) - } - - return nil -} diff --git a/cmd/anubis/internal/config/config_test.go b/cmd/anubis/internal/config/config_test.go deleted file mode 100644 index 9865860..0000000 --- a/cmd/anubis/internal/config/config_test.go +++ /dev/null @@ -1,248 +0,0 @@ -package config - -import ( - "encoding/json" - "errors" - "os" - "path/filepath" - "testing" -) - -func p[V any](v V) *V { return &v } - -func TestBotValid(t *testing.T) { - var tests = []struct { - name string - bot Bot - err error - }{ - { - name: "simple user agent", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleChallenge, - UserAgentRegex: p("Mozilla"), - }, - err: nil, - }, - { - name: "simple path", - bot: Bot{ - Name: "well-known-path", - Action: RuleAllow, - PathRegex: p("^/.well-known/.*$"), - }, - err: nil, - }, - { - name: "no rule name", - bot: Bot{ - Action: RuleChallenge, - UserAgentRegex: p("Mozilla"), - }, - err: ErrBotMustHaveName, - }, - { - name: "no rule matcher", - bot: Bot{ - Name: "broken-rule", - Action: RuleAllow, - }, - err: ErrBotMustHaveUserAgentOrPath, - }, - { - name: "both user-agent and path", - bot: Bot{ - Name: "path-and-user-agent", - Action: RuleDeny, - UserAgentRegex: p("Mozilla"), - PathRegex: p("^/.secret-place/.*$"), - }, - err: ErrBotMustHaveUserAgentOrPathNotBoth, - }, - { - name: "unknown action", - bot: Bot{ - Name: "Unknown action", - Action: RuleUnknown, - UserAgentRegex: p("Mozilla"), - }, - err: ErrUnknownAction, - }, - { - name: "invalid user agent regex", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleChallenge, - UserAgentRegex: p("a(b"), - }, - err: ErrInvalidUserAgentRegex, - }, - { - name: "invalid path regex", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleChallenge, - PathRegex: p("a(b"), - }, - err: ErrInvalidPathRegex, - }, - { - name: "challenge difficulty too low", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleChallenge, - PathRegex: p("Mozilla"), - Challenge: &ChallengeRules{ - Difficulty: 0, - ReportAs: 4, - Algorithm: "fast", - }, - }, - err: ErrChallengeDifficultyTooLow, - }, - { - name: "challenge difficulty too high", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleChallenge, - PathRegex: p("Mozilla"), - Challenge: &ChallengeRules{ - Difficulty: 420, - ReportAs: 4, - Algorithm: "fast", - }, - }, - err: ErrChallengeDifficultyTooHigh, - }, - { - name: "challenge wrong algorithm", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleChallenge, - PathRegex: p("Mozilla"), - Challenge: &ChallengeRules{ - Difficulty: 420, - ReportAs: 4, - Algorithm: "high quality rips", - }, - }, - err: ErrChallengeRuleHasWrongAlgorithm, - }, - { - name: "invalid cidr range", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleAllow, - RemoteAddr: []string{"0.0.0.0/33"}, - }, - err: ErrInvalidCIDR, - }, - { - name: "only filter by IP range", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleAllow, - RemoteAddr: []string{"0.0.0.0/0"}, - }, - err: nil, - }, - { - name: "filter by user agent and IP range", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleAllow, - UserAgentRegex: p("Mozilla"), - RemoteAddr: []string{"0.0.0.0/0"}, - }, - err: nil, - }, - { - name: "filter by path and IP range", - bot: Bot{ - Name: "mozilla-ua", - Action: RuleAllow, - PathRegex: p("^.*$"), - RemoteAddr: []string{"0.0.0.0/0"}, - }, - err: nil, - }, - } - - for _, cs := range tests { - cs := cs - t.Run(cs.name, func(t *testing.T) { - err := cs.bot.Valid() - if err == nil && cs.err == nil { - return - } - - if err == nil && cs.err != nil { - t.Errorf("didn't get an error, but wanted: %v", cs.err) - } - - if !errors.Is(err, cs.err) { - t.Logf("got wrong error from Valid()") - t.Logf("wanted: %v", cs.err) - t.Logf("got: %v", err) - t.Errorf("got invalid error from check") - } - }) - } -} - -func TestConfigValidKnownGood(t *testing.T) { - finfos, err := os.ReadDir("testdata/good") - if err != nil { - t.Fatal(err) - } - - for _, st := range finfos { - st := st - t.Run(st.Name(), func(t *testing.T) { - fin, err := os.Open(filepath.Join("testdata", "good", st.Name())) - if err != nil { - t.Fatal(err) - } - defer fin.Close() - - var c Config - if err := json.NewDecoder(fin).Decode(&c); err != nil { - t.Fatalf("can't decode file: %v", err) - } - - if err := c.Valid(); err != nil { - t.Fatal(err) - } - }) - } -} - -func TestConfigValidBad(t *testing.T) { - finfos, err := os.ReadDir("testdata/bad") - if err != nil { - t.Fatal(err) - } - - for _, st := range finfos { - st := st - t.Run(st.Name(), func(t *testing.T) { - fin, err := os.Open(filepath.Join("testdata", "bad", st.Name())) - if err != nil { - t.Fatal(err) - } - defer fin.Close() - - var c Config - if err := json.NewDecoder(fin).Decode(&c); err != nil { - t.Fatalf("can't decode file: %v", err) - } - - if err := c.Valid(); err == nil { - t.Fatal("validation should have failed but didn't somehow") - } else { - t.Log(err) - } - }) - } -} diff --git a/cmd/anubis/internal/config/testdata/bad/badregexes.json b/cmd/anubis/internal/config/testdata/bad/badregexes.json deleted file mode 100644 index e85b85b..0000000 --- a/cmd/anubis/internal/config/testdata/bad/badregexes.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "bots": [ - { - "name": "path-bad", - "path_regex": "a(b", - "action": "DENY" - }, - { - "name": "user-agent-bad", - "user_agent_regex": "a(b", - "action": "DENY" - } - ] -} \ No newline at end of file diff --git a/cmd/anubis/internal/config/testdata/bad/invalid.json b/cmd/anubis/internal/config/testdata/bad/invalid.json deleted file mode 100644 index c5d1ff6..0000000 --- a/cmd/anubis/internal/config/testdata/bad/invalid.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "bots": [ - {} - ] -} \ No newline at end of file diff --git a/cmd/anubis/internal/config/testdata/bad/nobots.json b/cmd/anubis/internal/config/testdata/bad/nobots.json deleted file mode 100644 index 9e26dfe..0000000 --- a/cmd/anubis/internal/config/testdata/bad/nobots.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/cmd/anubis/internal/config/testdata/good/allow_everyone.json b/cmd/anubis/internal/config/testdata/good/allow_everyone.json deleted file mode 100644 index a7e1af7..0000000 --- a/cmd/anubis/internal/config/testdata/good/allow_everyone.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bots": [ - { - "name": "everyones-invited", - "remote_addresses": [ - "0.0.0.0/0", - "::/0" - ], - "action": "ALLOW" - } - ] -} \ No newline at end of file diff --git a/cmd/anubis/internal/config/testdata/good/challengemozilla.json b/cmd/anubis/internal/config/testdata/good/challengemozilla.json deleted file mode 100644 index e9d34ee..0000000 --- a/cmd/anubis/internal/config/testdata/good/challengemozilla.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "bots": [ - { - "name": "generic-browser", - "user_agent_regex": "Mozilla", - "action": "CHALLENGE" - } - ] -} \ No newline at end of file diff --git a/cmd/anubis/internal/config/testdata/good/everything_blocked.json b/cmd/anubis/internal/config/testdata/good/everything_blocked.json deleted file mode 100644 index e1763e4..0000000 --- a/cmd/anubis/internal/config/testdata/good/everything_blocked.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "bots": [ - { - "name": "everything", - "user_agent_regex": ".*", - "action": "DENY" - } - ], - "dnsbl": false -} \ No newline at end of file diff --git a/cmd/anubis/internal/dnsbl/dnsbl.go b/cmd/anubis/internal/dnsbl/dnsbl.go deleted file mode 100644 index 60edd5c..0000000 --- a/cmd/anubis/internal/dnsbl/dnsbl.go +++ /dev/null @@ -1,95 +0,0 @@ -package dnsbl - -import ( - "errors" - "fmt" - "net" - "strings" -) - -//go:generate go tool golang.org/x/tools/cmd/stringer -type=DroneBLResponse - -type DroneBLResponse byte - -const ( - AllGood DroneBLResponse = 0 - IRCDrone DroneBLResponse = 3 - Bottler DroneBLResponse = 5 - UnknownSpambotOrDrone DroneBLResponse = 6 - DDOSDrone DroneBLResponse = 7 - SOCKSProxy DroneBLResponse = 8 - HTTPProxy DroneBLResponse = 9 - ProxyChain DroneBLResponse = 10 - OpenProxy DroneBLResponse = 11 - OpenDNSResolver DroneBLResponse = 12 - BruteForceAttackers DroneBLResponse = 13 - OpenWingateProxy DroneBLResponse = 14 - CompromisedRouter DroneBLResponse = 15 - AutoRootingWorms DroneBLResponse = 16 - AutoDetectedBotIP DroneBLResponse = 17 - Unknown DroneBLResponse = 255 -) - -func Reverse(ip net.IP) string { - if ip.To4() != nil { - return reverse4(ip) - } - - return reverse6(ip) -} - -func reverse4(ip net.IP) string { - splitAddress := strings.Split(ip.String(), ".") - - // swap first and last octet - splitAddress[0], splitAddress[3] = splitAddress[3], splitAddress[0] - // swap middle octets - splitAddress[1], splitAddress[2] = splitAddress[2], splitAddress[1] - - return strings.Join(splitAddress, ".") -} - -func reverse6(ip net.IP) string { - ipBytes := []byte(ip) - var sb strings.Builder - - for i := len(ipBytes) - 1; i >= 0; i-- { - // Split the byte into two nibbles - highNibble := ipBytes[i] >> 4 - lowNibble := ipBytes[i] & 0x0F - - // Append the nibbles in reversed order - sb.WriteString(fmt.Sprintf("%x.%x.", lowNibble, highNibble)) - } - - return sb.String()[:len(sb.String())-1] -} - -func Lookup(ipStr string) (DroneBLResponse, error) { - ip := net.ParseIP(ipStr) - if ip == nil { - return Unknown, errors.New("dnsbl: input is not an IP address") - } - - revIP := Reverse(ip) + ".dnsbl.dronebl.org" - - ips, err := net.LookupIP(revIP) - if err != nil { - var dnserr *net.DNSError - if errors.As(err, &dnserr) { - if dnserr.IsNotFound { - return AllGood, nil - } - } - - return Unknown, err - } - - if len(ips) != 0 { - for _, ip := range ips { - return DroneBLResponse(ip.To4()[3]), nil - } - } - - return UnknownSpambotOrDrone, nil -} diff --git a/cmd/anubis/internal/dnsbl/dnsbl_test.go b/cmd/anubis/internal/dnsbl/dnsbl_test.go deleted file mode 100644 index ccadd64..0000000 --- a/cmd/anubis/internal/dnsbl/dnsbl_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package dnsbl - -import ( - "fmt" - "net" - "os" - "testing" -) - -func TestReverse4(t *testing.T) { - cases := []struct { - inp, out string - }{ - {"1.2.3.4", "4.3.2.1"}, - } - - for _, cs := range cases { - t.Run(fmt.Sprintf("%s->%s", cs.inp, cs.out), func(t *testing.T) { - out := reverse4(net.ParseIP(cs.inp)) - - if out != cs.out { - t.Errorf("wanted %s\ngot: %s", cs.out, out) - } - }) - } -} - -func TestReverse6(t *testing.T) { - cases := []struct { - inp, out string - }{ - { - inp: "1234:5678:9ABC:DEF0:1234:5678:9ABC:DEF0", - out: "0.f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.f.e.d.c.b.a.9.8.7.6.5.4.3.2.1", - }, - } - - for _, cs := range cases { - t.Run(fmt.Sprintf("%s->%s", cs.inp, cs.out), func(t *testing.T) { - out := reverse6(net.ParseIP(cs.inp)) - - if out != cs.out { - t.Errorf("wanted %s, got: %s", cs.out, out) - } - }) - } -} - -func TestLookup(t *testing.T) { - if os.Getenv("DONT_USE_NETWORK") != "" { - t.Skip("test requires network egress") - return - } - - resp, err := Lookup("27.65.243.194") - if err != nil { - t.Fatalf("it broked: %v", err) - } - - t.Logf("response: %d", resp) -} diff --git a/cmd/anubis/internal/dnsbl/droneblresponse_string.go b/cmd/anubis/internal/dnsbl/droneblresponse_string.go deleted file mode 100644 index 5104dda..0000000 --- a/cmd/anubis/internal/dnsbl/droneblresponse_string.go +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by "stringer -type=DroneBLResponse"; DO NOT EDIT. - -package dnsbl - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[AllGood-0] - _ = x[IRCDrone-3] - _ = x[Bottler-5] - _ = x[UnknownSpambotOrDrone-6] - _ = x[DDOSDrone-7] - _ = x[SOCKSProxy-8] - _ = x[HTTPProxy-9] - _ = x[ProxyChain-10] - _ = x[OpenProxy-11] - _ = x[OpenDNSResolver-12] - _ = x[BruteForceAttackers-13] - _ = x[OpenWingateProxy-14] - _ = x[CompromisedRouter-15] - _ = x[AutoRootingWorms-16] - _ = x[AutoDetectedBotIP-17] - _ = x[Unknown-255] -} - -const ( - _DroneBLResponse_name_0 = "AllGood" - _DroneBLResponse_name_1 = "IRCDrone" - _DroneBLResponse_name_2 = "BottlerUnknownSpambotOrDroneDDOSDroneSOCKSProxyHTTPProxyProxyChainOpenProxyOpenDNSResolverBruteForceAttackersOpenWingateProxyCompromisedRouterAutoRootingWormsAutoDetectedBotIP" - _DroneBLResponse_name_3 = "Unknown" -) - -var ( - _DroneBLResponse_index_2 = [...]uint8{0, 7, 28, 37, 47, 56, 66, 75, 90, 109, 125, 142, 158, 175} -) - -func (i DroneBLResponse) String() string { - switch { - case i == 0: - return _DroneBLResponse_name_0 - case i == 3: - return _DroneBLResponse_name_1 - case 5 <= i && i <= 17: - i -= 5 - return _DroneBLResponse_name_2[_DroneBLResponse_index_2[i]:_DroneBLResponse_index_2[i+1]] - case i == 255: - return _DroneBLResponse_name_3 - default: - return "DroneBLResponse(" + strconv.FormatInt(int64(i), 10) + ")" - } -} diff --git a/cmd/anubis/js/main.mjs b/cmd/anubis/js/main.mjs deleted file mode 100644 index 297f16f..0000000 --- a/cmd/anubis/js/main.mjs +++ /dev/null @@ -1,89 +0,0 @@ -import processFast from "./proof-of-work.mjs"; -import processSlow from "./proof-of-work-slow.mjs"; -import { testVideo } from "./video.mjs"; - -const algorithms = { - "fast": processFast, - "slow": processSlow, -} - -// from Xeact -const u = (url = "", params = {}) => { - let result = new URL(url, window.location.href); - Object.entries(params).forEach((kv) => { - let [k, v] = kv; - result.searchParams.set(k, v); - }); - return result.toString(); -}; - -const imageURL = (mood, cacheBuster) => - u(`/.within.website/x/cmd/anubis/static/img/${mood}.webp`, { cacheBuster }); - -(async () => { - const status = document.getElementById('status'); - const image = document.getElementById('image'); - const title = document.getElementById('title'); - const spinner = document.getElementById('spinner'); - const anubisVersion = JSON.parse(document.getElementById('anubis_version').textContent); - - // const testarea = document.getElementById('testarea'); - - // const videoWorks = await testVideo(testarea); - // console.log(`videoWorks: ${videoWorks}`); - - // if (!videoWorks) { - // title.innerHTML = "Oh no!"; - // status.innerHTML = "Checks failed. Please check your browser's settings and try again."; - // image.src = imageURL("sad"); - // spinner.innerHTML = ""; - // spinner.style.display = "none"; - // return; - // } - - status.innerHTML = 'Calculating...'; - - const { challenge, rules } = await fetch("/.within.website/x/cmd/anubis/api/make-challenge", { method: "POST" }) - .then(r => { - if (!r.ok) { - throw new Error("Failed to fetch config"); - } - return r.json(); - }) - .catch(err => { - title.innerHTML = "Oh no!"; - status.innerHTML = `Failed to fetch config: ${err.message}`; - image.src = imageURL("sad", anubisVersion); - spinner.innerHTML = ""; - spinner.style.display = "none"; - throw err; - }); - - const process = algorithms[rules.algorithm]; - if (!process) { - title.innerHTML = "Oh no!"; - status.innerHTML = `Failed to resolve check algorithm. You may want to reload the page.`; - image.src = imageURL("sad", anubisVersion); - spinner.innerHTML = ""; - spinner.style.display = "none"; - return; - } - - status.innerHTML = `Calculating...
Difficulty: ${rules.report_as}`; - - const t0 = Date.now(); - const { hash, nonce } = await process(challenge, rules.difficulty); - const t1 = Date.now(); - console.log({ hash, nonce }); - - title.innerHTML = "Success!"; - status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`; - image.src = imageURL("happy", anubisVersion); - spinner.innerHTML = ""; - spinner.style.display = "none"; - - setTimeout(() => { - const redir = window.location.href; - window.location.href = u("/.within.website/x/cmd/anubis/api/pass-challenge", { response: hash, nonce, redir, elapsedTime: t1 - t0 }); - }, 250); -})(); \ No newline at end of file diff --git a/cmd/anubis/js/proof-of-work-slow.mjs b/cmd/anubis/js/proof-of-work-slow.mjs deleted file mode 100644 index e30dc21..0000000 --- a/cmd/anubis/js/proof-of-work-slow.mjs +++ /dev/null @@ -1,63 +0,0 @@ -// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm - -export default function process(data, difficulty = 5, _threads = 1) { - console.debug("slow algo"); - return new Promise((resolve, reject) => { - let webWorkerURL = URL.createObjectURL(new Blob([ - '(', processTask(), ')()' - ], { type: 'application/javascript' })); - - let worker = new Worker(webWorkerURL); - - worker.onmessage = (event) => { - worker.terminate(); - resolve(event.data); - }; - - worker.onerror = (event) => { - worker.terminate(); - reject(); - }; - - worker.postMessage({ - data, - difficulty - }); - - URL.revokeObjectURL(webWorkerURL); - }); -} - -function processTask() { - return function () { - const sha256 = (text) => { - const encoded = new TextEncoder().encode(text); - return crypto.subtle.digest("SHA-256", encoded.buffer) - .then((result) => - Array.from(new Uint8Array(result)) - .map((c) => c.toString(16).padStart(2, "0")) - .join(""), - ); - }; - - addEventListener('message', async (event) => { - let data = event.data.data; - let difficulty = event.data.difficulty; - - let hash; - let nonce = 0; - do { - hash = await sha256(data + nonce++); - } while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0')); - - nonce -= 1; // last nonce was post-incremented - - postMessage({ - hash, - data, - difficulty, - nonce, - }); - }); - }.toString(); -} \ No newline at end of file diff --git a/cmd/anubis/js/proof-of-work.mjs b/cmd/anubis/js/proof-of-work.mjs deleted file mode 100644 index b4f9c53..0000000 --- a/cmd/anubis/js/proof-of-work.mjs +++ /dev/null @@ -1,93 +0,0 @@ -export default function process(data, difficulty =