Merge pull request #1212 from danielqsj/bind-address

Add option to specify addresses on which the server will accept
This commit is contained in:
Manuel Alejandro de Brito Fontes 2017-08-25 12:05:52 -04:00 committed by GitHub
commit d2546d0291
5 changed files with 97 additions and 8 deletions

View file

@ -468,6 +468,8 @@ The default mime type list to compress is: `application/atom+xml application/jav
**add-headers:** Sets custom headers from a configmap before sending traffic to the client. See `proxy-set-headers` [example](https://github.com/kubernetes/ingress/tree/master/examples/customization/custom-headers/nginx) **add-headers:** Sets custom headers from a configmap before sending traffic to the client. See `proxy-set-headers` [example](https://github.com/kubernetes/ingress/tree/master/examples/customization/custom-headers/nginx)
**bind-address:** Sets the addresses on which the server will accept requests instead of *. It should be noted that these addresses must exist in the runtime environment or the controller will crash loop.
### Default configuration options ### Default configuration options
The following table shows the options, the default value and a description. The following table shows the options, the default value and a description.
@ -521,6 +523,7 @@ The following table shows the options, the default value and a description.
|whitelist-source-range|permit all| |whitelist-source-range|permit all|
|worker-processes|number of CPUs| |worker-processes|number of CPUs|
|limit-conn-zone-variable|$binary_remote_addr| |limit-conn-zone-variable|$binary_remote_addr|
|bind-address||
### Websockets ### Websockets

View file

@ -342,12 +342,19 @@ type Configuration struct {
// If no data is transmitted within this time, the connection is closed. // If no data is transmitted within this time, the connection is closed.
// http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_timeout // http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_timeout
ProxyStreamTimeout string `json:"proxy-stream-timeout,omitempty"` ProxyStreamTimeout string `json:"proxy-stream-timeout,omitempty"`
// Sets the ipv4 addresses on which the server will accept requests.
BindAddressIpv4 []string `json:"bind-address-ipv4,omitempty"`
// Sets the ipv6 addresses on which the server will accept requests.
BindAddressIpv6 []string `json:"bind-address-ipv6,omitempty"`
} }
// NewDefault returns the default nginx configuration // NewDefault returns the default nginx configuration
func NewDefault() Configuration { func NewDefault() Configuration {
defIPCIDR := make([]string, 0) defIPCIDR := make([]string, 0)
defIPCIDR = append(defIPCIDR, "0.0.0.0/0") defIPCIDR = append(defIPCIDR, "0.0.0.0/0")
defBindAddress := make([]string, 0)
cfg := Configuration{ cfg := Configuration{
AllowBackendServerHeader: false, AllowBackendServerHeader: false,
AccessLogPath: "/var/log/nginx/access.log", AccessLogPath: "/var/log/nginx/access.log",
@ -414,6 +421,8 @@ func NewDefault() Configuration {
}, },
UpstreamKeepaliveConnections: 0, UpstreamKeepaliveConnections: 0,
LimitConnZoneVariable: defaultLimitConnZoneVariable, LimitConnZoneVariable: defaultLimitConnZoneVariable,
BindAddressIpv4: defBindAddress,
BindAddressIpv6: defBindAddress,
} }
if glog.V(5) { if glog.V(5) {

View file

@ -17,6 +17,8 @@ limitations under the License.
package template package template
import ( import (
"fmt"
"net"
"strconv" "strconv"
"strings" "strings"
@ -24,6 +26,7 @@ import (
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"k8s.io/ingress/controllers/nginx/pkg/config" "k8s.io/ingress/controllers/nginx/pkg/config"
ing_net "k8s.io/ingress/core/pkg/net"
) )
const ( const (
@ -31,6 +34,7 @@ const (
skipAccessLogUrls = "skip-access-log-urls" skipAccessLogUrls = "skip-access-log-urls"
whitelistSourceRange = "whitelist-source-range" whitelistSourceRange = "whitelist-source-range"
proxyRealIPCIDR = "proxy-real-ip-cidr" proxyRealIPCIDR = "proxy-real-ip-cidr"
bindAddress = "bind-address"
) )
// ReadConfig obtains the configuration defined by the user merged with the defaults. // ReadConfig obtains the configuration defined by the user merged with the defaults.
@ -47,6 +51,8 @@ func ReadConfig(src map[string]string) config.Configuration {
skipUrls := make([]string, 0) skipUrls := make([]string, 0)
whitelist := make([]string, 0) whitelist := make([]string, 0)
proxylist := make([]string, 0) proxylist := make([]string, 0)
bindAddressIpv4List := make([]string, 0)
bindAddressIpv6List := make([]string, 0)
if val, ok := conf[customHTTPErrors]; ok { if val, ok := conf[customHTTPErrors]; ok {
delete(conf, customHTTPErrors) delete(conf, customHTTPErrors)
@ -73,12 +79,29 @@ func ReadConfig(src map[string]string) config.Configuration {
} else { } else {
proxylist = append(proxylist, "0.0.0.0/0") proxylist = append(proxylist, "0.0.0.0/0")
} }
if val, ok := conf[bindAddress]; ok {
delete(conf, bindAddress)
for _, i := range strings.Split(val, ",") {
ns := net.ParseIP(i)
if ns != nil {
if ing_net.IsIPV6(ns) {
bindAddressIpv6List = append(bindAddressIpv6List, fmt.Sprintf("[%v]", ns))
} else {
bindAddressIpv4List = append(bindAddressIpv4List, fmt.Sprintf("%v", ns))
}
} else {
glog.Warningf("%v is not a valid textual representation of an IP address", i)
}
}
}
to := config.NewDefault() to := config.NewDefault()
to.CustomHTTPErrors = filterErrors(errors) to.CustomHTTPErrors = filterErrors(errors)
to.SkipAccessLogURLs = skipUrls to.SkipAccessLogURLs = skipUrls
to.WhitelistSourceRange = whitelist to.WhitelistSourceRange = whitelist
to.ProxyRealIPCIDR = proxylist to.ProxyRealIPCIDR = proxylist
to.BindAddressIpv4 = bindAddressIpv4List
to.BindAddressIpv6 = bindAddressIpv6List
config := &mapstructure.DecoderConfig{ config := &mapstructure.DecoderConfig{
Metadata: nil, Metadata: nil,

View file

@ -45,6 +45,7 @@ func TestMergeConfigMapToStruct(t *testing.T) {
"enable-dynamic-tls-records": "false", "enable-dynamic-tls-records": "false",
"gzip-types": "text/html", "gzip-types": "text/html",
"proxy-real-ip-cidr": "1.1.1.1/8,2.2.2.2/24", "proxy-real-ip-cidr": "1.1.1.1/8,2.2.2.2/24",
"bind-address": "1.1.1.1,2.2.2.2,3.3.3,2001:db8:a0b:12f0::1,3731:54:65fe:2::a7,33:33:33::33::33",
} }
def := config.NewDefault() def := config.NewDefault()
def.CustomHTTPErrors = []int{300, 400} def.CustomHTTPErrors = []int{300, 400}
@ -58,6 +59,8 @@ func TestMergeConfigMapToStruct(t *testing.T) {
def.UseProxyProtocol = true def.UseProxyProtocol = true
def.GzipTypes = "text/html" def.GzipTypes = "text/html"
def.ProxyRealIPCIDR = []string{"1.1.1.1/8", "2.2.2.2/24"} def.ProxyRealIPCIDR = []string{"1.1.1.1/8", "2.2.2.2/24"}
def.BindAddressIpv4 = []string{"1.1.1.1", "2.2.2.2"}
def.BindAddressIpv6 = []string{"[2001:db8:a0b:12f0::1]", "[3731:54:65fe:2::a7]"}
to := ReadConfig(conf) to := ReadConfig(conf)
if diff := pretty.Compare(to, def); diff != "" { if diff := pretty.Compare(to, def); diff != "" {

View file

@ -319,12 +319,22 @@ http {
{{/* Build server redirects (from/to www) */}} {{/* Build server redirects (from/to www) */}}
{{ range $hostname, $to := .RedirectServers }} {{ range $hostname, $to := .RedirectServers }}
server { server {
{{ range $address := $all.Cfg.BindAddressIpv4 }}
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} ssl;
{{ else }}
listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}; listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
listen {{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} ssl; listen {{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} ssl;
{{ end }}
{{ if $IsIPV6Enabled }} {{ if $IsIPV6Enabled }}
{{ range $address := $all.Cfg.BindAddressIpv6 }}
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }};
{{ else }}
listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}; listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
listen [::]:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }}; listen [::]:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }};
{{ end }} {{ end }}
{{ end }}
server_name {{ $hostname }}; server_name {{ $hostname }};
return 301 $scheme://{{ $to }}$request_uri; return 301 $scheme://{{ $to }}$request_uri;
} }
@ -350,8 +360,8 @@ http {
# Use the port {{ $all.ListenPorts.Status }} (random value just to avoid known ports) as default port for nginx. # Use the port {{ $all.ListenPorts.Status }} (random value just to avoid known ports) as default port for nginx.
# Changing this value requires a change in: # Changing this value requires a change in:
# https://github.com/kubernetes/ingress/blob/master/controllers/nginx/pkg/cmd/controller/nginx.go # https://github.com/kubernetes/ingress/blob/master/controllers/nginx/pkg/cmd/controller/nginx.go
listen {{ $all.ListenPorts.Status }} default_server reuseport backlog={{ .BacklogSize }}; listen 127.0.0.1:{{ $all.ListenPorts.Status }} default_server reuseport backlog={{ $all.BacklogSize }};
{{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Status }} default_server reuseport backlog={{ .BacklogSize }};{{ end }} {{ if $IsIPV6Enabled }}listen [::1]:{{ $all.ListenPorts.Status }} default_server reuseport backlog={{ $all.BacklogSize }};{{ end }}
set $proxy_upstream_name "-"; set $proxy_upstream_name "-";
location {{ $healthzURI }} { location {{ $healthzURI }} {
@ -394,7 +404,7 @@ http {
# default server for services without endpoints # default server for services without endpoints
server { server {
listen {{ $all.ListenPorts.Default }}; listen 127.0.0.1:{{ $all.ListenPorts.Default }};
set $proxy_upstream_name "-"; set $proxy_upstream_name "-";
location / { location / {
@ -430,8 +440,18 @@ stream {
{{ end }} {{ end }}
} }
server { server {
{{ range $address := $all.Cfg.BindAddressIpv4 }}
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
{{ else }}
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }}; listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
{{ if $IsIPV6Enabled }}listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};{{ end }} {{ end }}
{{ if $IsIPV6Enabled }}
{{ range $address := $all.Cfg.BindAddressIpv6 }}
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
{{ else }}
listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
{{ end }}
{{ end }}
proxy_timeout {{ $cfg.ProxyStreamTimeout }}; proxy_timeout {{ $cfg.ProxyStreamTimeout }};
proxy_pass tcp-{{ $tcpServer.Port }}-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}; proxy_pass tcp-{{ $tcpServer.Port }}-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }};
} }
@ -447,8 +467,18 @@ stream {
} }
server { server {
{{ range $address := $all.Cfg.BindAddressIpv4 }}
listen {{ $address }}:{{ $udpServer.Port }} udp;
{{ else }}
listen {{ $udpServer.Port }} udp; listen {{ $udpServer.Port }} udp;
{{ if $IsIPV6Enabled }}listen [::]:{{ $udpServer.Port }} udp;{{ end }} {{ end }}
{{ if $IsIPV6Enabled }}
{{ range $address := $all.Cfg.BindAddressIpv6 }}
listen {{ $address }}:{{ $udpServer.Port }} udp;
{{ else }}
listen [::]:{{ $udpServer.Port }} udp;
{{ end }}
{{ end }}
proxy_responses 1; proxy_responses 1;
proxy_timeout {{ $cfg.ProxyStreamTimeout }}; proxy_timeout {{ $cfg.ProxyStreamTimeout }};
proxy_pass udp-{{ $udpServer.Port }}-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}; proxy_pass udp-{{ $udpServer.Port }}-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }};
@ -518,14 +548,35 @@ stream {
{{ define "SERVER" }} {{ define "SERVER" }}
{{ $all := .First }} {{ $all := .First }}
{{ $server := .Second }} {{ $server := .Second }}
{{ range $address := $all.Cfg.BindAddressIpv4 }}
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}};
{{ else }}
listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}}; listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}};
{{ if $all.IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{ end }};{{ end }} {{ end }}
{{ if $all.IsIPV6Enabled }}
{{ range $address := $all.Cfg.BindAddressIpv6 }}
listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{ end }};
{{ else }}
listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{ end }};
{{ end }}
{{ end }}
set $proxy_upstream_name "-"; set $proxy_upstream_name "-";
{{/* Listen on {{ $all.ListenPorts.SSLProxy }} because port {{ $all.ListenPorts.HTTPS }} is used in the TLS sni server */}} {{/* Listen on {{ $all.ListenPorts.SSLProxy }} because port {{ $all.ListenPorts.HTTPS }} is used in the TLS sni server */}}
{{/* This listener must always have proxy_protocol enabled, because the SNI listener forwards on source IP info in it. */}} {{/* This listener must always have proxy_protocol enabled, because the SNI listener forwards on source IP info in it. */}}
{{ if not (empty $server.SSLCertificate) }}listen {{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol {{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }}; {{ if not (empty $server.SSLCertificate) }}
{{ if $all.IsIPV6Enabled }}{{ if not (empty $server.SSLCertificate) }}listen [::]:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};{{ end }} {{ range $address := $all.Cfg.BindAddressIpv4 }}
listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol {{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
{{ else }}
listen {{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol {{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
{{ end }}
{{ if $all.IsIPV6Enabled }}
{{ range $address := $all.Cfg.BindAddressIpv6 }}
{{ if not (empty $server.SSLCertificate) }}listen {{ $address }}:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
{{ else }}
{{ if not (empty $server.SSLCertificate) }}listen [::]:{{ if $all.IsSSLPassthroughEnabled }}{{ $all.ListenPorts.SSLProxy }} proxy_protocol{{ else }}{{ $all.ListenPorts.HTTPS }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }}{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
{{ end }}
{{ end }}
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}} {{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
# PEM sha: {{ $server.SSLPemChecksum }} # PEM sha: {{ $server.SSLPemChecksum }}
ssl_certificate {{ $server.SSLCertificate }}; ssl_certificate {{ $server.SSLCertificate }};