599 words
3 minutes
Binding to Ports Below 1024 in Linux
2025-08-06

Privileged ports#

Ports below 1024 in Linux are referred to as privileged ports. These ports are normally reserved for common well-known services such as FTP on port 21, SSH on port 22, and HTTP and HTTPS on ports 80 and 443 respectively.

Root privileges are required to bind to them. This it to prevents unprivileged users or malicious software from impersonating the common services that would otherwise be listening on them.

This a classic example of the Principle of Least Privilege in action.

Using privileged ports without root#

Some fairly straight forward approach to the issue is:

  1. run your application as root.
  2. disable privileged ports.

These solutions are however not recommended as they beat the purpose of the Principle of Least Privilege.

Instead of these solutions, the following approaches are highly recommended:

1. Port Forwarding#

Port forwarding is a fairly simple approach to using privileged ports in Linux.

It works by starting your application in a higher non privileged port. The firewall is then configured to forward traffic from the desired privileged port to the unprivileged port.

Terminal window
# forward https traffic from port 443 to port 8080
### firewalld
firewall-cmd --add-forward-port=port=443:proto=tcp:toport=8080
### iptables
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080

2. Reverse Proxies#

Another almost straight approach is to use a reverse proxy such as nginx or apache.

Reverse proxies, just like in port forwarding, can be used to forward traffic from the privileged port to the unprivileged port.

The proxies are designed from the ground up as system-level services that start as a root process and then drops down to a much safer user that does the actual work.

apache
<VirtualHost *:80>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
nginx
server {
listen 80;
location / {
proxy_pass http://localhost:8080;
}
}

Port Forwarding vs Reverse Proxies#

Based on the Open Systems Interconnection Model(OSI) model, port forwarding works on layer 3 (Network) and 4 (Transport) . Reverse proxies on the other hand operate on the layer 7 (application).

To some level, reverse proxies can understand the traffic flowing through them and make intelligent forwarding decisions. This makes it possible to implement core functions such as load balancing, caching, SSL termination, and content-based traffic routing. Multiple destinations and complex forwarding rules can be implemented with reverse proxies.

With just port forwarding, you can only remap the traffic to just a single destination address and port.

3. Linux Capabilities#

The Linux kernel breaks down privileges into fine-grained privileges called capabilities. A process is granted only a small number of these capabilities so that even if its compromised, the attacker can do nothing beyond what the limited process can do.

Linux capabilites can be assigned to a process in one of the following ways:

3. AmbientCapabilities for Systemd service#

Systemd unit files allow you to specify the capabilities of a process via AmbientCapabilities parameter.

/lib/systemd/system/myservice.service
[Unit]
Description=A simple service
After=network.target
[Service]
User=MyUser
ExecStart='/opt/myprogram/myexecutable'
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
alias=myservice
WantedBy=multi-user.target

By using AmbientCapabilities, the service gets only the port binding privilege it needs while still running as a limited, non-root user.

3. setcap Command#

It’s also possible to grant the executable the cap_net_bind_service capability directly via the setcap command. In this case the granted capabilities metadata is stored on the extended attributes(xattrs) of the file.

The filesystem on which the executable resides needs to support extended attributes.

setcap 'cap_net_bind_service=+eip' /opt/myprogram/myexecutable

One downside for this approach is the capabilities could be lost if the file is moved, copied or replaced.


Conclusion#

You don’t have to grant your application root, permissions to bind to privileged ports. Port forwarding, reverse proxies and fine-grained linux capabilites offer a much more secure approach.

Personally, i would recommend going for the reverse proxy route. If the proxy overhead is too much, then the cap_net_bind_service is the next best option.

NOTE

Happy port binding !!

Binding to Ports Below 1024 in Linux
https://www.wizardofbits.com/posts/linux/binding-to-ports-below-1024-linux/
Author
Nahashon Mwongera
Published at
2025-08-06
License
CC BY-NC-SA 4.0