v0.26.0 proxy headers for acl
Test / test (push) Canceled after 0s
Test / e2e (push) Canceled after 0s

This commit is contained in:
lixen committed 2026-10-05 01:24:02 -04:00
1 parent 4af072f4e5
commit ee01cb00fe
21 files changed
+1115 -298

No files matched your search

+4
View File
@@ -280,6 +280,7 @@ func (h *HTTPSink) serve(ctx context.Context, ln net.Listener) error {
h.server = &http.Server{
Handler: handler,
ReadHeaderTimeout: HTTPReadHeaderTimeout,
ConnContext: netacl.ConnContext,
// WriteTimeout unset by design: SSE responses are long-lived.
// net/http bounds the TLS handshake by min(ReadHeaderTimeout,
// ReadTimeout, WriteTimeout), so ReadHeaderTimeout covers it here.
@@ -434,6 +435,9 @@ func (h *HTTPSink) handleStream(w http.ResponseWriter, r *http.Request) {
meta := map[string]any{
"type": "http_client",
}
if peer := netacl.ContextPeerAddr(r.Context()); peer != "" {
meta["peer_addr"] = peer
}
if r.TLS != nil {
meta["tls"] = true
if cn := tlsx.PeerCN(*r.TLS); cn != "" {
+21
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"io"
"maps"
"net"
"net/http"
"net/http/httptest"
"slices"
@@ -347,6 +348,26 @@ func TestProxyModeRefusesDirectPeers(t *testing.T) {
}
}
// A PROXY header names the client a stream's session records; the proxy
// stays as its peer_addr
func TestProxiedStreamSessionKeepsTheProxy(t *testing.T) {
h, manager := newTestHTTPSink(t, map[string]any{"acl": map[string]any{"proxy_protocol": "required", "proxy_from": []any{"127.0.0.1"}}})
_, baseURL := serveTestHTTPSink(t, h)
conn, err := net.Dial("tcp4", strings.TrimPrefix(baseURL, "http://"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { conn.Close() })
fmt.Fprint(conn, "PROXY TCP4 198.51.100.7 127.0.0.1 40000 8081\r\nGET /stream HTTP/1.1\r\nHost: logwisp\r\n\r\n")
if _, err := http.ReadResponse(bufio.NewReader(conn), nil); err != nil { // its body is the stream
t.Fatal(err)
}
sessions := manager.GetActiveSessions()
if len(sessions) != 1 || sessions[0].RemoteAddr != "198.51.100.7:40000" || sessions[0].Metadata["peer_addr"] != conn.LocalAddr().String() {
t.Fatalf("sessions %+v, proxy %s", sessions, conn.LocalAddr())
}
}
// The constructor refuses what it cannot serve: the login pages outside
// scram's proxy mode, a viewer without the login page, a path under /auth, and
// a path ServeMux or a URL would not take literally, which panicked at Start.
+3
View File
@@ -371,6 +371,9 @@ func (t *TCPSink) handleConn(conn net.Conn) {
"type": "tcp_client",
"remote_addr": remote,
}
if peer := netacl.PeerAddr(conn); peer != "" {
meta["peer_addr"] = peer
}
var tlsState *tls.ConnectionState
if tc, ok := conn.(*tls.Conn); ok {
hctx, cancel := context.WithTimeout(context.Background(), tlsx.HandshakeTimeout)