EN

Guide / Reti

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.

  1. VPN → WireGuard Client, poi NordVPN → Modifica informazioni account
  2. Incolla l’access token — come ottenerlo è il primo passo della procedura lunga, più sotto — e premi Avanti
  3. Il router scarica l’elenco dei server, oltre duemila, e li presenta per paese e città
  4. 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 curl su Linux, macOS o WSL

1. Generare l’access token

  1. Accedi a my.nordaccount.com
  2. Nella barra laterale, NordVPN
  3. Scorri fino a Advanced settings → Set up NordVPN manually
  4. Nord chiede di verificare l’email: inserisci il codice a sei cifre
  5. 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
  6. 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
Paeseid
Belgium21
Germany81
Italy106

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
CampoValoreDa dove viene
PrivateKeyla chiave dell’accountpasso 2
Address10.5.0.2/32fisso: NordLynx assegna sempre questo
DNSi due resolver Nordfissi
MTU1420standard NordLynx
PublicKeyla chiave del serverpasso 3
Endpointstation più :51820passo 3
AllowedIPs0.0.0.0/0tutto il traffico nel tunnel
PersistentKeepalive25tiene 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:

  1. Apri la console del router, di norma http://192.168.8.1
  2. VPN → WireGuard Client → Add New Profile
  3. Scegli Manual Config e incolla il contenuto del .conf
  4. Dai un nome riconoscibile al profilo, per esempio Nord-IT-536
  5. 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:

  1. Rilancia il passo 3 con l’id del nuovo paese
  2. Duplica il .conf cambiando solo due righe: Endpoint e PublicKey
  3. 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

ScopoIndirizzoAutenticazione
Credenziali del servizio/v1/users/services/credentialstoken
Dati account/v1/users/currenttoken
Elenco paesi/v1/servers/countriesno
Server consigliati/v1/servers/recommendationsno

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>.