Ambos comandos publican un servicio local mediante un nombre HTTPS de Tailscale, y desde la máquina que los ejecuta parecen casi idénticos. La diferencia es quién puede llegar a la URL después, y esa diferencia decide qué controles sigue necesitando tu aplicación. Serve mantiene al público dentro de la tailnet; Funnel lo traslada a internet abierto. Elige primero el público y luego el comando que encaje con él.

Serve responde a una pregunta dentro de tu tailnet

Serve hace de proxy de un puerto local o sirve contenido local a los dispositivos de tu tailnet, y las reglas de acceso de la tailnet siguen aplicándose a cada solicitud. Un panel en el puerto 3000 se vuelve accesible en un nombre HTTPS que solo tus dispositivos pueden resolver y al que pueden conectarse. Es el valor predeterminado correcto para herramientas internas, porque el público ya está autenticado por la tailnet y no añades una superficie pública. La URL parece un sitio web normal, y por eso mismo la gente la toma por uno.

Serve también puede adjuntar cabeceras de identidad que describen al usuario de la tailnet a las solicitudes que reenvía. Si tu aplicación confía en esas cabeceras como autenticación, ata el backend a localhost para que nada más pueda alcanzarlo directamente; un backend que escucha en una dirección enrutable puede recibir solicitudes que nunca pasaron por el proxy.

Funnel cambia el público a internet abierto

Funnel publica un servicio seleccionado para cualquiera que tenga la URL, y los visitantes no necesitan el cliente, una cuenta ni pertenencia a tu tailnet. El recurso necesita por tanto la autenticación, la limitación de tasa y los parches que aplicarías a cualquier servicio público. Las solicitudes públicas no llevan las cabeceras de identidad de tailnet de Serve, así que una aplicación que dependía de ellas no tiene ninguna identidad de usuario bajo Funnel. Elegir un comando de publicación distinto no responde por ti a la pregunta de la autenticación.

Funnel también tiene restricciones que un tutorial de una versión anterior puede no mencionar. Termina TLS con un certificado que Tailscale obtiene para el nombre, y solo admite puertos de escucha concretos, como describe la documentación de Funnel. Si tu servicio espera un protocolo distinto de HTTPS en uno de esos puertos, Funnel es la herramienta equivocada y no un rompecabezas de configuración.

Lee el modo en el cliente, no en el puerto

Comprueba el estado actual antes de compartir nada, porque los dos modos pueden configurarse para el mismo puerto local en momentos distintos. Los comandos de estado informan de lo que está realmente publicado y para quién. No deduzcas el público del hecho de que una URL responda.

tailscale serve status
tailscale funnel status
tailscale status --json | head -40

La sintaxis de los comandos ha cambiado entre versiones del cliente, así que una invocación copiada puede seleccionar un modo distinto del que pretendías. Prefiere la forma documentada para la versión que ejecutas y lee la confirmación que imprime el cliente en lugar de suponerla. Si existen tanto una configuración de Serve como una de Funnel, la pública es la que importa para la exposición. Restablece la configuración que no querías en lugar de añadir otra encima.

Detente y vuelve a leer el estado si la salida no nombra al público. Una URL publicada sin un público declarado es una conjetura, y las conjeturas son la forma en que los paneles internos acaban en internet abierto.

Prueba con el público que realmente querías

Prueba desde fuera de la tailnet, no desde la máquina que publicó el servicio. Una solicitud desde un dispositivo de la tailnet demuestra que el proxy funciona; no demuestra que un desconocido quede excluido. Usa una red que no tenga cliente de Tailscale ni ruta hacia la tailnet.

curl -sI https://host.tailnet-name.ts.net
curl -sI https://host.tailnet-name.ts.net --resolve host.tailnet-name.ts.net:443:203.0.113.10

Para un panel interno, la solicitud externa debería fallar al conectar o fallar la autorización, y la solicitud interna debería tener éxito con la identidad que esperas. Para un servicio público, la solicitud externa debería tener éxito y la aplicación debería pedir sus propias credenciales. Anota cuál de esos dos resultados observaste, porque la URL sola no te lo dice. Si el resultado es lo contrario de lo que pretendías, elimina primero la configuración pública e investiga después.

Publicar un servicio tampoco es la misma decisión que elegir un nodo de salida, que controla por dónde sale tu tráfico saliente. Serve y Funnel responden quién puede llegar a algo que ejecutas; un nodo de salida responde de dónde parecen venir tus propias conexiones. Mantén las dos preguntas separadas y la comparación sigue siendo sencilla.

Artículos relacionados