Skip to content

Commit

Permalink
Add support for proxy protocol decoding and encoding in TCP services
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean-Baptiste Guerraz committed Sep 27, 2017
1 parent 6e24dc6 commit a24d657
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 17 deletions.
4 changes: 2 additions & 2 deletions controllers/nginx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ version to fully support Kube-Lego is nginx Ingress controller 0.8.

## 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]`
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.
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 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`
```
Expand Down
11 changes: 7 additions & 4 deletions controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -434,19 +434,22 @@ stream {
}
server {
{{ 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 }}
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
{{ end }}
{{ if $IsIPV6Enabled }}
{{ 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 }}
listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.UseProxyProtocol }} proxy_protocol{{ end }};
listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }};
{{ end }}
{{ end }}
proxy_timeout {{ $cfg.ProxyStreamTimeout }};
proxy_pass tcp-{{ $tcpServer.Port }}-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }};
{{ if $tcpServer.Backend.ProxyProtocol.Encode }}
proxy_protocol on;
{{ end }}
}

{{ end }}
Expand Down
25 changes: 15 additions & 10 deletions core/pkg/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ func (ic *GenericController) getStreamServices(configmapName string, proto apiv1
}

var svcs []ingress.L4Service
var svcProxyProtocol ingress.ProxyProtocol
// k -> port to expose
// v -> <namespace>/<service name>:<port from service to be used>
for k, v := range configmap.Data {
Expand All @@ -363,18 +364,22 @@ func (ic *GenericController) getStreamServices(configmapName string, proto apiv1

nsSvcPort := strings.Split(v, ":")
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
}

nsName := nsSvcPort[0]
svcPort := nsSvcPort[1]
useProxyProtocol := false
svcProxyProtocol.Decode = false
svcProxyProtocol.Encode = false

// Proxy protocol is possible if the service is TCP
if len(nsSvcPort) == 3 && proto == apiv1.ProtocolTCP {
if strings.ToUpper(nsSvcPort[2]) == "PROXY" {
useProxyProtocol = true
if len(nsSvcPort) >= 3 && proto == apiv1.ProtocolTCP {
if len(nsSvcPort) >= 3 && strings.ToUpper(nsSvcPort[2]) == "PROXY" {
svcProxyProtocol.Decode = true
}
if len(nsSvcPort) == 4 && strings.ToUpper(nsSvcPort[3]) == "PROXY" {
svcProxyProtocol.Encode = true
}
}

Expand Down Expand Up @@ -432,11 +437,11 @@ func (ic *GenericController) getStreamServices(configmapName string, proto apiv1
svcs = append(svcs, ingress.L4Service{
Port: externalPort,
Backend: ingress.L4Backend{
Name: svcName,
Namespace: svcNs,
Port: intstr.FromString(svcPort),
Protocol: proto,
UseProxyProtocol: useProxyProtocol,
Name: svcName,
Namespace: svcNs,
Port: intstr.FromString(svcPort),
Protocol: proto,
ProxyProtocol: svcProxyProtocol,
},
Endpoints: endps,
})
Expand Down
8 changes: 7 additions & 1 deletion core/pkg/ingress/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,5 +359,11 @@ type L4Backend struct {
Namespace string `json:"namespace"`
Protocol apiv1.Protocol `json:"protocol"`
// +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"`
}

0 comments on commit a24d657

Please sign in to comment.