mirror of https://github.com/gofiber/fiber.git
🔥Feature: Add support for TrustProxy (#3170)
* 🔥 Feature: Add `TrustProxyConfig` and rename `EnableTrustedProxyCheck` to `TrustProxy` * 📚 Doc: Document TrustProxyConfig usage and migration * 🚨 Test: Validate and Benchmark use of TrustProxyConfig * 🩹 Fix: typo in RequestMethods docstring * 🩹 Fix: typos in TrustProxy docstring and JSON tags * 🩹 Fix: Move `TrustProxyConfig.Loopback` to beginning of if-statement * 🎨 Style: Cleanup spacing for Test_Ctx_IsProxyTrusted * 📚 Doc: Replace `whitelist` with `allowlist` for clarity * 📚 Doc: Improve `TrustProxy` doc wording * 🩹 Fix: validate IP addresses in `App.handleTrustedProxy` * 🩹 Fix: grammatical errors and capitalize "TLS"pull/3174/head
parent
7b3a36f22f
commit
298975a982
|
@ -561,8 +561,10 @@ import (
|
|||
|
||||
func main() {
|
||||
app := fiber.New(fiber.Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"0.0.0.0", "1.1.1.1/30"}, // IP address or IP address range
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: fiber.TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.0", "1.1.1.1/30"}, // IP address or IP address range
|
||||
},
|
||||
ProxyHeader: fiber.HeaderXForwardedFor,
|
||||
})
|
||||
|
||||
|
|
77
app.go
77
app.go
|
@ -330,29 +330,31 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa
|
|||
// For example, the Host HTTP header is usually used to return the requested host.
|
||||
// But when you’re behind a proxy, the actual host may be stored in an X-Forwarded-Host header.
|
||||
//
|
||||
// If you are behind a proxy, you should enable TrustedProxyCheck to prevent header spoofing.
|
||||
// If you enable EnableTrustedProxyCheck and leave TrustedProxies empty Fiber will skip
|
||||
// If you are behind a proxy, you should enable TrustProxy to prevent header spoofing.
|
||||
// If you enable TrustProxy and do not provide a TrustProxyConfig, Fiber will skip
|
||||
// all headers that could be spoofed.
|
||||
// If request ip in TrustedProxies whitelist then:
|
||||
// If the request IP is in the TrustProxyConfig.Proxies allowlist, then:
|
||||
// 1. c.Scheme() get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header
|
||||
// 2. c.IP() get value from ProxyHeader header.
|
||||
// 3. c.Host() and c.Hostname() get value from X-Forwarded-Host header
|
||||
// But if request ip NOT in Trusted Proxies whitelist then:
|
||||
// 1. c.Scheme() WON't get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header,
|
||||
// will return https in case when tls connection is handled by the app, of http otherwise
|
||||
// But if the request IP is NOT in the TrustProxyConfig.Proxies allowlist, then:
|
||||
// 1. c.Scheme() WON'T get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header,
|
||||
// will return https when a TLS connection is handled by the app, or http otherwise.
|
||||
// 2. c.IP() WON'T get value from ProxyHeader header, will return RemoteIP() from fasthttp context
|
||||
// 3. c.Host() and c.Hostname() WON'T get value from X-Forwarded-Host header, fasthttp.Request.URI().Host()
|
||||
// will be used to get the hostname.
|
||||
//
|
||||
// Default: false
|
||||
EnableTrustedProxyCheck bool `json:"enable_trusted_proxy_check"`
|
||||
|
||||
// Read EnableTrustedProxyCheck doc.
|
||||
// To automatically trust all loopback, link-local, or private IP addresses,
|
||||
// without manually adding them to the TrustProxyConfig.Proxies allowlist,
|
||||
// you can set TrustProxyConfig.Loopback, TrustProxyConfig.LinkLocal, or TrustProxyConfig.Private to true.
|
||||
//
|
||||
// Default: []string
|
||||
TrustedProxies []string `json:"trusted_proxies"`
|
||||
trustedProxiesMap map[string]struct{}
|
||||
trustedProxyRanges []*net.IPNet
|
||||
// Default: false
|
||||
TrustProxy bool `json:"trust_proxy"`
|
||||
|
||||
// Read TrustProxy doc.
|
||||
//
|
||||
// Default: DefaultTrustProxyConfig
|
||||
TrustProxyConfig TrustProxyConfig `json:"trust_proxy_config"`
|
||||
|
||||
// If set to true, c.IP() and c.IPs() will validate IP addresses before returning them.
|
||||
// Also, c.IP() will return only the first valid IP rather than just the raw header
|
||||
|
@ -372,7 +374,7 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa
|
|||
// Default: nil
|
||||
StructValidator StructValidator
|
||||
|
||||
// RequestMethods provides customizibility for HTTP methods. You can add/remove methods as you wish.
|
||||
// RequestMethods provides customizability for HTTP methods. You can add/remove methods as you wish.
|
||||
//
|
||||
// Optional. Default: DefaultMethods
|
||||
RequestMethods []string
|
||||
|
@ -385,6 +387,36 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa
|
|||
EnableSplittingOnParsers bool `json:"enable_splitting_on_parsers"`
|
||||
}
|
||||
|
||||
// Default TrustProxyConfig
|
||||
var DefaultTrustProxyConfig = TrustProxyConfig{}
|
||||
|
||||
// TrustProxyConfig is a struct for configuring trusted proxies if Config.TrustProxy is true.
|
||||
type TrustProxyConfig struct {
|
||||
ips map[string]struct{}
|
||||
|
||||
// Proxies is a list of trusted proxy IP addresses or CIDR ranges.
|
||||
//
|
||||
// Default: []string
|
||||
Proxies []string `json:"proxies"`
|
||||
|
||||
ranges []*net.IPNet
|
||||
|
||||
// LinkLocal enables trusting all link-local IP ranges (e.g., 169.254.0.0/16, fe80::/10).
|
||||
//
|
||||
// Default: false
|
||||
LinkLocal bool `json:"link_local"`
|
||||
|
||||
// Loopback enables trusting all loopback IP ranges (e.g., 127.0.0.0/8, ::1/128).
|
||||
//
|
||||
// Default: false
|
||||
Loopback bool `json:"loopback"`
|
||||
|
||||
// Private enables trusting all private IP ranges (e.g., 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7).
|
||||
//
|
||||
// Default: false
|
||||
Private bool `json:"private"`
|
||||
}
|
||||
|
||||
// RouteMessage is some message need to be print when server starts
|
||||
type RouteMessage struct {
|
||||
name string
|
||||
|
@ -510,8 +542,8 @@ func New(config ...Config) *App {
|
|||
app.config.RequestMethods = DefaultMethods
|
||||
}
|
||||
|
||||
app.config.trustedProxiesMap = make(map[string]struct{}, len(app.config.TrustedProxies))
|
||||
for _, ipAddress := range app.config.TrustedProxies {
|
||||
app.config.TrustProxyConfig.ips = make(map[string]struct{}, len(app.config.TrustProxyConfig.Proxies))
|
||||
for _, ipAddress := range app.config.TrustProxyConfig.Proxies {
|
||||
app.handleTrustedProxy(ipAddress)
|
||||
}
|
||||
|
||||
|
@ -529,17 +561,22 @@ func New(config ...Config) *App {
|
|||
return app
|
||||
}
|
||||
|
||||
// Adds an ip address to trustedProxyRanges or trustedProxiesMap based on whether it is an IP range or not
|
||||
// Adds an ip address to TrustProxyConfig.ranges or TrustProxyConfig.ips based on whether it is an IP range or not
|
||||
func (app *App) handleTrustedProxy(ipAddress string) {
|
||||
if strings.Contains(ipAddress, "/") {
|
||||
_, ipNet, err := net.ParseCIDR(ipAddress)
|
||||
if err != nil {
|
||||
log.Warnf("IP range %q could not be parsed: %v", ipAddress, err)
|
||||
} else {
|
||||
app.config.trustedProxyRanges = append(app.config.trustedProxyRanges, ipNet)
|
||||
app.config.TrustProxyConfig.ranges = append(app.config.TrustProxyConfig.ranges, ipNet)
|
||||
}
|
||||
} else {
|
||||
app.config.trustedProxiesMap[ipAddress] = struct{}{}
|
||||
ip := net.ParseIP(ipAddress)
|
||||
if ip == nil {
|
||||
log.Warnf("IP address %q could not be parsed", ipAddress)
|
||||
} else {
|
||||
app.config.TrustProxyConfig.ips[ipAddress] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
24
ctx.go
24
ctx.go
|
@ -155,7 +155,7 @@ type TLSHandler struct {
|
|||
|
||||
// GetClientInfo Callback function to set ClientHelloInfo
|
||||
// Must comply with the method structure of https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/tls/common.go;l=554-563
|
||||
// Since we overlay the method of the tls config in the listener method
|
||||
// Since we overlay the method of the TLS config in the listener method
|
||||
func (t *TLSHandler) GetClientInfo(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
t.clientHelloInfo = info
|
||||
return nil, nil //nolint:nilnil // Not returning anything useful here is probably fine
|
||||
|
@ -684,7 +684,7 @@ func (c *DefaultCtx) GetReqHeaders() map[string][]string {
|
|||
// while `Hostname` refers specifically to the name assigned to a device on a network, excluding any port information.
|
||||
// Example: URL: https://example.com:8080 -> Host: example.com:8080
|
||||
// Make copies or use the Immutable setting instead.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
func (c *DefaultCtx) Host() string {
|
||||
if c.IsProxyTrusted() {
|
||||
if host := c.Get(HeaderXForwardedHost); len(host) > 0 {
|
||||
|
@ -702,7 +702,7 @@ func (c *DefaultCtx) Host() string {
|
|||
// Returned value is only valid within the handler. Do not store any references.
|
||||
// Example: URL: https://example.com:8080 -> Hostname: example.com
|
||||
// Make copies or use the Immutable setting instead.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
func (c *DefaultCtx) Hostname() string {
|
||||
addr, _ := parseAddr(c.Host())
|
||||
|
||||
|
@ -720,7 +720,7 @@ func (c *DefaultCtx) Port() string {
|
|||
|
||||
// IP returns the remote IP address of the request.
|
||||
// If ProxyHeader and IP Validation is configured, it will parse that header and return the first valid IP address.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
func (c *DefaultCtx) IP() string {
|
||||
if c.IsProxyTrusted() && len(c.app.config.ProxyHeader) > 0 {
|
||||
return c.extractIPFromHeader(c.app.config.ProxyHeader)
|
||||
|
@ -1116,7 +1116,7 @@ func (c *DefaultCtx) Path(override ...string) string {
|
|||
}
|
||||
|
||||
// Scheme contains the request protocol string: http or https for TLS requests.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
func (c *DefaultCtx) Scheme() string {
|
||||
if c.fasthttp.IsTLS() {
|
||||
return schemeHTTPS
|
||||
|
@ -1819,20 +1819,26 @@ func (c *DefaultCtx) configDependentPaths() {
|
|||
}
|
||||
|
||||
// IsProxyTrusted checks trustworthiness of remote ip.
|
||||
// If EnableTrustedProxyCheck false, it returns true
|
||||
// If Config.TrustProxy false, it returns true
|
||||
// IsProxyTrusted can check remote ip by proxy ranges and ip map.
|
||||
func (c *DefaultCtx) IsProxyTrusted() bool {
|
||||
if !c.app.config.EnableTrustedProxyCheck {
|
||||
if !c.app.config.TrustProxy {
|
||||
return true
|
||||
}
|
||||
|
||||
ip := c.fasthttp.RemoteIP()
|
||||
|
||||
if _, trusted := c.app.config.trustedProxiesMap[ip.String()]; trusted {
|
||||
if (c.app.config.TrustProxyConfig.Loopback && ip.IsLoopback()) ||
|
||||
(c.app.config.TrustProxyConfig.Private && ip.IsPrivate()) ||
|
||||
(c.app.config.TrustProxyConfig.LinkLocal && ip.IsLinkLocalUnicast()) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, ipNet := range c.app.config.trustedProxyRanges {
|
||||
if _, trusted := c.app.config.TrustProxyConfig.ips[ip.String()]; trusted {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, ipNet := range c.app.config.TrustProxyConfig.ranges {
|
||||
if ipNet.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -127,19 +127,19 @@ type Ctx interface {
|
|||
// while `Hostname` refers specifically to the name assigned to a device on a network, excluding any port information.
|
||||
// Example: URL: https://example.com:8080 -> Host: example.com:8080
|
||||
// Make copies or use the Immutable setting instead.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
Host() string
|
||||
// Hostname contains the hostname derived from the X-Forwarded-Host or Host HTTP header using the c.Host() method.
|
||||
// Returned value is only valid within the handler. Do not store any references.
|
||||
// Example: URL: https://example.com:8080 -> Hostname: example.com
|
||||
// Make copies or use the Immutable setting instead.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
Hostname() string
|
||||
// Port returns the remote port of the request.
|
||||
Port() string
|
||||
// IP returns the remote IP address of the request.
|
||||
// If ProxyHeader and IP Validation is configured, it will parse that header and return the first valid IP address.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
IP() string
|
||||
// extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear.
|
||||
// When IP validation is enabled, any invalid IPs will be omitted.
|
||||
|
@ -209,7 +209,7 @@ type Ctx interface {
|
|||
// Optionally, you could override the path.
|
||||
Path(override ...string) string
|
||||
// Scheme contains the request protocol string: http or https for TLS requests.
|
||||
// Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy.
|
||||
// Please use Config.TrustProxy to prevent header spoofing, in case when your app is behind the proxy.
|
||||
Scheme() string
|
||||
// Protocol returns the HTTP protocol of request: HTTP/1.1 and HTTP/2.
|
||||
Protocol() string
|
||||
|
@ -315,7 +315,7 @@ type Ctx interface {
|
|||
// here the features for caseSensitive, decoded paths, strict paths are evaluated
|
||||
configDependentPaths()
|
||||
// IsProxyTrusted checks trustworthiness of remote ip.
|
||||
// If EnableTrustedProxyCheck false, it returns true
|
||||
// If Config.TrustProxy false, it returns true
|
||||
// IsProxyTrusted can check remote ip by proxy ranges and ip map.
|
||||
IsProxyTrusted() bool
|
||||
// IsFromLocal will return true if request came from local.
|
||||
|
|
428
ctx_test.go
428
ctx_test.go
|
@ -1572,7 +1572,7 @@ func Test_Ctx_Host_UntrustedProxy(t *testing.T) {
|
|||
t.Parallel()
|
||||
// Don't trust any proxy
|
||||
{
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{}})
|
||||
app := New(Config{TrustProxy: true, TrustProxyConfig: TrustProxyConfig{Proxies: []string{}}})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1581,7 +1581,7 @@ func Test_Ctx_Host_UntrustedProxy(t *testing.T) {
|
|||
}
|
||||
// Trust to specific proxy list
|
||||
{
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.8.0.0", "0.8.0.1"}})
|
||||
app := New(Config{TrustProxy: true, TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.8.0.0", "0.8.0.1"}}})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1594,7 +1594,7 @@ func Test_Ctx_Host_UntrustedProxy(t *testing.T) {
|
|||
func Test_Ctx_Host_TrustedProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
{
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0", "0.8.0.1"}})
|
||||
app := New(Config{TrustProxy: true, TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0", "0.8.0.1"}}})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1607,7 +1607,7 @@ func Test_Ctx_Host_TrustedProxy(t *testing.T) {
|
|||
func Test_Ctx_Host_TrustedProxyRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0/30"}})
|
||||
app := New(Config{TrustProxy: true, TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0/30"}}})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1619,7 +1619,7 @@ func Test_Ctx_Host_TrustedProxyRange(t *testing.T) {
|
|||
func Test_Ctx_Host_UntrustedProxyRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"1.0.0.0/30"}})
|
||||
app := New(Config{TrustProxy: true, TrustProxyConfig: TrustProxyConfig{Proxies: []string{"1.0.0.0/30"}}})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1653,7 +1653,7 @@ func Test_Ctx_IsProxyTrusted(t *testing.T) {
|
|||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: false,
|
||||
TrustProxy: false,
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.True(t, c.IsProxyTrusted())
|
||||
|
@ -1661,26 +1661,16 @@ func Test_Ctx_IsProxyTrusted(t *testing.T) {
|
|||
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustProxy: true,
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.False(t, c.IsProxyTrusted())
|
||||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
|
||||
TrustedProxies: []string{},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.False(t, c.IsProxyTrusted())
|
||||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
|
||||
TrustedProxies: []string{
|
||||
"127.0.0.1",
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
@ -1688,10 +1678,9 @@ func Test_Ctx_IsProxyTrusted(t *testing.T) {
|
|||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
|
||||
TrustedProxies: []string{
|
||||
"127.0.0.1/8",
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"127.0.0.1"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
@ -1699,10 +1688,19 @@ func Test_Ctx_IsProxyTrusted(t *testing.T) {
|
|||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
|
||||
TrustedProxies: []string{
|
||||
"0.0.0.0",
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"127.0.0.1/8"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.False(t, c.IsProxyTrusted())
|
||||
}
|
||||
{
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.0"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
@ -1710,10 +1708,9 @@ func Test_Ctx_IsProxyTrusted(t *testing.T) {
|
|||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
|
||||
TrustedProxies: []string{
|
||||
"0.0.0.1/31",
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.1/31"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
@ -1721,10 +1718,39 @@ func Test_Ctx_IsProxyTrusted(t *testing.T) {
|
|||
}
|
||||
{
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
|
||||
TrustedProxies: []string{
|
||||
"0.0.0.1/31junk",
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.1/31junk"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.False(t, c.IsProxyTrusted())
|
||||
}
|
||||
{
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Private: true,
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.False(t, c.IsProxyTrusted())
|
||||
}
|
||||
{
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Loopback: true,
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
require.False(t, c.IsProxyTrusted())
|
||||
}
|
||||
{
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
LinkLocal: true,
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
@ -1758,7 +1784,10 @@ func Benchmark_Ctx_Hostname(b *testing.B) {
|
|||
}
|
||||
// Trust to specific proxy list
|
||||
{
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.8.0.0", "0.8.0.1"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.8.0.0", "0.8.0.1"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1771,7 +1800,10 @@ func Benchmark_Ctx_Hostname(b *testing.B) {
|
|||
func Test_Ctx_Hostname_TrustedProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
{
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0", "0.8.0.1"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0", "0.8.0.1"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1784,7 +1816,10 @@ func Test_Ctx_Hostname_TrustedProxy(t *testing.T) {
|
|||
func Test_Ctx_Hostname_TrustedProxy_Multiple(t *testing.T) {
|
||||
t.Parallel()
|
||||
{
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0", "0.8.0.1"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0", "0.8.0.1"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com, google2.com")
|
||||
|
@ -1797,7 +1832,10 @@ func Test_Ctx_Hostname_TrustedProxy_Multiple(t *testing.T) {
|
|||
func Test_Ctx_Hostname_TrustedProxyRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0/30"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0/30"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1809,7 +1847,10 @@ func Test_Ctx_Hostname_TrustedProxyRange(t *testing.T) {
|
|||
func Test_Ctx_Hostname_UntrustedProxyRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"1.0.0.0/30"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"1.0.0.0/30"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
|
@ -1927,7 +1968,11 @@ func Test_Ctx_IP_ProxyHeader_With_IP_Validation(t *testing.T) {
|
|||
// go test -run Test_Ctx_IP_UntrustedProxy
|
||||
func Test_Ctx_IP_UntrustedProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.8.0.1"}, ProxyHeader: HeaderXForwardedFor})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.8.0.1"}},
|
||||
ProxyHeader: HeaderXForwardedFor,
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().Header.Set(HeaderXForwardedFor, "0.0.0.1")
|
||||
require.Equal(t, "0.0.0.0", c.IP())
|
||||
|
@ -1936,7 +1981,11 @@ func Test_Ctx_IP_UntrustedProxy(t *testing.T) {
|
|||
// go test -run Test_Ctx_IP_TrustedProxy
|
||||
func Test_Ctx_IP_TrustedProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0"}, ProxyHeader: HeaderXForwardedFor})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0"}},
|
||||
ProxyHeader: HeaderXForwardedFor,
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().Header.Set(HeaderXForwardedFor, "0.0.0.1")
|
||||
require.Equal(t, "0.0.0.1", c.IP())
|
||||
|
@ -2613,7 +2662,7 @@ func Benchmark_Ctx_Scheme(b *testing.B) {
|
|||
// go test -run Test_Ctx_Scheme_TrustedProxy
|
||||
func Test_Ctx_Scheme_TrustedProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0"}})
|
||||
app := New(Config{TrustProxy: true, TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0"}}})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
||||
c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS)
|
||||
|
@ -2638,7 +2687,10 @@ func Test_Ctx_Scheme_TrustedProxy(t *testing.T) {
|
|||
// go test -run Test_Ctx_Scheme_TrustedProxyRange
|
||||
func Test_Ctx_Scheme_TrustedProxyRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.0.0.0/30"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.0.0.0/30"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
||||
c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS)
|
||||
|
@ -2663,7 +2715,10 @@ func Test_Ctx_Scheme_TrustedProxyRange(t *testing.T) {
|
|||
// go test -run Test_Ctx_Scheme_UntrustedProxyRange
|
||||
func Test_Ctx_Scheme_UntrustedProxyRange(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"1.1.1.1/30"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"1.1.1.1/30"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
||||
c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS)
|
||||
|
@ -2688,7 +2743,10 @@ func Test_Ctx_Scheme_UntrustedProxyRange(t *testing.T) {
|
|||
// go test -run Test_Ctx_Scheme_UnTrustedProxy
|
||||
func Test_Ctx_Scheme_UnTrustedProxy(t *testing.T) {
|
||||
t.Parallel()
|
||||
app := New(Config{EnableTrustedProxyCheck: true, TrustedProxies: []string{"0.8.0.1"}})
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{Proxies: []string{"0.8.0.1"}},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
||||
c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS)
|
||||
|
@ -6173,7 +6231,7 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check simple
|
||||
b.Run("WithProxyCheckSimple", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustProxy: true,
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
|
@ -6189,7 +6247,7 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check simple in parallel
|
||||
b.Run("WithProxyCheckSimpleParallel", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustProxy: true,
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -6207,8 +6265,10 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check
|
||||
b.Run("WithProxyCheck", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"0.0.0.0"},
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.0"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
|
@ -6224,8 +6284,198 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check in parallel
|
||||
b.Run("WithProxyCheckParallel", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"0.0.0.0"},
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.0"},
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
for pb.Next() {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private
|
||||
b.Run("WithProxyCheckAllowPrivate", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Private: true,
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private in parallel
|
||||
b.Run("WithProxyCheckAllowPrivateParallel", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Private: true,
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
for pb.Next() {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private as subnets
|
||||
b.Run("WithProxyCheckAllowPrivateAsSubnets", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fc00::/7"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private as subnets in parallel
|
||||
b.Run("WithProxyCheckAllowPrivateAsSubnetsParallel", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fc00::/7"},
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
for pb.Next() {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private, loopback, and link-local
|
||||
b.Run("WithProxyCheckAllowAll", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Private: true,
|
||||
Loopback: true,
|
||||
LinkLocal: true,
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private, loopback, and link-local in parallel
|
||||
b.Run("WithProxyCheckAllowAllParallel", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Private: true,
|
||||
Loopback: true,
|
||||
LinkLocal: true,
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
for pb.Next() {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private, loopback, and link-local as subnets
|
||||
b.Run("WithProxyCheckAllowAllowAllAsSubnets", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{
|
||||
// Link-local
|
||||
"169.254.0.0/16",
|
||||
"fe80::/10",
|
||||
// Loopback
|
||||
"127.0.0.0/8",
|
||||
"::1/128",
|
||||
// Private
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16",
|
||||
"fc00::/7",
|
||||
},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
c.Request().Header.Set(HeaderXForwardedHost, "google1.com")
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for n := 0; n < b.N; n++ {
|
||||
c.IsProxyTrusted()
|
||||
}
|
||||
app.ReleaseCtx(c)
|
||||
})
|
||||
|
||||
// Scenario with trusted proxy check allow private, loopback, and link-local as subnets in parallel
|
||||
b.Run("WithProxyCheckAllowAllowAllAsSubnetsParallel", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{
|
||||
// Link-local
|
||||
"169.254.0.0/16",
|
||||
"fe80::/10",
|
||||
// Loopback
|
||||
"127.0.0.0/8",
|
||||
"::1/128",
|
||||
// Private
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16",
|
||||
"fc00::/7",
|
||||
},
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -6243,8 +6493,10 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check with subnet
|
||||
b.Run("WithProxyCheckSubnet", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"0.0.0.0/8"},
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.0/8"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
|
@ -6260,8 +6512,10 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check with subnet in parallel
|
||||
b.Run("WithProxyCheckParallelSubnet", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"0.0.0.0/8"},
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"0.0.0.0/8"},
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -6279,8 +6533,10 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check with multiple subnet
|
||||
b.Run("WithProxyCheckMultipleSubnet", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"192.168.0.0/24", "10.0.0.0/16", "0.0.0.0/8"},
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"192.168.0.0/24", "10.0.0.0/16", "0.0.0.0/8"},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
c.Request().SetRequestURI("http://google.com/test")
|
||||
|
@ -6296,8 +6552,10 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check with multiple subnet in parallel
|
||||
b.Run("WithProxyCheckParallelMultipleSubnet", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{"192.168.0.0/24", "10.0.0.0/16", "0.0.0.0/8"},
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{"192.168.0.0/24", "10.0.0.0/16", "0.0.0.0/8"},
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
@ -6315,17 +6573,19 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check with all subnets
|
||||
b.Run("WithProxyCheckAllSubnets", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{
|
||||
"127.0.0.0/8", // Loopback addresses
|
||||
"169.254.0.0/16", // Link-Local addresses
|
||||
"fe80::/10", // Link-Local addresses
|
||||
"192.168.0.0/16", // Private Network addresses
|
||||
"172.16.0.0/12", // Private Network addresses
|
||||
"10.0.0.0/8", // Private Network addresses
|
||||
"fc00::/7", // Unique Local addresses
|
||||
"173.245.48.0/20", // My custom range
|
||||
"0.0.0.0/8", // All IPv4 addresses
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{
|
||||
"127.0.0.0/8", // Loopback addresses
|
||||
"169.254.0.0/16", // Link-Local addresses
|
||||
"fe80::/10", // Link-Local addresses
|
||||
"192.168.0.0/16", // Private Network addresses
|
||||
"172.16.0.0/12", // Private Network addresses
|
||||
"10.0.0.0/8", // Private Network addresses
|
||||
"fc00::/7", // Unique Local addresses
|
||||
"173.245.48.0/20", // My custom range
|
||||
"0.0.0.0/8", // All IPv4 addresses
|
||||
},
|
||||
},
|
||||
})
|
||||
c := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
|
@ -6342,17 +6602,19 @@ func Benchmark_Ctx_IsProxyTrusted(b *testing.B) {
|
|||
// Scenario with trusted proxy check with all subnets in parallel
|
||||
b.Run("WithProxyCheckParallelAllSubnets", func(b *testing.B) {
|
||||
app := New(Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{
|
||||
"127.0.0.0/8", // Loopback addresses
|
||||
"169.254.0.0/16", // Link-Local addresses
|
||||
"fe80::/10", // Link-Local addresses
|
||||
"192.168.0.0/16", // Private Network addresses
|
||||
"172.16.0.0/12", // Private Network addresses
|
||||
"10.0.0.0/8", // Private Network addresses
|
||||
"fc00::/7", // Unique Local addresses
|
||||
"173.245.48.0/20", // My custom range
|
||||
"0.0.0.0/8", // All IPv4 addresses
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: TrustProxyConfig{
|
||||
Proxies: []string{
|
||||
"127.0.0.0/8", // Loopback addresses
|
||||
"169.254.0.0/16", // Link-Local addresses
|
||||
"fe80::/10", // Link-Local addresses
|
||||
"192.168.0.0/16", // Private Network addresses
|
||||
"172.16.0.0/12", // Private Network addresses
|
||||
"10.0.0.0/8", // Private Network addresses
|
||||
"fc00::/7", // Unique Local addresses
|
||||
"173.245.48.0/20", // My custom range
|
||||
"0.0.0.0/8", // All IPv4 addresses
|
||||
},
|
||||
},
|
||||
})
|
||||
b.ReportAllocs()
|
||||
|
|
|
@ -831,7 +831,7 @@ app.Get("/", func(c fiber.Ctx) error {
|
|||
## IsProxyTrusted
|
||||
|
||||
Checks trustworthiness of remote ip.
|
||||
If [`EnableTrustedProxyCheck`](fiber.md#enabletrustedproxycheck) false, it returns true
|
||||
If [`TrustProxy`](fiber.md#trustproxy) false, it returns true
|
||||
IsProxyTrusted can check remote ip by proxy ranges and ip map.
|
||||
|
||||
```go title="Signature"
|
||||
|
@ -841,10 +841,13 @@ func (c Ctx) IsProxyTrusted() bool
|
|||
```go title="Example"
|
||||
|
||||
app := fiber.New(fiber.Config{
|
||||
// EnableTrustedProxyCheck enables the trusted proxy check
|
||||
EnableTrustedProxyCheck: true,
|
||||
// TrustedProxies is a list of trusted proxy IP addresses
|
||||
TrustedProxies: []string{"0.8.0.0", "0.8.0.1"},
|
||||
// TrustProxy enables the trusted proxy check
|
||||
TrustProxy: true,
|
||||
// TrustProxyConfig allows for configuring trusted proxies.
|
||||
// Proxies is a list of trusted proxy IP ranges/addresses
|
||||
TrustProxyConfig: fiber.TrustProxyConfig{
|
||||
Proxies: []string{"0.8.0.0", "0.8.0.1"},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
@ -1640,7 +1643,7 @@ app.Post("/", func(c fiber.Ctx) error {
|
|||
Contains the request protocol string: http or https for TLS requests.
|
||||
|
||||
:::info
|
||||
Please use [`Config.EnableTrustedProxyCheck`](fiber.md#enabletrustedproxycheck) to prevent header spoofing, in case when your app is behind the proxy.
|
||||
Please use [`Config.TrustProxy`](fiber.md#trustproxy) to prevent header spoofing, in case when your app is behind the proxy.
|
||||
:::
|
||||
|
||||
```go title="Signature"
|
||||
|
|
|
@ -42,45 +42,45 @@ app := fiber.New(fiber.Config{
|
|||
|
||||
#### Config fields
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
|---------------------------------------------------------------------------------------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
|
||||
| <Reference id="appname">AppName</Reference> | `string` | This allows to setup app name for the app | `""` |
|
||||
| <Reference id="bodylimit">BodyLimit</Reference> | `int` | Sets the maximum allowed size for a request body, if the size exceeds the configured limit, it sends `413 - Request Entity Too Large` response. | `4 * 1024 * 1024` |
|
||||
| <Reference id="casesensitive">CaseSensitive</Reference> | `bool` | When enabled, `/Foo` and `/foo` are different routes. When disabled, `/Foo`and `/foo` are treated the same. | `false` |
|
||||
| <Reference id="colorscheme">ColorScheme</Reference> | [`Colors`](https://github.com/gofiber/fiber/blob/master/color.go) | You can define custom color scheme. They'll be used for startup message, route list and some middlewares. | [`DefaultColors`](https://github.com/gofiber/fiber/blob/master/color.go) |
|
||||
| <Reference id="compressedfilesuffixes">CompressedFileSuffixes</Reference> | `map[string]string` | Adds a suffix to the original file name and tries saving the resulting compressed file under the new file name. | `{"gzip": ".fiber.gz", "br": ".fiber.br", "zstd": ".fiber.zst"}` |
|
||||
| <Reference id="concurrency">Concurrency</Reference> | `int` | Maximum number of concurrent connections. | `256 * 1024` |
|
||||
| <Reference id="disabledefaultcontenttype">DisableDefaultContentType</Reference> | `bool` | When set to true, causes the default Content-Type header to be excluded from the Response. | `false` |
|
||||
| <Reference id="disabledefaultdate">DisableDefaultDate</Reference> | `bool` | When set to true causes the default date header to be excluded from the response. | `false` |
|
||||
| <Reference id="disableheadernormalizing">DisableHeaderNormalizing</Reference> | `bool` | By default all header names are normalized: conteNT-tYPE -> Content-Type | `false` |
|
||||
| <Reference id="disablekeepalive">DisableKeepalive</Reference> | `bool` | Disable keep-alive connections, the server will close incoming connections after sending the first response to the client | `false` |
|
||||
| <Reference id="disablepreparsemultipartform">DisablePreParseMultipartForm</Reference> | `bool` | Will not pre parse Multipart Form data if set to true. This option is useful for servers that desire to treat multipart form data as a binary blob, or choose when to parse the data. | `false` |
|
||||
| <Reference id="enableipvalidation">EnableIPValidation</Reference> | `bool` | If set to true, `c.IP()` and `c.IPs()` will validate IP addresses before returning them. Also, `c.IP()` will return only the first valid IP rather than just the raw header value that may be a comma separated string.<br /><br />**WARNING:** There is a small performance cost to doing this validation. Keep disabled if speed is your only concern and your application is behind a trusted proxy that already validates this header. | `false` |
|
||||
| <Reference id="enablesplittingonparsers">EnableSplittingOnParsers</Reference> | `bool` | EnableSplittingOnParsers splits the query/body/header parameters by comma when it's true. <br /> <br /> For example, you can use it to parse multiple values from a query parameter like this: `/api?foo=bar,baz == foo[]=bar&foo[]=baz` | `false` |
|
||||
| <Reference id="enabletrustedproxycheck">EnableTrustedProxyCheck</Reference> | `bool` | When set to true, fiber will check whether proxy is trusted, using TrustedProxies list. <br /><br />By default `c.Protocol()` will get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header, `c.IP()` will get value from `ProxyHeader` header, `c.Hostname()` will get value from X-Forwarded-Host header. <br /> If `EnableTrustedProxyCheck` is true, and `RemoteIP` is in the list of `TrustedProxies` `c.Protocol()`, `c.IP()`, and `c.Hostname()` will have the same behaviour when `EnableTrustedProxyCheck` disabled, if `RemoteIP` isn't in the list, `c.Protocol()` will return https in case when tls connection is handled by the app, or http otherwise, `c.IP()` will return RemoteIP() from fasthttp context, `c.Hostname()` will return `fasthttp.Request.URI().Host()` | `false` |
|
||||
| <Reference id="errorhandler">ErrorHandler</Reference> | `ErrorHandler` | ErrorHandler is executed when an error is returned from fiber.Handler. Mounted fiber error handlers are retained by the top-level app and applied on prefix associated requests. | `DefaultErrorHandler` |
|
||||
| <Reference id="getonly">GETOnly</Reference> | `bool` | Rejects all non-GET requests if set to true. This option is useful as anti-DoS protection for servers accepting only GET requests. The request size is limited by ReadBufferSize if GETOnly is set. | `false` |
|
||||
| <Reference id="idletimeout">IdleTimeout</Reference> | `time.Duration` | The maximum amount of time to wait for the next request when keep-alive is enabled. If IdleTimeout is zero, the value of ReadTimeout is used. | `nil` |
|
||||
| <Reference id="immutable">Immutable</Reference> | `bool` | When enabled, all values returned by context methods are immutable. By default, they are valid until you return from the handler; see issue [\#185](https://github.com/gofiber/fiber/issues/185). | `false` |
|
||||
| <Reference id="jsondecoder">JSONDecoder</Reference> | `utils.JSONUnmarshal` | Allowing for flexibility in using another json library for decoding. | `json.Unmarshal` |
|
||||
| <Reference id="jsonencoder">JSONEncoder</Reference> | `utils.JSONMarshal` | Allowing for flexibility in using another json library for encoding. | `json.Marshal` |
|
||||
| <Reference id="passlocalstoviews">PassLocalsToViews</Reference> | `bool` | PassLocalsToViews Enables passing of the locals set on a fiber.Ctx to the template engine. See our **Template Middleware** for supported engines. | `false` |
|
||||
| <Reference id="proxyheader">ProxyHeader</Reference> | `string` | This will enable `c.IP()` to return the value of the given header key. By default `c.IP()`will return the Remote IP from the TCP connection, this property can be useful if you are behind a load balancer e.g. _X-Forwarded-\*_. | `""` |
|
||||
| <Reference id="readbuffersize">ReadBufferSize</Reference> | `int` | per-connection buffer size for requests' reading. This also limits the maximum header size. Increase this buffer if your clients send multi-KB RequestURIs and/or multi-KB headers \(for example, BIG cookies\). | `4096` |
|
||||
| <Reference id="readtimeout">ReadTimeout</Reference> | `time.Duration` | The amount of time allowed to read the full request, including the body. The default timeout is unlimited. | `nil` |
|
||||
| <Reference id="reducememoryusage">ReduceMemoryUsage</Reference> | `bool` | Aggressively reduces memory usage at the cost of higher CPU usage if set to true. | `false` |
|
||||
| <Reference id="requestmethods">RequestMethods</Reference> | `[]string` | RequestMethods provides customizibility for HTTP methods. You can add/remove methods as you wish. | `DefaultMethods` |
|
||||
| <Reference id="serverheader">ServerHeader</Reference> | `string` | Enables the `Server` HTTP header with the given value. | `""` |
|
||||
| <Reference id="streamrequestbody">StreamRequestBody</Reference> | `bool` | StreamRequestBody enables request body streaming, and calls the handler sooner when given body is larger than the current limit. | `false` |
|
||||
| <Reference id="strictrouting">StrictRouting</Reference> | `bool` | When enabled, the router treats `/foo` and `/foo/` as different. Otherwise, the router treats `/foo` and `/foo/` as the same. | `false` |
|
||||
| <Reference id="structvalidator">StructValidator</Reference> | `StructValidator` | If you want to validate header/form/query... automatically when to bind, you can define struct validator. Fiber doesn't have default validator, so it'll skip validator step if you don't use any validator. | `nil` |
|
||||
| <Reference id="trustedproxies">TrustedProxies</Reference> | `[]string` | Contains the list of trusted proxy IP's. Look at `EnableTrustedProxyCheck` doc. <br /> <br /> It can take IP or IP range addresses. | `nil` |
|
||||
| <Reference id="unescapepath">UnescapePath</Reference> | `bool` | Converts all encoded characters in the route back before setting the path for the context, so that the routing can also work with URL encoded special characters | `false` |
|
||||
| <Reference id="views">Views</Reference> | `Views` | Views is the interface that wraps the Render function. See our **Template Middleware** for supported engines. | `nil` |
|
||||
| <Reference id="viewslayout">ViewsLayout</Reference> | `string` | Views Layout is the global layout for all template render until override on Render function. See our **Template Middleware** for supported engines. | `""` |
|
||||
| <Reference id="writebuffersize">WriteBufferSize</Reference> | `int` | Per-connection buffer size for responses' writing. | `4096` |
|
||||
| <Reference id="writetimeout">WriteTimeout</Reference> | `time.Duration` | The maximum duration before timing out writes of the response. The default timeout is unlimited. | `nil` |
|
||||
| <Reference id="xmlencoder">XMLEncoder</Reference> | `utils.XMLMarshal` | Allowing for flexibility in using another XML library for encoding. | `xml.Marshal` |
|
||||
| Property | Type | Description | Default |
|
||||
|---------------------------------------------------------------------------------------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
|
||||
| <Reference id="appname">AppName</Reference> | `string` | This allows to setup app name for the app | `""` |
|
||||
| <Reference id="bodylimit">BodyLimit</Reference> | `int` | Sets the maximum allowed size for a request body, if the size exceeds the configured limit, it sends `413 - Request Entity Too Large` response. | `4 * 1024 * 1024` |
|
||||
| <Reference id="casesensitive">CaseSensitive</Reference> | `bool` | When enabled, `/Foo` and `/foo` are different routes. When disabled, `/Foo`and `/foo` are treated the same. | `false` |
|
||||
| <Reference id="colorscheme">ColorScheme</Reference> | [`Colors`](https://github.com/gofiber/fiber/blob/master/color.go) | You can define custom color scheme. They'll be used for startup message, route list and some middlewares. | [`DefaultColors`](https://github.com/gofiber/fiber/blob/master/color.go) |
|
||||
| <Reference id="compressedfilesuffixes">CompressedFileSuffixes</Reference> | `map[string]string` | Adds a suffix to the original file name and tries saving the resulting compressed file under the new file name. | `{"gzip": ".fiber.gz", "br": ".fiber.br", "zstd": ".fiber.zst"}` |
|
||||
| <Reference id="concurrency">Concurrency</Reference> | `int` | Maximum number of concurrent connections. | `256 * 1024` |
|
||||
| <Reference id="disabledefaultcontenttype">DisableDefaultContentType</Reference> | `bool` | When set to true, causes the default Content-Type header to be excluded from the Response. | `false` |
|
||||
| <Reference id="disabledefaultdate">DisableDefaultDate</Reference> | `bool` | When set to true causes the default date header to be excluded from the response. | `false` |
|
||||
| <Reference id="disableheadernormalizing">DisableHeaderNormalizing</Reference> | `bool` | By default all header names are normalized: conteNT-tYPE -> Content-Type | `false` |
|
||||
| <Reference id="disablekeepalive">DisableKeepalive</Reference> | `bool` | Disable keep-alive connections, the server will close incoming connections after sending the first response to the client | `false` |
|
||||
| <Reference id="disablepreparsemultipartform">DisablePreParseMultipartForm</Reference> | `bool` | Will not pre parse Multipart Form data if set to true. This option is useful for servers that desire to treat multipart form data as a binary blob, or choose when to parse the data. | `false` |
|
||||
| <Reference id="enableipvalidation">EnableIPValidation</Reference> | `bool` | If set to true, `c.IP()` and `c.IPs()` will validate IP addresses before returning them. Also, `c.IP()` will return only the first valid IP rather than just the raw header value that may be a comma separated string.<br /><br />**WARNING:** There is a small performance cost to doing this validation. Keep disabled if speed is your only concern and your application is behind a trusted proxy that already validates this header. | `false` |
|
||||
| <Reference id="enablesplittingonparsers">EnableSplittingOnParsers</Reference> | `bool` | EnableSplittingOnParsers splits the query/body/header parameters by comma when it's true. <br /> <br /> For example, you can use it to parse multiple values from a query parameter like this: `/api?foo=bar,baz == foo[]=bar&foo[]=baz` | `false` |
|
||||
| <Reference id="trustproxy">TrustProxy</Reference> | `bool` | When set to true, fiber will check whether proxy is trusted, using TrustProxyConfig.Proxies list. <br /><br />By default `c.Protocol()` will get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header, `c.IP()` will get value from `ProxyHeader` header, `c.Hostname()` will get value from X-Forwarded-Host header. <br /> If `TrustProxy` is true, and `RemoteIP` is in the list of `TrustProxyConfig.Proxies` `c.Protocol()`, `c.IP()`, and `c.Hostname()` will have the same behaviour when `TrustProxy` disabled, if `RemoteIP` isn't in the list, `c.Protocol()` will return https when a TLS connection is handled by the app, or http otherwise, `c.IP()` will return RemoteIP() from fasthttp context, `c.Hostname()` will return `fasthttp.Request.URI().Host()` | `false` |
|
||||
| <Reference id="errorhandler">ErrorHandler</Reference> | `ErrorHandler` | ErrorHandler is executed when an error is returned from fiber.Handler. Mounted fiber error handlers are retained by the top-level app and applied on prefix associated requests. | `DefaultErrorHandler` |
|
||||
| <Reference id="getonly">GETOnly</Reference> | `bool` | Rejects all non-GET requests if set to true. This option is useful as anti-DoS protection for servers accepting only GET requests. The request size is limited by ReadBufferSize if GETOnly is set. | `false` |
|
||||
| <Reference id="idletimeout">IdleTimeout</Reference> | `time.Duration` | The maximum amount of time to wait for the next request when keep-alive is enabled. If IdleTimeout is zero, the value of ReadTimeout is used. | `nil` |
|
||||
| <Reference id="immutable">Immutable</Reference> | `bool` | When enabled, all values returned by context methods are immutable. By default, they are valid until you return from the handler; see issue [\#185](https://github.com/gofiber/fiber/issues/185). | `false` |
|
||||
| <Reference id="jsondecoder">JSONDecoder</Reference> | `utils.JSONUnmarshal` | Allowing for flexibility in using another json library for decoding. | `json.Unmarshal` |
|
||||
| <Reference id="jsonencoder">JSONEncoder</Reference> | `utils.JSONMarshal` | Allowing for flexibility in using another json library for encoding. | `json.Marshal` |
|
||||
| <Reference id="passlocalstoviews">PassLocalsToViews</Reference> | `bool` | PassLocalsToViews Enables passing of the locals set on a fiber.Ctx to the template engine. See our **Template Middleware** for supported engines. | `false` |
|
||||
| <Reference id="proxyheader">ProxyHeader</Reference> | `string` | This will enable `c.IP()` to return the value of the given header key. By default `c.IP()`will return the Remote IP from the TCP connection, this property can be useful if you are behind a load balancer e.g. _X-Forwarded-\*_. | `""` |
|
||||
| <Reference id="readbuffersize">ReadBufferSize</Reference> | `int` | per-connection buffer size for requests' reading. This also limits the maximum header size. Increase this buffer if your clients send multi-KB RequestURIs and/or multi-KB headers \(for example, BIG cookies\). | `4096` |
|
||||
| <Reference id="readtimeout">ReadTimeout</Reference> | `time.Duration` | The amount of time allowed to read the full request, including the body. The default timeout is unlimited. | `nil` |
|
||||
| <Reference id="reducememoryusage">ReduceMemoryUsage</Reference> | `bool` | Aggressively reduces memory usage at the cost of higher CPU usage if set to true. | `false` |
|
||||
| <Reference id="requestmethods">RequestMethods</Reference> | `[]string` | RequestMethods provides customizability for HTTP methods. You can add/remove methods as you wish. | `DefaultMethods` |
|
||||
| <Reference id="serverheader">ServerHeader</Reference> | `string` | Enables the `Server` HTTP header with the given value. | `""` |
|
||||
| <Reference id="streamrequestbody">StreamRequestBody</Reference> | `bool` | StreamRequestBody enables request body streaming, and calls the handler sooner when given body is larger than the current limit. | `false` |
|
||||
| <Reference id="strictrouting">StrictRouting</Reference> | `bool` | When enabled, the router treats `/foo` and `/foo/` as different. Otherwise, the router treats `/foo` and `/foo/` as the same. | `false` |
|
||||
| <Reference id="structvalidator">StructValidator</Reference> | `StructValidator` | If you want to validate header/form/query... automatically when to bind, you can define struct validator. Fiber doesn't have default validator, so it'll skip validator step if you don't use any validator. | `nil` |
|
||||
| <Reference id="trustproxyconfig">TrustProxyConfig</Reference> | `TrustProxyConfig` | Configure trusted proxy IP's. Look at `TrustProxy` doc. <br /> <br /> `TrustProxyConfig.Proxies` can take IP or IP range addresses. | `nil` |
|
||||
| <Reference id="unescapepath">UnescapePath</Reference> | `bool` | Converts all encoded characters in the route back before setting the path for the context, so that the routing can also work with URL encoded special characters | `false` |
|
||||
| <Reference id="views">Views</Reference> | `Views` | Views is the interface that wraps the Render function. See our **Template Middleware** for supported engines. | `nil` |
|
||||
| <Reference id="viewslayout">ViewsLayout</Reference> | `string` | Views Layout is the global layout for all template render until override on Render function. See our **Template Middleware** for supported engines. | `""` |
|
||||
| <Reference id="writebuffersize">WriteBufferSize</Reference> | `int` | Per-connection buffer size for responses' writing. | `4096` |
|
||||
| <Reference id="writetimeout">WriteTimeout</Reference> | `time.Duration` | The maximum duration before timing out writes of the response. The default timeout is unlimited. | `nil` |
|
||||
| <Reference id="xmlencoder">XMLEncoder</Reference> | `utils.XMLMarshal` | Allowing for flexibility in using another XML library for encoding. | `xml.Marshal` |
|
||||
|
||||
## Server listening
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ panic: [CORS] Configuration error: When 'AllowCredentials' is set to true, 'Allo
|
|||
| AllowOrigins | `[]string` | AllowOrigins defines a list of origins that may access the resource. This supports subdomain matching, so you can use a value like "https://*.example.com" to allow any subdomain of example.com to submit requests. If the special wildcard `"*"` is present in the list, all origins will be allowed. | `["*"]` |
|
||||
| AllowOriginsFunc | `func(origin string) bool` | `AllowOriginsFunc` is a function that dynamically determines whether to allow a request based on its origin. If this function returns `true`, the 'Access-Control-Allow-Origin' response header will be set to the request's 'origin' header. This function is only used if the request's origin doesn't match any origin in `AllowOrigins`. | `nil` |
|
||||
| AllowPrivateNetwork | `bool` | Indicates whether the `Access-Control-Allow-Private-Network` response header should be set to `true`, allowing requests from private networks. This aligns with modern security practices for web applications interacting with private networks. | `false` |
|
||||
| ExposeHeaders | `string` | ExposeHeaders defines whitelist headers that clients are allowed to access. | `[]` |
|
||||
| ExposeHeaders | `string` | ExposeHeaders defines an allowlist of headers that clients are allowed to access. | `[]` |
|
||||
| MaxAge | `int` | MaxAge indicates how long (in seconds) the results of a preflight request can be cached. If you pass MaxAge 0, the Access-Control-Max-Age header will not be added and the browser will use 5 seconds by default. To disable caching completely, pass MaxAge value negative. It will set the Access-Control-Max-Age header to 0. | `0` |
|
||||
| Next | `func(fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
|
||||
|
||||
|
@ -191,7 +191,7 @@ The `AllowHeaders` option specifies which headers are allowed in the actual requ
|
|||
|
||||
The `AllowCredentials` option indicates whether the response to the request can be exposed when the credentials flag is true. If `AllowCredentials` is set to `true`, the middleware adds the header `Access-Control-Allow-Credentials: true` to the response. To prevent security vulnerabilities, `AllowCredentials` cannot be set to `true` if `AllowOrigins` is set to a wildcard (`*`).
|
||||
|
||||
The `ExposeHeaders` option defines a whitelist of headers that clients are allowed to access. If `ExposeHeaders` is set to `"X-Custom-Header"`, the middleware adds the header `Access-Control-Expose-Headers: X-Custom-Header` to the response.
|
||||
The `ExposeHeaders` option defines an allowlist of headers that clients are allowed to access. If `ExposeHeaders` is set to `"X-Custom-Header"`, the middleware adds the header `Access-Control-Expose-Headers: X-Custom-Header` to the response.
|
||||
|
||||
The `MaxAge` option indicates how long the results of a preflight request can be cached. If `MaxAge` is set to `3600`, the middleware adds the header `Access-Control-Max-Age: 3600` to the response.
|
||||
|
||||
|
@ -207,7 +207,7 @@ When configuring CORS, misconfiguration can potentially expose your application
|
|||
|
||||
- **Use Credentials Carefully**: If your application needs to support credentials in cross-origin requests, ensure `AllowCredentials` is set to `true` and specify exact origins in `AllowOrigins`. Do not use a wildcard origin in this case.
|
||||
|
||||
- **Limit Exposed Headers**: Only whitelist headers that are necessary for the client-side application by setting `ExposeHeaders` appropriately. This minimizes the risk of exposing sensitive information.
|
||||
- **Limit Exposed Headers**: Only allowlist headers that are necessary for the client-side application by setting `ExposeHeaders` appropriately. This minimizes the risk of exposing sensitive information.
|
||||
|
||||
### Common Pitfalls
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ id: earlydata
|
|||
The Early Data middleware for [Fiber](https://github.com/gofiber/fiber) adds support for TLS 1.3's early data ("0-RTT") feature.
|
||||
Citing [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446#section-2-3), when a client and server share a PSK, TLS 1.3 allows clients to send data on the first flight ("early data") to speed up the request, effectively reducing the regular 1-RTT request to a 0-RTT request.
|
||||
|
||||
Make sure to enable fiber's `EnableTrustedProxyCheck` config option before using this middleware in order to not trust bogus HTTP request headers of the client.
|
||||
Make sure to enable fiber's `TrustProxy` config option before using this middleware in order to not trust bogus HTTP request headers of the client.
|
||||
|
||||
Also be aware that enabling support for early data in your reverse proxy (e.g. nginx, as done with a simple `ssl_early_data on;`) makes requests replayable. Refer to the following documents before continuing:
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ We have made several changes to the Fiber app, including:
|
|||
- EnablePrefork -> previously Prefork
|
||||
- EnablePrintRoutes
|
||||
- ListenerNetwork -> previously Network
|
||||
- app.Config.EnabledTrustedProxyCheck -> has been moved to app.Config.TrustProxy
|
||||
- TrustedProxies -> has been moved to TrustProxyConfig.Proxies
|
||||
|
||||
### new methods
|
||||
|
||||
|
@ -386,6 +388,35 @@ app.Get("*", static.New("./public/index.html"))
|
|||
You have to put `*` to the end of the route if you don't define static route with `app.Use`.
|
||||
:::
|
||||
|
||||
#### Trusted Proxies
|
||||
|
||||
We've renamed `EnableTrustedProxyCheck` to `TrustProxy` and moved `TrustedProxies` to `TrustProxyConfig`.
|
||||
|
||||
```go
|
||||
// Before
|
||||
app := fiber.New(fiber.Config{
|
||||
// EnableTrustedProxyCheck enables the trusted proxy check.
|
||||
EnableTrustedProxyCheck: true,
|
||||
// TrustedProxies is a list of trusted proxy IP ranges/addresses.
|
||||
TrustedProxies: []string{"0.8.0.0", "127.0.0.0/8", "::1/128"},
|
||||
})
|
||||
```
|
||||
|
||||
```go
|
||||
// After
|
||||
app := fiber.New(fiber.Config{
|
||||
// TrustProxy enables the trusted proxy check
|
||||
TrustProxy: true,
|
||||
// TrustProxyConfig allows for configuring trusted proxies.
|
||||
TrustProxyConfig: fiber.TrustProxyConfig{
|
||||
// Proxies is a list of trusted proxy IP ranges/addresses.
|
||||
Proxies: []string{"0.8.0.0"},
|
||||
// Trust all loop-back IP addresses (127.0.0.0/8, ::1/128)
|
||||
Loopback: true,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 🗺 Router
|
||||
|
||||
The signatures for [`Add`](#middleware-registration) and [`Route`](#route-chaining) have been changed.
|
||||
|
|
|
@ -41,7 +41,7 @@ type Config struct {
|
|||
// Optional. Default value []string{}
|
||||
AllowHeaders []string
|
||||
|
||||
// ExposeHeaders defines a whitelist headers that clients are allowed to
|
||||
// ExposeHeaders defines an allowlist of headers that clients are allowed to
|
||||
// access.
|
||||
//
|
||||
// Optional. Default value []string{}.
|
||||
|
|
|
@ -173,17 +173,19 @@ func Test_EarlyData(t *testing.T) {
|
|||
trustedRun(t, app)
|
||||
})
|
||||
|
||||
t.Run("config with EnableTrustedProxyCheck", func(t *testing.T) {
|
||||
t.Run("config with TrustProxy", func(t *testing.T) {
|
||||
app := appWithConfig(t, &fiber.Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustProxy: true,
|
||||
})
|
||||
untrustedRun(t, app)
|
||||
})
|
||||
t.Run("config with EnableTrustedProxyCheck and trusted TrustedProxies", func(t *testing.T) {
|
||||
t.Run("config with TrustProxy and trusted TrustProxyConfig.Proxies", func(t *testing.T) {
|
||||
app := appWithConfig(t, &fiber.Config{
|
||||
EnableTrustedProxyCheck: true,
|
||||
TrustedProxies: []string{
|
||||
"0.0.0.0",
|
||||
TrustProxy: true,
|
||||
TrustProxyConfig: fiber.TrustProxyConfig{
|
||||
Proxies: []string{
|
||||
"0.0.0.0",
|
||||
},
|
||||
},
|
||||
})
|
||||
trustedRun(t, app)
|
||||
|
|
Loading…
Reference in New Issue