Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to disable SSL passthrough #1190

Merged
merged 1 commit into from
Aug 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 64 additions & 54 deletions controllers/nginx/pkg/cmd/controller/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,47 +87,8 @@ func newNGINXController() ingress.Controller {
configmap: &api_v1.ConfigMap{},
isIPV6Enabled: isIPv6Enabled(),
resolver: h,
proxy: &proxy{
Default: &server{
Hostname: "localhost",
IP: "127.0.0.1",
Port: 442,
ProxyProtocol: true,
},
},
}

listener, err := net.Listen("tcp", ":443")
if err != nil {
glog.Fatalf("%v", err)
}

proxyList := &proxyproto.Listener{Listener: listener}

// start goroutine that accepts tcp connections in port 443
go func() {
for {
var conn net.Conn
var err error

if n.isProxyProtocolEnabled {
// we need to wrap the listener in order to decode
// proxy protocol before handling the connection
conn, err = proxyList.Accept()
} else {
conn, err = listener.Accept()
}

if err != nil {
glog.Warningf("unexpected error accepting tcp connection: %v", err)
continue
}

glog.V(3).Infof("remote address %s to local %s", conn.RemoteAddr(), conn.LocalAddr())
go n.proxy.Handle(conn)
}
}()

fcgiListener, err := net.Listen("unix", fastCGISocket)
if err != nil {
glog.Fatalf("%v", err)
Expand Down Expand Up @@ -197,6 +158,8 @@ type NGINXController struct {
// returns true if proxy protocol es enabled
isProxyProtocolEnabled bool

isSSLPassthroughEnabled bool

proxy *proxy
}

Expand Down Expand Up @@ -320,6 +283,7 @@ func (n NGINXController) Info() *ingress.BackendInfo {
// ConfigureFlags allow to configure more flags before the parsing of
// command line arguments
func (n *NGINXController) ConfigureFlags(flags *pflag.FlagSet) {
flags.BoolVar(&n.isSSLPassthroughEnabled, "enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)
}

// OverrideFlags customize NGINX controller flags
Expand All @@ -337,6 +301,49 @@ func (n *NGINXController) OverrideFlags(flags *pflag.FlagSet) {

flags.Set("ingress-class", ic)
n.stats = newStatsCollector(wc, ic, n.binary)

if n.isSSLPassthroughEnabled {
glog.Info("starting TLS proxy for SSL passthrough")
n.proxy = &proxy{
Default: &server{
Hostname: "localhost",
IP: "127.0.0.1",
Port: 442,
ProxyProtocol: true,
},
}

listener, err := net.Listen("tcp", ":443")
if err != nil {
glog.Fatalf("%v", err)
}

proxyList := &proxyproto.Listener{Listener: listener}

// start goroutine that accepts tcp connections in port 443
go func() {
for {
var conn net.Conn
var err error

if n.isProxyProtocolEnabled {
// we need to wrap the listener in order to decode
// proxy protocol before handling the connection
conn, err = proxyList.Accept()
} else {
conn, err = listener.Accept()
}

if err != nil {
glog.Warningf("unexpected error accepting tcp connection: %v", err)
continue
}

glog.V(3).Infof("remote address %s to local %s", conn.RemoteAddr(), conn.LocalAddr())
go n.proxy.Handle(conn)
}
}()
}
}

// DefaultIngressClass just return the default ingress class
Expand Down Expand Up @@ -449,7 +456,9 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
})
}

n.proxy.ServerList = servers
if n.isSSLPassthroughEnabled {
n.proxy.ServerList = servers
}

// we need to check if the status module configuration changed
if cfg.EnableVtsStatus {
Expand Down Expand Up @@ -570,20 +579,21 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
cfg.SSLDHParam = sslDHParam

tc := config.TemplateConfig{
ProxySetHeaders: setHeaders,
AddHeaders: addHeaders,
MaxOpenFiles: maxOpenFiles,
BacklogSize: sysctlSomaxconn(),
Backends: ingressCfg.Backends,
PassthroughBackends: ingressCfg.PassthroughBackends,
Servers: ingressCfg.Servers,
TCPBackends: ingressCfg.TCPEndpoints,
UDPBackends: ingressCfg.UDPEndpoints,
HealthzURI: ngxHealthPath,
CustomErrors: len(cfg.CustomHTTPErrors) > 0,
Cfg: cfg,
IsIPV6Enabled: n.isIPV6Enabled && !cfg.DisableIpv6,
RedirectServers: redirectServers,
ProxySetHeaders: setHeaders,
AddHeaders: addHeaders,
MaxOpenFiles: maxOpenFiles,
BacklogSize: sysctlSomaxconn(),
Backends: ingressCfg.Backends,
PassthroughBackends: ingressCfg.PassthroughBackends,
Servers: ingressCfg.Servers,
TCPBackends: ingressCfg.TCPEndpoints,
UDPBackends: ingressCfg.UDPEndpoints,
HealthzURI: ngxHealthPath,
CustomErrors: len(cfg.CustomHTTPErrors) > 0,
Cfg: cfg,
IsIPV6Enabled: n.isIPV6Enabled && !cfg.DisableIpv6,
RedirectServers: redirectServers,
IsSSLPassthroughEnabled: n.isSSLPassthroughEnabled,
}

// We need to extract the endpoints to be used in the fastcgi error handler
Expand Down
1 change: 1 addition & 0 deletions controllers/nginx/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,5 +428,6 @@ type TemplateConfig struct {
CustomErrors bool
Cfg Configuration
IsIPV6Enabled bool
IsSSLPassthroughEnabled bool
RedirectServers map[string]string
}
22 changes: 14 additions & 8 deletions controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,18 @@ http {
}
{{ end }}

{{ if $all.IsSSLPassthroughEnabled }}
# map port 442 to 443 for header X-Forwarded-Port
map $pass_server_port $pass_port {
442 443;
default $pass_server_port;
}
{{ else }}
map $pass_server_port $pass_port {
443 443;
default $pass_server_port;
}
{{ end }}

# Map a response error watching the header Content-Type
map $http_accept $httpAccept {
Expand Down Expand Up @@ -294,11 +301,11 @@ http {
{{ range $hostname, $to := .RedirectServers }}
server {
listen 80{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
listen 442{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }} ssl;
listen {{ if $all.IsSSLPassthroughEnabled }}442 proxy_protocol{{ else }}443{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }} ssl;
{{ if $IsIPV6Enabled }}
listen [::]:80{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
listen [::]:442{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }};
{{ end }}
listen {{ if $all.IsSSLPassthroughEnabled }}[::]:442 proxy_protocol{{ else }}[::]:443{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ end }};
{{ end }}
server_name {{ $hostname }};
return 301 $scheme://{{ $to }}$request_uri;
}
Expand Down Expand Up @@ -407,7 +414,7 @@ stream {
server {
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
{{ if $IsIPV6Enabled }}listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};{{ end }}
proxy_timeout {{ $cfg.ProxyStreamTimeout }};
proxy_timeout {{ $cfg.ProxyStreamTimeout }};
proxy_pass tcp-{{ $tcpServer.Port }}-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }};
}

Expand All @@ -425,7 +432,7 @@ stream {
listen {{ $udpServer.Port }} udp;
{{ if $IsIPV6Enabled }}listen [::]:{{ $udpServer.Port }} udp;{{ end }}
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 }};
}
{{ end }}
Expand Down Expand Up @@ -499,9 +506,8 @@ stream {

{{/* Listen on 442 because port 443 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. */}}
{{ if not (empty $server.SSLCertificate) }}listen 442 proxy_protocol{{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};
{{ if $all.IsIPV6Enabled }}{{ if not (empty $server.SSLCertificate) }}listen [::]:442 proxy_protocol{{ end }} {{ if eq $server.Hostname "_"}} default_server reuseport backlog={{ $all.BacklogSize }}{{end}} ssl {{ if $all.Cfg.UseHTTP2 }}http2{{ end }};{{ end }}
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
{{ if not (empty $server.SSLCertificate) }}listen {{ if $all.IsSSLPassthroughEnabled }}442 proxy_protocol {{ else }}443{{ 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 $all.IsIPV6Enabled }}{{ if not (empty $server.SSLCertificate) }}listen {{ if $all.IsSSLPassthroughEnabled }}[::]:442 proxy_protocol{{ else }}[::]:443{{ 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 }} {{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
# PEM sha: {{ $server.SSLPemChecksum }}
ssl_certificate {{ $server.SSLCertificate }};
ssl_certificate_key {{ $server.SSLCertificate }};
Expand Down