6 Commits

Author SHA1 Message Date
WeebDataHoarder
74a067ae10 ci: use mirror for image fetches 2025-04-23 23:45:43 +02:00
WeebDataHoarder
3bbd50764a challenge: add cookie prefix to cookies tied to host/pubkey to prevent reuse 2025-04-23 22:38:14 +02:00
WeebDataHoarder
49e46e7e9f condition: fix http query values context 2025-04-23 22:29:17 +02:00
WeebDataHoarder
cd372e1512 challenge: Skip already issued challenges 2025-04-23 22:06:11 +02:00
WeebDataHoarder
cef915b353 http: use Query.Get instead of FormValue, allows POST through 2025-04-23 21:30:39 +02:00
WeebDataHoarder
10ceca02c9 docker: Remove outdated DNSBL argument 2025-04-23 21:15:56 +02:00
12 changed files with 143 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
// yaml_stream.jsonnet // yaml_stream.jsonnet
local Build(go, alpine, os, arch) = { local Build(mirror, go, alpine, os, arch) = {
kind: "pipeline", kind: "pipeline",
type: "docker", type: "docker",
name: "build-" + go + "-alpine" + alpine + "-" + arch, name: "build-" + go + "-alpine" + alpine + "-" + arch,
@@ -17,6 +17,7 @@ local Build(go, alpine, os, arch) = {
{ {
name: "build", name: "build",
image: "golang:" + go +"-alpine" + alpine, image: "golang:" + go +"-alpine" + alpine,
mirror: mirror,
commands: [ commands: [
"apk update", "apk update",
"apk add --no-cache git", "apk add --no-cache git",
@@ -28,6 +29,7 @@ local Build(go, alpine, os, arch) = {
{ {
name: "check-policy-forgejo", name: "check-policy-forgejo",
image: "alpine:" + alpine, image: "alpine:" + alpine,
mirror: mirror,
depends_on: ["build"], depends_on: ["build"],
commands: [ commands: [
"./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 --policy examples/forgejo.yml --policy-snippets examples/snippets/" "./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 --policy examples/forgejo.yml --policy-snippets examples/snippets/"
@@ -36,6 +38,7 @@ local Build(go, alpine, os, arch) = {
{ {
name: "check-policy-generic", name: "check-policy-generic",
image: "alpine:" + alpine, image: "alpine:" + alpine,
mirror: mirror,
depends_on: ["build"], depends_on: ["build"],
commands: [ commands: [
"./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 --policy examples/generic.yml --policy-snippets examples/snippets/" "./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 --policy examples/generic.yml --policy-snippets examples/snippets/"
@@ -44,6 +47,7 @@ local Build(go, alpine, os, arch) = {
{ {
name: "test-wasm-success", name: "test-wasm-success",
image: "alpine:" + alpine, image: "alpine:" + alpine,
mirror: mirror,
depends_on: ["build"], depends_on: ["build"],
commands: [ commands: [
"./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm " + "./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm " +
@@ -56,6 +60,7 @@ local Build(go, alpine, os, arch) = {
{ {
name: "test-wasm-fail", name: "test-wasm-fail",
image: "alpine:" + alpine, image: "alpine:" + alpine,
mirror: mirror,
depends_on: ["build"], depends_on: ["build"],
commands: [ commands: [
"./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm " + "./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm " +
@@ -68,7 +73,7 @@ local Build(go, alpine, os, arch) = {
] ]
}; };
local Publish(registry, repo, secret, go, alpine, os, arch, trigger, platforms, extra) = { local Publish(mirror, registry, repo, secret, go, alpine, os, arch, trigger, platforms, extra) = {
kind: "pipeline", kind: "pipeline",
type: "docker", type: "docker",
name: "publish-" + go + "-alpine" + alpine + "-" + secret, name: "publish-" + go + "-alpine" + alpine + "-" + secret,
@@ -78,6 +83,15 @@ local Publish(registry, repo, secret, go, alpine, os, arch, trigger, platforms,
}, },
trigger: trigger, trigger: trigger,
steps: [ steps: [
{
name: "setup-buildkitd",
image: "alpine:" + alpine,
mirror: mirror,
commands: [
"echo '[registry.\"docker.io\"]' > buildkitd.toml",
"echo ' mirrors = [\"mirror.gcr.io\"]' >> buildkitd.toml"
],
},
{ {
name: "docker", name: "docker",
image: "plugins/buildx", image: "plugins/buildx",
@@ -87,13 +101,15 @@ local Publish(registry, repo, secret, go, alpine, os, arch, trigger, platforms,
SOURCE_DATE_EPOCH: 0, SOURCE_DATE_EPOCH: 0,
TZ: "UTC", TZ: "UTC",
LC_ALL: "C", LC_ALL: "C",
PLUGIN_BUILDER_CONFIG: "buildkitd.toml",
PLUGIN_BUILDER_DRIVER: "docker-container",
}, },
settings: { settings: {
registry: registry, registry: registry,
repo: repo, repo: repo,
mirror: mirror,
compress: true, compress: true,
platform: platforms, platform: platforms,
builder_driver: "docker-container",
build_args: { build_args: {
from_builder: "golang:" + go +"-alpine" + alpine, from_builder: "golang:" + go +"-alpine" + alpine,
from: "alpine:" + alpine, from: "alpine:" + alpine,
@@ -116,17 +132,19 @@ local containerArchitectures = ["linux/amd64", "linux/arm64", "linux/riscv64"];
local alpineVersion = "3.21"; local alpineVersion = "3.21";
local goVersion = "1.24"; local goVersion = "1.24";
local mirror = "https://mirror.gcr.io";
[ [
Build(goVersion, alpineVersion, "linux", "amd64"), Build(mirror, goVersion, alpineVersion, "linux", "amd64"),
Build(goVersion, alpineVersion, "linux", "arm64"), Build(mirror, goVersion, alpineVersion, "linux", "arm64"),
# latest # latest
Publish("git.gammaspectra.live", "git.gammaspectra.live/git/go-away", "git", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-git"}, Publish(mirror, "git.gammaspectra.live", "git.gammaspectra.live/git/go-away", "git", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-git"},
Publish("codeberg.org", "codeberg.org/weebdatahoarder/go-away", "codeberg", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-codeberg"}, Publish(mirror, "codeberg.org", "codeberg.org/weebdatahoarder/go-away", "codeberg", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-codeberg"},
Publish("ghcr.io", "ghcr.io/weebdatahoarder/go-away", "github", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-github"}, Publish(mirror, "ghcr.io", "ghcr.io/weebdatahoarder/go-away", "github", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-github"},
# modern # modern
Publish("git.gammaspectra.live", "git.gammaspectra.live/git/go-away", "git", goVersion, alpineVersion, "linux", "amd64", {event: ["promote", "tag"], target: ["production"], }, containerArchitectures, {auto_tag: true,}), Publish(mirror, "git.gammaspectra.live", "git.gammaspectra.live/git/go-away", "git", goVersion, alpineVersion, "linux", "amd64", {event: ["promote", "tag"], target: ["production"], }, containerArchitectures, {auto_tag: true,}),
Publish("codeberg.org", "codeberg.org/weebdatahoarder/go-away", "codeberg", goVersion, alpineVersion, "linux", "amd64", {event: ["promote", "tag"], target: ["production"], }, containerArchitectures, {auto_tag: true,}), Publish(mirror, "codeberg.org", "codeberg.org/weebdatahoarder/go-away", "codeberg", goVersion, alpineVersion, "linux", "amd64", {event: ["promote", "tag"], target: ["production"], }, containerArchitectures, {auto_tag: true,}),
Publish("ghcr.io", "ghcr.io/weebdatahoarder/go-away", "github", goVersion, alpineVersion, "linux", "amd64", {event: ["promote", "tag"], target: ["production"], }, containerArchitectures, {auto_tag: true,}), Publish(mirror, "ghcr.io", "ghcr.io/weebdatahoarder/go-away", "github", goVersion, alpineVersion, "linux", "amd64", {event: ["promote", "tag"], target: ["production"], }, containerArchitectures, {auto_tag: true,}),
] ]

View File

@@ -17,6 +17,7 @@ steps:
- go build -v -pgo=auto -v -trimpath -ldflags=-buildid= -o ./.bin/go-away ./cmd/go-away - go build -v -pgo=auto -v -trimpath -ldflags=-buildid= -o ./.bin/go-away ./cmd/go-away
- go build -v -o ./.bin/test-wasm-runtime ./cmd/test-wasm-runtime - go build -v -o ./.bin/test-wasm-runtime ./cmd/test-wasm-runtime
image: golang:1.24-alpine3.21 image: golang:1.24-alpine3.21
mirror: https://mirror.gcr.io
name: build name: build
- commands: - commands:
- ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 - ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80
@@ -24,6 +25,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: check-policy-forgejo name: check-policy-forgejo
- commands: - commands:
- ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 - ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80
@@ -31,6 +33,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: check-policy-generic name: check-policy-generic
- commands: - commands:
- ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm - ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm
@@ -41,6 +44,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: test-wasm-success name: test-wasm-success
- commands: - commands:
- ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm - ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm
@@ -51,6 +55,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: test-wasm-fail name: test-wasm-fail
type: docker type: docker
--- ---
@@ -72,6 +77,7 @@ steps:
- go build -v -pgo=auto -v -trimpath -ldflags=-buildid= -o ./.bin/go-away ./cmd/go-away - go build -v -pgo=auto -v -trimpath -ldflags=-buildid= -o ./.bin/go-away ./cmd/go-away
- go build -v -o ./.bin/test-wasm-runtime ./cmd/test-wasm-runtime - go build -v -o ./.bin/test-wasm-runtime ./cmd/test-wasm-runtime
image: golang:1.24-alpine3.21 image: golang:1.24-alpine3.21
mirror: https://mirror.gcr.io
name: build name: build
- commands: - commands:
- ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 - ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80
@@ -79,6 +85,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: check-policy-forgejo name: check-policy-forgejo
- commands: - commands:
- ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 - ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80
@@ -86,6 +93,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: check-policy-generic name: check-policy-generic
- commands: - commands:
- ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm - ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm
@@ -96,6 +104,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: test-wasm-success name: test-wasm-success
- commands: - commands:
- ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm - ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm
@@ -106,6 +115,7 @@ steps:
depends_on: depends_on:
- build - build
image: alpine:3.21 image: alpine:3.21
mirror: https://mirror.gcr.io
name: test-wasm-fail name: test-wasm-fail
type: docker type: docker
--- ---
@@ -115,9 +125,17 @@ platform:
arch: amd64 arch: amd64
os: linux os: linux
steps: steps:
- commands:
- echo '[registry."docker.io"]' > buildkitd.toml
- echo ' mirrors = ["mirror.gcr.io"]' >> buildkitd.toml
image: alpine:3.21
mirror: https://mirror.gcr.io
name: setup-buildkitd
- environment: - environment:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
LC_ALL: C LC_ALL: C
PLUGIN_BUILDER_CONFIG: buildkitd.toml
PLUGIN_BUILDER_DRIVER: docker-container
SOURCE_DATE_EPOCH: 0 SOURCE_DATE_EPOCH: 0
TZ: UTC TZ: UTC
image: plugins/buildx image: plugins/buildx
@@ -128,8 +146,8 @@ steps:
build_args: build_args:
from: alpine:3.21 from: alpine:3.21
from_builder: golang:1.24-alpine3.21 from_builder: golang:1.24-alpine3.21
builder_driver: docker-container
compress: true compress: true
mirror: https://mirror.gcr.io
password: password:
from_secret: git_password from_secret: git_password
platform: platform:
@@ -155,9 +173,17 @@ platform:
arch: amd64 arch: amd64
os: linux os: linux
steps: steps:
- commands:
- echo '[registry."docker.io"]' > buildkitd.toml
- echo ' mirrors = ["mirror.gcr.io"]' >> buildkitd.toml
image: alpine:3.21
mirror: https://mirror.gcr.io
name: setup-buildkitd
- environment: - environment:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
LC_ALL: C LC_ALL: C
PLUGIN_BUILDER_CONFIG: buildkitd.toml
PLUGIN_BUILDER_DRIVER: docker-container
SOURCE_DATE_EPOCH: 0 SOURCE_DATE_EPOCH: 0
TZ: UTC TZ: UTC
image: plugins/buildx image: plugins/buildx
@@ -168,8 +194,8 @@ steps:
build_args: build_args:
from: alpine:3.21 from: alpine:3.21
from_builder: golang:1.24-alpine3.21 from_builder: golang:1.24-alpine3.21
builder_driver: docker-container
compress: true compress: true
mirror: https://mirror.gcr.io
password: password:
from_secret: codeberg_password from_secret: codeberg_password
platform: platform:
@@ -195,9 +221,17 @@ platform:
arch: amd64 arch: amd64
os: linux os: linux
steps: steps:
- commands:
- echo '[registry."docker.io"]' > buildkitd.toml
- echo ' mirrors = ["mirror.gcr.io"]' >> buildkitd.toml
image: alpine:3.21
mirror: https://mirror.gcr.io
name: setup-buildkitd
- environment: - environment:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
LC_ALL: C LC_ALL: C
PLUGIN_BUILDER_CONFIG: buildkitd.toml
PLUGIN_BUILDER_DRIVER: docker-container
SOURCE_DATE_EPOCH: 0 SOURCE_DATE_EPOCH: 0
TZ: UTC TZ: UTC
image: plugins/buildx image: plugins/buildx
@@ -208,8 +242,8 @@ steps:
build_args: build_args:
from: alpine:3.21 from: alpine:3.21
from_builder: golang:1.24-alpine3.21 from_builder: golang:1.24-alpine3.21
builder_driver: docker-container
compress: true compress: true
mirror: https://mirror.gcr.io
password: password:
from_secret: github_password from_secret: github_password
platform: platform:
@@ -235,9 +269,17 @@ platform:
arch: amd64 arch: amd64
os: linux os: linux
steps: steps:
- commands:
- echo '[registry."docker.io"]' > buildkitd.toml
- echo ' mirrors = ["mirror.gcr.io"]' >> buildkitd.toml
image: alpine:3.21
mirror: https://mirror.gcr.io
name: setup-buildkitd
- environment: - environment:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
LC_ALL: C LC_ALL: C
PLUGIN_BUILDER_CONFIG: buildkitd.toml
PLUGIN_BUILDER_DRIVER: docker-container
SOURCE_DATE_EPOCH: 0 SOURCE_DATE_EPOCH: 0
TZ: UTC TZ: UTC
image: plugins/buildx image: plugins/buildx
@@ -249,8 +291,8 @@ steps:
build_args: build_args:
from: alpine:3.21 from: alpine:3.21
from_builder: golang:1.24-alpine3.21 from_builder: golang:1.24-alpine3.21
builder_driver: docker-container
compress: true compress: true
mirror: https://mirror.gcr.io
password: password:
from_secret: git_password from_secret: git_password
platform: platform:
@@ -275,9 +317,17 @@ platform:
arch: amd64 arch: amd64
os: linux os: linux
steps: steps:
- commands:
- echo '[registry."docker.io"]' > buildkitd.toml
- echo ' mirrors = ["mirror.gcr.io"]' >> buildkitd.toml
image: alpine:3.21
mirror: https://mirror.gcr.io
name: setup-buildkitd
- environment: - environment:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
LC_ALL: C LC_ALL: C
PLUGIN_BUILDER_CONFIG: buildkitd.toml
PLUGIN_BUILDER_DRIVER: docker-container
SOURCE_DATE_EPOCH: 0 SOURCE_DATE_EPOCH: 0
TZ: UTC TZ: UTC
image: plugins/buildx image: plugins/buildx
@@ -289,8 +339,8 @@ steps:
build_args: build_args:
from: alpine:3.21 from: alpine:3.21
from_builder: golang:1.24-alpine3.21 from_builder: golang:1.24-alpine3.21
builder_driver: docker-container
compress: true compress: true
mirror: https://mirror.gcr.io
password: password:
from_secret: codeberg_password from_secret: codeberg_password
platform: platform:
@@ -315,9 +365,17 @@ platform:
arch: amd64 arch: amd64
os: linux os: linux
steps: steps:
- commands:
- echo '[registry."docker.io"]' > buildkitd.toml
- echo ' mirrors = ["mirror.gcr.io"]' >> buildkitd.toml
image: alpine:3.21
mirror: https://mirror.gcr.io
name: setup-buildkitd
- environment: - environment:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
LC_ALL: C LC_ALL: C
PLUGIN_BUILDER_CONFIG: buildkitd.toml
PLUGIN_BUILDER_DRIVER: docker-container
SOURCE_DATE_EPOCH: 0 SOURCE_DATE_EPOCH: 0
TZ: UTC TZ: UTC
image: plugins/buildx image: plugins/buildx
@@ -329,8 +387,8 @@ steps:
build_args: build_args:
from: alpine:3.21 from: alpine:3.21
from_builder: golang:1.24-alpine3.21 from_builder: golang:1.24-alpine3.21
builder_driver: docker-container
compress: true compress: true
mirror: https://mirror.gcr.io
password: password:
from_secret: github_password from_secret: github_password
platform: platform:
@@ -350,6 +408,6 @@ trigger:
type: docker type: docker
--- ---
kind: signature kind: signature
hmac: 8aed9810938e4aa4b34c4afb35e1101f27f98a61ffe5349be9a30f22ce7480ed hmac: ad13c88b81cd1c6ebd4bb8d33479ffe8e67bc8caefdcc1c06dd1a6b75476bcd7
... ...

View File

@@ -47,7 +47,6 @@ ENV GOAWAY_CLIENT_IP_HEADER=""
ENV GOAWAY_BACKEND_IP_HEADER="" ENV GOAWAY_BACKEND_IP_HEADER=""
ENV GOAWAY_JWT_PRIVATE_KEY_SEED="" ENV GOAWAY_JWT_PRIVATE_KEY_SEED=""
ENV GOAWAY_BACKEND="" ENV GOAWAY_BACKEND=""
ENV GOAWAY_DNSBL="dnsbl.dronebl.org"
ENV GOAWAY_ACME_AUTOCERT="" ENV GOAWAY_ACME_AUTOCERT=""
ENV GOAWAY_CACHE="/cache" ENV GOAWAY_CACHE="/cache"
@@ -60,7 +59,6 @@ ENTRYPOINT /bin/go-away --bind "${GOAWAY_BIND}" --bind-network "${GOAWAY_BIND_N
--policy "${GOAWAY_POLICY}" --policy-snippets "${GOAWAY_POLICY_SNIPPETS}" \ --policy "${GOAWAY_POLICY}" --policy-snippets "${GOAWAY_POLICY_SNIPPETS}" \
--client-ip-header "${GOAWAY_CLIENT_IP_HEADER}" --backend-ip-header "${GOAWAY_BACKEND_IP_HEADER}" \ --client-ip-header "${GOAWAY_CLIENT_IP_HEADER}" --backend-ip-header "${GOAWAY_BACKEND_IP_HEADER}" \
--cache "${GOAWAY_CACHE}" \ --cache "${GOAWAY_CACHE}" \
--dnsbl "${GOAWAY_DNSBL}" \
--challenge-template "${GOAWAY_CHALLENGE_TEMPLATE}" --challenge-template-theme "${GOAWAY_CHALLENGE_TEMPLATE_THEME}" \ --challenge-template "${GOAWAY_CHALLENGE_TEMPLATE}" --challenge-template-theme "${GOAWAY_CHALLENGE_TEMPLATE_THEME}" \
--slog-level "${GOAWAY_SLOG_LEVEL}" \ --slog-level "${GOAWAY_SLOG_LEVEL}" \
--acme-autocert "${GOAWAY_ACME_AUTOCERT}" \ --acme-autocert "${GOAWAY_ACME_AUTOCERT}" \

View File

@@ -409,9 +409,6 @@ services:
GOAWAY_CHALLENGE_TEMPLATE: forgejo GOAWAY_CHALLENGE_TEMPLATE: forgejo
GOAWAY_CHALLENGE_TEMPLATE_THEME: forgejo-dark GOAWAY_CHALLENGE_TEMPLATE_THEME: forgejo-dark
# specify a DNSBL for usage in conditions. Defaults to DroneBL
# GOAWAY_DNSBL: "dnsbl.dronebl.org"
# Backend to match. Can be subdomain or full wildcards, "*.example.com" or "*" # Backend to match. Can be subdomain or full wildcards, "*.example.com" or "*"
GOAWAY_BACKEND: "git.example.com=http://forgejo:3000" GOAWAY_BACKEND: "git.example.com=http://forgejo:3000"
@@ -426,9 +423,12 @@ services:
## Other Similar Projects ## Other Similar Projects
* [Anubis](https://anubis.techaro.lol/): Proxy that uses JavaScript proof of work to weight request based on rules [[source]](https://github.com/TecharoHQ/anubis)
* [powxy](https://sr.ht/~runxiyu/powxy/): Powxy is a reverse proxy that protects your upstream service by challenging clients with SHA-256 proof-of-work. [[source](https://git.sr.ht/~runxiyu/powxy)] | Project | Forge | Description |
* [anticrawl](https://flak.tedunangst.com/post/anticrawl): Go http handler / proxy for regex based rules [[source]](https://humungus.tedunangst.com/r/anticrawl) |:-------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------|
| [Anubis](https://anubis.techaro.lol/) | [![GitHub](https://img.shields.io/badge/GitHub-TecharoHQ/anubis-blue?style=flat&logo=github&labelColor=fff&logoColor=24292f)](https://github.com/TecharoHQ/anubis)<br/>Go / [MIT](https://github.com/TecharoHQ/anubis/blob/main/LICENSE) | Proxy that uses JavaScript proof of work to weight request based on simple match rules |
| [powxy](https://sr.ht/~runxiyu/powxy/) | [![sourcehut](https://img.shields.io/badge/sourcehut-~runxiyu/powxy-blue?style=flat&logo=sourcehut&labelColor=fff&logoColor=000)](https://git.sr.ht/~runxiyu/powxy)<br/> Go / [BSD 2-Clause](https://git.sr.ht/~runxiyu/powxy/tree/master/item/LICENSE) | Powxy is a reverse proxy that protects your upstream service by challenging clients with SHA-256 proof-of-work. |
| [anticrawl](https://flak.tedunangst.com/post/anticrawl) | [[source]](https://humungus.tedunangst.com/r/anticrawl)<br/>Go / None | Go http handler / proxy for regex based rules |
## Development ## Development

View File

@@ -23,7 +23,7 @@ func FillRegistration(state challenge.StateInterface, reg *challenge.Registratio
return challenge.VerifyResultFail return challenge.VerifyResultFail
} }
utils.SetCookie(utils.CookiePrefix+reg.Name, token, expiry, w, r) utils.SetCookie(challenge.RequestDataFromContext(r.Context()).CookiePrefix+reg.Name, token, expiry, w, r)
uri, err := challenge.RedirectUrl(r, reg) uri, err := challenge.RedirectUrl(r, reg)
if err != nil { if err != nil {

View File

@@ -3,6 +3,7 @@ package challenge
import ( import (
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
@@ -37,6 +38,7 @@ type RequestData struct {
ChallengeState map[Id]VerifyState ChallengeState map[Id]VerifyState
RemoteAddress net.IP RemoteAddress net.IP
State StateInterface State StateInterface
CookiePrefix string
r *http.Request r *http.Request
@@ -75,6 +77,13 @@ func CreateRequestData(r *http.Request, state StateInterface) (*http.Request, *R
data.query = condition.NewValuesMap(r.URL.Query()) data.query = condition.NewValuesMap(r.URL.Query())
data.header = condition.NewMIMEMap(textproto.MIMEHeader(r.Header)) data.header = condition.NewMIMEMap(textproto.MIMEHeader(r.Header))
sum := sha256.New()
sum.Write([]byte(r.Host))
sum.Write([]byte{0})
sum.Write(state.PublicKey())
sum.Write([]byte{0})
data.CookiePrefix = utils.CookiePrefix + hex.EncodeToString(sum.Sum(nil)[:4]) + "-"
r = r.WithContext(context.WithValue(r.Context(), requestDataContextKey{}, &data)) r = r.WithContext(context.WithValue(r.Context(), requestDataContextKey{}, &data))
return r, &data return r, &data
@@ -108,12 +117,17 @@ func (d *RequestData) Parent() cel.Activation {
} }
func (d *RequestData) EvaluateChallenges(w http.ResponseWriter, r *http.Request) { func (d *RequestData) EvaluateChallenges(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
var issuedChallenge string
if q.Has(QueryArgChallenge) {
issuedChallenge = q.Get(QueryArgChallenge)
}
for _, reg := range d.State.GetChallenges() { for _, reg := range d.State.GetChallenges() {
key := GetChallengeKeyForRequest(d.State, reg, d.Expiration(reg.Duration), r) key := GetChallengeKeyForRequest(d.State, reg, d.Expiration(reg.Duration), r)
verifyResult, verifyState, err := reg.VerifyChallengeToken(d.State.PublicKey(), key, r) verifyResult, verifyState, err := reg.VerifyChallengeToken(d.State.PublicKey(), key, r)
if err != nil && !errors.Is(err, http.ErrNoCookie) { if err != nil && !errors.Is(err, http.ErrNoCookie) {
// clear invalid cookie // clear invalid cookie
utils.ClearCookie(utils.CookiePrefix+reg.Name, w, r) utils.ClearCookie(d.CookiePrefix+reg.Name, w, r)
} }
// prevent evaluating the challenge if not solved // prevent evaluating the challenge if not solved
@@ -130,6 +144,11 @@ func (d *RequestData) EvaluateChallenges(w http.ResponseWriter, r *http.Request)
} }
} }
} }
if !verifyResult.Ok() && issuedChallenge == reg.Name {
// we issued the challenge, must skip to prevent loops
verifyResult = VerifyResultSkip
}
d.ChallengeVerify[reg.Id()] = verifyResult d.ChallengeVerify[reg.Id()] = verifyResult
d.ChallengeState[reg.Id()] = verifyState d.ChallengeState[reg.Id()] = verifyState
} }

View File

@@ -133,14 +133,14 @@ func FillRegistration(state challenge.StateInterface, reg *challenge.Registratio
if err != nil { if err != nil {
return challenge.VerifyResultFail return challenge.VerifyResultFail
} }
utils.SetCookie(utils.CookiePrefix+reg.Name, token, expiry, w, r) utils.SetCookie(data.CookiePrefix+reg.Name, token, expiry, w, r)
return challenge.VerifyResultNotOK return challenge.VerifyResultNotOK
} else { } else {
token, err := reg.IssueChallengeToken(state.PrivateKey(), key, nil, expiry, true) token, err := reg.IssueChallengeToken(state.PrivateKey(), key, nil, expiry, true)
if err != nil { if err != nil {
return challenge.VerifyResultFail return challenge.VerifyResultFail
} }
utils.SetCookie(utils.CookiePrefix+reg.Name, token, expiry, w, r) utils.SetCookie(data.CookiePrefix+reg.Name, token, expiry, w, r)
return challenge.VerifyResultOK return challenge.VerifyResultOK
} }
} }

View File

@@ -39,11 +39,13 @@ const VerifyChallengeUrlSuffix = "/verify-challenge"
func GetVerifyInformation(r *http.Request, reg *Registration) (requestId RequestId, redirect, token string, err error) { func GetVerifyInformation(r *http.Request, reg *Registration) (requestId RequestId, redirect, token string, err error) {
if r.FormValue(QueryArgChallenge) != reg.Name { q := r.URL.Query()
return RequestId{}, "", "", fmt.Errorf("unexpected challenge: got %s", r.FormValue(QueryArgChallenge))
if q.Get(QueryArgChallenge) != reg.Name {
return RequestId{}, "", "", fmt.Errorf("unexpected challenge: got %s", q.Get(QueryArgChallenge))
} }
requestIdHex := r.FormValue(QueryArgRequestId) requestIdHex := q.Get(QueryArgRequestId)
if len(requestId) != hex.DecodedLen(len(requestIdHex)) { if len(requestId) != hex.DecodedLen(len(requestIdHex)) {
return RequestId{}, "", "", errors.New("invalid request id") return RequestId{}, "", "", errors.New("invalid request id")
@@ -55,8 +57,8 @@ func GetVerifyInformation(r *http.Request, reg *Registration) (requestId Request
return RequestId{}, "", "", errors.New("invalid request id") return RequestId{}, "", "", errors.New("invalid request id")
} }
token = r.FormValue(QueryArgToken) token = q.Get(QueryArgToken)
redirect, err = utils.EnsureNoOpenRedirect(r.FormValue(QueryArgRedirect)) redirect, err = utils.EnsureNoOpenRedirect(q.Get(QueryArgRedirect))
if err != nil { if err != nil {
return RequestId{}, "", "", err return RequestId{}, "", "", err
} }
@@ -136,7 +138,7 @@ func VerifyHandlerFunc(state StateInterface, reg *Registration, verify VerifyFun
if err != nil { if err != nil {
return err return err
} else if !verifyResult.Ok() { } else if !verifyResult.Ok() {
utils.ClearCookie(utils.CookiePrefix+reg.Name, w, r) utils.ClearCookie(data.CookiePrefix+reg.Name, w, r)
state.ChallengeFailed(r, reg, nil, redirect, nil) state.ChallengeFailed(r, reg, nil, redirect, nil)
responseFunc(state, data, w, r, verifyResult, nil, redirect) responseFunc(state, data, w, r, verifyResult, nil, redirect)
return nil return nil
@@ -144,9 +146,9 @@ func VerifyHandlerFunc(state StateInterface, reg *Registration, verify VerifyFun
challengeToken, err := reg.IssueChallengeToken(state.PrivateKey(), key, []byte(token), expiration, true) challengeToken, err := reg.IssueChallengeToken(state.PrivateKey(), key, []byte(token), expiration, true)
if err != nil { if err != nil {
utils.ClearCookie(utils.CookiePrefix+reg.Name, w, r) utils.ClearCookie(data.CookiePrefix+reg.Name, w, r)
} else { } else {
utils.SetCookie(utils.CookiePrefix+reg.Name, challengeToken, expiration, w, r) utils.SetCookie(data.CookiePrefix+reg.Name, challengeToken, expiration, w, r)
} }
data.ChallengeVerify[reg.id] = verifyResult data.ChallengeVerify[reg.id] = verifyResult
state.ChallengePassed(r, reg, redirect, nil) state.ChallengePassed(r, reg, redirect, nil)
@@ -155,7 +157,7 @@ func VerifyHandlerFunc(state StateInterface, reg *Registration, verify VerifyFun
return nil return nil
}() }()
if err != nil { if err != nil {
utils.ClearCookie(utils.CookiePrefix+reg.Name, w, r) utils.ClearCookie(data.CookiePrefix+reg.Name, w, r)
state.ChallengeFailed(r, reg, err, redirect, nil) state.ChallengeFailed(r, reg, err, redirect, nil)
responseFunc(state, data, w, r, VerifyResultFail, fmt.Errorf("access denied: error in challenge %s: %w", reg.Name, err), redirect) responseFunc(state, data, w, r, VerifyResultFail, fmt.Errorf("access denied: error in challenge %s: %w", reg.Name, err), redirect)
return return

View File

@@ -137,19 +137,21 @@ func FillRegistration(state challenge.StateInterface, reg *challenge.Registratio
defer response.Body.Close() defer response.Body.Close()
defer io.Copy(io.Discard, response.Body) defer io.Copy(io.Discard, response.Body)
data := challenge.RequestDataFromContext(r.Context())
if response.StatusCode != params.HttpCode { if response.StatusCode != params.HttpCode {
token, err := reg.IssueChallengeToken(state.PrivateKey(), key, sum, expiry, false) token, err := reg.IssueChallengeToken(state.PrivateKey(), key, sum, expiry, false)
if err != nil { if err != nil {
return challenge.VerifyResultFail return challenge.VerifyResultFail
} }
utils.SetCookie(utils.CookiePrefix+reg.Name, token, expiry, w, r) utils.SetCookie(data.CookiePrefix+reg.Name, token, expiry, w, r)
return challenge.VerifyResultNotOK return challenge.VerifyResultNotOK
} else { } else {
token, err := reg.IssueChallengeToken(state.PrivateKey(), key, sum, expiry, true) token, err := reg.IssueChallengeToken(state.PrivateKey(), key, sum, expiry, true)
if err != nil { if err != nil {
return challenge.VerifyResultFail return challenge.VerifyResultFail
} }
utils.SetCookie(utils.CookiePrefix+reg.Name, token, expiry, w, r) utils.SetCookie(data.CookiePrefix+reg.Name, token, expiry, w, r)
return challenge.VerifyResultOK return challenge.VerifyResultOK
} }
} }

View File

@@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"git.gammaspectra.live/git/go-away/lib/condition" "git.gammaspectra.live/git/go-away/lib/condition"
"git.gammaspectra.live/git/go-away/lib/policy" "git.gammaspectra.live/git/go-away/lib/policy"
"git.gammaspectra.live/git/go-away/utils"
"github.com/go-jose/go-jose/v4" "github.com/go-jose/go-jose/v4"
"github.com/go-jose/go-jose/v4/jwt" "github.com/go-jose/go-jose/v4/jwt"
"github.com/goccy/go-yaml/ast" "github.com/goccy/go-yaml/ast"
@@ -193,7 +192,7 @@ var ErrVerifyVerifyMismatch = errors.New("verify: verification mismatch")
var ErrTokenExpired = errors.New("token: expired") var ErrTokenExpired = errors.New("token: expired")
func (reg Registration) VerifyChallengeToken(publicKey ed25519.PublicKey, expectedKey Key, r *http.Request) (VerifyResult, VerifyState, error) { func (reg Registration) VerifyChallengeToken(publicKey ed25519.PublicKey, expectedKey Key, r *http.Request) (VerifyResult, VerifyState, error) {
cookie, err := r.Cookie(utils.CookiePrefix + reg.Name) cookie, err := r.Cookie(RequestDataFromContext(r.Context()).CookiePrefix + reg.Name)
if err != nil { if err != nil {
return VerifyResultNone, VerifyStateNone, err return VerifyResultNone, VerifyStateNone, err
} }

View File

@@ -154,5 +154,5 @@ func NewMIMEMap(m textproto.MIMEHeader) traits.Mapper {
} }
func NewValuesMap(m map[string][]string) traits.Mapper { func NewValuesMap(m map[string][]string) traits.Mapper {
return mimeLike{m: m} return valuesLike{m: m}
} }

View File

@@ -96,11 +96,12 @@ func (state *State) handleRequest(w http.ResponseWriter, r *http.Request) {
if fromChallenge { if fromChallenge {
r.Header.Del("Referer") r.Header.Del("Referer")
} }
if ref := r.FormValue(challenge.QueryArgReferer); ref != "" { q := r.URL.Query()
if ref := q.Get(challenge.QueryArgReferer); ref != "" {
r.Header.Set("Referer", ref) r.Header.Set("Referer", ref)
} }
q := r.URL.Query()
// delete query parameters that were set by go-away // delete query parameters that were set by go-away
for k := range q { for k := range q {
if strings.HasPrefix(k, challenge.QueryArgPrefix) { if strings.HasPrefix(k, challenge.QueryArgPrefix) {