Come usare SSH su un server senza IP pubblico o dietro CGNAT

Qualcosa deve portare la connessione dall'esterno. Puoi usare una VPN o una rete overlay come WireGuard o Tailscale, un tunnel SSH inverso verso un server con indirizzo pubblico, oppure IPv6 se ce l'hanno entrambe le estremità. Anche inoltrare una porta sul router funziona, ma non dietro CGNAT, perché il tuo router non ha un indirizzo pubblico da cui inoltrare.

Aggiornata il . I due file di WireGuard sono stati provati tra due container Debian 13 con wireguard-tools, e un accesso SSH su 10.0.0.2 ha funzionato.

Prima controlla cosa hai

Esegui questi comandi sulla macchina che vuoi raggiungere, oppure guarda la pagina di stato del router:

curl -4 https://ifconfig.me   # the public IPv4 others see
curl -6 https://ifconfig.me   # the public IPv6, if you have one
ip -6 addr show scope global  # IPv6 addresses on this machine

Poi trova l'indirizzo WAN nella pagina di stato del router. Se è diverso da quello mostrato dal primo comando, il tuo provider ha un altro NAT davanti a te. Un indirizzo da 100.64.0.0 a 100.127.255.255 sul lato WAN è un forte segno di CGNAT, perché la RFC 6598 riserva quell'intervallo a questo scopo.

Le opzioni

RichiedeFunziona dietro CGNATLimiti
VPN o overlaySoftware su entrambe le estremità. Un peer raggiungibile o un servizio di coordinamentoSìIl software va installato su ogni dispositivo da cui ti colleghi
Tunnel SSH inversoUn server con indirizzo pubblicoSìIl server aggiuntivo trasporta il traffico
IPv6IPv6 globale sulla macchina e sulla rete da cui ti colleghiSì, se il provider dà IPv6Fallisce da reti solo IPv4. Il firewall deve consentirlo
Inoltro di porta sul routerUn IPv4 pubblico sul router e accesso alle sue impostazioniNoLa porta è aperta a internet. L'indirizzo può cambiare

VPN o rete overlay

WireGuard

WireGuard è una VPN che gestisci tu. Dietro CGNAT, la macchina nascosta si collega in uscita a un peer che ha un indirizzo pubblico, e il keepalive mantiene aperta la mappatura NAT. La guida rapida di WireGuard suggerisce 25 secondi. Sulla macchina nascosta, /etc/wireguard/wg0.conf:

[Interface]
Address = 10.0.0.2/24
PrivateKey = HIDDEN_MACHINE_PRIVATE_KEY

[Peer]
PublicKey = PUBLIC_PEER_PUBLIC_KEY
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.0.0.1/32
PersistentKeepalive = 25

Sul peer con l'indirizzo pubblico:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = PUBLIC_PEER_PRIVATE_KEY

[Peer]
PublicKey = HIDDEN_MACHINE_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32

Crea le chiavi con wg genkey | tee priv | wg pubkey > pub, avvia ciascun lato con sudo wg-quick up wg0 e collegati con ssh user@10.0.0.2 dal peer. Su di esso la porta UDP 51820 deve essere aperta. Abbiamo eseguito questi due file tra container e il login SSH su 10.0.0.2 ha funzionato. Solo il peer ha bisogno di un indirizzo pubblico.

Tailscale

Tailscale è una rete overlay costruita su WireGuard, con un servizio di coordinamento ospitato e un account. Su Linux, secondo la sua documentazione:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

Fai lo stesso sul tuo dispositivo e poi collegati con SSH all'indirizzo che assegna, che tailscale ip -4 mostra sulla macchina nascosta. Tailscale prova prima una connessione diretta tra i dispositivi, e il suo articolo sul NAT traversal dice che dietro CGNAT è più difficile. Quando i percorsi diretti falliscono, il traffico passa dai suoi relay DERP, cifrato da un capo all'altro.

Tunnel SSH inverso

Servono solo SSH e un server con indirizzo pubblico, come 203.0.113.10. Sulla macchina nascosta:

ssh -N -o ExitOnForwardFailure=yes -R 2222:localhost:22 user@203.0.113.10

Dal tuo portatile:

ssh -J user@203.0.113.10 -p 2222 hiddenuser@localhost

I dettagli sono in tunnel SSH inversi. Per riavviarlo automaticamente dopo una caduta e limitare la chiave che usa, vedi autossh e systemd.

L'opzione -J è spiegata in ProxyJump e jump host.

IPv6

Il CGNAT riguarda IPv4, e alcuni provider che lo usano assegnano anche indirizzi IPv6 globali. Se ip -6 addr show scope global ne mostra uno, prova da una rete che ha IPv6:

ssh user@2001:db8::10

Il router o il provider possono bloccare l'IPv6 in ingresso, quindi un timeout può significare che il firewall ha bisogno di una regola per la porta 22. Vedi Connection timed out. Anche la rete da cui ti colleghi deve avere IPv6, e alcune reti di uffici e hotel non ce l'hanno. Se il tuo indirizzo cambia, aiuta un nome DNS dinamico.

Inoltro di porta sul router

Funziona quando il router ha un vero indirizzo IPv4 pubblico. Nelle sue impostazioni, inoltra una porta TCP esterna alla porta 22 della macchina, poi collegati all'indirizzo pubblico del router:

ssh -p 2222 user@203.0.113.10

Dietro CGNAT non serve a nulla, perché l'indirizzo pubblico appartiene al tuo provider. Alcuni provider ti danno un IPv4 pubblico su richiesta, a volte a pagamento, quindi può valere la pena chiedere. Una porta aperta riceve inoltre continui tentativi di login da internet, quindi usa solo chiavi. Vedi come disattivare l'accesso con password e fail2ban.

Domande

Come capisco se sono dietro CGNAT?

Confronta l'indirizzo WAN del router con quello che vedono siti come ifconfig.me. Se sono diversi, o se l'indirizzo WAN è tra 100.64.0.0 e 100.127.255.255, il tuo provider usa il CGNAT.

Posso collegarmi in SSH a una macchina dietro CGNAT senza VPN?

Sì, con un tunnel SSH inverso verso un server con indirizzo pubblico. La macchina nascosta si collega in uscita e tu la raggiungi passando da quel server.

Il port forwarding del router funziona dietro CGNAT?

No. L'indirizzo pubblico è del provider, non del tuo router, quindi non c'è niente da inoltrare. Chiedi al provider un IPv4 pubblico o usa una delle altre soluzioni.

Fonti

Altro in Tunnel e jump host

Tutte le guide