304 votos

¿Cómo puedo ejecutar un servidor en Linux en el puerto 80 como un usuario normal?

He buscado en google sobre ella durante bastante tiempo, pero no podía encontrarla.

Estoy en Ubuntu Linux y desea ejecutar un servidor en el puerto 80, pero debido a un mecanismo de seguridad de Ubuntu, me sale el siguiente error:

java.net.BindException: Permiso denegado:80

Creo que debe ser lo suficientemente simple para desactivar este mecanismo de seguridad para que el puerto 80 está disponible para todos los usuarios, o para dar privilegio necesario para el usuario actual para acceder a el puerto 80; pero la vergüenza de mí, no puede darse cuenta de eso.

348voto

Paul Roub Puntos 11185

Respuesta corta: no se puede. Los puertos por debajo del 1024 sólo puede ser abierta por la root.

La respuesta larga: puede redirigir las conexiones en el puerto 80 a algún otro puerto, se puede abrir como un usuario normal.

Ejecutar como root:

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Como dispositivos de loopback (como localhost) no utilice el prerouting reglas, si usted necesita para utilizar localhost, etc., agregar esta regla también (gracias @Francesco):

# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080

NOTA: La solución anterior no es muy adecuado para sistemas multi-usuario, ya que cualquier usuario puede abrir el puerto 8080 (o cualquier otro puerto alto decide usar), así interceptar el tráfico. (Créditos a CesarB).

EDIT: como por comentario pregunta - a eliminar la regla anterior:

# iptables -t nat --line-numbers -n -L

Esta salida será algo como:

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 redir ports 8088
2    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 8080

La regla que le interesa es nr. 2, así que para eliminarlo:

# iptables -t nat -D PREROUTING 2

79voto

geocar Puntos 1718

Uso authbind.

Incluso funciona con Java si habilitar Java sólo IPv4 de la pila. Yo uso:

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …

41voto

Jake Wharton Puntos 160

Otra solución es hacer que su aplicación setuid, de modo que se puede enlazar con el puerto 80. Como root, haga lo siguiente

chown root ./myapp
chmod +S ./myapp

Tenga en cuenta que hacer esto, a menos que sea hecho absolutamente a la derecha, le expondrá a los posibles agujeros de seguridad, debido a que su aplicación va a estar hablando a la red, y se ejecuta con privilegios de root completo. Si usted toma esta solución, usted debe buscar en el código fuente de Apache o Lighttpd o algo similar, donde se utilizan los privilegios de root para abrir el puerto, pero inmediatamente se dan esos privs y "llegar a ser" un menor de usuario con privilegios para que un secuestrador que no puede llevar a todo tu equipo.

Actualización: Como se ve en esta pregunta, parece que el kernel de Linux desde 2.6.24 tiene una nueva capacidad que le permiten marcar un archivo ejecutable (pero no una secuencia de comandos, por supuesto) como tener el "CAP_NET_BIND_SERVICE" de capacidad. Si instala el paquete de debian "libcap2-bin", usted puede hacer que al emitir el comando

setcap 'cap_net_bind_service=+ep' /path/to/program

36voto

xelurg Puntos 1655

Enfoque propuesto por Soleada y CesarB:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

funciona bien pero tiene un pequeño inconveniente, no evita que el usuario se conecta directamente al puerto 8080 en lugar de 80.

Considere el siguiente escenario cuando esto puede ser un problema.

Supongamos que tenemos un servidor que acepta conexiones HTTP en el puerto 8080 y conexiones HTTPS en el puerto 8181.

Hacemos uso de iptables para establecer los siguientes casos:

80  ---> 8080
443 ---> 8181

Ahora, vamos a suponer que nuestro servidor decide redirigir usuario a partir de una página HTTP a una página HTTPS. A menos que nosotros cuidadosamente reescribir la respuesta, se canalizaran a https://host:8181/. En este punto, estamos jodidos:

  • Algunos usuarios marcador de la https://host:8181/ URL y que sería necesario para mantener esta URL para evitar la ruptura de sus favoritos.
  • Otros usuarios no podrán conectarse debido a que sus servidores proxy no apoyo no-SSL estándar de los puertos.

Yo uso el siguiente enfoque:

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT

Combinado con la regla predeterminada de RECHAZAR la ENTRADA de la cadena de este enfoque evita que los usuarios que se conectan directamente a los puertos 8080, 8181

29voto

CesarB Puntos 908

Tradicionalmente en Unix, sólo root puede unirse a los puertos bajos (<1024).

La forma más sencilla de evitar esto es para ejecutar el servidor en un alto del puerto (por ejemplo, 8080) y el uso de una simple regla iptables adelante las conexiones desde el puerto 80 al puerto 8080. Tenga en cuenta que con esto se pierde la protección adicional de los bajos de los puertos; cualquier usuario puede enlazar con el puerto 8080.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: