mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-10-25 02:59:04 +02:00
feat: add support for proxy protocol
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
)
|
||||
|
||||
const proxyProtocolReadHeaderTimeout = 5 * time.Second
|
||||
|
||||
func newProxyProtocolListener(listener net.Listener, trustedProxies []string) (net.Listener, error) {
|
||||
if len(trustedProxies) == 0 {
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
// PROXY protocol transports client metadata on TCP connections before any TLS handshake
|
||||
network := listener.Addr().Network()
|
||||
if network != "tcp" && network != "tcp4" && network != "tcp6" {
|
||||
return nil, fmt.Errorf("PROXY protocol requires a TCP listener, got %q", network)
|
||||
}
|
||||
|
||||
// Require headers from configured network proxies and reject every other network peer
|
||||
trustedProxyPolicy, err := proxyproto.TrustProxyHeaderFromRanges(trustedProxies)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to configure PROXY protocol trusted proxies: %w", err)
|
||||
}
|
||||
|
||||
// We need to add another policy for loopback connections because healthcheck requests are made from the same host
|
||||
// loopbackPolicy handles requests from trusted loopback like normal, but it also allows untrusted loopback connections to be accepted
|
||||
// untrusted loopback connections aren't allowed to send PROXY headers though
|
||||
loopbackPolicy, err := proxyproto.PolicyFromRanges(trustedProxies, proxyproto.USE, proxyproto.SKIP)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to configure PROXY protocol loopback proxies: %w", err)
|
||||
}
|
||||
|
||||
// Create a policy which decides which of the two policies to use based on the upstream address
|
||||
policy := func(options proxyproto.ConnPolicyOptions) (proxyproto.Policy, error) {
|
||||
upstream, ok := options.Upstream.(*net.TCPAddr)
|
||||
if ok && upstream.IP.IsLoopback() {
|
||||
return loopbackPolicy(options)
|
||||
}
|
||||
|
||||
return trustedProxyPolicy(options)
|
||||
}
|
||||
|
||||
slog.Info("PROXY protocol enabled")
|
||||
return &proxyproto.Listener{
|
||||
Listener: listener,
|
||||
ConnPolicy: policy,
|
||||
ReadHeaderTimeout: proxyProtocolReadHeaderTimeout,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user