#!/usr/bin/env bash set -euo pipefail # Print the current public IPv4 address, with fast fallbacks. endpoints=( "https://ipv4.icanhazip.com" "https://ipinfo.io/ip" "https://ifconfig.co/ip" "https://api.ipify.org" "https://checkip.amazonaws.com" ) curl_opts=( -4 -fsS --max-time 2 --retry 0 ) validate_ipv4() { local ip="$1" [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1 IFS=. read -r a b c d <<< "$ip" || return 1 for o in "$a" "$b" "$c" "$d"; do [[ "$o" -ge 0 && "$o" -le 255 ]] || return 1 done printf '%s\n' "$ip" } for url in "${endpoints[@]}"; do if out=$(curl "${curl_opts[@]}" "$url" 2>/dev/null | tr -d ' \t\n\r'); then ip=$(printf '%s' "$out" | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -n1 || true) if [[ -n "${ip:-}" ]] && validate_ipv4 "$ip" >/dev/null; then printf '%s\n' "$ip" exit 0 fi fi done # Fallback using DNS if curl endpoints fail if command -v dig >/dev/null 2>&1; then if ip=$(dig +short -4 myip.opendns.com @resolver1.opendns.com | head -n1); then if [[ -n "$ip" ]] && validate_ipv4 "$ip" >/dev/null; then printf '%s\n' "$ip" exit 0 fi fi fi echo "unable to determine public IPv4" >&2 exit 1