How to add multiple path in kubernetes-nginx-ingress-server-snippet-annotation to deny the traffic - kubernetes-ingress

I've the following code in the my ingress config, I would like to add more path(s) to deny the hits from Hackers. Is there any best practices to be followed to ensure no automated scans made by hackers?
---
kind: Ingress
metadata:
name: example
labels:
app: example
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "200"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/server-snippet: |
location ~* "^/boaform" {
deny all;
return 403;
}
location ~* "^/api" {
deny all;
return 403;
}
location ~* "^/user" {
deny all;
return 403;
}
namespace: example-ns

Rather than block some common URLs from hackers, you could do your best so they cannot even start the request. Good IP restrictions should be better to security than some blocked paths.
If you really need to listen to the world, then you could do yourself several kinds of implementations (request rate, geoIP, search for injections, etc) according to your application needs.
If you want no trouble (or less trouble) with these rules, you could try a WAF, like Cloudflare

Related

Ingress creates location / (root path match all) in nginx config on specific servername, avoiding path to be found on default servername

I am running into this problem (or behave) of Ingress I can't understand:
If I have a path: /api1 configed in ingess without a specified host name, like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: api1
namespace: somenamespace
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/proxy-body-size: 100m
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
spec:
rules:
- http:
paths:
- path: /api1
pathType: ImplementationSpecific
backend:
serviceName: service-for-api1
servicePort: 1234
Then I can access this path in any hostname or IP address as long as it points to my server, e.g. my-server.com/api1 or 1.2.3.4/api1
And If I added another ingress config with a specified host name, like: /api2
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: api2
namespace: somenamespace
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/proxy-body-size: 100m
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
spec:
rules:
- host: my-server.com # Only difference is this one has a host field
http:
paths:
- path: /api2
pathType: ImplementationSpecific
backend:
serviceName: service-for-api2
servicePort: 1234
Then I can access my-server.com/api2 all right, But when accessing my-server.com/api1, I got a 404 not found error. If try to access through IP, 1.2.3.4/api1, It works all right.
I read the nginx config generated by ingress, found out when no host is specified in ingress config, the path rule (/api1) will be added to servername _ which is the default server of nginx. And once a hostname is provided in ingress config, It (/api2) will be added to servername hostname block in nginx configfile. Also there will be a location / rule to match all path in this hostname, preventing all paths fallback to default server. So when access my-server.com/api2, the route is okey but when access my-server.com/api1, It matches location / in servername my-server.com block, preventing default server functioning at all.
Why do ingress do this??
I was believing not specify any hostname in ingress config means host: *, thus any host can match the rule. But it behaves like only hostname unknown to ingress can match host: *.
The nginx config I looked at is like this (forgive my for only copying part of it):
## start server _
server {
server_name _ ;
listen 80 default_server reuseport backlog=65535 ;
listen [::]:80 default_server reuseport backlog=65535 ;
listen 443 default_server reuseport backlog=65535 ssl http2 ;
listen [::]:443 default_server reuseport backlog=65535 ssl http2 ;
set $proxy_upstream_name "-";
...
location /api1 {
...
}
...
}
## end server _
## start server my-server.com
server {
server_name my-server.com
listen 80 ;
listen [::]:80 ;
listen 443 ssl http2 ;
listen [::]:443 ssl http2 ;
set $proxy_upstream_name "-";
location /api2 {
....
}
location / {
set $namespace "somenamespace";
set $ingress_name "service-for-api2";
set $service_name "";
set $service_port "";
set $location_path "/";
set $global_rate_limit_exceeding n;
...
# In case of errors try the next upstream server before returning an error
proxy_next_upstream error timeout;
proxy_next_upstream_timeout 0;
proxy_next_upstream_tries 3;
...
}
}
## end server my-server.com
When copying I noticed the "try the next upstream server before returning an error", Is it not work properly so I got a 404 instead of actually trying servername _ ? When I looked the nginx log, it said the 404 request is sent to service [upstream-default-backend], I don't know what it means.
After I discover this problem I deleted the specified hostname in /api2 and it work allright. But I jsut can't help wondering why ingress does this behave...

redirect http to https using a kubernetes ingress controller on Amazon EKS

I need to configure a new listener from the Ingress.yaml manifest, currently the aws loadbalancer driver version is 2.4.4, when I perform the process from the AWS console it allows me to add the new listener and redirect the traffic to HTTPS without problem but after a few minutes it disappears, I perform the configuration directly in the ingress manifest with the annotations but the listener does not come out correctly in the AWS console.
Manifiest:
`
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig":{ "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:xxx-xxxxx:xxxxx:certificate/xxxx-xxxxxxx
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
alb.ingress.kubernetes.io/scheme: internal
kubernetes.io/ingress.class: alb
name: xxxxxx
namespace: xxxxx
spec:
rules:
- host: xxxxxxx
http:
paths:
- backend:
service:
name: service
port:
number: 80
path: /*
pathType: ImplementationSpecific
listener configured from maniefiest ingress
enter image description here
listener configuring it manually from AWS Console
enter image description here

Is it possible to configure Openshift coreDNS with "host" statement like for vanilla Kubernetes?

I want to resolve a particular external test hostname to its IP on my Openshift (4.10.32) cluster. Please note that it's needed for some workloads deployed by operators so cannot (I think) update the deployments yaml that are generated by the operator to add hostAliases for example.
I tried to add host statement in my DNS config like others do on vanilla Kubernetes, see here or here.
In other word I'd like my coreDNS configmap (generated by the dns.operator/default) and which look like that:
oc get configmap/dns-default -n openshift-dns -o yaml
apiVersion: v1
data:
Corefile: |
.:5353 {
bufsize 512
errors
log . {
class error
}
health {
lameduck 20s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus 127.0.0.1:9153
forward . /etc/resolv.conf {
policy sequential
}
cache 900 {
denial 9984 30
}
reload
}
kind: ConfigMap
metadata:
creationTimestamp: "2022-10-13T14:47:45Z"
labels:
dns.operator.openshift.io/owning-dns: default
name: dns-default
namespace: openshift-dns
ownerReferences:
- apiVersion: operator.openshift.io/v1
controller: true
kind: DNS
name: default
uid: ef6eb600-c5ec-4cf5-a4f0-ca654b613e16
resourceVersion: "2918009"
uid: cf3cd62e-fef0-4c52-a7e0-6d8d8bf149ed
to be updated so that the coreDNS config part would look like this (considering I want to add a host hostname.my-domain that resolves to IP 1.2.3.4)
Corefile: |
.:5353 {
bufsize 512
errors
log . {
class error
}
health {
lameduck 20s
}
ready
hosts {
1.2.3.4 hostname.my-domain
fallthrough
}
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus 127.0.0.1:9153
forward . /etc/resolv.conf {
policy sequential
}
cache 900 {
denial 9984 30
}
reload
}
Thx in advance for any hints on how to do that or on other ways to achieve what I'd like to do.

Regex paths in kubernetes Ingress not getting created as regex location in Nginx Ingress Controller

I am using Nginx Ingress Controller helm chart 0.6.0 and nginx ingress controller tag 1.8.0, kubernetes 1.15.
When I define a path in my Ingress which uses a regex, it does not work since it does not get specified as a regex in the Nginx controller's configuration file location section.
I need to use a version of nginx ingress controller which additionally supports VirtualServer and VirtualServerRoutes.
kind: Ingress
metadata:
name: test-ingress
namespace: ingress-test
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: test.any-xyz.com
http:
paths:
- path: /quack5/(.*)
backend:
serviceName: test
servicePort: 80
When I apply this, the nginx ingress controller has set up the location as a non-regex expression
$ kubectl -n nginx-ingress-controller exec nginx-ingress-controller-nginx-ingress-79984b9747-8pl4w -- grep -R quack /etc/nginx/conf.d
$ /etc/nginx/conf.d/ingress-test-test-ingress.conf: location /quack5/(.*) {
I expect to see location ~* /quack5/(.*) {
Try to add nginx.ingress.kubernetes.io/rewrite-target annotation to your Nginx Ingress Controller definition file.
Delete nginx.ingress.kubernetes.io/use-regex: "true" annotation.
EDIT:
I think the problem might be in the buildLocation function (&& location.Rewrite.Target != path). If the path and the nginx.ingress.kubernetes.io/rewrite-target are equal the nginx Location is not prefixed with ~* and handled as regex.
if len(location.Rewrite.Target) > 0 && location.Rewrite.Target != path {
if path == slash {
return fmt.Sprintf("~* %s", path)
}
// baseuri regex will parse basename from the given location
baseuri := `(?<baseuri>.*)`
if !strings.HasSuffix(path, slash) {
// Not treat the slash after "location path" as a part of baseuri
baseuri = fmt.Sprintf(`\/?%s`, baseuri)
}
return fmt.Sprintf(`~* ^%s%s`, path, baseuri)
}
return path
I would suggest a directive to specify that the spec.rules.http.paths.path should end up as a regex Location, regardless of what nginx.ingress.kubernetes.io/rewrite-target might be (even if it not specified). currently the only way to get the Location to be threatened as regex (added ~*) is to define a nginx.ingress.kubernetes.io/rewrite-target that is different from spec.rules.http.paths.path.
Please take a look: ingress-regex, ingress-path-matching, path-not-threated-as-regex.

Redirect specific sub directory to new url in Ingress

I need to redirect a specific URL to a new one.
I can use this code to redirect root domain but it doesn't work for subdirectory likes testdomain.com/specific-url
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'testdomain.com/specific-url') {
return 308 https://testdomain.com/new-url;
}
Try to use below approach I suggested here.
And copy paste for future:
My advice is to use NGINX Plus Ingress Controller annotation functionality if you can afford it.
You can find official example here.
Example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cafe-ingress
annotations:
nginx.org/rewrites: "serviceName=tea-svc rewrite=/;serviceName=coffee-svc rewrite=/beans/"
spec:
rules:
- host: cafe.example.com
http:
paths:
- path: /tea/
backend:
serviceName: tea-svc
servicePort: 80
- path: /coffee/
backend:
serviceName: coffee-svc
servicePort: 80
Below are the examples of how the URI of requests to the tea-svc are rewritten (Note that the /tea requests are redirected to /tea/).
/tea/ -> /
/tea/abc -> /abc
Below are the examples of how the URI of requests to the coffee-svc are rewritten (Note that the /coffee requests are redirected to /coffee/).
/coffee/ -> /beans/
/coffee/abc -> /beans/abc