Add support for proxy protocol decoding and encoding in TCP services

This commit is contained in:
Jean-Baptiste Guerraz 2017-09-27 16:10:16 +02:00
parent 6e24dc68f7
commit a24d65745e
4 changed files with 31 additions and 17 deletions

View file

@ -334,8 +334,8 @@ version to fully support Kube-Lego is nginx Ingress controller 0.8.
## Exposing TCP services ## Exposing TCP services
Ingress does not support TCP services (yet). For this reason this Ingress controller uses the flag `--tcp-services-configmap` to point to an existing config map where the key is the external port to use and the value is `<namespace/service name>:<service port>:[PROXY]` Ingress does not support TCP services (yet). For this reason this Ingress controller uses the flag `--tcp-services-configmap` to point to an existing config map where the key is the external port to use and the value is `<namespace/service name>:<service port>:[PROXY]:[PROXY]`
It is possible to use a number or the name of the port. The last field is optional. Adding `PROXY` in the last field we can enable Proxy Protocol in a TCP service. It is possible to use a number or the name of the port. The two last fields are optional. Adding `PROXY` in either or both of the two last fields we can use Proxy Protocol decoding (listen) and/or encoding (proxy_pass) in a TCP service (https://www.nginx.com/resources/admin-guide/proxy-protocol/).
The next example shows how to expose the service `example-go` running in the namespace `default` in the port `8080` using the port `9000` The next example shows how to expose the service `example-go` running in the namespace `default` in the port `8080` using the port `9000`
``` ```

View file

@ -434,19 +434,22 @@ stream {
} }
server { server {
{{ range $address := $all.Cfg.BindAddressIpv4 }} {{ range $address := $all.Cfg.BindAddressIpv4 }}
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }}; listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
{{ else }} {{ else }}
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }}; listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
{{ end }} {{ end }}
{{ if $IsIPV6Enabled }} {{ if $IsIPV6Enabled }}
{{ range $address := $all.Cfg.BindAddressIpv6 }} {{ range $address := $all.Cfg.BindAddressIpv6 }}
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }}; listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
{{ else }} {{ else }}
listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }}; listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
{{ end }} {{ 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 }};
{{ if $tcpServer.Backend.ProxyProtocol.Encode }}
proxy_protocol on;
{{ end }}
} }
{{ end }} {{ end }}

View file

@ -346,6 +346,7 @@ func (ic *GenericController) getStreamServices(configmapName string, proto apiv1
} }
var svcs []ingress.L4Service var svcs []ingress.L4Service
var svcProxyProtocol ingress.ProxyProtocol
// k -> port to expose // k -> port to expose
// v -> <namespace>/<service name>:<port from service to be used> // v -> <namespace>/<service name>:<port from service to be used>
for k, v := range configmap.Data { for k, v := range configmap.Data {
@ -363,18 +364,22 @@ func (ic *GenericController) getStreamServices(configmapName string, proto apiv1
nsSvcPort := strings.Split(v, ":") nsSvcPort := strings.Split(v, ":")
if len(nsSvcPort) < 2 { if len(nsSvcPort) < 2 {
glog.Warningf("invalid format (namespace/name:port:[PROXY]) '%v'", k) glog.Warningf("invalid format (namespace/name:port:[PROXY]:[PROXY]) '%v'", k)
continue continue
} }
nsName := nsSvcPort[0] nsName := nsSvcPort[0]
svcPort := nsSvcPort[1] svcPort := nsSvcPort[1]
useProxyProtocol := false svcProxyProtocol.Decode = false
svcProxyProtocol.Encode = false
// Proxy protocol is possible if the service is TCP // Proxy protocol is possible if the service is TCP
if len(nsSvcPort) == 3 && proto == apiv1.ProtocolTCP { if len(nsSvcPort) >= 3 && proto == apiv1.ProtocolTCP {
if strings.ToUpper(nsSvcPort[2]) == "PROXY" { if len(nsSvcPort) >= 3 && strings.ToUpper(nsSvcPort[2]) == "PROXY" {
useProxyProtocol = true svcProxyProtocol.Decode = true
}
if len(nsSvcPort) == 4 && strings.ToUpper(nsSvcPort[3]) == "PROXY" {
svcProxyProtocol.Encode = true
} }
} }
@ -436,7 +441,7 @@ func (ic *GenericController) getStreamServices(configmapName string, proto apiv1
Namespace: svcNs, Namespace: svcNs,
Port: intstr.FromString(svcPort), Port: intstr.FromString(svcPort),
Protocol: proto, Protocol: proto,
UseProxyProtocol: useProxyProtocol, ProxyProtocol: svcProxyProtocol,
}, },
Endpoints: endps, Endpoints: endps,
}) })

View file

@ -359,5 +359,11 @@ type L4Backend struct {
Namespace string `json:"namespace"` Namespace string `json:"namespace"`
Protocol apiv1.Protocol `json:"protocol"` Protocol apiv1.Protocol `json:"protocol"`
// +optional // +optional
UseProxyProtocol bool `json:"useProxyProtocol"` ProxyProtocol ProxyProtocol `json:"proxyProtocol"`
}
// ProxyProtocol describes the proxy protocol configuration
type ProxyProtocol struct {
Decode bool `json:"decode"`
Encode bool `json:"encode"`
} }