From 1ea083cd6ffae9e9b47936e31c1da9b543390e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Tue, 24 Mar 2026 12:52:41 +0800 Subject: [PATCH] Apply cloudflare origin proxy transport options --- protocol/cloudflare/dispatch.go | 25 ++++++++++- protocol/cloudflare/origin_request_test.go | 49 +++++++++++++++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/protocol/cloudflare/dispatch.go b/protocol/cloudflare/dispatch.go index 7cf664aca..6d049d66c 100644 --- a/protocol/cloudflare/dispatch.go +++ b/protocol/cloudflare/dispatch.go @@ -393,6 +393,7 @@ func (i *Inbound) newRouterOriginTransport(ctx context.Context, metadata adapter return input, nil }, } + applyHTTPTransportProxy(transport, originRequest) return transport, func() { common.Close(input, output) select { @@ -403,6 +404,13 @@ func (i *Inbound) newRouterOriginTransport(ctx context.Context, metadata adapter } func (i *Inbound) newDirectOriginTransport(service ResolvedService, requestHost string) (*http.Transport, func(), error) { + dialer := &net.Dialer{ + Timeout: service.OriginRequest.ConnectTimeout, + KeepAlive: service.OriginRequest.TCPKeepAlive, + } + if service.OriginRequest.NoHappyEyeballs { + dialer.FallbackDelay = -1 + } transport := &http.Transport{ DisableCompression: true, ForceAttemptHTTP2: service.OriginRequest.HTTP2Origin, @@ -412,14 +420,13 @@ func (i *Inbound) newDirectOriginTransport(service ResolvedService, requestHost MaxIdleConnsPerHost: service.OriginRequest.KeepAliveConnections, TLSClientConfig: buildOriginTLSConfig(service.OriginRequest, requestHost), } + applyHTTPTransportProxy(transport, service.OriginRequest) switch service.Kind { case ResolvedServiceUnix, ResolvedServiceUnixTLS: - dialer := &net.Dialer{} transport.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) { return dialer.DialContext(ctx, "unix", service.UnixPath) } case ResolvedServiceHelloWorld: - dialer := &net.Dialer{} target := service.BaseURL.Host transport.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) { return dialer.DialContext(ctx, "tcp", target) @@ -449,6 +456,20 @@ func buildOriginTLSConfig(originRequest OriginRequestConfig, requestHost string) return tlsConfig } +func applyHTTPTransportProxy(transport *http.Transport, originRequest OriginRequestConfig) { + if originRequest.ProxyAddress == "" || originRequest.ProxyPort == 0 { + return + } + switch strings.ToLower(originRequest.ProxyType) { + case "", "http": + proxyURL := &url.URL{ + Scheme: "http", + Host: net.JoinHostPort(originRequest.ProxyAddress, strconv.Itoa(int(originRequest.ProxyPort))), + } + transport.Proxy = http.ProxyURL(proxyURL) + } +} + func originTLSServerName(originRequest OriginRequestConfig, requestHost string) string { if originRequest.OriginServerName != "" { return originRequest.OriginServerName diff --git a/protocol/cloudflare/origin_request_test.go b/protocol/cloudflare/origin_request_test.go index b56a0a52f..d8a6716ab 100644 --- a/protocol/cloudflare/origin_request_test.go +++ b/protocol/cloudflare/origin_request_test.go @@ -2,7 +2,11 @@ package cloudflare -import "testing" +import ( + "net/http" + "net/url" + "testing" +) func TestOriginTLSServerName(t *testing.T) { t.Run("origin server name overrides host", func(t *testing.T) { @@ -31,3 +35,46 @@ func TestOriginTLSServerName(t *testing.T) { } }) } + +func TestApplyHTTPTransportProxy(t *testing.T) { + transport := &http.Transport{} + applyHTTPTransportProxy(transport, OriginRequestConfig{ + ProxyAddress: "127.0.0.1", + ProxyPort: 8080, + ProxyType: "http", + }) + if transport.Proxy == nil { + t.Fatal("expected proxy function to be configured") + } + proxyURL, err := transport.Proxy(&http.Request{URL: &url.URL{Scheme: "http", Host: "example.com"}}) + if err != nil { + t.Fatal(err) + } + if proxyURL == nil || proxyURL.String() != "http://127.0.0.1:8080" { + t.Fatalf("unexpected proxy URL: %#v", proxyURL) + } +} + +func TestNewDirectOriginTransportNoHappyEyeballs(t *testing.T) { + inbound := &Inbound{} + transport, cleanup, err := inbound.newDirectOriginTransport(ResolvedService{ + Kind: ResolvedServiceHelloWorld, + BaseURL: &url.URL{ + Scheme: "http", + Host: "127.0.0.1:8080", + }, + OriginRequest: OriginRequestConfig{ + NoHappyEyeballs: true, + }, + }, "") + if err != nil { + t.Fatal(err) + } + defer cleanup() + if transport.Proxy != nil { + t.Fatal("expected no proxy when proxy fields are empty") + } + if transport.DialContext == nil { + t.Fatal("expected custom direct dial context") + } +}