How to Bind Syslog to Privileged Port 514 as Non-Root User in Linux


2 views

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.