Necesito permitir que un usuario (diferente del root) ejecute un servidor que escucha en el puerto 80.
¿Hay alguna forma de hacer esto?
Necesito permitir que un usuario (diferente del root) ejecute un servidor que escucha en el puerto 80.
¿Hay alguna forma de hacer esto?
Respuestas:
setcap 'cap_net_bind_service=+ep' /path/to/program
Esto funcionará para procesos específicos. Pero para permitir que un usuario en particular se vincule a puertos inferiores a 1024, deberá agregarlo a los sudoers.
Echa un vistazo a esta discusión para más información.
(Algunos de estos métodos se han mencionado en otras respuestas; estoy dando varias opciones posibles en un orden aproximado de preferencia).
Puede redirigir el puerto bajo a un puerto alto y escuchar en el puerto alto.
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080
Puede iniciar su servidor como privilegios de root y soltar después de que haya comenzado a escuchar en el puerto privilegiado. Preferiblemente, en lugar de codificarlo usted mismo, inicie su servidor desde un contenedor que haga el trabajo por usted. Si su servidor inicia una instancia por conexión, inicie desde inetd
(o un programa similar como xinetd
). Para inetd
, use una línea como esta en /etc/inetd.conf
:
http stream tcp nowait username:groupname /path/to/server/executable argv[0] argv[1]…
Si su servidor escucha en una sola instancia, inícielo desde un programa como authbind
. Cree un archivo vacío /etc/authbind/byport/80
y hágalo ejecutable para el usuario que ejecuta el servidor; o crear /etc/authbind/byuid/1234
, donde 1234 es el UID que ejecuta el servidor, que contiene la línea 0.0.0.0/0:80,80
.
Si el archivo ejecutable de su servidor está almacenado en un sistema de archivos que admite capacidades, puede darle la capacidad . Tenga en cuenta que las capacidades aún son relativamente nuevas y todavía tienen algunos problemas .cap_net_bind_service
setcap cap_net_bind_service=ep /path/to/server/executable
-A INPUT -p tcp --dport 1080 -j ACCEPT
que de lo contrario no funcionaría (también tengo un -j DROP
comodín). Así que me quedan dos tomas de escucha.
La respuesta corta es que esto no es posible por diseño.
La respuesta larga es que en los mundos de código abierto hay muchas personas que juegan con el diseño y proponen métodos alternativos. En general, es una práctica ampliamente aceptada que esto no debería ser posible. El hecho de que lo esté intentando probablemente significa que tiene otra falla de diseño en su sistema y debe reconsiderar la arquitectura de todo el sistema a la luz de las mejores prácticas * nix y las implicaciones de seguridad.
Dicho esto, un programa para autorizar el acceso no root a puertos bajos es authbind . Tanto selinux como grsecurity también proporcionan marcos para esas autenticaciones afinadas.
Por último, si desea que usuarios específicos ejecuten programas específicos como root y lo que realmente necesita es permitir que un usuario reinicie apache o algo así, ¡ sudo
es su amigo!
Puede usar el reenvío de puertos netcat o xinetd o iptables, o usar apache como proxy front-end y ejecutar el proceso en un puerto no privilegiado.
Authbind , @Gilles ya lo mencionó, pero me gustaría ampliarlo un poco.
Tiene un conveniente control de acceso (detalles en la página del manual): puede filtrar el acceso por puerto, dirección de interfaz, uid, rangos de dirección o puerto y la combinación de estos.
Tiene un parámetro muy útil --depth
:
- niveles de profundidad
Hace que authbind afecte a los programas que están en niveles profundos en el gráfico de llamada. El valor predeterminado es 1.
"Niveles profundos" significa que cuando un script (o programa) ejecuta otro script desciende un nivel. Entonces, si lo tiene --depth 5
significa en los niveles 1 (¿o es 0?) A 5, tiene permiso para vincular, mientras que en el nivel 6 y más, no lo tiene. Útil cuando desea que un script tenga acceso, pero no programas que se ejecutan con o sin su conocimiento.
Para ilustrar, podría tener algo como esto: por razones de seguridad, tiene un usuario java
destinado a ejecutar solo Java y desea darle acceso al puerto 80:
echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80
Lo creé ../byport/80 file
, se lo di al java
grupo de usuarios (cada usuario tiene su propio grupo) y lo hice ejecutable por grupo, lo que significa que es ejecutable por java
usuario. Si está dando acceso por puerto, el archivo debe ser ejecutable por el usuario que debería tener acceso, así que lo hicimos.
Esto podría ser suficiente para el Joe promedio, pero debido a que sabe cómo usar el --depth
parámetro, corre (como java
usuario) authbind --depth [depth] my_web_app's_start_script
comenzando --depth 1
y avanzando hasta encontrar la profundidad más pequeña que funciona y la usa.
Intenté el método iptables PREROUTING REDIRECT, pero descubrí que también afecta los paquetes reenviados. Es decir, si la máquina también reenvía paquetes entre interfaces (por ejemplo, si actúa como un punto de acceso Wi-Fi conectado a una red Ethernet), entonces la regla de iptables también detectará las conexiones de los clientes conectados a los destinos de Internet y los redirigirá a la máquina. Eso no era lo que quería: solo quería redirigir las conexiones que se dirigían a la máquina misma.
Una posibilidad es utilizar el reenvío de puertos TCP. Por ejemplo, usando socat
:
socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080
Sin embargo, una desventaja de ese método es que la aplicación que está escuchando en el puerto 8080 no conoce la dirección de origen de las conexiones entrantes (por ejemplo, para el registro u otros fines de identificación).