Cómo verificar puertos abiertos en Mac: lsof, netstat y nc

Verifica puertos abiertos en Mac con lsof -i :3000, netstat y nc. Incluye ejemplos reales de salida para puertos locales y hosts remotos.

Ejecutaste rails server y nada carga. O intentas conectarte a un servidor remoto y no obtienes respuesta. La primera pregunta siempre es la misma: ¿el puerto está realmente abierto?

Verificar el estado de un puerto en Mac se hace con un solo comando. El truco está en saber cuál usar dependiendo de si revisas tu propia Mac o un host remoto.

Verificar los puertos abiertos de tu propia Mac

Este es el caso más común para desarrolladores. Tu servidor debería estar corriendo en el puerto 3000, pero el navegador dice que no puede conectarse. ¿El puerto siquiera está escuchando?

lsof -i :puerto (la respuesta rápida)

lsof -i :3000

Si algo está escuchando, verás una salida como esta:

COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby     8421  aaron  13u  IPv4 0x3f8a2b4c      0t0  TCP *:3000 (LISTEN)

Si la salida está vacía, nada está vinculado a ese puerto. Tu servidor Rails no está corriendo, o inició en un puerto diferente.

Para el puerto 8080:

lsof -i :8080

Para el puerto 80 (requiere sudo porque es un puerto privilegiado):

sudo lsof -i :80

lsof -i | grep LISTEN (ver todo de una vez)

Para ver todos los puertos que tu Mac está escuchando en este momento:

lsof -i | grep LISTEN

La salida muestra cada proceso con un puerto activo en escucha:

ruby      8421  aaron  13u  IPv4  TCP *:3000 (LISTEN)
node      9102  aaron  21u  IPv6  TCP *:8080 (LISTEN)
postgres  1234  aaron   5u  IPv4  TCP localhost:5432 (LISTEN)

Nota la diferencia entre localhost:5432 y *:3000. Postgres solo acepta conexiones desde la misma computadora. Rails acepta desde cualquier lugar en la red. Esa diferencia importa cuando intentas conectarte desde otro dispositivo.

Si quieres puertos numéricos sin resolver hostnames (más rápido):

lsof -i -n -P | grep LISTEN

netstat -an | grep LISTEN

netstat te da una vista similar en un formato diferente:

netstat -an | grep LISTEN

La salida se ve así:

tcp4       0      0  *.3000                 *.*                    LISTEN
tcp4       0      0  127.0.0.1.5432         *.*                    LISTEN
tcp6       0      0  *.8080                 *.*                    LISTEN

La dirección antes del puerto indica la interfaz. *.3000 significa todas las interfaces (accesible desde la red). 127.0.0.1.5432 significa solo localhost.

netstat es útil cuando quieres una lista plana sin nombres de procesos. lsof es mejor cuando necesitas saber qué app es dueña de cada puerto.

Qué significan los resultados

Algo aparece en LISTEN: El puerto está abierto y un proceso lo tiene. Si aún no puedes conectarte, el problema está en otro lado (firewall, IP incorrecta, autenticación).

Sin salida de lsof / nada en netstat: Nada está escuchando en ese puerto. El servicio no está corriendo o inició en un puerto diferente.

La salida muestra 127.0.0.1 o localhost: El servicio solo acepta conexiones locales. No podrás acceder desde otra computadora ni desde tu celular en la misma red.

Verificar el puerto de un host remoto

Cuando necesitas probar si un puerto está abierto en un servidor que no controlas, no puedes usar lsof. En cambio, intentas conectarte directamente y ves qué pasa.

nc -zv (la herramienta correcta)

nc -zv hostname 443

Si el puerto está abierto:

Connection to hostname port 443 [https] succeeded!

Si está cerrado (nada escuchando):

nc: connectx to hostname port 80 (tcp) failed: Connection refused

Si está filtrado (firewall descartando paquetes):

nc: connectx to hostname port 25 (tcp) failed: Operation timed out

“Connection refused” significa que el servidor es alcanzable pero nada está en ese puerto. “Operation timed out” significa que probablemente un firewall está descartando tus paquetes antes de que lleguen.

Ejemplos reales:

# ¿HTTPS funciona en mi servidor?
nc -zv miservidor.com 443

# ¿SSH está abierto en este equipo?
nc -zv 192.168.1.100 22

# ¿Puedo alcanzar el puerto de la base de datos desde aquí?
nc -zv db.internal 5432

También puedes revisar varios puertos al mismo tiempo:

nc -zv hostname 80 443 8080

Interpretar los resultados

Resultado Significado
Connection succeeded Puerto abierto, algo está escuchando
Connection refused Puerto cerrado, nada escuchando
Operation timed out Un firewall está bloqueando la conexión
Name or service not known El hostname no resuelve (problema de DNS)

Si el puerto responde pero tu servicio igual no funciona, el problema está en la capa de aplicación: credenciales incorrectas, protocolo incompatible, la app rechazando la conexión.

Puertos comunes a verificar

Al depurar, estos son los puertos que aparecen con más frecuencia:

  • 22 (SSH): ¿No puedes conectarte por SSH? Empieza aquí.
  • 80 (HTTP) y 443 (HTTPS): Servidor web sin respuesta.
  • 3000, 3001, 8000, 8080: Puertos comunes de servidores de desarrollo. Rails usa 3000 por defecto, muchas apps de Node usan 8080.
  • 5432 (PostgreSQL), 3306 (MySQL), 27017 (MongoDB): Problemas de conexión a bases de datos.
  • 25 (SMTP): ¿La app no puede enviar correo? Frecuentemente bloqueado por ISPs y proveedores de nube.

Seguridad: ¿qué puertos está exponiendo tu Mac?

Ejecutar lsof -i | grep LISTEN de vez en cuando es una buena práctica de seguridad. Cada puerto en escucha es un punto de entrada potencial. En una laptop, lo ideal es ver la menor cantidad posible de puertos abiertos.

Causas comunes de puertos abiertos inesperados:

  • Servidores de desarrollo dejados corriendo (Rails, Node, Webpack)
  • Docker mapeando puertos al host
  • Remote Desktop o Screen Sharing activados
  • Receptor de AirPlay
  • Apps de terceros con servicios en segundo plano

Si ves algo que no reconoces, toma el PID de la salida de lsof y búscalo:

ps aux | grep <PID>

Firewall de macOS

El firewall de macOS controla qué puede conectarse a tu Mac desde afuera. Puedes revisarlo en Configuración del Sistema > Red > Firewall (o Configuración del Sistema > Privacidad y Seguridad > Firewall en algunas versiones).

Con el firewall activado, otras computadoras no pueden acceder a los servicios en escucha de tu Mac a menos que los hayas permitido explícitamente. Tu Mac sigue pudiendo hacer conexiones salientes.

Si tu servidor de desarrollo carga bien en tu navegador pero no desde tu celular en la misma red, el firewall es probablemente el motivo.

Opción con interfaz gráfica: el escáner de puertos de NetUtil

Si prefieres no escribir comandos, NetUtil incluye un escáner de puertos. Ingresa un hostname y rango de puertos, y muestra cuáles están abiertos en una tabla. Es el reemplazo directo del escáner que venía en la app Utilidad de Red de Apple antes de que la eliminaran en macOS Monterey.

Para depuración frecuente, los comandos de Terminal son más rápidos una vez que los conoces. lsof -i :3000 se convierte en algo automático después de hacerlo unas pocas veces. Para revisiones ocasionales o cuando quieres escanear un rango de puertos en un servidor remoto, una app con interfaz gráfica ahorra tiempo.

Referencia rápida

Verificar si tu Mac está escuchando en un puerto específico:

lsof -i :3000

Ver todos los puertos en escucha en tu Mac:

lsof -i | grep LISTEN

Lo mismo con netstat:

netstat -an | grep LISTEN

Verificar si un puerto remoto está abierto:

nc -zv hostname 443

El estado de un puerto en tu Mac te dice si un servicio está corriendo. El estado de un puerto en un host remoto te dice si ese servicio es alcanzable. Dos preguntas distintas, dos herramientas distintas.