traefik-library-image
traefik-library-image copied to clipboard
Allow traefik to bind to service ports when not running as root
Description
This pull request allows Traefik to bind to service ports (< port number 1024) by setting cap_net_bind_service on the Traefik binary.
This allows to start Traefik as non-root user in Kubernetes and drop all capabilities except NET_BIND_SERVICE, e.g. using the following securityContext:
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop: [ALL]
add: [NET_BIND_SERVICE]
This feature has been requested multiple times, e.g.:
and would allow us to run Traefik in a more secure way
Background
There has been some discussion that adding NET_BIND_SERVICE is enough to achieve this, and the image need not be changed. However, this is not sufficient. In order to work correctly, the capability has to be added to the Pod in Kubernetes and also be set on the binary with setcap.
Default kubernetes install with chart is already non-root and secured on pod level with
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
and on deployment level with:
securityContext:
runAsGroup: 65532
runAsNonRoot: true
runAsUser: 65532
=> @jochenseeber It's already read-only, non-root and drop all capabilities. Would you please detail your use case ?
=> @jochenseeber It's already read-only, non-root and drop all capabilities. Would you please detail your use case ?
Yes, and when running it and trying to bind to a service port (<1024) it fails. Setting capability NET_BIND_SERVICE on the traefik binary in the image allows the non-root traefik to successfully bind to e.g. port 80 or 443.
Yes, and when running it and trying to bind to a service port (<1024) it fails.
:thinking: Mmmh ... :thinking: I'm not sure I follow. Default install with the Chart listen on tcp/80 and tcp/443 using a (LoadBalancer) Service with ports (<1024) on this Service. On the pod level, ports are > 1024, allowing to drop all capabilities by default.
I understand why it fails but I do not understand how it can be more secure by adding a capability requirement when it can run without any.
Our use case is to run Traefik as DaemonSet and have the pod bind directly to ports 80 & 443. Binding directly simplifies our network setup -- no need to do DNAT & very simple to create stateless firewall rules.
Giving NET_BIND_SERVICE to the pod is an additional capability, but imo a negligible risk. If the pod is running behind a service it most likely only has access to an internal network interface. It probably does not matter to which port it binds on that.
To sum it up, it would enable our use case, provide a feature that has been requested by multiple other users, and imo not introduce a security risk.
That's a very specific and un-common use case.
setcap can be quite unreliable.
Did you try to set with sysctl net.ipv4.ip_unprivileged_port_start to 0 ?
AFAIK, it's working and far more reliable.
Hey @jochenseeber, Thanks for your contribution. After discussing with the team, we think it's not a common practice and we don't want to enforce capabilities at the dockerfile level. Therefore, we are closing this PR.