NordVPN in WireGuard: sul GL.iNet basta il token
Sul GL.iNet il token basta e il router fa il resto. Altrove la chiave privata va estratta dalle API dell'account: come si fa, e da quale macchina.
NordVPN non fornisce file .conf pronti. NordLynx è la loro implementazione di WireGuard, ma la chiave privata non compare da nessuna parte nella console: va estratta dalle API dell’account.
Salvo un caso, che conviene togliere di mezzo subito.
Sul GL.iNet basta il token
Il firmware 4.x dei router GL.iNet ha un client NordVPN integrato, e fa da solo tutto quello che nel resto di questa guida si fa a mano.
- VPN → WireGuard Client, poi NordVPN → Modifica informazioni account
- Incolla l’access token — come ottenerlo è il primo passo della procedura lunga, più sotto — e premi Avanti
- Il router scarica l’elenco dei server, oltre duemila, e li presenta per paese e città
- Scegli e premi Applica
Nessuna chiave da estrarre, nessun file da comporre. Sotto il cofano il router interroga le stesse API descritte più avanti: si prende la chiave privata dell’account e le chiavi pubbliche dei server, e se le tiene senza mostrarle. L’elenco che vedi nella finestra di selezione è la risposta di recommendations.
Verificato su firmware 4.8.1.
Quando invece serve la via lunga
Tutto il resto della guida serve per i dispositivi che non hanno un client NordVPN integrato, e dove quindi le chiavi devi procurartele tu:
- pfSense e OPNsense
- OpenWrt originale, senza il firmware GL.iNet
- MikroTik con RouterOS 7
- i client WireGuard su Windows, Linux, macOS, Android e iOS
- router di altre marche con WireGuard generico
Lì nessuno chiama l’API al posto tuo: serve la chiave privata dell’account, la chiave pubblica del server scelto, e un .conf scritto a mano.
Cosa serve
- Un abbonamento NordVPN attivo e l’accesso a
my.nordaccount.com - Una macchina con PowerShell, oppure
curlsu Linux, macOS o WSL
1. Generare l’access token
- Accedi a
my.nordaccount.com - Nella barra laterale, NordVPN
- Scorri fino a Advanced settings → Set up NordVPN manually
- Nord chiede di verificare l’email: inserisci il codice a sei cifre
- Nella pagina di configurazione manuale ci sono due riquadri distinti: Service credentials, cioè utente e password per OpenVPN, che qui non servono, e Access token, che è quello che ci serve
- Premi Generate new token e, se chiede la durata, scegli senza scadenza
2. Estrarre la chiave privata
Su Windows, in PowerShell:
# Solo su PowerShell 5.1: forza TLS 1.2 per la sessione corrente
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$token = "INCOLLA_QUI_IL_TOKEN"
# Controllo preventivo: deve stampare 64 e True
$token.Length
$token -match '^[0-9a-f]{64}$'
$b64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("token:$token"))
$cred = Invoke-RestMethod -Uri "https://api.nordvpn.com/v1/users/services/credentials" `
-Headers @{ Authorization = "Basic $b64" }
$cred.nordlynx_private_key
Su Linux, macOS o WSL:
curl -s -u token:INCOLLA_QUI_IL_TOKEN \
https://api.nordvpn.com/v1/users/services/credentials | jq -r .nordlynx_private_key
Il risultato è una stringa base64 di 44 caratteri che finisce con =. Tre cose da sapere subito:
- È legata all’account, non al server: la stessa chiave vale per qualunque endpoint Nord
- Non scade da sola, ma si invalida se rigeneri le credenziali di servizio
- Vale come una password: chi la possiede usa il tuo abbonamento
Salvala in un gestore di password prima di andare avanti.
3. Scegliere il paese e il server
Queste chiamate non richiedono autenticazione: sono dati pubblici, e si possono lanciare da qualsiasi macchina.
$paesi = Invoke-RestMethod "https://api.nordvpn.com/v1/servers/countries"
# elenco completo, 149 paesi
$paesi | Sort-Object name | Select-Object id, name
# oppure ricerca diretta: i nomi sono in inglese
$paesi | Where-Object { $_.name -eq 'Italy' } | Select-Object id, name
| Paese | id |
|---|---|
| Belgium | 21 |
| Germany | 81 |
| Italy | 106 |
Questi tre sono verificati. Per gli altri ricava l’id dall’elenco vivo: non seguono un ordine prevedibile e possono cambiare.
Poi i server consigliati, sostituendo 106 con l’id che ti serve:
$s = Invoke-RestMethod "https://api.nordvpn.com/v1/servers/recommendations?filters%5Bservers_technologies%5D%5Bidentifier%5D=wireguard_udp&filters%5Bcountry_id%5D=106&limit=5"
$s | Format-List name, hostname, station, load
hostname : it536.nordvpn.com
station : 187.13.214.133
load : 7
name : Italy #536
Scegli quello con load più basso, poi prendi la sua chiave pubblica:
($s[0].technologies | Where-Object identifier -eq 'wireguard_udp').metadata
Per un server diverso dal primo usa $s[1], $s[2] e così via: ogni server ha la sua coppia di chiavi, quindi la pubblica va presa dall’oggetto giusto.
station è l’indirizzo pubblico del server. Conviene usare quello nell’endpoint invece del nome host, così il router non dipende dalla risoluzione DNS al momento dell’avvio — cioè proprio quando il tunnel non è ancora su.
4. Comporre il file .conf
[Interface]
PrivateKey = LA_TUA_CHIAVE_PRIVATA
Address = 10.5.0.2/32
DNS = 103.86.96.100, 103.86.99.100
MTU = 1420
[Peer]
PublicKey = PUBLIC_KEY_DEL_SERVER
AllowedIPs = 0.0.0.0/0
Endpoint = IP_DEL_SERVER:51820
PersistentKeepalive = 25
| Campo | Valore | Da dove viene |
|---|---|---|
PrivateKey | la chiave dell’account | passo 2 |
Address | 10.5.0.2/32 | fisso: NordLynx assegna sempre questo |
DNS | i due resolver Nord | fissi |
MTU | 1420 | standard NordLynx |
PublicKey | la chiave del server | passo 3 |
Endpoint | station più :51820 | passo 3 |
AllowedIPs | 0.0.0.0/0 | tutto il traffico nel tunnel |
PersistentKeepalive | 25 | tiene aperto il NAT |
5. Importare il file
Su pfSense, OPNsense o un client WireGuard il .conf si importa dove previsto da quel sistema: i campi sono gli stessi, cambia solo il modulo.
Su un GL.iNet questa è la strada da prendere solo se vuoi un profilo che il client integrato non ti dà — un server preciso, o parametri modificati:
- Apri la console del router, di norma
http://192.168.8.1 - VPN → WireGuard Client → Add New Profile
- Scegli Manual Config e incolla il contenuto del
.conf - Dai un nome riconoscibile al profilo, per esempio
Nord-IT-536 - Salva e premi Connect
Nelle impostazioni della sezione VPN dei GL.iNet ci sono tre interruttori che su un firewall qualunque andrebbero costruiti a mano:
- Kill Switch — blocca il traffico se il tunnel cade, invece di lasciarlo uscire in chiaro dalla WAN. Da attivare
- Block Non-VPN Traffic — la variante più rigida dello stesso concetto
- VPN Policy, in certe versioni Proxy Mode — fa passare nel tunnel solo alcuni dispositivi, filtrando per indirizzo MAC, oppure solo certi domini
Il NAT lo gestisce il firmware: non c’è niente da configurare.
6. Verificare che funzioni
Entro pochi secondi dal Connect il profilo passa a connesso e i contatori di traffico salgono. Poi, da un dispositivo dietro il router:
- Apri
https://ipinfo.io/json: devi vedere l’indirizzo del server Nord e il paese che hai scelto - Controlla le perdite DNS su un servizio come
dnsleaktest.com: i resolver riportati devono essere quelli Nord, non quelli del tuo provider
Se il tunnel si connette ma non naviga, il primo sospetto è l’MTU: scendi a 1400, poi a 1380.
7. Più paesi, più profili
Il router tiene più profili e permette di passare dall’uno all’altro dalla console. Per aggiungerne uno:
- Rilancia il passo 3 con l’id del nuovo paese
- Duplica il
.confcambiando solo due righe:EndpointePublicKey - Importalo come profilo nuovo, con un nome diverso
PrivateKey, Address, DNS e MTU restano identici in tutti i profili, perché la chiave privata è dell’account e non del server.
8. Dopo, e nel tempo
Ripulisci la cronologia sulla macchina usata per l’estrazione: il token vi resta in chiaro.
Remove-Item "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt"
Su Linux e macOS, ~/.bash_history o l’equivalente della tua shell.
Revoca il token dal Nord Account: non serve più, e la chiave privata continua a funzionare senza.
Quando un server viene dismesso il tunnel smette di funzionare. Si rilancia il passo 3, si prendono indirizzo e chiave pubblica di un altro server, si aggiornano le due righe.
Ogni tunnel WireGuard attivo conta sul limite di connessioni simultanee dell’abbonamento, esattamente come farebbe l’applicazione ufficiale.
Quando qualcosa non torna
Quando il certificato non è quello che dovrebbe essere
PowerShell 5.1 negozia TLS 1.0 per impostazione predefinita, e l’errore che ne esce parla di «relazione di trust» senza dire altro. La prima cosa da provare è forzare TLS 1.2, come nel passo 2.
Se l’errore resta, il problema è la catena del certificato. Si guarda chi firma:
$c = New-Object Net.Sockets.TcpClient("api.nordvpn.com",443)
$s = New-Object Net.Security.SslStream($c.GetStream(),$false,{$true})
$s.AuthenticateAsClient("api.nordvpn.com")
[Security.Cryptography.X509Certificates.X509Certificate2]$s.RemoteCertificate | Format-List Subject,Issuer
$s.Close(); $c.Close()
Atteso: Subject: CN=*.nordvpn.com, con un’autorità pubblica come emittente — Sectigo, Google Trust Services.
Errore 401, in ordine di probabilità
Token troncato. $token.Length deve dare 64. Se dà meno, hai selezionato col mouse invece di usare il pulsante di copia.
Variabile vuota. Incollando le righe una alla volta capita che $token non sia valorizzata. E dopo ogni correzione del token va rigenerato $b64: non si aggiorna da solo, quindi si continua a mandare il valore vecchio.
Valore sbagliato. Hai copiato la password OpenVPN dal riquadro Service credentials invece dell’access token. Sono entrambe stringhe esadecimali, sulla stessa pagina.
Token revocato. Cambiare la password dell’account invalida tutti i token.
Il controllo che separa i casi: se anche https://api.nordvpn.com/v1/users/current risponde 401, il token non è valido in assoluto e non è una questione di permessi.
«Elemento pipe vuoto non consentito»
In PowerShell il foreach come istruzione non si può mettere in pipe. Va racchiuso:
$(foreach ($id in 106, 81, 21) { ... }) | Format-Table -AutoSize
Oppure si usa ForEach-Object, ricordando che dentro l’URL la variabile diventa $_ invece di $id.
Colonne vuote o valori collassati fra graffe
Invoke-RestMethod restituisce già un array deserializzato. Passandolo a un ForEach-Object che costruisce un [pscustomobject] esce una riga sola con liste fra graffe. Si usa Select-Object direttamente sull’array:
$s | Select-Object hostname, station, load
Gli indirizzi sembrano di un altro paese
Non fidarti dei blocchi di indirizzi a memoria: NordVPN usa provider di hosting che riassegnano intervalli fra continenti. Si verifica con una fonte indipendente:
Invoke-RestMethod "https://ipinfo.io/187.13.214.133/json"
Il campo name della risposta di Nord — per esempio Italy #536 — è il riferimento autorevole per il paese.
Il tunnel si connette ma non naviga
MTU troppo alto: prova 1400, poi 1380. Oppure i DNS non configurati: senza i resolver Nord alcuni setup non risolvono nulla. Verifica anche che AllowedIPs sia 0.0.0.0/0.
Handshake mai completato
Controlla che l’endpoint sia raggiungibile sulla porta UDP 51820, e di aver copiato la chiave pubblica del server giusto. Se la linea è dietro CG-NAT o un firewall restrittivo, il keepalive a 25 secondi aiuta ma non sempre basta.
Riferimento rapido delle API
| Scopo | Indirizzo | Autenticazione |
|---|---|---|
| Credenziali del servizio | /v1/users/services/credentials | token |
| Dati account | /v1/users/current | token |
| Elenco paesi | /v1/servers/countries | no |
| Server consigliati | /v1/servers/recommendations | no |
Tutti sotto https://api.nordvpn.com. I filtri utili per recommendations, da codificare nell’URL, sono filters[servers_technologies][identifier]=wireguard_udp, filters[country_id]=<id> e limit=<n>.