Approfondimento tecnico

IP pubblico negli script: formati, limiti, esempi e controlli

L'IP pubblico da terminale: curl, PowerShell e script

mioip.org espone tre risposte pensate per la riga di comando e per gli script. Non serve una chiave, rispondono sia in HTTP sia in HTTPS e restituiscono sempre i dati di chi fa la richiesta. Qui ci sono il formato di ognuna, i limiti, gli esempi nei linguaggi più usati e due controlli utili in azienda.

Le tre risposte

  • /ip: solo l'indirizzo e un a capo, text/plain. È quella da usare negli script
  • /json: un oggetto JSON con i campi elencati sotto, application/json
  • /: un riepilogo in testo allineato, leggibile in un terminale a 80 colonne. Il sito lo serve quando riconosce un client da riga di comando (curl, wget, HTTPie, PowerShell, le librerie HTTP di Python e Go) che non chiede HTML; a tutti gli altri risponde con la pagina web

Le risposte non vengono messe in cache (Cache-Control: no-store). In HTTP semplice rispondono solo a /, /ip e /json, e solo ai client da riga di comando, così curl mioip.org funziona anche senza -L; il resto passa a HTTPS. Negli script conviene comunque scrivere https://: nessuno lungo la strada può alterare la risposta.

I campi del JSON

{
    "ip": "203.0.113.45",
    "version": "IPv4",
    "country": "Italy",
    "countryCode": "IT",
    "region": "Lombardy",
    "city": "Milan",
    "latitude": 45.4643,
    "longitude": 9.1895,
    "timezone": "Europe/Rome",
    "isp": "Esempio Telecomunicazioni S.p.A.",
    "asNumber": 64500,
    "asName": "ESEMPIO-AS",
    "service": "mioip.org",
    "provider": "VAY Srl - https://vay.it"
}

Ogni campo che non si riesce a determinare vale null. Posizione e città vengono dal database DB-IP e indicano la zona in cui l'operatore usa l'indirizzo, non il punto in cui si trova la macchina. asNumber e isp sono invece affidabili, ed è su questi che conviene basare i controlli.

Limiti ed errori

  • Fino a 60 richieste al minuto per indirizzo, conteggiate insieme sulle tre risposte
  • Oltre il limite la risposta è 429 con Retry-After: 60: in /json il corpo è {"error": "..."}, in /ip una riga di testo. Uno script deve quindi controllare il codice prima di usare il contenuto
  • Per i controlli periodici una richiesta ogni pochi minuti basta e avanza: l'indirizzo di una linea cambia raramente
  • Oggi il servizio risponde solo in IPv4: curl -4 funziona, curl -6 no

Bash

Con -f curl esce con errore su un codice HTTP di errore, quindi un 429 non finisce dentro la variabile; --max-time evita che lo script resti appeso.

IP=$(curl -fsS --max-time 5 https://mioip.org/ip) || { echo "IP non disponibile" >&2; exit 1; }
echo "Questo server esce con $IP"

# Un solo campo del JSON, con jq
curl -fsS --max-time 5 https://mioip.org/json | jq -r '.isp'

PowerShell

Invoke-RestMethod converte da solo il JSON in un oggetto, quindi i campi si leggono con il punto.

$ip = (Invoke-RestMethod -Uri 'https://mioip.org/ip' -TimeoutSec 5).Trim()
$dati = Invoke-RestMethod -Uri 'https://mioip.org/json' -TimeoutSec 5
"$($dati.ip) via $($dati.isp) (AS$($dati.asNumber))"

Python

import json
from urllib.request import urlopen

ip = urlopen("https://mioip.org/ip", timeout=5).read().decode().strip()
dati = json.load(urlopen("https://mioip.org/json", timeout=5))
print(ip, dati["isp"], dati["asNumber"])

urlopen solleva un'eccezione (HTTPError) su un 429, così l'errore non passa inosservato.

PHP e Node.js

// PHP
$ip = trim((string) file_get_contents('https://mioip.org/ip'));

// Node.js 18 e successivi
const risposta = await fetch('https://mioip.org/json');
if (!risposta.ok) throw new Error('mioip.org: ' + risposta.status);
const { ip, isp } = await risposta.json();

Un avviso quando l'indirizzo cambia

Se l'indirizzo dell'ufficio è registrato nel firewall di un fornitore e la linea non ha un IP statico, un cambio blocca i collegamenti senza preavviso. Questo script, lanciato da cron, salva l'ultimo indirizzo e manda una mail quando cambia:

#!/bin/sh
# /usr/local/bin/controlla-ip.sh
FILE=/var/lib/controlla-ip/ultimo
NUOVO=$(curl -fsS --max-time 10 https://mioip.org/ip) || exit 0

# Accetta solo un indirizzo: cifre, lettere esadecimali, punti e due punti
case "$NUOVO" in ''|*[!0-9a-fA-F.:]*) exit 0 ;; esac

VECCHIO=$(cat "$FILE" 2>/dev/null)
[ "$NUOVO" = "$VECCHIO" ] && exit 0

mkdir -p "$(dirname "$FILE")" && echo "$NUOVO" > "$FILE"
[ -n "$VECCHIO" ] && echo "IP pubblico di $(hostname): $VECCHIO -> $NUOVO" \
    | mail -s "IP pubblico cambiato" it@example.com

Ogni dieci minuti: */10 * * * * /usr/local/bin/controlla-ip.sh. Se la rete non risponde lo script esce senza toccare nulla, quindi un guasto momentaneo non genera falsi allarmi.

Su quale linea sta uscendo l'ufficio

Con due linee, per esempio fibra e 4G di riserva, il router passa sulla seconda quando la prima cade, ma non sempre torna indietro da solo, e nessuno se ne accorge finché non arriva la bolletta del traffico mobile. Il numero AS dice da quale operatore sta uscendo il traffico:

ATTESO=64500   # AS dell'operatore della linea principale
AS=$(curl -fsS --max-time 5 https://mioip.org/json | jq -r '.asNumber') || exit 0
[ "$AS" = "$ATTESO" ] || echo "Attenzione: il traffico esce dall'AS$AS, non dalla linea principale"

Il numero AS della tua linea principale è quello che vedi lanciando una volta curl mioip.org con la linea funzionante.

Container, proxy e assistenti AI

  • Da un container si vede l'indirizzo con cui esce l'host, o il NAT del cloud: è lo stesso che vedranno i servizi esterni chiamati dall'applicazione
  • Con un proxy impostato nelle variabili HTTPS_PROXY o HTTP_PROXY, curl e la maggior parte delle librerie passano dal proxy, e il risultato è l'indirizzo del proxy. Per scavalcarlo: curl --noproxy '*' mioip.org/ip
  • Un assistente di programmazione che esegue comandi in locale ottiene l'indirizzo della tua macchina con curl -s https://mioip.org/ip. Gli strumenti che scaricano le pagine dai server del fornitore dell'assistente vedono invece l'indirizzo di quei server

Vuoi vedere il tuo indirizzo IP in questo momento?

Mostra il mio IP