@@ -5,7 +5,12 @@ import (
55 "net"
66 "net/http"
77 "net/http/httputil"
8+ "slices"
9+ "strings"
810 "time"
11+
12+ "github.com/1Panel-dev/1Panel/core/utils/clientip"
13+ "github.com/1Panel-dev/1Panel/core/utils/publicshare"
914)
1015
1116const SockPath = "/etc/1panel/agent.sock"
@@ -28,20 +33,26 @@ func Init() {
2833 MaxIdleConnsPerHost : 50 ,
2934 IdleConnTimeout : 30 * time .Second ,
3035 }
31- LocalAgentProxy = & httputil. ReverseProxy {
32- Director : func ( req * http. Request ) {
33- if req . Header . Get ( "X-Forwarded-Proto" ) == "" {
34- if req . TLS != nil {
35- req . Header . Set ( "X-Forwarded-Proto" , "https" )
36- } else {
37- req . Header . Set ( "X-Forwarded-Proto" , "http" )
38- }
36+ LocalAgentProxy = newLocalAgentProxy ( transport )
37+ }
38+
39+ func newLocalAgentProxy ( transport http. RoundTripper ) * httputil. ReverseProxy {
40+ return & httputil. ReverseProxy {
41+ Rewrite : func ( proxyReq * httputil. ProxyRequest ) {
42+ if proxyReq . In . Form == nil {
43+ proxyReq . Out . URL . RawQuery = proxyReq . In . URL . RawQuery
3944 }
40- if req .Header .Get ("X-Forwarded-Host" ) == "" && req .Host != "" {
41- req .Header .Set ("X-Forwarded-Host" , req .Host )
45+ if publicshare .IsAPI (proxyReq .In .URL .Path ) {
46+ proxyReq .SetXForwarded ()
47+ clientip .ReplaceForwardingHeaders (
48+ proxyReq .Out .Header ,
49+ clientip .FromRemoteAddr (proxyReq .In .RemoteAddr ),
50+ )
51+ } else {
52+ restoreLegacyForwardingHeaders (proxyReq )
4253 }
43- req .URL .Scheme = "http"
44- req .URL .Host = "unix"
54+ proxyReq . Out .URL .Scheme = "http"
55+ proxyReq . Out .URL .Host = "unix"
4556 },
4657 Transport : transport ,
4758 ErrorHandler : func (rw http.ResponseWriter , req * http.Request , err error ) {
@@ -50,3 +61,64 @@ func Init() {
5061 },
5162 }
5263}
64+
65+ func restoreLegacyForwardingHeaders (proxyReq * httputil.ProxyRequest ) {
66+ restoreInboundHeader (proxyReq , "Forwarded" )
67+ restoreLegacyForwardedFor (proxyReq )
68+ restoreLegacyForwardedMetadata (proxyReq , "X-Forwarded-Host" , proxyReq .In .Host )
69+
70+ forwardedProto := "http"
71+ if proxyReq .In .TLS != nil {
72+ forwardedProto = "https"
73+ }
74+ restoreLegacyForwardedMetadata (proxyReq , "X-Forwarded-Proto" , forwardedProto )
75+ }
76+
77+ func restoreLegacyForwardedFor (proxyReq * httputil.ProxyRequest ) {
78+ restoreInboundHeader (proxyReq , "X-Forwarded-For" )
79+ clientIP , _ , err := net .SplitHostPort (proxyReq .In .RemoteAddr )
80+ if err != nil {
81+ return
82+ }
83+ prior , ok := proxyReq .Out .Header ["X-Forwarded-For" ]
84+ omit := ok && prior == nil
85+ if len (prior ) > 0 {
86+ clientIP = strings .Join (prior , ", " ) + ", " + clientIP
87+ }
88+ if ! omit {
89+ proxyReq .Out .Header .Set ("X-Forwarded-For" , clientIP )
90+ }
91+ }
92+
93+ func restoreLegacyForwardedMetadata (proxyReq * httputil.ProxyRequest , name , fallback string ) {
94+ if ! isConnectionHeader (proxyReq .In .Header , name ) && proxyReq .In .Header .Get (name ) != "" {
95+ restoreInboundHeader (proxyReq , name )
96+ return
97+ }
98+ proxyReq .Out .Header .Del (name )
99+ if fallback != "" {
100+ proxyReq .Out .Header .Set (name , fallback )
101+ }
102+ }
103+
104+ func restoreInboundHeader (proxyReq * httputil.ProxyRequest , name string ) {
105+ proxyReq .Out .Header .Del (name )
106+ if isConnectionHeader (proxyReq .In .Header , name ) {
107+ return
108+ }
109+ canonicalName := http .CanonicalHeaderKey (name )
110+ if values , ok := proxyReq .In .Header [canonicalName ]; ok {
111+ proxyReq .Out .Header [canonicalName ] = slices .Clone (values )
112+ }
113+ }
114+
115+ func isConnectionHeader (header http.Header , name string ) bool {
116+ for _ , value := range header .Values ("Connection" ) {
117+ for _ , token := range strings .Split (value , "," ) {
118+ if strings .EqualFold (strings .TrimSpace (token ), name ) {
119+ return true
120+ }
121+ }
122+ }
123+ return false
124+ }
0 commit comments