Files
fn_registry/bash/functions/cybersecurity/geolocate_ip.sh
T
egutierrez 7c3f01c9eb feat: add bash cybersecurity audit and hardening functions
12 funciones Bash del dominio cybersecurity: auditoria de red y servicios
(analyze_dns, audit_http_headers, inspect_ssl_cert, list_active_connections,
enumerate_subdomains, geolocate_ip), auditoria de sistema (audit_ssh_config,
check_firewall, detect_suspicious_users), y utilidades crypto (encrypt_file,
generate_password, verify_file_hash). Dominio nuevo en bash/functions/.
2026-04-12 13:54:25 +02:00

151 lines
5.3 KiB
Bash

#!/usr/bin/env bash
# geolocate_ip
# ------------
# Geolocaliza una IP o dominio usando la API pública de ip-api.com.
# Muestra país, ciudad, ISP, ASN y detecta VPN/Proxy/Hosting.
#
# USO (directo):
# geolocate_ip <ip_o_dominio>
#
# Depende de: curl, dig (para resolver dominios)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../shell/bash_colors.sh"
source "$SCRIPT_DIR/../shell/bash_log.sh"
bash_colors
bash_log_init
# ─── Constantes ───────────────────────────────────────────────────────────────
_GEOIP_API="http://ip-api.com/json"
_GEOIP_FIELDS="status,message,country,countryCode,regionName,city,zip,lat,lon,isp,org,as,proxy,hosting,query"
# ─── Funciones puras ──────────────────────────────────────────────────────────
_geo_is_ip() {
[[ "$1" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
}
_geo_build_api_url() {
local target="$1"
echo "${_GEOIP_API}/${target}?fields=${_GEOIP_FIELDS}"
}
_geo_extract_field() {
local json="$1"
local key="$2"
echo "$json" | grep -o "\"${key}\":[^,}]*" | cut -d: -f2- | tr -d '"' | xargs
}
# ─── Funciones de efecto ──────────────────────────────────────────────────────
_geo_resolve_domain() {
local domain="$1"
dig +short A "$domain" 2>/dev/null | head -1 || true
}
_geo_fetch() {
local target="$1"
local url
url="$(_geo_build_api_url "$target")"
curl -s --max-time 10 "$url" 2>/dev/null
}
_geo_display_result() {
local json="$1"
local status
status="$(_geo_extract_field "$json" "status")"
if [[ "$status" != "success" ]]; then
local msg
msg="$(_geo_extract_field "$json" "message")"
error "La API devolvió error: ${msg:-respuesta inesperada}" >&2
return 1
fi
local ip_queried country country_code region city zip lat lon isp org asn proxy hosting
ip_queried="$(_geo_extract_field "$json" "query")"
country="$(_geo_extract_field "$json" "country")"
country_code="$(_geo_extract_field "$json" "countryCode")"
region="$(_geo_extract_field "$json" "regionName")"
city="$(_geo_extract_field "$json" "city")"
zip="$(_geo_extract_field "$json" "zip")"
lat="$(_geo_extract_field "$json" "lat")"
lon="$(_geo_extract_field "$json" "lon")"
isp="$(_geo_extract_field "$json" "isp")"
org="$(_geo_extract_field "$json" "org")"
asn="$(_geo_extract_field "$json" "as")"
proxy="$(_geo_extract_field "$json" "proxy")"
hosting="$(_geo_extract_field "$json" "hosting")"
echo ""
echo -e "${PURPLE}════════════════════════════════════════════════════════════${NC}"
echo -e " ${CYAN}IP consultada:${NC} ${ip_queried}"
echo -e " ${CYAN}País:${NC} ${country} (${country_code})"
echo -e " ${CYAN}Región:${NC} ${region}"
echo -e " ${CYAN}Ciudad:${NC} ${city} ${zip}"
echo -e " ${CYAN}Coordenadas:${NC} ${lat}, ${lon}"
echo -e " ${CYAN}ISP:${NC} ${isp}"
echo -e " ${CYAN}Organización:${NC} ${org}"
echo -e " ${CYAN}ASN:${NC} ${asn}"
echo ""
if [[ "$proxy" == "true" ]]; then
echo -e " ${RED}[!] VPN / Proxy detectado${NC}"
fi
if [[ "$hosting" == "true" ]]; then
echo -e " ${YELLOW}[i] Hosting / datacenter detectado${NC}"
fi
if [[ "$proxy" != "true" && "$hosting" != "true" ]]; then
echo -e " ${GREEN}[ok] Sin indicios de VPN, Proxy o Tor${NC}"
fi
echo -e "${PURPLE}════════════════════════════════════════════════════════════${NC}"
}
# ─── Punto de entrada ─────────────────────────────────────────────────────────
geolocate_ip() {
local target="$1"
if [[ -z "$target" ]]; then
error "geolocate_ip: se requiere una IP o dominio como argumento" >&2
return 1
fi
if ! command -v curl &>/dev/null; then
error "geolocate_ip: 'curl' no está instalado (sudo apt install curl)" >&2
return 1
fi
local query_target="$target"
if ! _geo_is_ip "$target"; then
info "Resolviendo dominio a IP..."
local resolved
resolved="$(_geo_resolve_domain "$target")"
if [[ -z "$resolved" ]]; then
error "geolocate_ip: no se pudo resolver '$target'" >&2
return 1
fi
info "Resuelto: ${target} -> ${resolved}"
query_target="$resolved"
fi
info "Consultando geolocalización de ${query_target}..."
local json
json="$(_geo_fetch "$query_target")"
if [[ -z "$json" ]]; then
error "geolocate_ip: no se obtuvo respuesta de la API" >&2
return 1
fi
_geo_display_result "$json"
}
# Ejecutar si se llama directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
geolocate_ip "$@"
fi