In Linux systems, ports below 1024 are considered privileged and require root permissions. This becomes problematic when we want to run services like syslog (which traditionally uses UDP/TCP port 514) under non-root users for security hardening. Here are several practical solutions:
The most straightforward approach is to redirect traffic from the privileged port to a higher port:
# Redirect UDP 514 to 10514
sudo iptables -t nat -A PREROUTING -p udp --dport 514 -j REDIRECT --to-port 10514
# Make changes persistent
sudo apt install iptables-persistent # Debian/Ubuntu
sudo service iptables save # CentOS/RHEL
Linux capabilities allow granting specific privileges without full root access:
# Grant the capability
sudo setcap 'cap_net_bind_service=+ep' /path/to/syslogd
# Verify
getcap /path/to/syslogd
# For systemd services, add in service file:
AmbientCapabilities=CAP_NET_BIND_SERVICE
Authbind specifically handles this use case:
# Install authbind
sudo apt install authbind # Debian/Ubuntu
# Configure port access
sudo touch /etc/authbind/byport/514
sudo chown sysloguser:sysloguser /etc/authbind/byport/514
sudo chmod 755 /etc/authbind/byport/514
# Launch service through authbind
authbind --deep /usr/sbin/syslogd -f /etc/syslog.conf
Modern approach using systemd's socket activation:
# /etc/systemd/system/syslog.socket
[Socket]
ListenDatagram=0.0.0.0:514
BindIPv6Only=both
[Install]
WantedBy=sockets.target
# /etc/systemd/system/syslog@.service
[Service]
User=sysloguser
Group=sysloguser
ExecStart=/usr/sbin/syslogd -f /etc/syslog.conf
While all methods work, each has security implications:
- iptables: Minimal privilege escalation but requires maintaining rules
- CAP_NET_BIND_SERVICE: Granular control but capability inheritance must be managed
- Authbind: Simple but requires third-party tool
- Systemd: Most modern approach but systemd-specific
For rsyslog users, here's how to implement Method 2:
# Set capability on rsyslogd
sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/rsyslogd
# Configure rsyslog to run as non-root
# In /etc/rsyslog.conf:
$PrivDropToUser syslog
$PrivDropToGroup syslog
# For UDP 514, ensure this line exists:
$ModLoad imudp
$UDPServerRun 514
In Linux systems, ports below 1024 are considered privileged ports and can only be bound by the root user. This creates challenges when we want services like syslog to run under a non-privileged user for security reasons while still needing to listen on standard ports (e.g., port 514 for syslog).
The modern approach involves granting the CAP_NET_BIND_SERVICE
capability to the binary:
# Set capability on the executable sudo setcap 'cap_net_bind_service=+ep' /path/to/your/daemon # Verify the capability getcap /path/to/your/daemon
For a specific user, you can create a wrapper script:
#!/bin/sh exec /usr/bin/setpriv --reuid=sysloguser --regid=sysloggroup --init-groups \ /usr/sbin/your_service
Redirect traffic from privileged port to an unprivileged one:
sudo iptables -t nat -A PREROUTING -p tcp --dport 514 -j REDIRECT --to-port 10514 sudo iptables -t nat -A PREROUTING -p udp --dport 514 -j REDIRECT --to-port 10514
Configure systemd to handle the privileged port and pass the socket to your service:
# /etc/systemd/system/syslog.socket [Socket] ListenStream=514 ListenDatagram=514 SocketUser=sysloguser
Authbind allows specific users/programs to bind to low ports:
sudo apt install authbind sudo touch /etc/authbind/byport/514 sudo chown sysloguser /etc/authbind/byport/514 sudo chmod 755 /etc/authbind/byport/514
Then modify your service startup to use authbind:
authbind --deep /usr/sbin/your-service
While all these methods work, they have different security implications:
- CAP_NET_BIND_SERVICE is the most granular but requires capability support
- Authbind is simple but Debian-specific
- Port forwarding adds network-level complexity
Choose the method that best fits your security model and distribution requirements.