Add ump load balancing and naxsi as WAF. Update nginx to 1.9.13

This commit is contained in:
Manuel de Brito Fontes 2016-03-29 20:30:44 -03:00
parent a06f0a707e
commit c9f8a06399
9 changed files with 105 additions and 15 deletions

View file

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM gcr.io/google_containers/nginx-slim:0.4
FROM gcr.io/google_containers/nginx-slim:0.5
RUN apt-get update && apt-get install -y \
diffutils \

View file

@ -1,7 +1,7 @@
all: push
# 0.0 shouldn't clobber any release builds
TAG = 0.4
TAG = 0.5
PREFIX = gcr.io/google_containers/nginx-ingress-controller
controller: controller.go clean

View file

@ -130,6 +130,27 @@ data:
Please check the [tcp services](examples/tcp/README.md) example
## Exposing UDP services
Since 1.9.13 NGINX provides [UDP Load Balancing](https://www.nginx.com/blog/announcing-udp-load-balancing/).
Ingress does not support UDP services (yet). For this reason this Ingress controller uses a ConfigMap where the key is the external port to use and the value is
`<namespace/service name>:<service port>`
It is possible to use a number or the name of the port.
The next example shows how to expose the service `kube-dns` running in the namespace `kube-system` in the port `53` using the port `53`
```
apiVersion: v1
kind: ConfigMap
metadata:
name: udp-configmap-example
data:
53: "kube-system/kube-dns:53"
```
Please check the [udp services](examples/udp/README.md) example
## Custom NGINX configuration

View file

@ -62,6 +62,7 @@ type loadBalancerController struct {
defaultSvc string
nxgConfigMap string
tcpConfigMap string
udpConfigMap string
syncQueue *taskQueue
@ -75,7 +76,7 @@ type loadBalancerController struct {
// newLoadBalancerController creates a controller for nginx loadbalancer
func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Duration, defaultSvc,
namespace, nxgConfigMapName, tcpConfigMapName string, lbRuntimeInfo *lbInfo) (*loadBalancerController, error) {
namespace, nxgConfigMapName, tcpConfigMapName, udpConfigMapName string, lbRuntimeInfo *lbInfo) (*loadBalancerController, error) {
lbc := loadBalancerController{
client: kubeClient,
stopCh: make(chan struct{}),
@ -83,6 +84,7 @@ func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
nginx: nginx.NewManager(kubeClient),
nxgConfigMap: nxgConfigMapName,
tcpConfigMap: tcpConfigMapName,
udpConfigMap: udpConfigMapName,
defaultSvc: defaultSvc,
}
@ -174,6 +176,10 @@ func (lbc *loadBalancerController) getTCPConfigMap(ns, name string) (*api.Config
return lbc.client.ConfigMaps(ns).Get(name)
}
func (lbc *loadBalancerController) getUDPConfigMap(ns, name string) (*api.ConfigMap, error) {
return lbc.client.ConfigMaps(ns).Get(name)
}
func (lbc *loadBalancerController) sync(key string) {
if !lbc.controllersInSync() {
lbc.syncQueue.requeue(key, fmt.Errorf("deferring sync till endpoints controller has synced"))
@ -217,10 +223,34 @@ func (lbc *loadBalancerController) getTCPServices() []*nginx.Location {
return []*nginx.Location{}
}
var tcpSvcs []*nginx.Location
return lbc.getServices(tcpMap.Data, api.ProtocolTCP)
}
func (lbc *loadBalancerController) getUDPServices() []*nginx.Location {
if lbc.udpConfigMap == "" {
// no configmap for TCP services
return []*nginx.Location{}
}
ns, name, err := parseNsName(lbc.udpConfigMap)
if err != nil {
glog.Warningf("%v", err)
return []*nginx.Location{}
}
tcpMap, err := lbc.getUDPConfigMap(ns, name)
if err != nil {
glog.V(3).Infof("no configured tcp services found: %v", err)
return []*nginx.Location{}
}
return lbc.getServices(tcpMap.Data, api.ProtocolUDP)
}
func (lbc *loadBalancerController) getServices(data map[string]string, proto api.Protocol) []*nginx.Location {
var svcs []*nginx.Location
// k -> port to expose in nginx
// v -> <namespace>/<service name>:<port from service to be used>
for k, v := range tcpMap.Data {
for k, v := range data {
port, err := strconv.Atoi(k)
if err != nil {
glog.Warningf("%v is not valid as a TCP port", k)
@ -273,7 +303,7 @@ func (lbc *loadBalancerController) getTCPServices() []*nginx.Location {
continue
}
tcpSvcs = append(tcpSvcs, &nginx.Location{
svcs = append(svcs, &nginx.Location{
Path: k,
Upstream: nginx.Upstream{
Name: fmt.Sprintf("%v-%v-%v", svcNs, svcName, port),
@ -282,7 +312,7 @@ func (lbc *loadBalancerController) getTCPServices() []*nginx.Location {
})
}
return tcpSvcs
return svcs
}
func (lbc *loadBalancerController) getDefaultUpstream() *nginx.Upstream {

View file

@ -57,6 +57,12 @@ var (
name of the port.
The ports 80 and 443 are not allowed as external ports. This ports are reserved for nginx`)
udpConfigMapName = flags.String("udp-services-configmap", "",
`Name of the ConfigMap that containes the definition of the UDP services to expose.
The key in the map indicates the external port to be used. The value is the name of the
service with the format namespace/serviceName and the port of the service could be a number of the
name of the port.`)
resyncPeriod = flags.Duration("sync-period", 30*time.Second,
`Relist and confirm cloud resources this often.`)
@ -99,7 +105,7 @@ func main() {
glog.Fatalf("no service with name %v found: %v", *defaultSvc, err)
}
lbc, err := newLoadBalancerController(kubeClient, *resyncPeriod, *defaultSvc, *watchNamespace, *nxgConfigMap, *tcpConfigMapName, lbInfo)
lbc, err := newLoadBalancerController(kubeClient, *resyncPeriod, *defaultSvc, *watchNamespace, *nxgConfigMap, *tcpConfigMapName, *udpConfigMapName, lbInfo)
if err != nil {
glog.Fatalf("%v", err)
}

View file

@ -0,0 +1,8 @@
SecRulesEnabled;
DeniedUrl "/RequestDenied";
## check rules
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;

View file

@ -24,6 +24,11 @@ http {
require("error_page")
}
{{ if $cfg.enableWaf}}
# https://github.com/nbs-system/naxsi/wiki/basicsetup
include /etc/nginx/naxsi/*.rules;
{{ end }}
sendfile on;
aio threads;
tcp_nopush on;
@ -80,11 +85,6 @@ http {
'' $scheme;
}
map $http_x_forwarded_proto $pass_forwarded_for {
default $http_x_forwarded_for;
'' $proxy_add_x_forwarded_for;
}
map $pass_access_scheme $sts {
'https' 'max-age={{ $cfg.htsMaxAge }}{{ if $cfg.htsIncludeSubdomains }}; includeSubDomains{{ end }}; preload';
}
@ -202,7 +202,7 @@ http {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $pass_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
@ -219,6 +219,11 @@ http {
proxy_pass http://{{ $location.Upstream.Name }};
}
{{ end }}
{{ if $cfg.enableWaf}}
location /RequestDenied {
return 418;
}
{{ end }}
{{ template "CUSTOM_ERRORS" $cfg }}
}
{{ end }}
@ -265,8 +270,10 @@ http {
}
}
# TCP services
stream {
# TCP services
{{ range $i, $tcpServer := .tcpUpstreams }}
upstream tcp-{{ $tcpServer.Upstream.Name }} {
{{ range $server := $tcpServer.Upstream.Backends }}server {{ $server.Address }}:{{ $server.Port }};
@ -280,6 +287,22 @@ stream {
proxy_pass tcp-{{ $tcpServer.Upstream.Name }};
}
{{ end }}
# UDP services
{{ range $i, $udpServer := .udpUpstreams }}
upstream udp-{{ $udpServer.Upstream.Name }} {
{{ range $server := $tcpServer.Upstream.Backends }}server {{ $server.Address }}:{{ $server.Port }};
{{ end }}
}
server {
listen {{ $tcpServer.Path }} udp;
proxy_timeout 1s;
proxy_responses 1;
proxy_pass udp-{{ $tcpServer.Upstream.Name }};
}
{{ end }}
}
{{/* definition of templates to avoid repetitions */}}

View file

@ -21,6 +21,7 @@ type IngressConfig struct {
Upstreams []*Upstream
Servers []*Server
TCPUpstreams []*Location
UDPUpstreams []*Location
}
// Upstream describes an NGINX upstream

View file

@ -56,6 +56,7 @@ func (ngx *Manager) writeCfg(cfg nginxConfiguration, ingressCfg IngressConfig) (
conf["upstreams"] = ingressCfg.Upstreams
conf["servers"] = ingressCfg.Servers
conf["tcpUpstreams"] = ingressCfg.TCPUpstreams
conf["udpUpstreams"] = ingressCfg.UDPUpstreams
conf["defResolver"] = ngx.defResolver
conf["sslDHParam"] = ngx.sslDHParam
conf["cfg"] = fixKeyNames(curNginxCfg)