From 0ca8e277f96c0f6fae227e0a52b02ae839b10642 Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:35:34 +0200 Subject: [PATCH] Patches to bring compatibility to Go 1.22 * Disabled container building * No TLS Fingerprinting * HTTP/2 H2C uses golang.org/x/net/http2/h2c * html DOM walking uses custom function instead of iterator * Pinned these packages to latest compatible releases: * github.com/go-jose/go-jose/v4 v4.0.5 * golang.org/x/crypto v0.33.0 * golang.org/x/net v0.37.0 * golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac * golang.org/x/text v0.22.0 * google.golang.org/genproto/googleapis v0.0.0-20240826202546-f6391c0de4c7 --- .drone.jsonnet | 21 +- .drone.yml | 397 ++---------------------------------- go.mod | 36 ++-- go.sum | 36 ++-- lib/challenge/data.go | 8 +- utils/fingerprint.go | 256 ----------------------- utils/fingerprint_modern.go | 269 ++++++++++++++++++++++++ utils/http.go | 21 -- utils/http_legacy.go | 28 +++ utils/http_modern.go | 29 +++ utils/tagfetcher.go | 11 +- 11 files changed, 403 insertions(+), 709 deletions(-) create mode 100644 utils/fingerprint_modern.go create mode 100644 utils/http_legacy.go create mode 100644 utils/http_modern.go diff --git a/.drone.jsonnet b/.drone.jsonnet index 7dbcabe..6084050 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -138,25 +138,12 @@ local Publish(mirror, registry, repo, secret, go, alpine, os, arch, trigger, pla # local containerArchitectures = ["linux/amd64", "linux/arm64", "linux/riscv64"]; -local alpineVersion = "3.21"; -local goVersion = "1.24"; +local alpineVersion = "3.20"; +local goVersion = "1.22"; local mirror = "https://mirror.gcr.io"; [ - Build(mirror, goVersion, alpineVersion, "linux", "amd64") + {"trigger": {event: ["push", "tag"], }}, - Build(mirror, goVersion, alpineVersion, "linux", "arm64") + {"trigger": {event: ["push", "tag"], }}, - - # Test PRs - Build(mirror, goVersion, alpineVersion, "linux", "amd64") + {"name": "test-pr", "trigger": {event: ["pull_request"], }}, - - # latest - 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(mirror, "codeberg.org", "codeberg.org/gone/go-away", "codeberg", goVersion, alpineVersion, "linux", "amd64", {event: ["push"], branch: ["master"], }, containerArchitectures, {tags: ["latest"],}) + {name: "publish-latest-codeberg"}, - 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 - 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(mirror, "codeberg.org", "codeberg.org/gone/go-away", "codeberg", 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,}), + Build(mirror, goVersion, alpineVersion, "linux", "amd64"), + Build(mirror, goVersion, alpineVersion, "linux", "arm64"), ] \ No newline at end of file diff --git a/.drone.yml b/.drone.yml index e74b2d3..48ab3d8 100644 --- a/.drone.yml +++ b/.drone.yml @@ -5,7 +5,7 @@ environment: GOOS: linux GOTOOLCHAIN: local kind: pipeline -name: build-1.24-alpine3.21-amd64 +name: build-1.22-alpine3.20-amd64 platform: arch: amd64 os: linux @@ -16,7 +16,7 @@ steps: - mkdir .bin - 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 - image: golang:1.24-alpine3.21 + image: golang:1.22-alpine3.20 mirror: https://mirror.gcr.io name: build - commands: @@ -24,7 +24,7 @@ steps: --policy examples/forgejo.yml --policy-snippets examples/snippets/ depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: check-policy-forgejo - commands: @@ -32,7 +32,7 @@ steps: --policy examples/generic.yml --policy-snippets examples/snippets/ depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: check-policy-generic - commands: @@ -40,7 +40,7 @@ steps: --policy examples/spa.yml --policy-snippets examples/snippets/ depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: check-policy-spa - commands: @@ -51,7 +51,7 @@ steps: 0 depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: test-wasm-success - commands: @@ -62,13 +62,9 @@ steps: 1 depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: test-wasm-fail -trigger: - event: - - push - - tag type: docker --- environment: @@ -77,7 +73,7 @@ environment: GOOS: linux GOTOOLCHAIN: local kind: pipeline -name: build-1.24-alpine3.21-arm64 +name: build-1.22-alpine3.20-arm64 platform: arch: arm64 os: linux @@ -88,7 +84,7 @@ steps: - mkdir .bin - 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 - image: golang:1.24-alpine3.21 + image: golang:1.22-alpine3.20 mirror: https://mirror.gcr.io name: build - commands: @@ -96,7 +92,7 @@ steps: --policy examples/forgejo.yml --policy-snippets examples/snippets/ depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: check-policy-forgejo - commands: @@ -104,7 +100,7 @@ steps: --policy examples/generic.yml --policy-snippets examples/snippets/ depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: check-policy-generic - commands: @@ -112,7 +108,7 @@ steps: --policy examples/spa.yml --policy-snippets examples/snippets/ depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: check-policy-spa - commands: @@ -123,7 +119,7 @@ steps: 0 depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: test-wasm-success - commands: @@ -134,375 +130,12 @@ steps: 1 depends_on: - build - image: alpine:3.21 + image: alpine:3.20 mirror: https://mirror.gcr.io name: test-wasm-fail -trigger: - event: - - push - - tag -type: docker ---- -environment: - CGO_ENABLED: "0" - GOARCH: amd64 - GOOS: linux - GOTOOLCHAIN: local -kind: pipeline -name: test-pr -platform: - arch: amd64 - os: linux -steps: -- commands: - - apk update - - apk add --no-cache git - - mkdir .bin - - 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 - image: golang:1.24-alpine3.21 - mirror: https://mirror.gcr.io - name: build -- 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/ - depends_on: - - build - image: alpine:3.21 - mirror: https://mirror.gcr.io - name: check-policy-forgejo -- 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/ - depends_on: - - build - image: alpine:3.21 - mirror: https://mirror.gcr.io - name: check-policy-generic -- commands: - - ./.bin/go-away --check --slog-level DEBUG --backend example.com=http://127.0.0.1:80 - --policy examples/spa.yml --policy-snippets examples/snippets/ - depends_on: - - build - image: alpine:3.21 - mirror: https://mirror.gcr.io - name: check-policy-spa -- commands: - - ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm - -make-challenge ./embed/challenge/js-pow-sha256/test/make-challenge.json -make-challenge-out - ./embed/challenge/js-pow-sha256/test/make-challenge-out.json -verify-challenge - ./embed/challenge/js-pow-sha256/test/verify-challenge.json -verify-challenge-out - 0 - depends_on: - - build - image: alpine:3.21 - mirror: https://mirror.gcr.io - name: test-wasm-success -- commands: - - ./.bin/test-wasm-runtime -wasm ./embed/challenge/js-pow-sha256/runtime/runtime.wasm - -make-challenge ./embed/challenge/js-pow-sha256/test/make-challenge.json -make-challenge-out - ./embed/challenge/js-pow-sha256/test/make-challenge-out.json -verify-challenge - ./embed/challenge/js-pow-sha256/test/verify-challenge-fail.json -verify-challenge-out - 1 - depends_on: - - build - image: alpine:3.21 - mirror: https://mirror.gcr.io - name: test-wasm-fail -trigger: - event: - - pull_request -type: docker ---- -kind: pipeline -name: publish-latest-git -platform: - arch: amd64 - os: linux -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: - DOCKER_BUILDKIT: "1" - LC_ALL: C - PLUGIN_BUILDER_CONFIG: buildkitd.toml - PLUGIN_BUILDER_DRIVER: docker-container - SOURCE_DATE_EPOCH: 0 - TZ: UTC - image: plugins/buildx - name: docker - privileged: true - settings: - auto_tag_suffix: alpine3.21 - build_args: - from: alpine:3.21 - from_builder: golang:1.24-alpine3.21 - compress: true - mirror: https://mirror.gcr.io - password: - from_secret: git_password - platform: - - linux/amd64 - - linux/arm64 - - linux/riscv64 - registry: git.gammaspectra.live - repo: git.gammaspectra.live/git/go-away - tags: - - latest - username: - from_secret: git_username -trigger: - branch: - - master - event: - - push -type: docker ---- -kind: pipeline -name: publish-latest-codeberg -platform: - arch: amd64 - os: linux -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: - DOCKER_BUILDKIT: "1" - LC_ALL: C - PLUGIN_BUILDER_CONFIG: buildkitd.toml - PLUGIN_BUILDER_DRIVER: docker-container - SOURCE_DATE_EPOCH: 0 - TZ: UTC - image: plugins/buildx - name: docker - privileged: true - settings: - auto_tag_suffix: alpine3.21 - build_args: - from: alpine:3.21 - from_builder: golang:1.24-alpine3.21 - compress: true - mirror: https://mirror.gcr.io - password: - from_secret: codeberg_password - platform: - - linux/amd64 - - linux/arm64 - - linux/riscv64 - registry: codeberg.org - repo: codeberg.org/gone/go-away - tags: - - latest - username: - from_secret: codeberg_username -trigger: - branch: - - master - event: - - push -type: docker ---- -kind: pipeline -name: publish-latest-github -platform: - arch: amd64 - os: linux -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: - DOCKER_BUILDKIT: "1" - LC_ALL: C - PLUGIN_BUILDER_CONFIG: buildkitd.toml - PLUGIN_BUILDER_DRIVER: docker-container - SOURCE_DATE_EPOCH: 0 - TZ: UTC - image: plugins/buildx - name: docker - privileged: true - settings: - auto_tag_suffix: alpine3.21 - build_args: - from: alpine:3.21 - from_builder: golang:1.24-alpine3.21 - compress: true - mirror: https://mirror.gcr.io - password: - from_secret: github_password - platform: - - linux/amd64 - - linux/arm64 - - linux/riscv64 - registry: ghcr.io - repo: ghcr.io/weebdatahoarder/go-away - tags: - - latest - username: - from_secret: github_username -trigger: - branch: - - master - event: - - push -type: docker ---- -kind: pipeline -name: publish-1.24-alpine3.21-git -platform: - arch: amd64 - os: linux -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: - DOCKER_BUILDKIT: "1" - LC_ALL: C - PLUGIN_BUILDER_CONFIG: buildkitd.toml - PLUGIN_BUILDER_DRIVER: docker-container - SOURCE_DATE_EPOCH: 0 - TZ: UTC - image: plugins/buildx - name: docker - privileged: true - settings: - auto_tag: true - auto_tag_suffix: alpine3.21 - build_args: - from: alpine:3.21 - from_builder: golang:1.24-alpine3.21 - compress: true - mirror: https://mirror.gcr.io - password: - from_secret: git_password - platform: - - linux/amd64 - - linux/arm64 - - linux/riscv64 - registry: git.gammaspectra.live - repo: git.gammaspectra.live/git/go-away - username: - from_secret: git_username -trigger: - event: - - promote - - tag - target: - - production -type: docker ---- -kind: pipeline -name: publish-1.24-alpine3.21-codeberg -platform: - arch: amd64 - os: linux -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: - DOCKER_BUILDKIT: "1" - LC_ALL: C - PLUGIN_BUILDER_CONFIG: buildkitd.toml - PLUGIN_BUILDER_DRIVER: docker-container - SOURCE_DATE_EPOCH: 0 - TZ: UTC - image: plugins/buildx - name: docker - privileged: true - settings: - auto_tag: true - auto_tag_suffix: alpine3.21 - build_args: - from: alpine:3.21 - from_builder: golang:1.24-alpine3.21 - compress: true - mirror: https://mirror.gcr.io - password: - from_secret: codeberg_password - platform: - - linux/amd64 - - linux/arm64 - - linux/riscv64 - registry: codeberg.org - repo: codeberg.org/gone/go-away - username: - from_secret: codeberg_username -trigger: - event: - - promote - - tag - target: - - production -type: docker ---- -kind: pipeline -name: publish-1.24-alpine3.21-github -platform: - arch: amd64 - os: linux -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: - DOCKER_BUILDKIT: "1" - LC_ALL: C - PLUGIN_BUILDER_CONFIG: buildkitd.toml - PLUGIN_BUILDER_DRIVER: docker-container - SOURCE_DATE_EPOCH: 0 - TZ: UTC - image: plugins/buildx - name: docker - privileged: true - settings: - auto_tag: true - auto_tag_suffix: alpine3.21 - build_args: - from: alpine:3.21 - from_builder: golang:1.24-alpine3.21 - compress: true - mirror: https://mirror.gcr.io - password: - from_secret: github_password - platform: - - linux/amd64 - - linux/arm64 - - linux/riscv64 - registry: ghcr.io - repo: ghcr.io/weebdatahoarder/go-away - username: - from_secret: github_username -trigger: - event: - - promote - - tag - target: - - production type: docker --- kind: signature -hmac: df53e4ea6f1c47df4d2a3f89b931b8513e83daa9c6c15baba2662d8112a721c8 +hmac: 00be8252a86e2c760c07c2baa6efa55d75f46fdc22299bb3feb1b199cc54af9e ... diff --git a/go.mod b/go.mod index 509ce14..32fa4af 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,12 @@ module git.gammaspectra.live/git/go-away -go 1.24.0 - -toolchain go1.24.2 +go 1.22.12 require ( codeberg.org/gone/http-cel v1.0.0 codeberg.org/meta/gzipped/v2 v2.0.0-20231111234332-aa70c3194756 github.com/alphadose/haxmap v1.4.1 - github.com/go-jose/go-jose/v4 v4.1.0 + github.com/go-jose/go-jose/v4 v4.0.5 github.com/goccy/go-yaml v1.17.1 github.com/google/cel-go v0.25.0 github.com/itchyny/gojq v0.12.17 @@ -16,7 +14,8 @@ require ( github.com/prometheus/client_golang v1.22.0 github.com/tetratelabs/wazero v1.9.0 github.com/yl2chen/cidranger v1.0.2 - golang.org/x/crypto v0.37.0 + golang.org/x/crypto v0.33.0 + golang.org/x/net v0.37.0 ) require ( @@ -29,13 +28,26 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.16.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect - golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect + golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect google.golang.org/protobuf v1.36.6 // indirect ) + +// Pin latest versions to support Go 1.22 to prevent a package update from changing them +// TODO: remove this when Go 1.22+ is supported by other downstream users +replace ( + github.com/go-jose/go-jose/v4 => github.com/go-jose/go-jose/v4 v4.0.5 + github.com/prometheus/procfs => github.com/prometheus/procfs v0.15.1 + golang.org/x/crypto => golang.org/x/crypto v0.33.0 + golang.org/x/exp => golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac + golang.org/x/net => golang.org/x/net v0.35.0 + golang.org/x/sys => golang.org/x/sys v0.30.0 + golang.org/x/text => golang.org/x/text v0.22.0 + google.golang.org/genproto/googleapis/api => google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 + google.golang.org/genproto/googleapis/rpc => google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 +) diff --git a/go.sum b/go.sum index b1e74f6..1fb7cc8 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY= -github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY= github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY= @@ -45,8 +45,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -62,20 +62,20 @@ github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZB github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU= github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f h1:tjZsroqekhC63+WMqzmWyW5Twj/ZfR5HAlpd5YQ1Vs0= -google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:Cd8IzgPo5Akum2c9R6FsXNaZbH3Jpa2gpHlW89FqlyQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f h1:N/PrbTw4kdkqNRzVfWPrBekzLuarFREcbFOiOLkXon4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= +golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 h1:YcyjlL1PRr2Q17/I0dPk2JmYS5CDXfcdb2Z3YRioEbw= +google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 h1:2035KHhUv+EpyB+hWgJnaWKJOdX1E95w2S8Rr4uWKTs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/lib/challenge/data.go b/lib/challenge/data.go index bb4936e..b65a4be 100644 --- a/lib/challenge/data.go +++ b/lib/challenge/data.go @@ -433,7 +433,13 @@ func (d *RequestData) verifyChallengeStateCookie(cookie *http.Cookie) (TokenChal } func (d *RequestData) verifyChallengeState() (state TokenChallengeMap, err error) { - cookies := d.r.CookiesNamed(d.cookieName) + var cookies []*http.Cookie + for _, cookie := range d.r.Cookies() { + if cookie.Name == d.cookieName { + cookies = append(cookies, cookie) + } + } + if len(cookies) == 0 { return nil, http.ErrNoCookie } diff --git a/utils/fingerprint.go b/utils/fingerprint.go index c717664..55f4bae 100644 --- a/utils/fingerprint.go +++ b/utils/fingerprint.go @@ -1,48 +1,13 @@ package utils import ( - "context" "crypto/md5" - "crypto/sha256" - "crypto/tls" "encoding/hex" - "fmt" - "net" "net/http" - "slices" - "strconv" "strings" "sync/atomic" ) -func applyTLSFingerprinter(server *http.Server) { - if server.TLSConfig == nil { - return - } - server.TLSConfig = server.TLSConfig.Clone() - - getConfigForClient := server.TLSConfig.GetConfigForClient - - if getConfigForClient == nil { - getConfigForClient = func(info *tls.ClientHelloInfo) (*tls.Config, error) { - return nil, nil - } - } - - server.TLSConfig.GetConfigForClient = func(clientHello *tls.ClientHelloInfo) (*tls.Config, error) { - ja3n, ja4 := buildTLSFingerprint(clientHello) - ptr := clientHello.Context().Value(tlsFingerprintKey{}) - if fpPtr, ok := ptr.(*TLSFingerprint); ok && ptr != nil && fpPtr != nil { - fpPtr.ja3n.Store(&ja3n) - fpPtr.ja4.Store(&ja4) - } - return getConfigForClient(clientHello) - } - server.ConnContext = func(ctx context.Context, c net.Conn) context.Context { - return context.WithValue(ctx, tlsFingerprintKey{}, &TLSFingerprint{}) - } -} - type tlsFingerprintKey struct{} type TLSFingerprint struct { ja3n atomic.Pointer[TLSFingerprintJA3N] @@ -105,227 +70,6 @@ const ( extensionEncryptedClientHello uint16 = 0xfe0d ) -func tlsFingerprintJA3(hello *tls.ClientHelloInfo, sortExtensions bool) []byte { - buf := make([]byte, 0, 256) - - { - var sslVersion uint16 - var hasGrease bool - for _, v := range hello.SupportedVersions { - if v&greaseMask != greaseValue { - if v > sslVersion { - sslVersion = v - } - } else { - hasGrease = true - } - } - - // maximum TLS 1.2 as specified on JA3, as TLS 1.3 is put in SupportedVersions - if slices.Contains(hello.Extensions, extensionSupportedVersions) && hasGrease && sslVersion > tls.VersionTLS12 { - sslVersion = tls.VersionTLS12 - } - - buf = strconv.AppendUint(buf, uint64(sslVersion), 10) - buf = append(buf, ',') - } - - n := 0 - for _, cipher := range hello.CipherSuites { - //if !slices.Contains(greaseValues[:], cipher) { - if cipher&greaseMask != greaseValue { - buf = strconv.AppendUint(buf, uint64(cipher), 10) - buf = append(buf, '-') - n = 1 - } - } - - buf = buf[:len(buf)-n] - buf = append(buf, ',') - n = 0 - - extensions := hello.Extensions - if sortExtensions { - extensions = slices.Clone(extensions) - slices.Sort(extensions) - } - - for _, extension := range extensions { - if extension&greaseMask != greaseValue { - buf = strconv.AppendUint(buf, uint64(extension), 10) - buf = append(buf, '-') - n = 1 - } - } - - buf = buf[:len(buf)-n] - buf = append(buf, ',') - n = 0 - - for _, curve := range hello.SupportedCurves { - if curve&greaseMask != greaseValue { - buf = strconv.AppendUint(buf, uint64(curve), 10) - buf = append(buf, '-') - n = 1 - } - } - - buf = buf[:len(buf)-n] - buf = append(buf, ',') - n = 0 - - for _, point := range hello.SupportedPoints { - buf = strconv.AppendUint(buf, uint64(point), 10) - buf = append(buf, '-') - n = 1 - } - - buf = buf[:len(buf)-n] - - sum := md5.Sum(buf) - return sum[:] -} - -func tlsFingerprintJA4(hello *tls.ClientHelloInfo) (ja4 TLSFingerprintJA4) { - buf := make([]byte, 0, 10) - - // TODO: t = TLS, q = QUIC - buf = append(buf, 't') - - { - var sslVersion uint16 - for _, v := range hello.SupportedVersions { - if v&greaseMask != greaseValue { - if v > sslVersion { - sslVersion = v - } - } - } - - switch sslVersion { - case tls.VersionSSL30: - buf = append(buf, 's', '3') - case tls.VersionTLS10: - buf = append(buf, '1', '0') - case tls.VersionTLS11: - buf = append(buf, '1', '1') - case tls.VersionTLS12: - buf = append(buf, '1', '2') - case tls.VersionTLS13: - buf = append(buf, '1', '3') - default: - sslVersion -= 0x0201 - buf = strconv.AppendUint(buf, uint64(sslVersion>>8), 10) - buf = strconv.AppendUint(buf, uint64(sslVersion&0xff), 10) - } - - } - - if slices.Contains(hello.Extensions, extensionServerName) && hello.ServerName != "" { - buf = append(buf, 'd') - } else { - buf = append(buf, 'i') - } - - ciphers := make([]uint16, 0, len(hello.CipherSuites)) - for _, cipher := range hello.CipherSuites { - if cipher&greaseMask != greaseValue { - ciphers = append(ciphers, cipher) - } - } - - extensionCount := 0 - extensions := make([]uint16, 0, len(hello.Extensions)) - for _, extension := range hello.Extensions { - if extension&greaseMask != greaseValue { - extensionCount++ - if extension != extensionALPN && extension != extensionServerName { - extensions = append(extensions, extension) - } - } - } - - schemes := make([]tls.SignatureScheme, 0, len(hello.SignatureSchemes)) - - for _, scheme := range hello.SignatureSchemes { - if scheme&greaseMask != greaseValue { - schemes = append(schemes, scheme) - } - } - - //TODO: maybe little endian - slices.Sort(ciphers) - slices.Sort(extensions) - //slices.Sort(schemes) - - if len(ciphers) < 10 { - buf = append(buf, '0') - buf = strconv.AppendUint(buf, uint64(len(ciphers)), 10) - } else if len(ciphers) > 99 { - buf = append(buf, '9', '9') - } else { - buf = strconv.AppendUint(buf, uint64(len(ciphers)), 10) - } - - if extensionCount < 10 { - buf = append(buf, '0') - buf = strconv.AppendUint(buf, uint64(extensionCount), 10) - } else if extensionCount > 99 { - buf = append(buf, '9', '9') - } else { - buf = strconv.AppendUint(buf, uint64(extensionCount), 10) - } - - if len(hello.SupportedProtos) > 0 && len(hello.SupportedProtos[0]) > 1 { - buf = append(buf, hello.SupportedProtos[0][0], hello.SupportedProtos[0][len(hello.SupportedProtos[0])-1]) - } else { - buf = append(buf, '0', '0') - } - - copy(ja4.A[:], buf) - - ja4.B = ja4SHA256(uint16SliceToHex(ciphers)) - - extBuf := uint16SliceToHex(extensions) - - if len(schemes) > 0 { - extBuf = append(extBuf, '_') - extBuf = append(extBuf, uint16SliceToHex(schemes)...) - } - - ja4.C = ja4SHA256(extBuf) - - return ja4 -} - -func uint16SliceToHex[T ~uint16](in []T) (out []byte) { - if len(in) == 0 { - return out - } - out = slices.Grow(out, hex.EncodedLen(len(in)*2)+len(in)) - - for _, n := range in { - out = append(out, fmt.Sprintf("%04x", uint16(n))...) - out = append(out, ',') - } - out = out[:len(out)-1] - - return out -} - -func ja4SHA256(buf []byte) [6]byte { - if len(buf) == 0 { - return [6]byte{0, 0, 0, 0, 0, 0} - } - sum := sha256.Sum256(buf) - - return [6]byte(sum[:6]) -} - -func buildTLSFingerprint(hello *tls.ClientHelloInfo) (ja3n TLSFingerprintJA3N, ja4 TLSFingerprintJA4) { - return TLSFingerprintJA3N(tlsFingerprintJA3(hello, true)), tlsFingerprintJA4(hello) -} - func GetTLSFingerprint(r *http.Request) *TLSFingerprint { ptr := r.Context().Value(tlsFingerprintKey{}) if fpPtr, ok := ptr.(*TLSFingerprint); ok && ptr != nil && fpPtr != nil { diff --git a/utils/fingerprint_modern.go b/utils/fingerprint_modern.go new file mode 100644 index 0000000..befbeca --- /dev/null +++ b/utils/fingerprint_modern.go @@ -0,0 +1,269 @@ +//go:build !go1.22 && !go1.23 + +package utils + +import ( + "context" + "crypto/md5" + "crypto/sha256" + "crypto/tls" + "encoding/hex" + "fmt" + "net" + "net/http" + "slices" + "strconv" +) + +func applyTLSFingerprinter(server *http.Server) { + server.TLSConfig = server.TLSConfig.Clone() + + getCertificate := server.TLSConfig.GetCertificate + if getCertificate == nil { + server.TLSConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { + ja3n, ja4 := buildTLSFingerprint(clientHello) + ptr := clientHello.Context().Value(tlsFingerprintKey{}) + if fpPtr, ok := ptr.(*TLSFingerprint); ok && ptr != nil && fpPtr != nil { + fpPtr.ja3n.Store(&ja3n) + fpPtr.ja4.Store(&ja4) + } + + return nil, nil + } + } else { + server.TLSConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { + ja3n, ja4 := buildTLSFingerprint(clientHello) + ptr := clientHello.Context().Value(tlsFingerprintKey{}) + if fpPtr, ok := ptr.(*TLSFingerprint); ok && ptr != nil && fpPtr != nil { + fpPtr.ja3n.Store(&ja3n) + fpPtr.ja4.Store(&ja4) + } + + return getCertificate(clientHello) + } + } + server.ConnContext = func(ctx context.Context, c net.Conn) context.Context { + return context.WithValue(ctx, tlsFingerprintKey{}, &TLSFingerprint{}) + } +} + +func tlsFingerprintJA3(hello *tls.ClientHelloInfo, sortExtensions bool) []byte { + buf := make([]byte, 0, 256) + + { + var sslVersion uint16 + var hasGrease bool + for _, v := range hello.SupportedVersions { + if v&greaseMask != greaseValue { + if v > sslVersion { + sslVersion = v + } + } else { + hasGrease = true + } + } + + // maximum TLS 1.2 as specified on JA3, as TLS 1.3 is put in SupportedVersions + if slices.Contains(hello.Extensions, extensionSupportedVersions) && hasGrease && sslVersion > tls.VersionTLS12 { + sslVersion = tls.VersionTLS12 + } + + buf = strconv.AppendUint(buf, uint64(sslVersion), 10) + buf = append(buf, ',') + } + + n := 0 + for _, cipher := range hello.CipherSuites { + //if !slices.Contains(greaseValues[:], cipher) { + if cipher&greaseMask != greaseValue { + buf = strconv.AppendUint(buf, uint64(cipher), 10) + buf = append(buf, '-') + n = 1 + } + } + + buf = buf[:len(buf)-n] + buf = append(buf, ',') + n = 0 + + extensions := hello.Extensions + if sortExtensions { + extensions = slices.Clone(extensions) + slices.Sort(extensions) + } + + for _, extension := range extensions { + if extension&greaseMask != greaseValue { + buf = strconv.AppendUint(buf, uint64(extension), 10) + buf = append(buf, '-') + n = 1 + } + } + + buf = buf[:len(buf)-n] + buf = append(buf, ',') + n = 0 + + for _, curve := range hello.SupportedCurves { + if curve&greaseMask != greaseValue { + buf = strconv.AppendUint(buf, uint64(curve), 10) + buf = append(buf, '-') + n = 1 + } + } + + buf = buf[:len(buf)-n] + buf = append(buf, ',') + n = 0 + + for _, point := range hello.SupportedPoints { + buf = strconv.AppendUint(buf, uint64(point), 10) + buf = append(buf, '-') + n = 1 + } + + buf = buf[:len(buf)-n] + + sum := md5.Sum(buf) + return sum[:] +} + +func tlsFingerprintJA4(hello *tls.ClientHelloInfo) (ja4 TLSFingerprintJA4) { + buf := make([]byte, 0, 10) + + // TODO: t = TLS, q = QUIC + buf = append(buf, 't') + + { + var sslVersion uint16 + for _, v := range hello.SupportedVersions { + if v&greaseMask != greaseValue { + if v > sslVersion { + sslVersion = v + } + } + } + + switch sslVersion { + case tls.VersionSSL30: + buf = append(buf, 's', '3') + case tls.VersionTLS10: + buf = append(buf, '1', '0') + case tls.VersionTLS11: + buf = append(buf, '1', '1') + case tls.VersionTLS12: + buf = append(buf, '1', '2') + case tls.VersionTLS13: + buf = append(buf, '1', '3') + default: + sslVersion -= 0x0201 + buf = strconv.AppendUint(buf, uint64(sslVersion>>8), 10) + buf = strconv.AppendUint(buf, uint64(sslVersion&0xff), 10) + } + + } + + if slices.Contains(hello.Extensions, extensionServerName) && hello.ServerName != "" { + buf = append(buf, 'd') + } else { + buf = append(buf, 'i') + } + + ciphers := make([]uint16, 0, len(hello.CipherSuites)) + for _, cipher := range hello.CipherSuites { + if cipher&greaseMask != greaseValue { + ciphers = append(ciphers, cipher) + } + } + + extensionCount := 0 + extensions := make([]uint16, 0, len(hello.Extensions)) + for _, extension := range hello.Extensions { + if extension&greaseMask != greaseValue { + extensionCount++ + if extension != extensionALPN && extension != extensionServerName { + extensions = append(extensions, extension) + } + } + } + + schemes := make([]tls.SignatureScheme, 0, len(hello.SignatureSchemes)) + + for _, scheme := range hello.SignatureSchemes { + if scheme&greaseMask != greaseValue { + schemes = append(schemes, scheme) + } + } + + //TODO: maybe little endian + slices.Sort(ciphers) + slices.Sort(extensions) + //slices.Sort(schemes) + + if len(ciphers) < 10 { + buf = append(buf, '0') + buf = strconv.AppendUint(buf, uint64(len(ciphers)), 10) + } else if len(ciphers) > 99 { + buf = append(buf, '9', '9') + } else { + buf = strconv.AppendUint(buf, uint64(len(ciphers)), 10) + } + + if extensionCount < 10 { + buf = append(buf, '0') + buf = strconv.AppendUint(buf, uint64(extensionCount), 10) + } else if extensionCount > 99 { + buf = append(buf, '9', '9') + } else { + buf = strconv.AppendUint(buf, uint64(extensionCount), 10) + } + + if len(hello.SupportedProtos) > 0 && len(hello.SupportedProtos[0]) > 1 { + buf = append(buf, hello.SupportedProtos[0][0], hello.SupportedProtos[0][len(hello.SupportedProtos[0])-1]) + } else { + buf = append(buf, '0', '0') + } + + copy(ja4.A[:], buf) + + ja4.B = ja4SHA256(uint16SliceToHex(ciphers)) + + extBuf := uint16SliceToHex(extensions) + + if len(schemes) > 0 { + extBuf = append(extBuf, '_') + extBuf = append(extBuf, uint16SliceToHex(schemes)...) + } + + ja4.C = ja4SHA256(extBuf) + + return ja4 +} + +func uint16SliceToHex[T ~uint16](in []T) (out []byte) { + if len(in) == 0 { + return out + } + out = slices.Grow(out, hex.EncodedLen(len(in)*2)+len(in)) + + for _, n := range in { + out = append(out, fmt.Sprintf("%04x", uint16(n))...) + out = append(out, ',') + } + out = out[:len(out)-1] + + return out +} + +func ja4SHA256(buf []byte) [6]byte { + if len(buf) == 0 { + return [6]byte{0, 0, 0, 0, 0, 0} + } + sum := sha256.Sum256(buf) + + return [6]byte(sum[:6]) +} + +func buildTLSFingerprint(hello *tls.ClientHelloInfo) (ja3n TLSFingerprintJA3N, ja4 TLSFingerprintJA4) { + return TLSFingerprintJA3N(tlsFingerprintJA3(hello, true)), tlsFingerprintJA4(hello) +} diff --git a/utils/http.go b/utils/http.go index e55e263..72d0bd2 100644 --- a/utils/http.go +++ b/utils/http.go @@ -16,27 +16,6 @@ import ( "time" ) -func NewServer(handler http.Handler, tlsConfig *tls.Config) *http.Server { - if tlsConfig == nil { - proto := new(http.Protocols) - proto.SetHTTP1(true) - proto.SetUnencryptedHTTP2(true) - h1s := &http.Server{ - Handler: handler, - Protocols: proto, - } - - return h1s - } else { - server := &http.Server{ - TLSConfig: tlsConfig, - Handler: handler, - } - applyTLSFingerprinter(server) - return server - } -} - func SelectHTTPHandler(backends map[string]http.Handler, host string) http.Handler { backend, ok := backends[host] if !ok { diff --git a/utils/http_legacy.go b/utils/http_legacy.go new file mode 100644 index 0000000..a817a79 --- /dev/null +++ b/utils/http_legacy.go @@ -0,0 +1,28 @@ +//go:build go1.22 || go1.23 + +package utils + +import ( + "crypto/tls" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "net/http" +) + +func NewServer(handler http.Handler, tlsConfig *tls.Config) *http.Server { + if tlsConfig == nil { + h2s := &http2.Server{} + + h1s := &http.Server{ + Handler: h2c.NewHandler(handler, h2s), + } + + return h1s + } else { + server := &http.Server{ + TLSConfig: tlsConfig, + Handler: handler, + } + return server + } +} diff --git a/utils/http_modern.go b/utils/http_modern.go new file mode 100644 index 0000000..f8d9c82 --- /dev/null +++ b/utils/http_modern.go @@ -0,0 +1,29 @@ +//go:build !go1.22 && !go1.23 + +package utils + +import ( + "crypto/tls" + "net/http" +) + +func NewServer(handler http.Handler, tlsConfig *tls.Config) *http.Server { + if tlsConfig == nil { + proto := new(http.Protocols) + proto.SetHTTP1(true) + proto.SetUnencryptedHTTP2(true) + h1s := &http.Server{ + Handler: handler, + Protocols: proto, + } + + return h1s + } else { + server := &http.Server{ + TLSConfig: tlsConfig, + Handler: handler, + } + applyTLSFingerprinter(server) + return server + } +} diff --git a/utils/tagfetcher.go b/utils/tagfetcher.go index 00c59a0..4191173 100644 --- a/utils/tagfetcher.go +++ b/utils/tagfetcher.go @@ -39,7 +39,7 @@ func FetchTags(backend http.Handler, uri *url.URL, kinds ...string) (result []ht return nil } - for n := range node.Descendants() { + descendants(node, func(n *html.Node) { if n.Type == html.ElementNode && slices.Contains(kinds, n.Data) { result = append(result, html.Node{ Type: n.Type, @@ -49,7 +49,14 @@ func FetchTags(backend http.Handler, uri *url.URL, kinds ...string) (result []ht Attr: n.Attr, }) } - } + }) return result } + +func descendants(n *html.Node, f func(n *html.Node)) { + f(n) + for c := n.FirstChild; c != nil; c = c.NextSibling { + descendants(c, f) + } +}