← Volver al blog

Guía

¿Qué es localhost? 127.0.0.1, ::1 y por qué tu servidor de desarrollo vive ahí

14 de septiembre de 20264 min de lectura

localhost es la primera URL que escribe casi todo desarrollador, y una de las menos examinadas. Vale cinco minutos, porque dos de los problemas más molestos de red local salen justo de entenderlo mal.

localhost es un nombre, y significa “yo”

Es un nombre de host, como example.com, salvo que resuelve a tu propia máquina. El tráfico que le mandas nunca llega a tu tarjeta de red, nunca toca tu router y nunca sale del computador. El kernel lo devuelve de inmediato.

Por eso la interfaz se llama loopback, o de bucle invertido. En macOS es lo0, y la puedes mirar:

ifconfig lo0
# inet 127.0.0.1 netmask 0xff000000
# inet6 ::1 prefixlen 128

Dos direcciones, porque hay dos protocolos de internet. 127.0.0.1 es loopback en IPv4, ::1 es loopback en IPv6. localhost normalmente resuelve a las dos, y cuál se usa depende del programa.

La trampa de IPv4 contra IPv6

Esta es la que le cuesta una tarde a mucha gente.

Tu servidor se ata a 127.0.0.1. Tu cliente, o tu navegador, resuelve localhost y obtiene ::1 primero. La conexión es rechazada, y quedas mirando un servidor que ves corriendo en otra terminal.

Si una conexión local te da rechazada y estás seguro de que el proceso está arriba, prueba con la dirección en vez del nombre:

curl http://127.0.0.1:3000
curl http://[::1]:3000

Si una funciona y la otra no, ahí está el problema. Ata el servidor a las dos, o apunta el cliente a la dirección que sí responde.

Esa misma división explica algo que quizás notaste en los listados de puertos. Un mismo proceso aparece dos veces, una por IPv4 y otra por IPv6. Es un solo servidor escuchando en ambas pilas, no dos servidores.

Todo el rango 127.0.0.0/8 es loopback

No solo 127.0.0.1. Todo desde 127.0.0.1 hasta 127.255.255.254 vuelve a tu máquina. El 127.0.0.2 funciona exactamente igual.

A veces sirve. Si quieres dos servicios en el mismo puerto sin cambiarle el puerto a ninguno, puedes atarlos a direcciones de loopback distintas y no van a chocar, porque la regla de exclusividad aplica por dirección y puerto, no por puerto solo.

localhost contra 0.0.0.0

Se parecen en un archivo de configuración y se comportan muy distinto.

127.0.0.1 significa “acepta conexiones solo de esta máquina”. Nada de afuera lo alcanza, diga lo que diga tu firewall.

0.0.0.0 significa “acepta conexiones en todas las interfaces que tengo”. Eso incluye tu dirección de Wi-Fi, así que cualquiera en la misma red puede llegar.

La mayoría de los frameworks usa localhost por defecto por una razón. Cuando cambias a propósito a 0.0.0.0, normalmente para probar desde el teléfono, estás exponiendo ese servicio a toda tu red. En tu casa da lo mismo, en el Wi-Fi de un café conviene pensarlo dos veces.

Esta distinción importa también para contenedores. Un servidor dentro de Docker que se ata a 127.0.0.1 solo es alcanzable desde dentro de ese contenedor, y por eso el consejo estándar para apps en contenedores es atarse a 0.0.0.0 y dejar que el puerto publicado de Docker maneje el borde.

Dónde entra /etc/hosts

El nombre tiene que resolver de alguna forma, y en macOS viene de /etc/hosts:

grep localhost /etc/hosts

Vas a ver entradas que mapean localhost a 127.0.0.1 y a ::1. Ahí mismo es donde la gente agrega nombres propios como miapp.local, apuntándolos a loopback para que un proyecto tenga una dirección más amable que un número de puerto.

Si alguna vez localhost deja de resolver del todo, que es raro, ese archivo es el primer lugar donde mirar.

Cuando aun así no conecta

Si tienes bien la dirección y bien el puerto y sigue rechazando, las causas habituales son, en orden: el proceso se murió sin que te dieras cuenta, se ató a un puerto distinto al que crees, o se ató a 127.0.0.1 mientras tú te conectas por ::1.

Revisar qué está escuchando de verdad resuelve las tres:

lsof -i -P -n -sTCP:LISTEN

Eso imprime cada socket escuchando con su dirección y su puerto, así ves exactamente qué está ofreciendo tu máquina en vez de adivinar.

Bosun muestra lo mismo de forma continua en la barra de menú, y colapsa en una sola fila los duplicados IPv4 e IPv6 del mismo proceso. Prueba de 14 días, sin registro, macOS 14 o posterior.

Ve esto en vez de escribirlo

Bosun vive en tu barra de menú y muestra cada puerto abierto en tu Mac, en vivo, mapeado al proceso detrás. Un clic para matarlo, SIGTERM primero. Útil la primera vez que pasa esto. Realmente útil la quinta vez que pasa en una misma tarde.