#!/usr/bin/env bash # ============================================================================= # demo-03 · La prueba del ciudadano # ============================================================================= # A qué punto del guion sirve: punto 15 # «Qué puedes hacer tú: prueba, mide y denuncia» # # Qué hace: cuando un sitio legítimo te falla, guarda la prueba CON FECHA en un # fichero fechado. Dominio, operador, hora exacta y el error tal cual. # · curl → ¿responde? ¿con qué código? ¿cuánto tarda? y el error completo. # · dig → ¿resuelve? ¿a qué direcciones? ¿con qué servidor de nombres? # · whois → ¿de quién es esa dirección? (si es de un rango compartido, no se # ha caído «tu» servidor: se ha caído un vector que usan cientos de # miles de sitios). Si no hay `whois` instalado, se usa RDAP con # `curl`, que da la misma información sin instalar nada. # # Uso: # ./demo-03-prueba-del-ciudadano.sh [operador] # ./demo-03-prueba-del-ciudadano.sh tudominio.example "Mi operador" # # El informe se guarda en: # $PRUEBAS_DIR/-prueba-.txt # (por defecto $PRUEBAS_DIR=/tmp/opencode/pruebas-ciudadano) # # Códigos de salida (para que sirva también en un cron o en un script): # 0 = el sitio responde # 1 = el sitio NO responde (conexión, TLS o tiempo agotado) # 2 = el nombre no resuelve # 3 = no se ha podido escribir el informe # # Estado: VERIFICADO en local (cuatro casos: responde, no resuelve, no responde # y bloqueo detectado). Salidas reales en `verificacion/demo-03-*.txt`. # # Seguridad de la demo: solo lectura. Nada de `ssh`, nada de tocar servidores # ajenos, nada que modifique el sistema. El único tráfico que sale es el de tus # propias consultas DNS/HTTP, que es justo lo que se está probando. # ============================================================================= set -u DOMINIO="${1:-example.com}" OPERADOR="${2:-${OPERADOR:-(anota aquí tu operador: Movistar, Vodafone, Digi…)}}" DESTINO="${PRUEBAS_DIR:-/tmp/opencode/pruebas-ciudadano}" if [ "$DOMINIO" = "-h" ] || [ "$DOMINIO" = "--help" ]; then sed -n '2,32p' "$0" | sed 's/^# \{0,1\}//' exit 0 fi mkdir -p "$DESTINO" || { printf 'no se puede crear %s\n' "$DESTINO" >&2; exit 3; } FECHA="$(date +%Y-%m-%d_%H%M%S)" INFORME="$DESTINO/${FECHA}-prueba-${DOMINIO}.txt" : > "$INFORME" || exit 3 ULTIMO_RC=0 salida() { printf '%s\n' "$*" | tee -a "$INFORME"; } orden() { printf '\n$ %s\n' "$*" | tee -a "$INFORME"; } run() { # run → lanza, guarda la salida y el código, nunca aborta local cabecera salida_cmd rc=0 cabecera="$(printf '$'; for a in "$@"; do case "$a" in *" "*) printf " '%s'" "$a" ;; *) printf ' %s' "$a" ;; esac done)" printf '\n%s\n' "$cabecera" | tee -a "$INFORME" salida_cmd="$("$@" 2>&1)" || rc=$? printf '%s\n' "$salida_cmd" | tee -a "$INFORME" if [ "$rc" -ne 0 ]; then printf '[exit %s]\n' "$rc" | tee -a "$INFORME"; fi ULTIMO_RC=$rc return 0 } # ------------------------------------------------------------------ cabecera salida "================================================================" salida " PRUEBA DE ACCESO — prueba del ciudadano" salida "================================================================" salida " Dominio : $DOMINIO" salida " Operador : $OPERADOR" salida " Fecha : $(date -Is)" salida " Equipo : $(hostname) · $(uname -sr)" salida "================================================================" salida "" salida "Nota: esta prueba NO dice quién bloquea ni por qué. Solo deja constancia" salida "fechada de lo que ha pasado desde tu conexión. Una prueba, o varias, es" salida "lo que se adjunta a una reclamación." # --------------------------------------------------------------- 1 · curl salida "" salida "--- 1 · ¿El sitio responde? -------------------------------------" if command -v curl >/dev/null 2>&1; then run curl -sS -o /dev/null \ --connect-timeout 10 --max-time 20 \ -w 'HTTP %{http_code} · connect %{time_connect}s · TLS %{time_appconnect}s · total %{time_total}s · IP destino %{remote_ip}\n' \ "https://$DOMINIO/" RC_CURL=$ULTIMO_RC orden "curl -v https://$DOMINIO/ # el error tal cual, para adjuntar" curl -v -o /dev/null --connect-timeout 10 --max-time 20 "https://$DOMINIO/" 2>&1 \ | tee -a "$INFORME" else salida "curl no está instalado: sin esta parte no hay prueba de acceso." RC_CURL=127 fi # --------------------------------------------------------------- 2 · dig salida "" salida "--- 2 · ¿Resuelve el nombre? ------------------------------------" IP_A="" if command -v dig >/dev/null 2>&1; then run dig "$DOMINIO" A IP_A="$(dig +short A "$DOMINIO" | grep -E '^[0-9.]+$' | head -1)" run dig +short "$DOMINIO" AAAA run dig +short "$DOMINIO" NS if [ -n "$IP_A" ]; then salida "" salida "Primera dirección IPv4 anotada: $IP_A" fi else salida "dig no está instalado (paquete bind-utils / dnsutils)." fi # --------------------------------------------------------------- 3 · whois salida "" salida "--- 3 · ¿De quién es esa dirección? -----------------------------" salida "(si es de un rango compartido, no está caído «tu» servidor:" salida " está caído un vector que usan cientos de miles de sitios)" if [ -z "$IP_A" ]; then salida "Sin dirección IPv4 no hay nada que consultar." elif command -v whois >/dev/null 2>&1; then run whois "$IP_A" else salida "No hay 'whois' instalado en este equipo. Alternativa sin instalar nada:" salida "RDAP, el registro de direcciones que habla HTTP." if command -v curl >/dev/null 2>&1; then orden "curl -sSL https://rdap.org/ip/$IP_A" RDAP="$(curl -sSL --connect-timeout 10 --max-time 20 "https://rdap.org/ip/$IP_A" 2>&1)" \ || salida "(la consulta RDAP ha fallado)" if command -v jq >/dev/null 2>&1 && printf '%s' "$RDAP" | jq -e . >/dev/null 2>&1; then printf '%s' "$RDAP" | jq -r ' " titular : " + (.name // .handle // (.entities[0].handle // "?")), " registro : " + (.handle // "?"), " país : " + (.country // "?"), " rango : " + ( if .["cidr0_cidrs"] then (.["cidr0_cidrs"][0] | "\(.v4prefix // .v6prefix)/\(.length)") elif .startAddress then "\(.startAddress) - \(.endAddress)" else "?" end ) ' | tee -a "$INFORME" else printf '%s\n' "$RDAP" | head -40 | tee -a "$INFORME" fi fi fi # ------------------------------------------------------------- veredicto salida "" salida "--- Resultado ---------------------------------------------------" if [ -n "$IP_A" ] && [ "${RC_CURL:-1}" -eq 0 ]; then salida " ALCANZABLE: el sitio ha respondido desde esta conexión." salida " Si aún así a ti te falla a ratos, repite esta prueba cada vez que" salida " falle: lo que vale es la serie con fecha y hora, no una sola foto." VEREDICTO=0 elif [ -z "$IP_A" ]; then salida " NO RESUELVE EL NOMBRE: el dominio no se ha podido traducir a dirección." salida " Prueba desde otra red (datos móviles, otra casa) para saber si es" salida " cosa de tu operador o del dominio." VEREDICTO=2 else salida " NO ALCANZABLE: el nombre resuelve ($IP_A) pero la conexión no llega." salida " Guarda este fichero: es exactamente la prueba que hay que adjuntar." VEREDICTO=1 fi # ------------------------------------------------------- qué hacer ahora cat <<'TEXTO' | tee -a "$INFORME" --- Y ahora, los otros dos pasos --------------------------------- 2 · MEDIR. Instala OONI Probe (libre, sin registro) y lanza la prueba desde tu propia red: las mediciones se publican solas en OONI Explorer. Una anomalía sola no prueba nada, pero suma. App e instrucciones : https://ooni.org/install/ Mediciones públicas : https://explorer.ooni.org/ 3 · DENUNCIAR (esto deja constancia; no hay caso documentado de una reclamación individual que levante uno de estos bloqueos): · Tu operador, primero, y pide respuesta por escrito. · Oficina de Atención al Usuario de Telecomunicaciones (SETELECO): https://usuariosteleco.digital.gob.es/reclamaciones/telefonia-e-internet/tramitacion-electronica · AEPD, solo si hubo inspección de comunicaciones o tratamiento indebido de datos: https://www.aepd.es/ · CNMC, como coordinador de servicios digitales (DSA): https://www.cnmc.es/sectores-que-regulamos/servicios-digitales-dsa/reclamaciones Guarda también: capturas con la fecha visible, tu operador y, si puedes, la misma prueba desde otra conexión. TEXTO salida "" salida "Informe guardado en: $INFORME" # Sin códigos ANSI a propósito: la salida se guarda tal cual y se puede pegar en # un informe o un tique de incidencia sin que aparezcan escapes de color. printf '\nInforme guardado en: %s\n' "$INFORME" printf 'Código de salida: %s (0 responde · 1 no responde · 2 no resuelve)\n\n' "$VEREDICTO" exit "$VEREDICTO"