From b2e88665bc4e00771a26c5707f4580d692003937 Mon Sep 17 00:00:00 2001 From: Gustavo Ocanto Date: Fri, 12 Sep 2025 14:53:34 +0800 Subject: [PATCH 1/5] remove ip from public mw --- pkg/middleware/public_middleware.go | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/pkg/middleware/public_middleware.go b/pkg/middleware/public_middleware.go index 790a6db6..7481b754 100644 --- a/pkg/middleware/public_middleware.go +++ b/pkg/middleware/public_middleware.go @@ -61,12 +61,6 @@ func (p PublicMiddleware) Handle(next http.ApiHandler) http.ApiHandler { return mwguards.RateLimitedError("Too many requests", "Too many requests for key: "+limiterKey) } - if err := p.HasInvalidIP(r); err != nil { - p.rateLimiter.Fail(limiterKey) - - return err - } - vt := mwguards.NewValidTimestamp(ts, p.now) if err := vt.Validate(p.clockSkew, p.disallowFuture); err != nil { p.rateLimiter.Fail(limiterKey) @@ -89,20 +83,6 @@ func (p PublicMiddleware) Handle(next http.ApiHandler) http.ApiHandler { } } -func (p PublicMiddleware) HasInvalidIP(r *baseHttp.Request) *http.ApiError { - ip := portal.ParseClientIP(r) - - if ip == "" { - return mwguards.InvalidRequestError("Clients IPs are required to access this endpoint", "") - } - - if p.isProduction && ip != p.allowedIP { - return mwguards.InvalidRequestError("The given IP is not allowed", "unauthorised ip: "+ip) - } - - return nil -} - func (p PublicMiddleware) GuardDependencies() *http.ApiError { missing := []string{} From 7cb453b456a91655eb510e3f4820a2d75026b792 Mon Sep 17 00:00:00 2001 From: Gustavo Ocanto Date: Fri, 12 Sep 2025 14:59:41 +0800 Subject: [PATCH 2/5] fix handshake --- caddy/Caddyfile.prod | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/caddy/Caddyfile.prod b/caddy/Caddyfile.prod index 4e98908e..e2e269d3 100644 --- a/caddy/Caddyfile.prod +++ b/caddy/Caddyfile.prod @@ -89,24 +89,20 @@ oullin.io { # INTERNAL mTLS entrypoint for the single protected path :8443 { - tls internal { - client_auth { - mode require_and_verify - trust_pool file { - pem_file /etc/caddy/mtls/ca.pem - } - } - } + tls /etc/caddy/mtls/ca.pem /etc/caddy/mtls/ca.key { + client_auth { + mode require_and_verify + trust_pool file /etc/caddy/mtls/ca.pem + } + } - encode gzip zstd + encode gzip zstd - # Only this path is reachable here - handle_path /api/generate-signature* { - reverse_proxy api:8080 - } + handle_path /api/generate-signature* { + reverse_proxy api:8080 + } - # Everything else is denied on this listener. - handle { - respond 403 - } + handle { + respond 403 + } } From 862ee6bc2ee618a05c7a54cff01eda5c9da79d44 Mon Sep 17 00:00:00 2001 From: Gustavo Ocanto Date: Fri, 12 Sep 2025 15:19:45 +0800 Subject: [PATCH 3/5] generate server keys too --- caddy/Caddyfile.prod | 13 +++++++------ metal/makefile/caddy.mk | 31 +++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/caddy/Caddyfile.prod b/caddy/Caddyfile.prod index e2e269d3..d6adab92 100644 --- a/caddy/Caddyfile.prod +++ b/caddy/Caddyfile.prod @@ -89,12 +89,13 @@ oullin.io { # INTERNAL mTLS entrypoint for the single protected path :8443 { - tls /etc/caddy/mtls/ca.pem /etc/caddy/mtls/ca.key { - client_auth { - mode require_and_verify - trust_pool file /etc/caddy/mtls/ca.pem - } - } + tls /etc/caddy/mtls/server.pem /etc/caddy/mtls/server.key { + client_auth { + mode require_and_verify + # The client must present a cert trusted by the CA + trust_pool file /etc/caddy/mtls/ca.pem + } + } encode gzip zstd diff --git a/metal/makefile/caddy.mk b/metal/makefile/caddy.mk index ad6dcaf9..116b7c10 100644 --- a/metal/makefile/caddy.mk +++ b/metal/makefile/caddy.mk @@ -1,9 +1,13 @@ -.PHONY: caddy-gen-certs caddy-del-certs caddy-validate +.PHONY: caddy-gen-certs caddy-del-certs caddy-validate caddy-fresh CADDY_MTLS_DIR = $(ROOT_PATH)/caddy/mtls APP_CADDY_CONFIG_PROD_FILE ?= caddy/Caddyfile.prod APP_CADDY_CONFIG_LOCAL_FILE ?= caddy/Caddyfile.local +caddy-fresh: + @make caddy-del-certs; + @make caddy-gen-certs; + caddy-gen-certs: @set -eu; \ mkdir -p "$(CADDY_MTLS_DIR)"; chmod 700 "$(CADDY_MTLS_DIR)"; \ @@ -27,10 +31,33 @@ caddy-gen-certs: printf "$(WHITE)🔍 CA fingerprint:$(NC)\n"; \ openssl x509 -noout -fingerprint -sha256 -in "$(CADDY_MTLS_DIR)/ca.pem" | sed 's/^/ /'; \ fi + if [ -e "$(CADDY_MTLS_DIR)/server.key" ] || [ -e "$(CADDY_MTLS_DIR)/server.pem" ]; then \ + printf "$(YELLOW)⚠️ Server certificate already exists.$(NC)\n"; \ + else \ + umask 077; \ + printf "$(BLUE)🔑 Generating Server private key...$(NC)\n"; \ + openssl genrsa -out "$(CADDY_MTLS_DIR)/server.key" 4096; \ + printf "$(WHITE)📜 Creating Server signing request...$(NC)"; \ + openssl req -new -key "$(CADDY_MTLS_DIR)/server.key" -subj "/CN=oullin_proxy_prod" -out "$(CADDY_MTLS_DIR)/server.csr"; \ + printf "$(NC)🖊️ Signing Server certificate with CA...$(NC)\n"; \ + openssl x509 -req -in "$(CADDY_MTLS_DIR)/server.csr" \ + -CA "$(CADDY_MTLS_DIR)/ca.pem" -CAkey "$(CADDY_MTLS_DIR)/ca.key" -CAserial "$(CADDY_MTLS_DIR)/ca.srl" \ + -out "$(CADDY_MTLS_DIR)/server.pem" -days 1095 -sha256; \ + chmod 600 "$(CADDY_MTLS_DIR)/server.key"; \ + chmod 644 "$(CADDY_MTLS_DIR)/server.pem"; \ + rm "$(CADDY_MTLS_DIR)/server.csr"; \ + printf "$(NC)✅ Server certificate written to %s\033[0m\n" "$(CADDY_MTLS_DIR)$(NC)\n"; \ + fi; \ + printf "$(NC)🔎 Verifying server cert against CA...$(NC)\n"; \ + openssl verify -CAfile "$(CADDY_MTLS_DIR)/ca.pem" "$(CADDY_MTLS_DIR)/server.pem"; caddy-del-certs: @set -eu; \ - rm -f "$(CADDY_MTLS_DIR)/ca.key" "$(CADDY_MTLS_DIR)/ca.pem" "$(CADDY_MTLS_DIR)/ca.srl"; \ + rm -f "$(CADDY_MTLS_DIR)/ca.key" \ + "$(CADDY_MTLS_DIR)/ca.pem" \ + "$(CADDY_MTLS_DIR)/ca.srl" \ + "$(CADDY_MTLS_DIR)/server.key" \ + "$(CADDY_MTLS_DIR)/server.pem" \; \ printf "$(BLUE)✅ files removed from [$(NC)$(CADDY_MTLS_DIR)$(BLUE)]$(NC)\n" caddy-validate: From 9371d1ad194329433ba533be6e333bfe45626676 Mon Sep 17 00:00:00 2001 From: Gustavo Ocanto Date: Fri, 12 Sep 2025 15:44:40 +0800 Subject: [PATCH 4/5] format --- metal/makefile/caddy.mk | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/metal/makefile/caddy.mk b/metal/makefile/caddy.mk index 116b7c10..ee850ed8 100644 --- a/metal/makefile/caddy.mk +++ b/metal/makefile/caddy.mk @@ -5,63 +5,64 @@ APP_CADDY_CONFIG_PROD_FILE ?= caddy/Caddyfile.prod APP_CADDY_CONFIG_LOCAL_FILE ?= caddy/Caddyfile.local caddy-fresh: - @make caddy-del-certs; - @make caddy-gen-certs; + @make caddy-del-certs + @make caddy-gen-certs caddy-gen-certs: @set -eu; \ mkdir -p "$(CADDY_MTLS_DIR)"; chmod 700 "$(CADDY_MTLS_DIR)"; \ if [ -d "$(CADDY_MTLS_DIR)/ca.pem" ]; then \ printf "$(RED)✘ ERROR:$(NC) %s is a directory. Move or remove it.\n" "$(CADDY_MTLS_DIR)/ca.pem"; \ + exit 1; \ fi; \ if [ -e "$(CADDY_MTLS_DIR)/ca.key" ] || [ -e "$(CADDY_MTLS_DIR)/ca.pem" ]; then \ printf "$(YELLOW)⚠️ CA already exists in %s.$(NC)\n" "$(CADDY_MTLS_DIR)"; \ - printf "$(CYAN)👉 Remove it with 'make caddy-clean-certs' if you want to recreate.$(NC)\n"; \ + printf "$(CYAN)👉 Remove it with 'make caddy-del-certs' if you want to recreate.$(NC)\n"; \ else \ umask 077; \ printf "$(BLUE)🔑 Generating CA private key...$(NC)\n"; \ - openssl genrsa -out "$(CADDY_MTLS_DIR)/ca.key" 4096 >/dev/null 2>&1; \ + openssl genrsa -out "$(CADDY_MTLS_DIR)/ca.key" 4096; \ printf "$(BLUE)📜 Creating self-signed CA certificate...$(NC)\n"; \ openssl req -x509 -new -key "$(CADDY_MTLS_DIR)/ca.key" -sha256 -days 3650 \ - -subj "/CN=oullin-mtls-ca" -out "$(CADDY_MTLS_DIR)/ca.pem" >/dev/null 2>&1; \ + -subj "/CN=oullin-mtls-ca" -out "$(CADDY_MTLS_DIR)/ca.pem"; \ printf '01\n' > "$(CADDY_MTLS_DIR)/ca.srl"; \ chmod 600 "$(CADDY_MTLS_DIR)/ca.key"; \ chmod 644 "$(CADDY_MTLS_DIR)/ca.pem" "$(CADDY_MTLS_DIR)/ca.srl"; \ printf "$(GREEN)✅ CA written to %s$(NC)\n" "$(CADDY_MTLS_DIR)"; \ printf "$(WHITE)🔍 CA fingerprint:$(NC)\n"; \ openssl x509 -noout -fingerprint -sha256 -in "$(CADDY_MTLS_DIR)/ca.pem" | sed 's/^/ /'; \ - fi + fi; \ if [ -e "$(CADDY_MTLS_DIR)/server.key" ] || [ -e "$(CADDY_MTLS_DIR)/server.pem" ]; then \ printf "$(YELLOW)⚠️ Server certificate already exists.$(NC)\n"; \ else \ umask 077; \ printf "$(BLUE)🔑 Generating Server private key...$(NC)\n"; \ openssl genrsa -out "$(CADDY_MTLS_DIR)/server.key" 4096; \ - printf "$(WHITE)📜 Creating Server signing request...$(NC)"; \ + printf "$(WHITE)📜 Creating Server signing request...$(NC)\n"; \ openssl req -new -key "$(CADDY_MTLS_DIR)/server.key" -subj "/CN=oullin_proxy_prod" -out "$(CADDY_MTLS_DIR)/server.csr"; \ printf "$(NC)🖊️ Signing Server certificate with CA...$(NC)\n"; \ openssl x509 -req -in "$(CADDY_MTLS_DIR)/server.csr" \ - -CA "$(CADDY_MTLS_DIR)/ca.pem" -CAkey "$(CADDY_MTLS_DIR)/ca.key" -CAserial "$(CADDY_MTLS_DIR)/ca.srl" \ - -out "$(CADDY_MTLS_DIR)/server.pem" -days 1095 -sha256; \ + -CA "$(CADDY_MTLS_DIR)/ca.pem" -CAkey "$(CADDY_MTLS_DIR)/ca.key" -CAserial "$(CADDY_MTLS_DIR)/ca.srl" \ + -out "$(CADDY_MTLS_DIR)/server.pem" -days 1095 -sha256; \ chmod 600 "$(CADDY_MTLS_DIR)/server.key"; \ chmod 644 "$(CADDY_MTLS_DIR)/server.pem"; \ rm "$(CADDY_MTLS_DIR)/server.csr"; \ - printf "$(NC)✅ Server certificate written to %s\033[0m\n" "$(CADDY_MTLS_DIR)$(NC)\n"; \ + printf "$(GREEN)✅ Server certificate written to %s$(NC)\n" "$(CADDY_MTLS_DIR)"; \ fi; \ printf "$(NC)🔎 Verifying server cert against CA...$(NC)\n"; \ - openssl verify -CAfile "$(CADDY_MTLS_DIR)/ca.pem" "$(CADDY_MTLS_DIR)/server.pem"; + openssl verify -CAfile "$(CADDY_MTLS_DIR)/ca.pem" "$(CADDY_MTLS_DIR)/server.pem" caddy-del-certs: @set -eu; \ rm -f "$(CADDY_MTLS_DIR)/ca.key" \ - "$(CADDY_MTLS_DIR)/ca.pem" \ - "$(CADDY_MTLS_DIR)/ca.srl" \ - "$(CADDY_MTLS_DIR)/server.key" \ - "$(CADDY_MTLS_DIR)/server.pem" \; \ + "$(CADDY_MTLS_DIR)/ca.pem" \ + "$(CADDY_MTLS_DIR)/ca.srl" \ + "$(CADDY_MTLS_DIR)/server.key" \ + "$(CADDY_MTLS_DIR)/server.pem"; \ printf "$(BLUE)✅ files removed from [$(NC)$(CADDY_MTLS_DIR)$(BLUE)]$(NC)\n" caddy-validate: - docker run --rm \ - -v "$(ROOT_PATH)/caddy/Caddyfile.prod:/etc/caddy/Caddyfile:ro" \ - -v "$(ROOT_PATH)/caddy/mtls:/etc/caddy/mtls:ro" \ - caddy:2.10.0 caddy validate --config /etc/caddy/Caddyfile + @docker run --rm \ + -v "$(ROOT_PATH)/caddy/Caddyfile.prod:/etc/caddy/Caddyfile:ro" \ + -v "$(ROOT_PATH)/caddy/mtls:/etc/caddy/mtls:ro" \ + caddy:2.10.0 caddy validate --config /etc/caddy/Caddyfile From 175525cc1d0bc586dc07fbd5c9487d370267a4a0 Mon Sep 17 00:00:00 2001 From: Gustavo Ocanto Date: Fri, 12 Sep 2025 15:49:39 +0800 Subject: [PATCH 5/5] remve ip tets --- metal/kernel/router_signature_test.go | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/metal/kernel/router_signature_test.go b/metal/kernel/router_signature_test.go index e246cca2..2b252cc6 100644 --- a/metal/kernel/router_signature_test.go +++ b/metal/kernel/router_signature_test.go @@ -41,25 +41,4 @@ func TestSignatureRoute_PublicMiddleware(t *testing.T) { t.Fatalf("expected status %d, got %d", http.StatusBadRequest, rec.Code) } }) - - t.Run("production rejects requests from non-whitelisted IP", func(t *testing.T) { - r := Router{ - Mux: http.NewServeMux(), - Pipeline: middleware.Pipeline{ - PublicMiddleware: middleware.MakePublicMiddleware("31.97.60.190", true), - }, - validator: portal.GetDefaultValidator(), - } - r.Signature() - - req := httptest.NewRequest("POST", "/generate-signature", strings.NewReader("{")) - req.Header.Set(portal.RequestIDHeader, "req-1") - req.Header.Set(portal.TimestampHeader, fmt.Sprintf("%d", time.Now().Unix())) - req.Header.Set("X-Forwarded-For", "1.2.3.4") - rec := httptest.NewRecorder() - r.Mux.ServeHTTP(rec, req) - if rec.Code != http.StatusUnauthorized { - t.Fatalf("expected status %d, got %d", http.StatusUnauthorized, rec.Code) - } - }) }