Usted es 172.26.▒▒▒.▒▒▒
Entra en la sede electrónica del Ayuntamiento de Vitoria-Gasteiz y la página apunta, en su código, con qué navegador llegas, y acierta. También apunta desde qué dirección llegas, el número con el que cada aparato se identifica en internet, y ahí escribe siempre la misma: una dirección de red privada, de las que no viajan por internet. Nos la ha escrito cada vez que hemos mirado, en cuatro fechas.
- Guardado
- 08 SEP 2026
- Comprobado en vivo
- 14 SEP 2026
- Citas
- 7 en 1 fichero guardado
- Lectura
- unos 4 min
Cada página de un portal Liferay lleva, entre sus primeras líneas de JavaScript, el lenguaje de los programas que corren en el navegador, una ficha que el servidor, el ordenador que sirve la página, escribe sobre la visita: Liferay.ThemeDisplay, 48 funciones en la portada de la sede, de la línea 356 a la 520. Dicen la dirección pública del portal, el número de la página, el idioma, el huso horario (Europe/Paris, que es el de aquí con otro nombre), si el visitante se ha identificado (no) y con qué número se le conoce mientras tanto. Los programas de la propia página consultan esa ficha: el idioma lo leen de ahí.

- Copia
- archivo
- Guardado
- 8 sep 2026
- Peso
- 235,6 kB
- sha256
- 42db5c76290a…
| 345 | Liferay.PortletKeys = { |
| 346 | DOCUMENT_LIBRARY: 'com_ |
| 347 | DYNAMIC_DATA_MAPPING: 'com_ |
| 348 | ITEM_SELECTOR: 'com_ |
| 349 | }; |
| 350 | |
| 351 | Liferay.PropsValues = { |
| 352 | JAVASCRIPT_ |
| 353 | UPLOAD_ |
| 354 | }; |
| 355 | |
| 356 | Liferay.ThemeDisplay = { |
| 357 | |
| 358 | |
| 359 | |
| 360 | |
| 361 | getLayoutId: function () { |
| 362 | return '53'; |
| 363 | }, |
| 364 | |
| 365 | |
| 366 | |
| 367 | getLayout |
| 488 | return '20099'; |
| 489 | }, |
| 490 | getUserName: function () { |
| 491 | return ''; |
| 492 | }, |
| 493 | isAddSessionIdToURL: function () { |
| 494 | return false; |
| 495 | }, |
| 496 | isImpersonated: function () { |
| 497 | return false; |
| 498 | }, |
| 499 | isSignedIn: function () { |
| 500 | return false; |
| 501 | }, |
| 502 | |
| 503 | isStagedPortlet: function () { |
| 504 | |
| 505 | |
| 506 | return false; |
| 507 | |
| 508 | |
| 509 | }, |
Dos de esas 48 funciones se llaman getRemoteAddr y getRemoteHost: la dirección y el nombre del extremo remoto, es decir, del visitante, tal como los ve el servidor. En la portada guardada el 8 de septiembre de 2026 las dos devuelven lo mismo, 172.26.▒▒▒.▒▒▒ (los dos últimos números los tapamos nosotros). Nuestro capturador, el programa con el que guardamos las páginas, llegó desde una dirección pública, que no es esa.
- Copia
- archivo
- Guardado
- 8 sep 2026
- Peso
- 235,6 kB
- sha256
- 42db5c76290a…
- Tapado
- 4 tramos ▒
| 437 | return '/portal/es/c'; |
| 438 | }, |
| 439 | getPathThemeImages: function () { |
| 440 | return 'https:// |
| 441 | }, |
| 442 | getPathThemeRoot: function () { |
| 443 | return '/portal/o/dialect-theme'; |
| 444 | }, |
| 445 | getPlid: function () { |
| 446 | return '79'; |
| 447 | }, |
| 448 | getPortalURL3: function () { |
| 449 | return 'https:// |
| 450 | }, |
| 451 | getRealUserId: function () { |
| 452 | return '20099'; |
| 453 | }, |
| 454 | getRemoteAddr4: function () { |
| 455 | return '172.26.▒▒▒.▒▒▒'; |
| 456 | }, |
| 457 | getRemoteHost5: function () { |
| 458 | return '172.26.▒▒▒.▒▒▒'; |
| 459 | }, |
| 460 | getScopeGroupId: function () { |
| 461 | return '236088'; |
| 462 | }, |
| 463 | getScope |
| 464 | return '236088'; |
| 465 | }, |
| 466 | getSessionId: function () { |
| 467 | return ''; |
| 468 | }, |
No podía serlo. En febrero de 1996 el RFC 1918, una de las normas técnicas de internet, reservó tres bloques de direcciones para redes privadas: 10.0.0.0/8, 172.16.0.0/12 y 192.168.0.0/16. Son las direcciones de la oficina, del router de casa, del pasillo entre servidores: ningún router de internet las encamina, y por eso las puede usar todo el mundo a la vez sin estorbarse. 172.26 cae dentro del segundo bloque. Nadie que llegue desde fuera puede tener esa dirección, así que nadie que llegue desde fuera puede ser el visitante al que el portal se la atribuye.
Tampoco es cosa de un día. El archivo guarda 1.004 ficheros del dominio con esa función (929 páginas y 75 bloques de JavaScript), 53 capturados el 31 de agosto de 2026 y 951 el 8 de septiembre, y el valor es el mismo en los 1.004. El 14 de septiembre volvimos a pedir la portada: 129 de sus 6.066 líneas eran distintas, entre ellas las marcas de versión de sus programas y la ficha del navegador, pero las líneas 454 a 458 seguían iguales, con la misma dirección. El 23 de septiembre, otra vez la misma. Cuatro fechas, un visitante.
Tampoco es un caso raro. En el archivo hay 62 portadas de dominios de la Administración que declaran esa misma función. En 17 devuelve la dirección desde la que capturamos: ahí funciona. En 34 devuelve una dirección privada, como aquí. En 4 devuelve 127.0.0.1, la dirección de la propia máquina, con lo que el servidor sostiene que el visitante es él. En 5, otra dirección pública que no es la nuestra. En 2, nada. Damos la cuenta y no los nombres: el museo ordena piezas, no organismos, y la pieza es la misma en 34 sitios.
Lo que se puede explicar sin adivinar: getRemoteAddr devuelve la dirección del otro extremo de la conexión que llegó al servidor. Aquí, delante del portal, hay un intermediario, una máquina que recibe las visitas y se las pasa: las respuestas del 8, del 14 y del 23 de septiembre vienen firmadas por nginx y traen la marca de una caché intermedia, un almacén de copias de las páginas. Así, el otro extremo de la conexión es el intermediario, no el visitante. El servidor cuenta lo único que ve.
Para que sepa la dirección real, el intermediario tiene que pasársela en una cabecera, una línea de datos que acompaña a cada petición (X-Forwarded-For es la habitual), y al servidor hay que decirle que se la crea. Una de las dos cosas no pasa; cuál, la página no lo dice. En dos portales más del archivo el valor no es uno sino dos direcciones vecinas, repartidas entre sus páginas. Dos máquinas intermedias lo explicarían, pero eso ya no se ve desde fuera.
El portal sí escucha al navegador. Antes de la ficha del visitante, en la misma página, va Liferay.Browser, otra ficha, esta sobre el programa con el que se llega, y está bien hecha: la copia del 8 de septiembre dice getMajorVersion 125.0 e isLinux true, que es lo que declara nuestro capturador, un Chrome 125 sobre Linux. La copia del 14, pedida declarando un Chrome 128 de Windows, dice 128.0 e isWindows true. El portal lee la cabecera en la que el navegador cuenta quién es y la transcribe con precisión. La dirección de la que viene, en cambio, no la oye.
- Copia
- archivo
- Guardado
- 8 sep 2026
- Peso
- 235,6 kB
- sha256
- 42db5c76290a…
| 195 | <script type="text/javascript" data-senna-track=" |
| 196 | // <![CDATA[ |
| 197 | var Liferay = Liferay || {}; |
| 198 | |
| 199 | Liferay.Browser = { |
| 200 | acceptsGzip: function () { |
| 201 | return false; |
| 202 | }, |
| 203 | |
| 204 | |
| 205 | |
| 206 | getMajorVersion: function () { |
| 207 | return 125.0; |
| 208 | }, |
| 209 | |
| 210 | getRevision: function () { |
| 211 | return '537.36'; |
| 212 | }, |
| 213 | getVersion: function () { |
| 214 | return '125.0'; |
| 215 | }, |
| 229 | return false; |
| 230 | }, |
| 231 | isGecko: function () { |
| 232 | return true; |
| 233 | }, |
| 234 | isIe: function () { |
| 235 | return false; |
| 236 | }, |
| 237 | isIphone: function () { |
| 238 | return false; |
| 239 | }, |
| 240 | isLinux: function () { |
| 241 | return true; |
| 242 | }, |
| 243 | isMac: function () { |
| 244 | return false; |
| 245 | }, |
| 246 | isMobile: function () { |
| 247 | return false; |
| 248 | }, |
| 249 | isMozilla: function () { |
| 250 | return false; |
| 251 | }, |
Consecuencias, las que se ven. En los 2.754 ficheros capturados del dominio nadie llama a getRemoteAddr(): los programas de la sede no usan ese valor, así que ninguna función de la página se equivoca por él. Lo que el portal hace con esa dirección puertas adentro, registros o auditoría, no se ve desde fuera. Se ven dos cosas. Cada página publica, a quien lea su código, una dirección de una red interna. Y a nosotros, cada vez que hemos entrado, nos ha escrito en nuestra propia página que éramos otro.
Sabe con qué navegador llegamos y que no nos identificamos. Y nos presentó igual las cuatro veces: usted es 172.26.▒▒▒.▒▒▒.
- La portada de sedeelectronica.vitoria-gasteiz.org declara Liferay.ThemeDisplay.
getRemoteAddrygetRemoteHostdevolviendo la misma dirección privada del bloque 172.16.0.0/12. - Ese valor es idéntico en los 1.004 ficheros del dominio que lo llevan, capturados el 31 de agosto y el 8 de septiembre de 2026, y en la portada pedida de nuevo el 14 y el 23 de septiembre, siempre por nosotros.
- La ficha del navegador de la misma página sí refleja el User-Agent, la línea en la que el navegador dice quién es, con el que se pide.
- En el archivo hay 62 portadas de la Administración con esa función y en 34 devuelve una dirección privada.
- Ningún script capturado del dominio llama a
getRemoteAddr().
- Que otros visitantes reciban esa misma dirección: solo hemos visto nuestras visitas. Una dirección privada, en todo caso, no puede ser la de nadie que llegue desde internet.
- Por qué el intermediario no pasa la dirección real ni si el portal está configurado para leerla: la página no lo dice y no lo hemos probado.
- Qué hace el servidor con ese valor en sus registros: no se ve desde fuera.
- Que esa dirección sirva para llegar a nada desde internet: es privada y no se encamina.
- Qué máquina concreta es: solo que está dentro.
- Cuáles son los otros 61 portales: la cuenta se da sin nombres a propósito.
De dónde sale cada cita
Cada trozo de código de esta ficha está en un fichero guardado tal como lo entregó el servidor, con su huella (sha256) y su hora. Las citas entre «» se comprueban por programa contra ese fichero antes de publicar.
- https://sedeelectronica.vitoria-gasteiz.org/portal/es/8 de septiembre de 2026, 03:46archivosha256 42db5c76290a187638bf3d8e552bc15aa7735ac149a7a1bd712faeff66ca55af
- https://sedeelectronica.vitoria-gasteiz.org/portal/es/14 de septiembre de 2026, 23:23en vivo · distinto · las 7 citas siguensha256 d6663db2237f03d8b401e5c66b94a7baec76a3786cbcb85dacd1a0c44271df95