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.