Add ump load balancing and naxsi as WAF. Update nginx to 1.9.13
This commit is contained in:
parent
a06f0a707e
commit
c9f8a06399
9 changed files with 105 additions and 15 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
8
controllers/nginx/naxsi/basic.rules
Normal file
8
controllers/nginx/naxsi/basic.rules
Normal 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;
|
|
@ -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 */}}
|
||||
|
|
|
@ -21,6 +21,7 @@ type IngressConfig struct {
|
|||
Upstreams []*Upstream
|
||||
Servers []*Server
|
||||
TCPUpstreams []*Location
|
||||
UDPUpstreams []*Location
|
||||
}
|
||||
|
||||
// Upstream describes an NGINX upstream
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue