Aunque 80 y 443 son puertos del sistema, ¿cómo pueden conectarse la mayoría de los servidores web de todos modos?

18

La ejecución de un servicio web que se vincula al puerto 80 generalmente no requiere privilegios de sudoer. Dado que los puertos 80/443 son puertos del sistema, lo que significa que solo pueden ser utilizados por usuarios privilegiados, ¿cómo es que esos servicios aún pueden unirse a estos puertos?

adaml
fuente
1
"por lo general no requiere privilegios de sudoer" es incorrecto.
tedder42

Respuestas:

29

Básicamente hay dos enfoques diferentes:

  1. Inicialmente comience a ejecutarse como root, enlace al puerto privilegiado y luego desplácese a un usuario sin privilegios.

  2. inetd o xinetd se ejecuta con privilegios y reenvía las solicitudes al servidor web que se ejecuta sin privilegios.

Joe Sniderman
fuente
3
En Linux también puede aplicar la capacidad CAP_NET_BIND_SERVICE al programa o puede usar iptables para redirigir un puerto del sistema a un puerto normal.
Zan Lynx
10
y solo para aclarar para OP: la razón por la que la opción # 1 funciona es porque cuando los procesos abandonan los privilegios, se les permite retener los descriptores de archivos abiertos, incluso si no se les permitiera abrirlos por segunda vez.
Strugee
También hay Authbind .
Boris the Spider
5

Dado que el puerto 80/443 son puertos del sistema, significa que solo pueden ser utilizados por usuarios privilegiados

Creo que te equivocas. Cualquiera puede usar estos puertos. Vincularse a ellos es una operación privilegiada.

La razón aquí es que algún usuario Joe no debería poder escribir un servidor web malicioso y luego crear algún host en el que no tenga ningún derecho administrativo. Por supuesto, este es un modelo bastante débil, generalmente no hay nada que impida a Joe poner su propia computadora en la red, y podría tener derechos administrativos sobre cualquier máquina a la que tenga acceso físico.

Haré una demostración con netcat.

Como usuario normal, no puedo vincularme al puerto 80:

$ nc -l -p 80
Can't grab 0.0.0.0:80 with bind : Permission denied

Me puedo unir al puerto 8080:

$ nc -l -p 8080

Mientras tanto, en otra terminal, puedo conectarme al puerto 80 y enviar algunos datos, y veo que aparece en el extremo del servidor que acabo de comenzar:

$ nc 127.0.0.1 8080 <<<"Hello world"

Si quiero enlazar al puerto 80, necesito ser root:

$ sudo nc -l -p 80

O puedo asignar la CAP_NET_BIND_SERVICEcapacidad al ncbinario:

$ cp `which nc` .
$ sudo setcap 'cap_net_bind_service=+ep' ./nc
$ ./nc -l -p 80

Otra opción es escribir el programa del servidor de modo que después de que se llame listen(), elimine los privilegios de root. Esta es una solución bastante común, y la verás con la mayoría de los demonios. Apache, por ejemplo, se inicia desde init como root, y luego abandona los privilegios de root y se convierte en el usuario www-datao algo similar una vez que está vinculado al puerto 80. Intente ejecutarlo /etc/init.d/apache startcomo no root y Apache probablemente no se iniciará.

Phil Frost
fuente
La pregunta dice "unirse a estos puertos". ¿Por qué crees que se equivoca?
Barmar