Saltar al contenido
Nuevo

DeepSeek V4.1 Flash gratis por 7 días: 10M tokens al día tras cualquier recarga. Hasta el 30/11.

Cómo funciona

Nmap básico en tu propio laboratorio

Nmap lista los puertos abiertos de tu propia máquina. Revisa escaneos connect y SYN, detección de servicios y cómo ligar cada puerto a su proceso.

Principiante13 min de lecturaPor NotHoly

La respuesta corta

Nmap es un escáner de red. Lo apuntas a un host y te informa qué puertos responden, en qué estado está cada uno y, si lo pides, qué servicio y versión hay detrás de un puerto abierto. En tu propia máquina, eso lo convierte en una herramienta rápida de inventario. Obtienes la lista de lo que está escuchando y puedes compararla con lo que crees que tienes corriendo.

Trata la salida de Nmap como un inventario de partida. No es un hallazgo. Un puerto abierto solo te dice que un socket está escuchando. Si ese socket es un problema depende de qué proceso es su dueño, de quién puede alcanzarlo y de si debería existir. Este artículo termina con el paso que la mayoría se salta: relacionar cada puerto abierto con el proceso que está detrás.

Por qué importa

La mayoría de las sorpresas en una máquina vienen de algo que nadie recuerda haber iniciado. Un servidor de desarrollo que quedó corriendo desde la semana pasada. Un contenedor que publicó un puerto en todas las interfaces. Un servicio en segundo plano que se instaló solo durante una actualización. No puedes evaluar lo que no has listado, y un inventario de puertos es la forma más barata de empezar. El mismo método sirve en una laptop, en una máquina virtual que tú construiste o en una red de cliente que tienes autorización para probar.

Lee esto antes de ejecutar cualquier escaneo. El libro de Nmap tiene un capítulo sobre temas legales, y su consejo central es sencillo: pide permiso antes de escanear una red que no controlas. Recuerda que algunos proveedores de internet prohíben el escaneo no autorizado en sus políticas de uso aceptable y pueden desconectar a quien las incumpla. En trabajo profesional, dice que la mejor forma de evitar problemas es obtener autorización por escrito de quienes representan la red objetivo, con el Statement of Work como lugar para registrarla. También señala que rara vez te molestan por escanear tu propia máquina o las redes que administras.

Para este artículo, la regla es:

  • Escanea solo sistemas que son tuyos, o sistemas para los que tienes un permiso por escrito que los nombre.
  • Tu laptop, una VM que construiste y un contenedor que tú iniciaste sí cuentan. La máquina de un compañero, la red de una escuela, el Wi-Fi de un hotel o el router del vecino no cuentan, aunque la dirección parezca privada.
  • Una dirección IP pública no es un objetivo de práctica. El dueño y el proveedor de red pueden leer el escaneo como un ataque.

Todos los comandos de este laboratorio apuntan a 127.0.0.1, la dirección de loopback. Los paquetes enviados ahí nunca salen de tu máquina. Por eso el laboratorio es seguro para practicar, y el alcance es fácil de definir: el único host involucrado es el tuyo.

Cómo un puerto se convierte en un estado

Un puerto es un número que el sistema operativo usa para entregar tráfico entrante a un proceso. Si un programa le avisó al sistema que aceptará conexiones en el puerto TCP 3000, ese socket está escuchando. Un escaneo pregunta, para cada puerto, qué pasa cuando llega una sonda.

Nmap informa uno de varios estados. Los tres que más vas a ver son:

  • open: algo aceptó la conexión.
  • closed: el host respondió que no hay nada escuchando en ese puerto.
  • filtered: Nmap no recibió una respuesta útil, normalmente porque un firewall descartó la sonda.

Estos estados describen la sonda, no el riesgo. Un puerto cerrado puede causarte problemas si un servicio del que dependes está caído. Un puerto filtrado puede ser un firewall haciendo su trabajo. Mantén el estado separado de lo que significa.

Escaneo connect y escaneo SYN

Nmap tiene varios tipos de escaneo. Dos de ellos importan para quien empieza.

Escaneo TCP connect (-sT)

Un escaneo connect le pide al sistema operativo que abra una conexión TCP completa a cada puerto. El sistema hace el handshake normal de tres pasos. Si la conexión funciona, el puerto está abierto, y Nmap la cierra. La guía de Nmap describe el connect como el predeterminado cuando el escaneo SYN no está disponible, porque no necesita privilegios para enviar paquetes sin procesar. Nmap usa la llamada connect del propio sistema en lugar de construir paquetes por su cuenta.

El costo es la visibilidad. Una conexión completa aparece en los registros del objetivo, lo cual está bien en tu laboratorio y merece pensarse en cualquier red que no es tuya.

Escaneo TCP SYN (-sS)

Un escaneo SYN envía un paquete SYN, el mismo primer paso que usa una conexión real, y luego lee la respuesta. Un SYN/ACK significa que el puerto está escuchando. Un RST significa que no hay nada escuchando. Nmap no termina el handshake, y por eso a este escaneo se le llama a menudo half-open. La guía dice que el escaneo SYN es el predeterminado cuando Nmap tiene privilegios para enviar paquetes sin procesar, lo que normalmente significa permisos de root o de administrador.

En Windows, revisa en las notas de instalación de Nmap el soporte para paquetes sin procesar antes de depender de -sS. Este laboratorio usa -sT porque funciona sin privilegios elevados y aun así da los estados de puerto que necesitas.

Para quien empieza, la diferencia útil es qué deja cada escaneo. Un escaneo connect completa el handshake y aparece en los registros de ambos lados. Un escaneo SYN se detiene antes de que termine el handshake.

Detección de servicios con -sV

El estado del puerto te dice que algo escucha en el 8000. No te dice qué es ese algo. La opción -sV envía sondas a los puertos abiertos, compara las respuestas con la base de firmas de Nmap y reporta un nombre de servicio y una versión cuando la reconoce.

La intensidad va de 0, que envía las menos sondas, a 9, que prueba todas. Los niveles altos tardan más y generan más tráfico. Por defecto, la detección de versión omite el puerto TCP 9100, un puerto de impresora que puede reaccionar mal a las sondas. Usa la menor intensidad que responda tu pregunta, y ejecuta -sV solo contra sistemas que controlas.

Las cadenas de versión son evidencia, no prueba. Quien administra un servicio puede cambiar su banner, así que un número de versión es una afirmación que hay que contrastar con el propio software.

Formatos de salida

Nmap puede escribir los resultados en un archivo además de mostrarlos en pantalla. Los formatos que más vas a usar son:

  • -oN archivo: salida normal, legible para una persona.
  • -oX archivo: XML, para herramientas que procesan resultados.
  • -oG archivo: salida "grepable", una línea por host, para filtros rápidos en la terminal.

Usa -oN para notas que vas a leer tú, y -oX cuando otra herramienta vaya a procesar el resultado. Guarda los archivos de escaneo junto a tus notas del laboratorio. Un escaneo de la semana pasada es un registro de lo que era verdad la semana pasada, no de hoy.

Práctica: laboratorio

Necesitas Docker, Python 3, Nmap y una máquina donde los puertos 3000 y 8000 estén libres en 127.0.0.1. Si todavía no tienes una red de laboratorio, empieza por cómo crear una red Docker aislada para laboratorios. Cada paso de abajo se ejecuta en tu máquina. Los comandos son los del laboratorio. Cuando los ejecuté en mi Windows 11, muestro la salida que vi. Cuando no pude ejecutarlos, lo digo y explico qué buscar.

Paso 1: levantar Juice Shop en loopback

OWASP Juice Shop es una aplicación web deliberadamente vulnerable, hecha para practicar. Levántala con su puerto ligado solo a loopback:

bash
docker run -d --name juice-local -p 127.0.0.1:3000:3000 bkimminich/juice-shop

La parte 127.0.0.1 importa. Sin ella, Docker publica el puerto en todas las interfaces, y cualquier dispositivo de tu red podría alcanzar una aplicación pensada solo para practicar.

Si el nombre ya está en uso, Docker se detiene con un error de conflicto. No borres ese contenedor hasta saber quién lo creó. Inspecciónalo primero:

bash
docker inspect juice-local --format 'image={{.Config.Image}} ports={{json .NetworkSettings.Ports}} status={{.State.Status}}'

Lo que observé en mi máquina:

text
image=bkimminich/juice-shop ports={"3000/tcp":[{"HostIp":"127.0.0.1","HostPort":"3000"}]} status=running

Levanté uno nuevo para esta ejecución y confirmé el mapeo con docker port juice-local, que mostró 3000/tcp -> 127.0.0.1:3000. Docker ya tenía la imagen en caché, así que no se descargó nada. Dale unos segundos a la aplicación para arrancar antes de abrirla en el navegador.

Paso 2: levantar un servidor web de Python en loopback

bash
python3 -m http.server 8000 --bind 127.0.0.1 &

En Windows, python3 puede no existir. En mi máquina no estaba en el PATH, así que ejecuté Python 3.12 con la ruta completa de instalación y los mismos argumentos. El & deja el servidor corriendo en segundo plano del shell actual. Pruébalo desde otra terminal:

bash
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/index.txt

El archivo que pedí existía en la carpeta desde donde inicié el servidor, y la prueba devolvió 200. El log del servidor registró la solicitud:

text
127.0.0.1 - - [08/Nov/2026 06:20:25] "GET /index.txt HTTP/1.1" 200 -

Paso 3: listar lo que el sistema dice que está escuchando

Antes de escanear, pregúntale al sistema operativo. Esta lista es tu referencia, y no depende de Nmap.

En Linux:

bash
ss -tlnp

En Windows, en PowerShell:

powershell
Get-NetTCPConnection -State Listen

En mi máquina ejecuté una versión que además muestra el proceso dueño:

powershell
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -lt 10000 } | Sort-Object LocalPort | ForEach-Object { $p = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue; '{0,-15} {1,6} {2,8} {3}' -f $_.LocalAddress, $_.LocalPort, $_.OwningProcess, $p.ProcessName }

La salida en mi máquina, limitada a los puertos menores de 10000:

text
::                 135     2204 svchost
0.0.0.0            135     2204 svchost
192.168.0.100      139        4 System
172.23.112.1       139        4 System
::                 445        4 System
0.0.0.0            515     6084 svchost
::                 515     6084 svchost
127.0.0.1         1026    23620 com.docker.backend
127.0.0.1         3000    23620 com.docker.backend
::                3311    11308 node
127.0.0.1         5000    43252 python
0.0.0.0           5040    10556 svchost
::                7680     4604 svchost
127.0.0.1         8000    49736 python
127.0.0.1         8001     7976 python
127.0.0.1         8026    23620 com.docker.backend

Cuenta las líneas. Muchos de esos puertos pertenecen al propio Windows, no a algo que tú iniciaste. Es normal, y justamente por eso un inventario tiene que nombrar al dueño de cada puerto.

Paso 4: ejecutar el escaneo connect

bash
nmap -sT -p 1-10000 127.0.0.1

No ejecuté este comando. Nmap no está instalado en la máquina que usé, y no lo instalé. Qué buscar cuando lo ejecutes: una tabla PORT STATE SERVICE. Cada línea marcada como open debe coincidir con una fila del paso 3. En este laboratorio, 3000/tcp y 8000/tcp deberían aparecer como abiertos. Nmap suele resumir los puertos cerrados en una sola línea, así que las líneas que hay que leer son las abiertas.

Como sustituto, escribí una verificación corta en loopback con la biblioteca estándar de Python. Abre una conexión TCP a cada puerto del 1 al 10000 en 127.0.0.1 e informa cuáles aceptan. Hace el mismo handshake que hace un escaneo connect, pero no es Nmap:

python
import socket
from concurrent.futures import ThreadPoolExecutor

HOST = "127.0.0.1"

def is_open(port: int) -> bool:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.settimeout(0.3)
        return s.connect_ex((HOST, port)) == 0

if __name__ == "__main__":
    with ThreadPoolExecutor(max_workers=200) as ex:
        results = list(ex.map(is_open, range(1, 10001)))
    open_ports = [p for p, ok in zip(range(1, 10001), results) if ok]
    print(f"open on {HOST} in 1-10000: {open_ports}")

Salida en mi máquina:

text
open on 127.0.0.1 in 1-10000: [135, 445, 515, 1026, 3000, 3311, 5000, 5040, 7680, 8000, 8001, 8026]

Cada puerto de esa lista también aparece en la tabla de listeners del paso 3. Las dos fuentes coinciden, y esa es la verificación que quieres antes de confiar en cualquiera de las dos.

Paso 5: ejecutar la detección de servicios y guardar la salida

bash
nmap -sV -p 3000,8000 127.0.0.1 -oN localhost-scan.txt

No lo ejecuté aquí, por el mismo motivo que en el paso 4. Qué buscar: una columna VERSION junto a 3000 y 8000, y un archivo llamado localhost-scan.txt en la carpeta actual. El texto de versión que Nmap muestra para el puerto 3000 es una afirmación que hay que verificar. Abre la aplicación en el navegador o lee la documentación del propio software antes de anotar la versión en cualquier lugar.

Paso 6: relacionar cada puerto abierto con su proceso

Este paso convierte un escaneo en un inventario. Para cada puerto abierto necesitas el proceso que lo posee. En Linux, ss -tlnp muestra el nombre del proceso y el PID en la última columna. En Windows, toma el PID de OwningProcess y búscalo:

powershell
Get-Process -Id 23620 | Select-Object Id, ProcessName

Hice eso para los puertos de la lista. Así resultaron ser los dueños en mi máquina:

Puerto Escuchando en PID Dueño Qué es
3000 127.0.0.1 23620 com.docker.backend Proxy de Docker Desktop para el contenedor juice-local, confirmado con docker port juice-local
8000 127.0.0.1 49736 python El http.server del paso 2
3311 todas las interfaces (::) 11308 node Un proceso Node.js; tasklist /svc no muestra ningún servicio para él, así que es un programa que alguien inició
515 todas las interfaces 6084 svchost El servicio de impresión LPD de Windows; tasklist /svc /fi "PID eq 6084" muestra LPDSVC

Dos filas piden una decisión, y el escaneo por sí solo no puede tomarla. El proceso Node.js del 3311 escucha en todas las interfaces, así que, si es un servidor de desarrollo para trabajo local, otros dispositivos pueden alcanzarlo. El servicio LPD del 515 también escucha en todas las interfaces. Decidir si alguno de los dos debe seguir corriendo es tu decisión, y la corrección le corresponde al dueño del proceso, no al escáner. No detengas un servicio solo porque aparece en una lista.

La fila de Docker necesita una segunda verificación. El proceso de backend reenvía el puerto, así que el PID por sí solo no dice qué contenedor hay detrás. docker port juice-local dio el mapeo que esperaba:

text
3000/tcp -> 127.0.0.1:3000

Los PID cambian. El servidor de Python tenía el PID 49668 en una lista anterior en esta máquina. Después de reiniciarlo para esta ejecución, la misma línea de comandos ocupó el puerto 8000 con el PID 49736. Lee el PID justo antes de actuar, y confirma la línea de comandos además del nombre.

Limpieza

bash
docker rm -f juice-local
kill %1

Ejecuta el primer comando solo en un contenedor que hayas creado para este laboratorio. kill %1 solo funciona en el shell que inició el job; desde otro shell, busca el PID como en el paso 6, revisa su línea de comandos y luego detenlo.

Errores comunes

Escanear una dirección que no es tuya. Un rango privado como 192.168.x.x puede pertenecer a un router o a un dispositivo que administra otra persona. Escanea solo lo que tienes permiso escrito para escanear.

Leer "open" como "vulnerable". Un puerto abierto es un hecho sobre un listener. Solo se vuelve un hallazgo cuando sabes qué servicio es, por qué es alcanzable y si debería serlo.

Olvidar el -p. Sin un rango de puertos, Nmap escanea los 1.000 puertos más comunes de cada protocolo. El laboratorio usa -p 1-10000 a propósito, porque un servicio en un puerto poco común es justo lo que un inventario debe detectar.

Publicar sin la dirección. -p 3000:3000 publica en todas las interfaces. Mantén 127.0.0.1: delante cuando la aplicación sea solo para ti.

Confiar en una cadena de versión. -sV lee lo que el servicio dice de sí mismo. Verifica la versión contra el software antes de depender de ella.

Quedarse en el escaneo. El escaneo te da números de puerto. Encontrar el dueño de cada puerto es la parte que todavía tienes que hacer.

Cómo seguir

Anota los puertos que esperas antes de escanear y compáralos después. Es la forma más rápida de notar algo que no sabías que estaba corriendo.

Escanea dos veces: una con el servidor de Python corriendo y otra después de detenerlo. Guarda ambos archivos con -oN y compáralos. La diferencia es lo que cambiaste.

Lee en la guía de Nmap las secciones sobre -oX y -Pn. Cuando conozcas los formatos de salida, puedes llevar los resultados a un script y seguir sus cambios en el tiempo, siempre solo en tus propias máquinas.

El siguiente artículo de la serie pasa de los puertos a la capa web, con OWASP ZAP: primeros pasos contra Juice Shop ejecutado contra el mismo contenedor.

Fuentes

Fuentes

  1. Nmap Reference Guide (Chapter 15)
  2. Nmap Network Scanning: Legal Issues
  3. Nmap Network Scanning: Version Detection
  4. Nmap Network Scanning: Port Scanning Techniques
  5. Nmap Network Scanning: Port Specification and Scan Order
  6. Nmap Network Scanning: Output

Más en Herramientas de seguridad

Herramientas de seguridad

Lo básico de OWASP ZAP contra tu Juice Shop local

Ejecuta el escaneo pasivo de ZAP contra Juice Shop en tu máquina, lee el informe y verifica una alerta a mano antes de confiar en ella.

Principiante13 min de lectura