Busqué en Google una solución durante bastante tiempo, pero no pude encontrar una respuesta.
Estoy en Ubuntu Linux y quiero ejecutar un servidor en el puerto 80, pero debido al mecanismo de seguridad de Ubuntu, aparece el siguiente error:
java.net.BindException: Permiso denegado: 80
Creo que debería ser lo suficientemente simple como deshabilitar este mecanismo de seguridad para que el puerto 80 esté disponible para todos los usuarios o para asignar los privilegios necesarios al usuario actual para acceder al puerto 80.
Respuestas:
Respuesta corta: no puedes. Los puertos por debajo de 1024 solo se pueden abrir por root. Según el comentario, bueno, puede hacerlo , usando CAP_NET_BIND_SERVICE , pero ese enfoque, aplicado a java bin hará que cualquier programa java se ejecute con esta configuración, lo que es indeseable, si no es un riesgo de seguridad.
La respuesta larga: puede redirigir las conexiones en el puerto 80 a algún otro puerto que pueda abrir como usuario normal.
Ejecutar como root:
Como los dispositivos de bucle invertido (como localhost) no usan las reglas de enrutamiento previo, si necesita usar localhost, etc., agregue esta regla también ( gracias @Francesco ):
NOTA: La solución anterior no es adecuada para sistemas multiusuario, ya que cualquier usuario puede abrir el puerto 8080 (o cualquier otro puerto alto que decida usar), interceptando así el tráfico. (Créditos a CesarB ).
EDITAR: según la pregunta de comentario - para eliminar la regla anterior:
Esto generará algo como:
La regla que le interesa es nr. 2, para eliminarlo:
fuente
sudo iptables --list
. Sé lo que es y hace iptables, pero nunca lo he usado antes.Usa authbind .
Incluso funciona con Java si habilita la pila solo de Java IPv4. Yo suelo:
fuente
AUTHBIND=yes
/ etc / default / tomcat6authbind
para permitir que esto suceda. Desde la página de manual: "/ etc / authbind / byport / port se prueba. Si este archivo es accesible para la ejecución del usuario que realiza la llamada, de acuerdo con access (2), se autoriza el enlace al puerto". , Por ejemplo para el puerto 80,sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80
. La instalación inicial deauthbind
generalmente no tiene ninguna autorización preconfigurada.Si su sistema lo admite, tal vez podría usar capacidades. Vea las capacidades de man, la que necesita sería CAP_NET_BIND_SERVICE.
En las versiones más recientes de Debian / Ubuntu puedes ejecutar:
fuente
Otra solución es hacer que su aplicación sea setuid para que pueda enlazarse con el puerto 80. Como root, haga lo siguiente
Tenga en cuenta que hacer esto, a menos que se haga de manera absolutamente correcta, lo expondrá a posibles agujeros de seguridad, porque su aplicación estará hablando con la red y se ejecutará con privilegios de root completos. Si toma esta solución, debe mirar el código fuente de Apache o Lighttpd o algo similar, donde usan los privilegios de root para abrir el puerto, pero luego renuncian inmediatamente a esos privilegios y "se convierten" en un usuario con menos privilegios para que un secuestrador no puede hacerse cargo de toda su computadora.
Actualización: Como se ve en esta pregunta , parece que los núcleos de Linux desde 2.6.24 tienen una nueva capacidad que le permite marcar un ejecutable (pero no un script, por supuesto) que tiene la
CAP_NET_BIND_SERVICE
capacidad " ". Si instala el paquete debian "libcap2-bin", puede hacerlo emitiendo el comandofuente
Simplemente uso Nginx en frente. También puede ejecutarse en localhost.
apt-get install nginx
.. o ..
pkg_add -r nginx
.. o lo que mejor se adapte a su sistema operativo.
Todo lo que necesita en nginx.conf, si se ejecuta en localhost, es:
fuente
Enfoque propuesto por Sunny y CesarB:
funciona bien pero tiene un pequeño inconveniente: no impide que el usuario se conecte directamente al puerto 8080 en lugar de 80.
Considere el siguiente escenario cuando esto puede ser un problema.
Digamos que tenemos un servidor que acepta conexiones HTTP en el puerto 8080 y conexiones HTTPS en el puerto 8181.
Utilizamos iptables para establecer las siguientes redirecciones:
Ahora, supongamos que nuestro servidor decide redirigir al usuario desde una página HTTP a una página HTTPS. A menos que reescribamos cuidadosamente la respuesta, se redirigirá a
https://host:8181/
. En este punto, estamos jodidos:https://host:8181/
URL y deberíamos mantener esta URL para evitar romper sus marcadores.Yo uso el siguiente enfoque:
Combinado con la regla de RECHAZO predeterminada en la cadena de ENTRADA, este enfoque evita que los usuarios se conecten directamente a los puertos 8080, 8181
fuente
Tradicionalmente en Unix, solo la raíz puede unirse a puertos bajos (<1024).
La forma más sencilla de evitar esto es ejecutar su servidor en un puerto alto (por ejemplo, 8080) y usar una regla simple de iptables para reenviar las conexiones del puerto 80 al puerto 8080. Tenga en cuenta que con esto pierde la protección adicional del puertos bajos; cualquier usuario en su máquina puede unirse al puerto 8080.
fuente
Si su sistema lo admite, tal vez podría usar capacidades. Mira
man capabilities
, el que necesitas seríaCAP_NET_BIND_SERVICE
. No, nunca los he usado yo mismo y no sé si realmente funcionan :-)fuente
¡Use un proxy inverso (nginx, apache + mod_proxy) o un proxy inverso de almacenamiento en caché (Squid, Varnish) frente a los servidores de su aplicación!
Con un proxy inverso puedes lograr muchas cosas interesantes como:
fuente
Puede usar el programa redir:
fuente
Usa sudo.
Configure sudo para que el usuario normal pueda ejecutar los comandos apropiados:
O
O
O
(O cualquier otro comando / script que use para iniciar / detener su servidor web / aplicación en particular)
fuente
la respuesta de sunny es correcta, pero puede enfrentar problemas adicionales ya que la interfaz de bucle invertido no usa la tabla PREROUTING,
entonces las reglas de iptables para agregar son dos:
fuente
Con Linux, tiene otras dos opciones:
Ambas extensiones del kernel de Linux permiten otorgar derechos de acceso en un nivel muy fino. Esto le permitiría otorgar este proceso para abrir el puerto 80, pero no heredaría ninguno de los otros derechos de root.
Por lo que escuché, la seguridad es mucho más simple de usar, pero SELinux es más seguro.
fuente
Una solución es usar iptables para realizar PAT en los paquetes para el puerto 80. Puede usar esto para enrutar los paquetes al puerto local 8080, por ejemplo. Asegúrese de ajustar los paquetes salientes nuevamente al puerto 80.
En mi experiencia, las características de permisos específicos de Linux no se compilan en núcleos estándar debido a problemas de seguridad.
fuente
Si está intentando hacer esto para que un comando ejecutado por el usuario pueda usar el puerto 80, entonces sus únicas soluciones son los trucos de iptables o la configuración del setuid-to-root ejecutable.
La forma en que algo como Apache hace esto (se une al puerto 80, pero se ejecuta como alguien que no sea root) es ejecutarlo como root, vincularse al puerto y luego cambiar la propiedad del proceso al usuario no privilegiado después del puerto está arreglado. Si la aplicación que está escribiendo puede ejecutarse desde la raíz, puede hacer que cambie de propietario al usuario no privado después de configurar los puertos. Pero si esto es solo para que un usuario promedio lo ejecute desde la línea de comandos, entonces tendrá que usar una de las otras soluciones.
fuente
Cuando tengo varias aplicaciones de servicio web (scripts de python, motores tomcat, ...) que no quiero ejecutar como root, generalmente configuro un servidor web apache frente a ellos. Apache escucha el puerto 80 y Tomcat escucha el 8080.
En apache: s config:
Consulte la documentación de mod-proxy para obtener más información: http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
fuente
Creo que la mejor solución es sgid su aplicación y tan pronto como tenga su puerto vinculado, debería abandonar los privilegios al cambiar a otro usuario.
fuente
Algunos sistemas host no permiten usar el módulo NAT, 'iptables' no resuelve el problema en este caso.
¿Qué tal xinetd?
En mi caso (ubuntu 10.04)
Pegue la configuración:
Entonces:
http://docs.codehaus.org/display/JETTY/port80 explica mejor.
fuente
Por otro lado, FreeBSD y Solaris (¿alguien recuerda eso ?) Le permiten hacer esto (enlazar a puertos bajos) sin escalada de privilegios (es decir, usar programas para cambiar a root). Como especificó Linux, solo publico esto como un aviso para otros que puedan encontrar esta pregunta.
fuente
Nigromancia
Sencillo. Con un núcleo normal o antiguo, no lo hace.
Como señalaron otros, iptables puede reenviar un puerto.
Como también señalaron otros, CAP_NET_BIND_SERVICE también puede hacer el trabajo.
Por supuesto, CAP_NET_BIND_SERVICE fallará si inicia su programa desde un script, a menos que establezca el límite en el intérprete de shell, lo cual no tiene sentido, podría ejecutar su servicio como root ...
por ejemplo, para Java, debe aplicarlo a la JVM JAVA
Obviamente, eso significa que cualquier programa Java puede enlazar puertos del sistema.
Dito para mono / .NET.
También estoy bastante seguro de que xinetd no es la mejor de las ideas.
Pero dado que ambos métodos son hacks, ¿por qué no simplemente levantar el límite levantando la restricción?
Nadie dijo que tenía que ejecutar un núcleo normal, por lo que puede ejecutar el suyo.
Simplemente descargue la fuente del último kernel (o el mismo que tiene actualmente). Luego, vas a:
Ahí buscas esta línea
y cambiarlo a
si no desea tener una situación ssh insegura, modifíquela así: #define PROT_SOCK 24
En general, usaría la configuración más baja que necesite, por ejemplo, 79 para http, o 24 cuando use SMTP en el puerto 25.
Eso ya es todo.
Compile el núcleo e instálelo.
Reiniciar.
Terminado: ese límite estúpido se ha ido, y eso también funciona para los scripts.
Así es como compila un núcleo:
https://help.ubuntu.com/community/Kernel/Compile
En pocas palabras, use iptables si desea mantenerse seguro, compile el kernel si desea asegurarse de que esta restricción nunca lo moleste nuevamente.
fuente
sudo setcap cap_net_bind_service=+ep /path-to-java/java
) pero siempre obtengojava: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
si Java tiene mayúsculas. vea también la primera parte de unix.stackexchange.com/a/16670/55508<javahome>/lib/amd64/jli/
ald.so.conf
y en funcionamientosudo ldconfig