mirror of
https://github.com/umputun/reproxy.git
synced 2025-11-29 22:08:14 +02:00
don't add dbl headers for X-Forwarded-Proto and X-Forwarded-Proto #172
This commit is contained in:
@@ -213,8 +213,8 @@ func (h *Http) proxyHandler() http.HandlerFunc {
|
||||
keepHost := ctx.Value(ctxKeepHost).(bool)
|
||||
r.Header.Add("X-Forwarded-Host", r.Host)
|
||||
if h.SSLConfig.SSLMode == SSLAuto || h.SSLConfig.SSLMode == SSLStatic {
|
||||
r.Header.Add("X-Forwarded-Proto", "https")
|
||||
r.Header.Add("X-Forwarded-Port", "443")
|
||||
h.setHeaderIfNotExists(r, "X-Forwarded-Proto", "https")
|
||||
h.setHeaderIfNotExists(r, "X-Forwarded-Port", "443")
|
||||
}
|
||||
r.URL.Path = uu.Path
|
||||
r.URL.Host = uu.Host
|
||||
@@ -466,3 +466,9 @@ func (h *Http) discoveredServers(ctx context.Context, interval time.Duration) (s
|
||||
}
|
||||
return servers
|
||||
}
|
||||
|
||||
func (h *Http) setHeaderIfNotExists(r *http.Request, key, value string) {
|
||||
if _, ok := r.Header[key]; !ok {
|
||||
r.Header.Set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package proxy
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -120,6 +122,111 @@ func TestHttp_Do(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestHttp_DoWithSSL(t *testing.T) {
|
||||
port := rand.Intn(10000) + 40000
|
||||
h := Http{Timeouts: Timeouts{ResponseHeader: 200 * time.Millisecond}, Address: fmt.Sprintf("localhost:%d", port),
|
||||
AccessLog: io.Discard, Signature: true, ProxyHeaders: []string{"hh1:vv1", "hh2:vv2"}, StdOutEnabled: true,
|
||||
Reporter: &ErrorReporter{Nice: true},
|
||||
SSLConfig: SSLConfig{SSLMode: SSLStatic, Cert: "testdata/localhost.crt", Key: "testdata/localhost.key"}, Insecure: true,
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
ds := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Logf("req: %v", r)
|
||||
w.Header().Add("h1", "v1")
|
||||
require.Equal(t, "127.0.0.1", r.Header.Get("X-Real-IP"))
|
||||
require.Equal(t, "127.0.0.1", r.Header.Get("X-Forwarded-For"))
|
||||
require.Equal(t, "https", r.Header.Get("X-Forwarded-Proto")) // ssl auto only
|
||||
require.Equal(t, "443", r.Header.Get("X-Forwarded-Port"))
|
||||
fmt.Fprintf(w, "response %s", r.URL.String())
|
||||
}))
|
||||
|
||||
svc := discovery.NewService([]discovery.Provider{
|
||||
&provider.Static{Rules: []string{
|
||||
"localhost,^/api/(.*)," + strings.Replace(ds.URL, "127.0.0.1", "localhost", 1) + "/123/$1,",
|
||||
"127.0.0.1,^/api/(.*)," + strings.Replace(ds.URL, "127.0.0.1", "localhost", 1) + "/567/$1,",
|
||||
},
|
||||
}}, time.Millisecond*10)
|
||||
|
||||
go func() {
|
||||
_ = svc.Run(context.Background())
|
||||
}()
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
h.Matcher = svc
|
||||
h.Metrics = mgmt.NewMetrics()
|
||||
|
||||
go func() {
|
||||
_ = h.Run(ctx)
|
||||
}()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
client := http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("to localhost, good", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "https://localhost:"+strconv.Itoa(port)+"/api/something", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
t.Logf("%+v", resp.Header)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "response /123/something", string(body))
|
||||
assert.Equal(t, "reproxy", resp.Header.Get("App-Name"))
|
||||
assert.Equal(t, "v1", resp.Header.Get("h1"))
|
||||
assert.Equal(t, "vv1", resp.Header.Get("hh1"))
|
||||
assert.Equal(t, "vv2", resp.Header.Get("hh2"))
|
||||
})
|
||||
|
||||
t.Run("to localhost, request with X-Forwarded-Proto and X-Forwarded-Port", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "https://localhost:"+strconv.Itoa(port)+"/api/something", http.NoBody)
|
||||
req.Header.Set("X-Forwarded-Proto", "https")
|
||||
req.Header.Set("X-Forwarded-Port", "443")
|
||||
require.NoError(t, err)
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
t.Logf("%+v", resp.Header)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "response /123/something", string(body))
|
||||
assert.Equal(t, "reproxy", resp.Header.Get("App-Name"))
|
||||
assert.Equal(t, "v1", resp.Header.Get("h1"))
|
||||
assert.Equal(t, "vv1", resp.Header.Get("hh1"))
|
||||
assert.Equal(t, "vv2", resp.Header.Get("hh2"))
|
||||
})
|
||||
|
||||
t.Run("to 127.0.0.1", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "https://127.0.0.1:"+strconv.Itoa(port)+"/api/something", http.NoBody)
|
||||
req.Header.Set("X-Forwarded-Proto", "https")
|
||||
req.Header.Set("X-Forwarded-Port", "443")
|
||||
require.NoError(t, err)
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
t.Logf("%+v", resp.Header)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "response /567/something", string(body))
|
||||
assert.Equal(t, "reproxy", resp.Header.Get("App-Name"))
|
||||
assert.Equal(t, "v1", resp.Header.Get("h1"))
|
||||
assert.Equal(t, "vv1", resp.Header.Get("hh1"))
|
||||
assert.Equal(t, "vv2", resp.Header.Get("hh2"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestHttp_DoWithAssets(t *testing.T) {
|
||||
port := rand.Intn(10000) + 40000
|
||||
cc := NewCacheControl(time.Hour * 12)
|
||||
|
||||
37
app/proxy/testdata/localhost.crt
vendored
37
app/proxy/testdata/localhost.crt
vendored
@@ -1,18 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC5TCCAc2gAwIBAgIJALiRj0+veRc9MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
||||
BAMMCWxvY2FsaG9zdDAeFw0yMTA0MjcwNzQ1MzlaFw0yMTA1MjcwNzQ1MzlaMBQx
|
||||
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||
ggEBAKku5qZGexf0uvgVY+u8DOSnq8W10w+yQ1wSkMR5T0ag3hyimIDmDhNB3dI0
|
||||
5/B9IsIC9ZwUxOGHVCjP+TODXAGYIGYRx3BQb8si2369UXTQYNvVNQzPFdThjdcN
|
||||
gXUmLN08a3ZMdXDC62DcOcVv1+oHd1qbuugkHqwA9CEn/aMJeYPso/4cfbgXX0WD
|
||||
LEYkzgYwkyVf4JxyDWjm5d5fh/Tgpuu3lgH8qgKi51BmuSdiMiWsZ+AZykjpwAY6
|
||||
FsNHHmi1NZ1gLj/bzXNjziK50SIgIBiqTIxYdQBrYliRYC3RD252M4Sjk+WAOkVs
|
||||
RvLDvYLcl0kqclayzBr2qI/2RkECAwEAAaM6MDgwFAYDVR0RBA0wC4IJbG9jYWxo
|
||||
b3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEARvUEtFQC/l73/cTyEy24Om3t7uwHWzYRBQDz2dkj2V+OHuXaXKQW
|
||||
9ucv9DupNYxuXLVg93IPZgDGlFUZMlNnTvP5APBdQZyuoyZER7pqlJg8Sfo1BO5P
|
||||
KUqaspgdIzd8BmIYMkOaDgd/kOgqjGKjXJwHVvSl7oBcZ8WrxDBMuopXuFosYHVK
|
||||
z9ZsknqbxibgWBhwLKgDSOwLwVRIPIXlgJpSIyfDpQt0D3PbiFfcXYHqZ09ocZ/b
|
||||
mIRqF7/OpWW/15Zdo3+gqohWr5qoDZIH8gtBWRs6Ai3cbE/D5jSNdfDrrjRs0HkN
|
||||
GHmkcX4ABMze6SN7cWFpgeIvy1mxKfMoZw==
|
||||
-----END CERTIFICATE-----
|
||||
MIIDhzCCAm+gAwIBAgIUKMrw5NqY2c4v/ziNzA+JGC7keMgwDQYJKoZIhvcNAQEL
|
||||
BQAwUjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAklMMRAwDgYDVQQHDAdDaGljYWdv
|
||||
MRAwDgYDVQQKDAdyZXByb3h5MRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMjQwMjA2
|
||||
MDQ1NDIxWhgPMjA1MTA2MjQwNDU0MjFaMFIxCzAJBgNVBAYTAlVTMQswCQYDVQQI
|
||||
DAJJTDEQMA4GA1UEBwwHQ2hpY2FnbzEQMA4GA1UECgwHcmVwcm94eTESMBAGA1UE
|
||||
AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxvql
|
||||
fklS0YOZhy2KmP+LlGvYpt2j5GgUr7FWXS/nUdYPtT8GhTzhP6AuVO5a63vmUuoY
|
||||
XP61DtnirC571eIpgxNiZSUzRYn/IFR75BT025hZ6hwpAU+6ccpJjbQs48O74cgS
|
||||
xL+QML2/zqgWIvT9hZg5+/fi8gO76Gcwyi/r1pwk4Gac1HJTdicQes5AewUuFQt+
|
||||
AdN/VSklzDmQAn+mgWmXqxnTMgccGBlsiiYTjKkBSIrUB5TEXIpASzU12EzF8LCU
|
||||
mG2g4/wUGgKAXEUXI/KGdhm83XR7a0vWRsKNZDokNIeFfohr0JI1h1uJNM+2bfN5
|
||||
bTaLEjnxxwnw7j+ApwIDAQABo1MwUTAdBgNVHQ4EFgQUYiSDgICi9jUqX3K5hDXz
|
||||
sZlksBswHwYDVR0jBBgwFoAUYiSDgICi9jUqX3K5hDXzsZlksBswDwYDVR0TAQH/
|
||||
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEArSpccPKHbnS4Xc0SUdqhBiEpM49v
|
||||
u3yVXvUFaFq6drIJNeAjmMundw4qPuSl8w56YVwzHwmv8OSAyb15RUl+1mSpT//i
|
||||
sIqn3Ph3y6AcnyrkobCYOPho4dZMTsuSPfa9WRuFdvpUuZcn9JlvzlPZeYs6ba32
|
||||
wZfGBu6We26u89dcUKstKLEWZOI6rvTwViDiNafpnQc2JmP8U27wkyQe0uRuwUUY
|
||||
nLlB44QmWWHgct2YJz7wIJ0R9LQB32rhvLvkDnpl2VRA87xl8Q4z6yGfZVSzkRtq
|
||||
2K8HX+VuCB3NB61tC+eYbNEehkcdfJmuXzO/fLcoMWKEH5Q1ExmPMn+BKQ==
|
||||
-----END CERTIFICATE-----
|
||||
54
app/proxy/testdata/localhost.key
vendored
54
app/proxy/testdata/localhost.key
vendored
@@ -1,28 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCpLuamRnsX9Lr4
|
||||
FWPrvAzkp6vFtdMPskNcEpDEeU9GoN4copiA5g4TQd3SNOfwfSLCAvWcFMThh1Qo
|
||||
z/kzg1wBmCBmEcdwUG/LItt+vVF00GDb1TUMzxXU4Y3XDYF1JizdPGt2THVwwutg
|
||||
3DnFb9fqB3dam7roJB6sAPQhJ/2jCXmD7KP+HH24F19FgyxGJM4GMJMlX+Cccg1o
|
||||
5uXeX4f04Kbrt5YB/KoCoudQZrknYjIlrGfgGcpI6cAGOhbDRx5otTWdYC4/281z
|
||||
Y84iudEiICAYqkyMWHUAa2JYkWAt0Q9udjOEo5PlgDpFbEbyw72C3JdJKnJWsswa
|
||||
9qiP9kZBAgMBAAECggEAcCZ7F3ZZWwQMfTAQ0NAT6++KWsGxbBJLvNlBxjx0ZOl2
|
||||
05ylY60dX36mQRZ5Ol55kArOLe1GpgpDq9pR4+gMMbJap87ZWoa31P0Ca/2r5bfM
|
||||
vW2UgS0116y9jfWR/8qSqwXGZuFAaMONrOPQGCWQB79zS0k4mXJ4MqVfMCuGY3Bs
|
||||
IkeyT96/pcYg36KeTGfvZOrX1GvH3udht5x2BxwuWdNjLEqL391OetnZe1H3NArs
|
||||
fklboxgc/G0kRfx6X9/pqB+zytqeYec1nqc13I+3z6xjD1a2dK7rldY6CAp0IhwU
|
||||
54hmu8MO/Laq3159xbB0BR48ClIwox+4z0pT5hDtEQKBgQDbfVMOma9TYmWGd7Or
|
||||
/iuOVS64Jm2vrGySg/JlSBFskogy1vTtzwuAWe/3NLy5FVt1W7WC2Wt8OM1LIsh1
|
||||
lBiWM4Fz2bqLAgu1Y48Y0DsNVtckgo1jmwT4i1Ub664NMVvsaXLNtiSWzf53Jmh9
|
||||
J5zyg9ZiLXA7q+P5QDpZdskmowKBgQDFU1jC0LoaQaw+vH06eIoXVWYYwU+xpAK+
|
||||
AXZv7N3nBafhYTaTfWT/j54xoJr4kCnavXADMZq3oeHzR20B9oc4F1qT/6rEzYlu
|
||||
pi7EtxXHf406Huf1uLOU8VckYEZd31i9dM0By7RD+EopYcI1TEIN1UR5XYv/bwHa
|
||||
tZHjAFoBywKBgQCjnrZG4QxRFb3nUt6OrYgcr6WHQ6Zq2heJ1XDiTaonjMiZVaL6
|
||||
kGjbgrAfUaIKO0CVqQsTgy7cSJ/JjiFvfToi5jxvd3TXYWwHCTPIZJpQ5Fa3cdci
|
||||
1JINEhkdGkECtrP29djOPyThgqhafDhSbDBUnTE4uPS8lvP4gAe/X4yuDwKBgQC6
|
||||
AGaavMWwGleSi3o/s3/3nrgufYnxmPg8woQx3MUPD3XALTKUtI6Pl4E2pn1t7/aE
|
||||
Ci2b1RZSInYqLBnEz+2GIf1vpIAEIvp5IozTQQF2m/Uz5A4iwYgFzbimwVmTAwVT
|
||||
ENZt6uZxa4n8l/nI46kgAPgaruNYU/sbfiuWHq65IQKBgCMYfLML4oeRt+Xm5wcy
|
||||
T+PrP0qKt20wW/nqn4TVjuO606ywD2aLS/AJ96k04maEEAebahy6ODoEjNb3erQW
|
||||
VGsMydDBZ0QlMs6x7LDh3JLP0+JNETCezd1Nl20ykjpaoZ8Unzf/gpgaVjZON+wF
|
||||
ON1xMW7NBrs9xvcjhBVgtn6r
|
||||
-----END PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDG+qV+SVLRg5mH
|
||||
LYqY/4uUa9im3aPkaBSvsVZdL+dR1g+1PwaFPOE/oC5U7lrre+ZS6hhc/rUO2eKs
|
||||
LnvV4imDE2JlJTNFif8gVHvkFPTbmFnqHCkBT7pxykmNtCzjw7vhyBLEv5Awvb/O
|
||||
qBYi9P2FmDn79+LyA7voZzDKL+vWnCTgZpzUclN2JxB6zkB7BS4VC34B039VKSXM
|
||||
OZACf6aBaZerGdMyBxwYGWyKJhOMqQFIitQHlMRcikBLNTXYTMXwsJSYbaDj/BQa
|
||||
AoBcRRcj8oZ2GbzddHtrS9ZGwo1kOiQ0h4V+iGvQkjWHW4k0z7Zt83ltNosSOfHH
|
||||
CfDuP4CnAgMBAAECggEAVx8xzOyf5XqAg26OS9VAMTlTQCS1ePGVdSPpk53A49Ud
|
||||
RZeV7EquuWQSRT+j8Y1rWIyFJFqlvh3qoMctk4WV9X1MTMsP+vekDGzRXhlK6Md5
|
||||
PwcbcSaOlPokYHYuXX+7SO2IQjs6EA1U6VAxeRbZ1l/Dq65q4Np/sQ9VjoGS+oDX
|
||||
ApTYm5lKiKjBzf4xJ9jE61YaC9phxE099Tl8CEDRUUCEFL7fd6I+cPpCZE6094P5
|
||||
OHjMJYXAONclhXCXmPeGjtio9VnGgrGaclnBzjHs94XcW+slXBZdzDubXsi5Uhb3
|
||||
6P+GVpuyhpgFLEqtAbl6HUcGtS/Gbq4uYW+2FhlpWQKBgQD5pmKiJ7P2W2a3gZto
|
||||
/Rb9r6Q2YnbtAPigKCaN6Ntzahrej1we7Qqi4lYS1z9YmRaXxyvySdNiTbYo/qLm
|
||||
XEK2F8AnJUpaEK0+QJ7EQbTww8bElhPnpG9246+qMTbUwSgf6sRZ+RToGMQ5EBTY
|
||||
deFgz4H0qXrDj2RQkOC1ayvDRQKBgQDMClBjsZa+FKoTWBGnHFlBzQQ9X0jAaSno
|
||||
sPPsd9N8pcHZ2P3NehSEGeCeRc8xcZZib4TK1APnRGg+56tX+QSvwGT4P8C5GHvM
|
||||
S3T8xojgpFK6JGai/jrcBWqOCa3xXrP3miiF8Es01Q2Wy3EuMffkBlUBgsW66PPU
|
||||
A3W4UwWc+wKBgGtz4iBJVnxC+wMhFfMqfCrU3qlJ2EZKlLjajz2lbE9Q7B+/NLda
|
||||
76kMImAZpXpM6hyJ7bBrdkBpkm4yq4rbSxt1PY+bzVTWuLqCtdNjNK4slfEnZ4nc
|
||||
jN1vQrzOUftg6BRUyA6x1v3PKyYkddR1aHxy1EyqZdyma1cCBLYRWtTBAoGAUpD5
|
||||
5t2+OjzyddF1k0INfGsSBCPCtNnZc6fnjREQK6iHwTflvHhiRPKTynhFV6S3Ti4C
|
||||
dnFFAxjTdmEZHQhPtS8NrMdfnYci0ZDXTlKooP7d2yVPwzVNbCtk6wVPthS0jsV7
|
||||
EHgkdsSgMx0wN5lQzp0hWPMqQHBz+p9Ly8MMynECgYEAr+zCEd1v3n6okfaZKFV9
|
||||
czy1jigLgXOdDSzqAe8FE53hFQiCkYn5fj7byNRYrCmUb1dtoQJsM7AmN1LkWVv3
|
||||
5hC8FKHS78SBkeCRplWIr329z+xoBrV+9b4DubUQXACW7zQh911404TdbZMjGohW
|
||||
oJdJyZA2raAm/gaOyTIqDz0=
|
||||
-----END PRIVATE KEY-----
|
||||
Reference in New Issue
Block a user