10 Commits

Author SHA1 Message Date
8beb22a93b no more needs
All checks were successful
CI/CD Pipeline / publish (push) Successful in 24m58s
2025-07-25 11:00:59 +05:30
b28d39ab74 fix ci
Some checks failed
CI/CD Pipeline / publish (push) Has been cancelled
2025-07-24 16:58:21 +05:30
158462136b CI attempt Uno
Some checks failed
CI/CD Pipeline / build (amd64) (push) Failing after 3m35s
CI/CD Pipeline / build (arm64) (push) Failing after 29s
CI/CD Pipeline / publish (push) Has been skipped
2025-07-22 14:05:51 +01:00
458022b3c2 Was that reaaaaaaally necessary?
Defining full path don't work and cause a panic, I'll have to patch that
up.
2025-07-19 03:14:54 +01:00
WeebDataHoarder
e1a318bc38 build/wasm: update script to build TinyGo v0.38.0, update resulting js-pow-sha256 wasm artifact 2025-07-03 02:41:50 +02:00
WeebDataHoarder
8323536e84 build/docker: disable PIE buildmode under riscv64 due to https://github.com/golang/go/issues/64875 2025-06-28 10:44:08 +02:00
WeebDataHoarder
99ddb2b62b build/docker: address legacy "ENV key value" form and RedundantTargetPlatform 2025-06-28 10:35:10 +02:00
WeebDataHoarder
e4e5b0bc5d build/docker: pass JWT_PRIVATE_KEY_SEED as a secret env, add alternate GOAWAY_JWT_PRIVATE_KEY_SEED env 2025-06-28 10:29:42 +02:00
WeebDataHoarder
057bca753d build: set -buildmode pie, -bindnow linker flag. Enables Full RELRO, NX, PIE, no RPATH/RUNPATH, nothing to FORTIFY 2025-06-28 10:19:38 +02:00
Geoffrey “Frogeye” Preud'homme
d1d80c5078 challenges/context: add JA4 fingerprint in the headers 2025-06-27 21:28:43 +02:00
10 changed files with 132 additions and 153 deletions

View File

@@ -22,8 +22,8 @@ local Build(mirror, go, alpine, os, arch) = {
"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",
"go build -v -pgo=auto -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie -o ./.bin/go-away ./cmd/go-away",
"go build -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie -o ./.bin/test-wasm-runtime ./cmd/test-wasm-runtime",
],
},
{

View File

@@ -14,8 +14,10 @@ steps:
- 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
- go build -v -pgo=auto -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie
-o ./.bin/go-away ./cmd/go-away
- go build -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie -o ./.bin/test-wasm-runtime
./cmd/test-wasm-runtime
image: golang:1.24-alpine3.21
mirror: https://mirror.gcr.io
name: build
@@ -86,8 +88,10 @@ steps:
- 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
- go build -v -pgo=auto -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie
-o ./.bin/go-away ./cmd/go-away
- go build -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie -o ./.bin/test-wasm-runtime
./cmd/test-wasm-runtime
image: golang:1.24-alpine3.21
mirror: https://mirror.gcr.io
name: build
@@ -158,8 +162,10 @@ steps:
- 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
- go build -v -pgo=auto -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie
-o ./.bin/go-away ./cmd/go-away
- go build -v -trimpath -ldflags='-buildid= -bindnow' -buildmode pie -o ./.bin/test-wasm-runtime
./cmd/test-wasm-runtime
image: golang:1.24-alpine3.21
mirror: https://mirror.gcr.io
name: build
@@ -503,6 +509,6 @@ trigger:
type: docker
---
kind: signature
hmac: df53e4ea6f1c47df4d2a3f89b931b8513e83daa9c6c15baba2662d8112a721c8
hmac: 9a3872c0b58810924c4342c9dbd338e16da20631c9a0848e3abd2bf6773f9ba6
...

View File

@@ -0,0 +1,34 @@
---
name: CI/CD Pipeline
on: push
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install docker
uses: papodaca/install-docker-action@main
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Git Forge registry
uses: docker/login-action@v3
with:
registry: git.projectsegfau.lt
username: ${{ secrets.GIT_USERNAME }}
password: ${{ secrets.GIT_TOKEN }}
- name: Build and push Docker images
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: git.projectsegfau.lt/${{ secrets.GIT_USERNAME }}/go-away:latest
platforms: linux/amd64, linux/arm64

View File

@@ -24,18 +24,26 @@ ENV CGO_ENABLED=0
ENV GOOS=${TARGETOS}
ENV GOARCH=${TARGETARCH}
ENV GOTOOLCHAIN=${GOTOOLCHAIN}
ENV BUILDMODE=pie
# riscv64 requires GCC for pie buildmode
# see https://github.com/golang/go/issues/64875
RUN if [[ "$GOARCH" == "riscv64" ]]; then export BUILDMODE=exe; fi && \
go build -v \
-pgo=auto \
-trimpath -ldflags='-buildid= -bindnow' -buildmode $BUILDMODE \
-o "${GOBIN}/go-away" ./cmd/go-away
RUN go build -pgo=auto -v -trimpath -ldflags=-buildid= -o "${GOBIN}/go-away" ./cmd/go-away
RUN test -e "${GOBIN}/go-away"
FROM --platform=$TARGETPLATFORM ${from}
FROM ${from}
COPY --from=build /go/bin/go-away /bin/go-away
COPY examples/snippets/ /snippets/
COPY docker-entrypoint.sh /
ENV TZ UTC
ENV TZ=UTC
ENV GOAWAY_METRICS_BIND=""
ENV GOAWAY_DEBUG_BIND=""
@@ -52,7 +60,6 @@ ENV GOAWAY_CHALLENGE_TEMPLATE_LOGO=""
ENV GOAWAY_SLOG_LEVEL="WARN"
ENV GOAWAY_CLIENT_IP_HEADER=""
ENV GOAWAY_BACKEND_IP_HEADER=""
ENV GOAWAY_JWT_PRIVATE_KEY_SEED=""
ENV GOAWAY_BACKEND=""
ENV GOAWAY_ACME_AUTOCERT=""
ENV GOAWAY_CACHE="/cache"
@@ -63,6 +70,6 @@ EXPOSE 8080/udp
EXPOSE 9090/tcp
EXPOSE 6060/tcp
ENV JWT_PRIVATE_KEY_SEED="${GOAWAY_JWT_PRIVATE_KEY_SEED}"
# Use GOAWAY_JWT_PRIVATE_KEY_SEED or JWT_PRIVATE_KEY_SEED secret mount to expose this value to docker
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@@ -9,18 +9,17 @@ mkdir -p .bin/ 2>/dev/null
# Setup tinygo first
if [[ ! -d .bin/tinygo ]]; then
git clone --depth=1 --branch v0.37.0 https://github.com/tinygo-org/tinygo.git .bin/tinygo
git clone --depth=1 --branch v0.38.0 https://github.com/tinygo-org/tinygo.git .bin/tinygo
pushd .bin/tinygo
git submodule update --init --recursive
go mod download -x && go mod verify
make binaryen STATIC=1
make wasi-libc
make llvm-source
make llvm-build
make binaryen STATIC=1
make build/release
else
pushd .bin/tinygo

View File

@@ -154,7 +154,9 @@ func main() {
var seed []byte
var kValue string
if kValue = os.Getenv("JWT_PRIVATE_KEY_SEED"); kValue != "" {
if kValue = os.Getenv("GOAWAY_JWT_PRIVATE_KEY_SEED"); kValue != "" {
// prefer first
} else if kValue = os.Getenv("JWT_PRIVATE_KEY_SEED"); kValue != "" {
} else if *jwtPrivateKeySeed != "" {
kValue = *jwtPrivateKeySeed

View File

@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en" class="fixed_navbar">
<head>
<title>{{ .Title }}</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{ range .MetaTags }}
<meta {{ range $key, $value := . }}{{ $key | attr }}="{{ $value }}" {{end}}/>
{{ end }}
{{ range .LinkTags }}
<link {{ range $key, $value := . }}{{ $key | attr }}="{{ $value }}" {{end}}/>
{{ end }}
{{ range .HeaderTags }}
{{ . }}
{{ end }}
<link rel="stylesheet" type="text/css" href="/style.css?v=0.36.0">
</head>
<body class="fixed_navbar">
<!-- NAVIGATION BAR -->
<nav class="fixed_navbar">
<div id="logo">
<a id="redlib" href="/"><span id="red">red</span><span id="lib">lib.</span></a>
</div>
</nav>
<!-- MAIN CONTENT -->
<main>
<div id="error">
<h1 id="status">Please wait while we verify you aren't a robot!</h1>
{{ if .Challenge }}
<h3 id="status">{{ .Strings.Get "status_loading_challenge" }} : {{.Challenge }}...</h3>
{{ else if .Error }}
<h3 id="status">{{ .Strings.Get "status_error" }} {{ .Error }}</h3>
{{ else }}
<h3 id="status">{{ .Strings.Get "status_loading" }}</h3>
{{ end }}
<details style="padding-top: 5px;">
<summary>{{ .Strings.Get "details_title" }}</summary>
{{.Strings.Get "details_text"}}
</details>
{{ if .Redirect }}
<h3><a href="{{ .Redirect }}">{{ .Strings.Get "button_refresh_page" }}</a></h3>
</div>
{{ end }}
{{if .EndTags }}
<noscript>
{{ .Strings.Get "noscript_warning" }}
</noscript>
{{end}}
</main>
<!-- FOOTER -->
<footer>
<div class="footer-buttons">
<p><small>{{ .Strings.Get "details_contact_admin_with_request_id" }}: <em>{{ .Id }}</em></small></p>
</div>
</footer>
</body>
</html>

View File

@@ -368,7 +368,7 @@ func (d *RequestData) RequestHeaders(headers http.Header) {
}
}
if ja4, ok := d.fp["fp4"]; ok {
if ja4, ok := d.fp["ja4"]; ok {
headers.Set("X-TLS-Fingerprint-JA4", ja4)
}

View File

@@ -13,18 +13,10 @@ import (
"net/http"
"os"
"strconv"
"strings"
"sync/atomic"
"time"
)
type TLSEntry struct {
// Certificate Path to the certificate file
Certificate string `yaml:"certificate"`
// Key Path to the corresponding key file
Key string `yaml:"key"`
}
type Bind struct {
Address string `yaml:"address"`
Network string `yaml:"network"`
@@ -36,35 +28,11 @@ type Bind struct {
// TLSAcmeAutoCert URL to ACME directory, or letsencrypt
TLSAcmeAutoCert string `yaml:"tls-acme-autocert"`
// TLSEntries Alternate to TLSAcmeAutoCert. Allows multiple entries with matching.
// Entries on this list can be live-reloaded if application implements SIGHUP handling
TLSEntries []TLSEntry `yaml:"tls-entries"`
// TLSCertificate Alternate to TLSAcmeAutoCert. Preferred over TLSEntries if specified.
// TLSCertificate Alternate to TLSAcmeAutoCert
TLSCertificate string `yaml:"tls-certificate"`
// TLSPrivateKey Alternate to TLSAcmeAutoCert. Preferred over TLSEntries if specified.
// TLSPrivateKey Alternate to TLSAcmeAutoCert
TLSPrivateKey string `yaml:"tls-key"`
// General TLS config
// TLSMinVersion TLS Minimum supported version.
// Default is Golang's default, at writing time it's TLS 1.2. Lowest supported is TLS 1.0
TLSMinVersion string `yaml:"tls-min-version"`
// TLSMaxVersion TLS Maximum supported version.
// Default is Golang's default, at writing time it's TLS 1.3, and is automatically increased.
// Lowest supported is TLS 1.2
TLSMaxVersion string `yaml:"tls-max-version"`
// TLSCurves List of supported TLS curve ids from Golang internals
// See this list https://github.com/golang/go/blob/go1.24.0/src/crypto/tls/common.go#L138-L153 for supported values
// Default values are chosen by Golang. It's recommended to leave the default
TLSCurves []tls.CurveID `yaml:"tls-curves"`
// TLSCiphers List of supported TLS ciphers from Golang internals, case sensitive. TLS 1.3 suites are not configurable.
// See this list https://github.com/golang/go/blob/go1.24.0/src/crypto/tls/cipher_suites.go#L56-L73 for supported values
// Default values are chosen by Golang. It's recommended to leave the default
TLSCiphers []string `yaml:"tls-ciphers"`
// ReadTimeout is the maximum duration for reading the entire
// request, including the body. A zero or negative value means
// there will be no timeout.
@@ -136,105 +104,6 @@ func (b *Bind) Server(backends map[string]http.Handler, acmeCachePath string) (*
"TLS enabled",
"certificate", b.TLSCertificate,
)
} else if len(b.TLSEntries) > 0 {
tlsConfig = &tls.Config{}
var err error
var certificatesPtr atomic.Pointer[[]tls.Certificate]
swapTls := func() error {
certs := make([]tls.Certificate, 0, len(b.TLSEntries))
for _, entry := range b.TLSEntries {
cert, err := tls.LoadX509KeyPair(entry.Certificate, entry.Key)
if err != nil {
return fmt.Errorf("failed to load TLS certificate %s: %w", entry.Certificate, err)
}
certs = append(certs, cert)
}
certificatesPtr.Swap(&certs)
return nil
}
tlsConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
certs := certificatesPtr.Load()
if certs == nil || len(*certs) == 0 {
panic("no certificates found")
}
for _, cert := range *certs {
if err := clientHello.SupportsCertificate(&cert); err == nil {
return &cert, nil
}
}
// if none match, return first
return &(*certs)[0], nil
}
err = swapTls()
if err != nil {
return nil, nil, err
}
slog.Warn(
"TLS enabled with multiple certificates",
"certificates", len(b.TLSEntries),
)
}
if tlsConfig != nil {
if b.TLSMinVersion != "" {
switch strings.NewReplacer("-", "", "_", "", " ", "", ".", "").Replace(strings.ToLower(b.TLSMinVersion)) {
case "13", "tls13":
tlsConfig.MinVersion = tls.VersionTLS13
case "12", "tls12":
tlsConfig.MinVersion = tls.VersionTLS12
case "11", "tls11":
tlsConfig.MinVersion = tls.VersionTLS11
case "10", "tls10":
tlsConfig.MinVersion = tls.VersionTLS10
default:
return nil, nil, fmt.Errorf("unsupported minimum TLS version: %s", b.TLSMinVersion)
}
}
if b.TLSMaxVersion != "" {
switch strings.NewReplacer("-", "", "_", "", " ", "", ".", "").Replace(strings.ToLower(b.TLSMaxVersion)) {
case "13", "tls13":
tlsConfig.MaxVersion = tls.VersionTLS13
case "12", "tls12":
tlsConfig.MaxVersion = tls.VersionTLS12
default:
return nil, nil, fmt.Errorf("unsupported maximum TLS version: %s", b.TLSMinVersion)
}
}
if len(b.TLSCiphers) > 0 {
for _, cipher := range b.TLSCiphers {
if c := func() *tls.CipherSuite {
for _, c := range tls.CipherSuites() {
if c.Name == cipher {
return c
}
}
for _, c := range tls.InsecureCipherSuites() {
if c.Name == cipher {
return c
}
}
return nil
}(); c != nil {
tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, c.ID)
} else {
return nil, nil, fmt.Errorf("unsupported TLS cipher suite: %s", cipher)
}
}
}
if len(b.TLSCurves) > 0 {
tlsConfig.CurvePreferences = append(tlsConfig.CurvePreferences, b.TLSCurves...)
}
}
var serverHandler atomic.Pointer[http.Handler]