Skip to content

Commit

Permalink
Merge pull request kubernetes#5887 from dschwar/force-use-forwarded-for
Browse files Browse the repository at this point in the history
Add force-enable-realip-module
  • Loading branch information
k8s-ci-robot authored Jul 17, 2020
2 parents 274d094 + d52141c commit e825af8
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
5 changes: 5 additions & 0 deletions docs/user-guide/nginx-configuration/configmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ The following table shows a configuration option's name, type, and the default v
|[proxy-stream-responses](#proxy-stream-responses)|int|1|
|[bind-address](#bind-address)|[]string|""|
|[use-forwarded-headers](#use-forwarded-headers)|bool|"false"|
|[enable-real-ip](#enable-real-ip)|bool|"false"|
|[forwarded-for-header](#forwarded-for-header)|string|"X-Forwarded-For"|
|[compute-full-forwarded-for](#compute-full-forwarded-for)|bool|"false"|
|[proxy-add-original-uri-header](#proxy-add-original-uri-header)|bool|"false"|
Expand Down Expand Up @@ -745,6 +746,10 @@ If true, NGINX passes the incoming `X-Forwarded-*` headers to upstreams. Use thi

If false, NGINX ignores incoming `X-Forwarded-*` headers, filling them with the request information it sees. Use this option if NGINX is exposed directly to the internet, or it's behind a L3/packet-based load balancer that doesn't alter the source IP in the packets.

## enable-real-ip

`enable-real-ip` enables the configuration of [http://nginx.org/en/docs/http/ngx_http_realip_module.html](http://nginx.org/en/docs/http/ngx_http_realip_module.html). Specific attributes of the module can be configured further by using `forwarded-for-header` and `proxy-real-ip-cidr` settings.

## forwarded-for-header

Sets the header field for identifying the originating IP address of a client. _**default:**_ X-Forwarded-For
Expand Down
4 changes: 4 additions & 0 deletions internal/ingress/controller/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,9 @@ type Configuration struct {
// Sets whether to use incoming X-Forwarded headers.
UseForwardedHeaders bool `json:"use-forwarded-headers"`

// Sets whether to enable the real ip module
EnableRealIp bool `json:"enable-real-ip"`

// Sets the header field for identifying the originating IP address of a client
// Default is X-Forwarded-For
ForwardedForHeader string `json:"forwarded-for-header,omitempty"`
Expand Down Expand Up @@ -712,6 +715,7 @@ func NewDefault() Configuration {
EnableUnderscoresInHeaders: false,
ErrorLogLevel: errorLevel,
UseForwardedHeaders: false,
EnableRealIp: false,
ForwardedForHeader: "X-Forwarded-For",
ComputeFullForwardedFor: false,
ProxyAddOriginalURIHeader: false,
Expand Down
2 changes: 1 addition & 1 deletion rootfs/etc/nginx/template/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ http {

{{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}}
{{/* we use the value of the real IP for the geo_ip module */}}
{{ if or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol }}
{{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIp }}
{{ if $cfg.UseProxyProtocol }}
real_ip_header proxy_protocol;
{{ else }}
Expand Down
113 changes: 113 additions & 0 deletions test/e2e/settings/enable_real_ip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package settings

import (
"fmt"
"net/http"
"strings"

"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"

"k8s.io/ingress-nginx/test/e2e/framework"
)

var _ = framework.DescribeSetting("enable-real-ip", func() {
f := framework.NewDefaultFramework("enable-real-ip")

setting := "enable-real-ip"

ginkgo.BeforeEach(func() {
f.NewEchoDeployment()
f.UpdateNginxConfigMapData(setting, "false")
})

ginkgo.It("trusts X-Forwarded-For header only when setting is true", func() {
host := "forwarded-for-header"

f.UpdateNginxConfigMapData(setting, "true")

ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)

f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name "+host) &&
!strings.Contains(server, "proxy_set_header X-Forwarded-Proto $full_x_forwarded_proto;")
})

ginkgo.By("ensuring single values are parsed correctly")
body := f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("X-Forwarded-Port", "1234").
WithHeader("X-Forwarded-Proto", "myproto").
WithHeader("X-Forwarded-For", "1.2.3.4").
WithHeader("X-Forwarded-Host", "myhost").
Expect().
Status(http.StatusOK).
Body().
Raw()

assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("host=myhost"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-host=myhost"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-proto=myproto"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-port=1234"))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("host=%s", host))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-host=%s", host))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-proto=http"))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-port=80"))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-for=1.2.3.4"))
})

ginkgo.It("should not trust X-Forwarded-For header when setting is false", func() {
host := "forwarded-for-header"

f.UpdateNginxConfigMapData(setting, "false")

f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil))

f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name "+host) &&
strings.Contains(server, "proxy_set_header X-Forwarded-Proto $pass_access_scheme;")
})

body := f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("X-Forwarded-Port", "1234").
WithHeader("X-Forwarded-Proto", "myproto").
WithHeader("X-Forwarded-For", "1.2.3.4").
WithHeader("X-Forwarded-Host", "myhost").
Expect().
Status(http.StatusOK).
Body().
Raw()

assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("host=%s", host))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-port=80"))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-proto=http"))
assert.Contains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-original-forwarded-for=1.2.3.4"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("host=myhost"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-host=myhost"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-proto=myproto"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-port=1234"))
assert.NotContains(ginkgo.GinkgoT(), body, fmt.Sprintf("x-forwarded-for=1.2.3.4"))
})
})

0 comments on commit e825af8

Please sign in to comment.