Skip to content

Commit

Permalink
Merge pull request #1190 from aledbf/disable-ssl-passthrough
Browse files Browse the repository at this point in the history
Add flag to disable SSL passthrough
  • Loading branch information
aledbf authored Aug 21, 2017
2 parents a0e4661 + daa9fea commit 6ef6343
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 62 deletions.
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

0 comments on commit 6ef6343

Please sign in to comment.