SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-21

Reverse tunnel con VPS per superare il CGNAT

Il CGNAT impedisce il port forwarding: configura frp su un VPS economico, crea il tunnel in uscita da casa e termina HTTPS con un certificato valido.

Perché il port forwarding non funziona dietro CGNAT

Dietro CGNAT (carrier-grade network address translation), l'indirizzo WAN del router è condiviso con altri abbonati. Nessun indirizzo IP pubblico è assegnato esclusivamente a te, quindi non esiste una porta da inoltrare. Un reverse tunnel risolve il problema: un VPS economico mantiene l'indirizzo IP pubblico, il server di casa avvia una connessione in uscita verso il VPS e le richieste in ingresso vengono instradate nuovamente attraverso la connessione già aperta dal server di casa. Puoi continuare a usare l'hardware che possiedi. Noleggi l'unica risorsa che il provider ISP non ti offre: un indirizzo instradabile.

Ogni comando seguente indica il server su cui deve essere eseguito. Sono necessari due server: il VPS con un indirizzo IP pubblico e il server di casa che esegue il servizio a cui vuoi accedere.

Come verificare se si è effettivamente dietro CGNAT

Apri la pagina di amministrazione del router e leggi l'indirizzo WAN visualizzato. Poi chiedi a Internet quale indirizzo rileva.

# on the home box
curl -4 -s https://ifconfig.me; echo

Se i due indirizzi coincidono, hai un IP pubblico e non ti serve nulla di tutto questo. Inoltra la porta e interrompi la lettura. Se l'indirizzo WAN del router rientra in 100.64.0.0/10, sei dietro CGNAT. Questo blocco è lo spazio di indirizzamento condiviso RFC 6598, riservato esattamente a questo uso. Alcuni ISP assegnano invece 10.0.0.0/8 sul lato WAN; la situazione è la stessa, anche se indicata con un'etichetta diversa.

Prima di noleggiare qualsiasi risorsa, verifica un aspetto. Molti ISP che usano CGNAT assegnano un prefisso IPv6 reale e, se il dispositivo di rete domestico dispone di un indirizzo IPv6 globale, puoi aprire il firewall su quell'indirizzo e fare a meno del tunnel. Questa soluzione smette di funzionare non appena un visitatore si trova su una rete che supporta solo IPv4, motivo per cui la maggior parte delle persone arriva comunque a questa soluzione.

Come funziona un reverse tunnel verso un VPS, avviato dall'interno

CGNAT e i normali router domestici bloccano entrambi le connessioni in ingresso non richieste. Lo stesso vale per i firewall aziendali. Nessuno di questi dispositivi blocca le connessioni in uscita, perché sono quelle utilizzate continuamente da ogni browser e da ogni client di aggiornamento. Quando un dispositivo NAT rileva una connessione TCP in uscita, crea una mappatura e consente quindi il traffico di ritorno associato a quella connessione. Dall'esterno, nessuno può avviare una connessione verso il computer di casa. È quindi il computer di casa ad avviarla, mentre il tunnel trasporta il traffico indietro sulla stessa connessione, nella direzione opposta.

Questo è l'intero meccanismo. Il computer di casa si connette in uscita al VPS su una porta e mantiene aperta la connessione. Il VPS accetta le richieste pubbliche e le inoltra tramite quella connessione già esistente. Nessuno tenta mai di raggiungere l'indirizzo IP di casa, quindi non è necessario consentirlo.

Da questo derivano due conseguenze, entrambe utili. Il record DNS punta al VPS, mai alla rete domestica. Inoltre, il tuo indirizzo pubblico è ora quello del VPS: quindi, qualunque informazione un osservatore ricavi da una ricerca dell'indirizzo IP, riguarderà un server noleggiato anziché la tua connessione domestica.

Tre modi per realizzarlo

  1. ssh -R: già installato su entrambe le estremità, adatto a un solo servizio o a una demo temporanea. Non offre una dashboard né una gestione della riconnessione degna di questo nome.
  2. frp: un server Go di piccole dimensioni (frps) e un client corrispondente (frpc). Adatto a una configurazione permanente con più servizi pubblicati tramite un unico hostname. Questa è la soluzione trattata principalmente nella guida.
  3. Una VPN mesh: Tailscale oppure un server WireGuard gestito autonomamente. È la scelta giusta quando vuoi che i tuoi dispositivi comunichino privatamente tra loro, invece di pubblicare un servizio su Internet.

Scegli la mesh se il tuo obiettivo è consentire l'accesso privato dai dispositivi che controlli. Tailscale Serve e Funnel descrive come pubblicare un servizio al di fuori di una tailnet, mentre una VPN WireGuard self-hosted sullo stesso VPS offre una configurazione analoga senza un server di coordinamento di terze parti nel percorso. Leggi una di queste sezioni e ignora il resto di questa pagina. Tutto ciò che segue presuppone che tu voglia un hostname HTTPS pubblico accessibile da chiunque.

La versione rapida: ssh -R per un servizio

Supponiamo che il computer di casa esegua un'applicazione su 127.0.0.1:3000 e che tu disponga già dell'accesso SSH al VPS.

# on the home box
ssh -N \
  -o ExitOnForwardFailure=yes \
  -o ServerAliveInterval=30 \
  -o ServerAliveCountMax=3 \
  -R 127.0.0.1:8080:127.0.0.1:3000 \
  tunnel@vps.example.com

-R 127.0.0.1:8080:127.0.0.1:3000 configura il demone sshd del VPS affinché resti in ascolto sulla propria 127.0.0.1:8080 e inoltri tutto ciò che vi arriva a 127.0.0.1:3000 sul computer di casa. -N indica di non avviare una shell. Le due opzioni ServerAlive fanno sì che ssh rilevi un collegamento interrotto dopo circa novanta secondi, invece di restare bloccato su una connessione che non esiste più.

Ora veniamo alla parte che crea più confusione. Il listener è associato all'interfaccia di loopback, quindi curl http://vps.example.com:8080 da qualsiasi altra posizione non funziona. sshd viene fornito con GatewayPorts no, che fa sì che un inoltro remoto sia associato soltanto all'interfaccia di loopback. Non risolvere il problema impostando GatewayPorts yes. Lascia l'inoltro sulla loopback e metti nginx davanti a esso, come nella configurazione con frp riportata più avanti: la porta pubblica sarà la 443 con un certificato, mentre la porta del tunnel non sarà mai esposta a Internet. Se non sai con certezza cosa è attualmente in ascolto e su quale interfaccia, un breve riepilogo di porte e listener su Linux richiede dieci minuti di lettura.

Se la porta è già occupata sul VPS, ssh stampa questo messaggio e ExitOnForwardFailure=yes gli consente di terminare invece di stabilire una connessione senza un tunnel funzionante:

Warning: remote port forwarding failed for listen port 8080

La causa abituale è una sessione precedente terminata senza che sshd se ne accorgesse. Imposta ClientAliveInterval 30 e ClientAliveCountMax 3 nel /etc/ssh/sshd_config del VPS, in modo che le sessioni interrotte vengano eliminate e la porta venga liberata. Incapsula l'intero comando in un'unità systemd con Restart=always e una chiave dedicata, oppure usa autossh. Per qualsiasi configurazione con più di un servizio, interrompi qui e usa frp.

Installare frp sul VPS con una versione fissata

frp viene distribuito come binario Go statico e non è incluso negli archivi Ubuntu o Debian, quindi è necessario scaricare una release e verificarla manualmente. Fissare la versione. Il formato della configurazione è cambiato con la versione v0.52.0 e da allora i nomi delle opzioni sono stati spostati, quindi una guida obsoleta può fornire chiavi che il binario non riconosce. Questa guida usa v0.71.0, pubblicato il 14 agosto 2026.

# on the VPS
FRP_VERSION=0.71.0
ARCH=amd64   # use arm64 if `uname -m` prints aarch64
cd /tmp
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_sha256_checksums.txt"
sha256sum --check --ignore-missing frp_sha256_checksums.txt

sha256sum deve stampare esattamente una riga:

frp_0.71.0_linux_amd64.tar.gz: OK

--ignore-missing è necessario perché il file dei checksum include tutti i diciotto artefatti della release e ne è stato scaricato uno. Senza quel flag, sha256sum segnala come mancanti gli altri diciassette ed esce con un codice diverso da zero. Il risultato sembra una verifica fallita, anche se non c'è alcun problema.

# on the VPS
tar xzf "frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
sudo install -m 755 "frp_${FRP_VERSION}_linux_${ARCH}/frps" /usr/local/bin/frps
sudo useradd --system --no-create-home --shell /usr/sbin/nologin frp
sudo install -d -m 750 -o root -g frp /etc/frp
frps --version

frps --version stampa 0.71.0. Solo frps deve essere installato sul VPS. frpc deve essere installato sul computer di casa. Installare entrambi i binari ovunque è il modo in cui si finisce per eseguire accidentalmente un server tunnel a casa.

Configurazione del VPS: token, TLS obbligatorio, listener sull'interfaccia di loopback

Genera prima un token. È l'unico elemento che protegge il tunnel da chiunque esegua una scansione delle porte del VPS.

# on the VPS
openssl rand -base64 32

Scrivi quel valore in /etc/frp/frps.toml:

bindAddr = "0.0.0.0"
bindPort = 7000

# Every listener frp creates for a proxy, including the HTTP vhost, stays on loopback.
proxyBindAddr = "127.0.0.1"
vhostHTTPPort = 8080

auth.method = "token"
auth.token = "PASTE_THE_OPENSSL_OUTPUT_HERE"

transport.tls.force = true

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASTE_A_SECOND_SECRET_HERE"

log.level = "info"

Quattro di quelle righe gestiscono la sicurezza. Esaminale una alla volta.

auth.token deve corrispondere a auth.token sul client. Senza questa impostazione, frps accetta qualsiasi client che trovi la porta 7000. Quel client può quindi pubblicare attraverso il VPS e il relativo certificato qualsiasi servizio desideri.

transport.tls.force = true rifiuta qualsiasi connessione di controllo che non utilizzi TLS (Transport Layer Security). I client abilitano TLS per impostazione predefinita da v0.50.0. Nella pratica non comporta costi e impedisce che un client obsoleto o creato manualmente si connetta in chiaro senza avvisarti.

proxyBindAddr = "127.0.0.1" è la riga che la maggior parte delle guide omette. È anche il motivo per cui questa configurazione può rimanere attiva in sicurezza. Sposta sull'interfaccia di loopback ogni listener che frp apre per conto di un proxy, sia il virtual host HTTP sia qualsiasi remotePort richiesto da un client. Internet non può raggiungere in alcun modo questi listener. L'unico punto di accesso pubblico è nginx sulla porta 443, che configuri e controlli tu.

webServer.addr = "127.0.0.1" mantiene il dashboard fuori dall'interfaccia pubblica. Il dashboard offre una mappa completa dei servizi privati e del relativo traffico ed è protetto da una sola password HTTP Basic Auth. Non deve quindi essere esposto su 0.0.0.0.

Imposta il proprietario in modo che il token non sia leggibile da tutti, quindi verifica la sintassi prima di avviare qualsiasi componente:

# on the VPS
sudo chown root:frp /etc/frp/frps.toml
sudo chmod 640 /etc/frp/frps.toml
sudo -u frp frps verify -c /etc/frp/frps.toml

Un file valido restituisce:

frps: the configuration file /etc/frp/frps.toml syntax is ok

Una nota sul formato può farti risparmiare un'ora. frp sceglie il parser in base all'estensione del file e riconosce .toml, .yaml, .yml e .json. I file .ini meno recenti vengono ancora caricati tramite un percorso di conversione legacy, ma INI è deprecato e le nuove opzioni sono documentate solo per TOML. Se una guida mostra una sezione [common] e server_addr = x.x.x.x, è precedente a v0.52.0 e i nomi delle chiavi non corrisponderanno al binary appena installato.

Eseguire frps come servizio senza privilegi

bindPort è 7000 e vhostHTTPPort è 8080. Entrambe sono superiori a 1024, quindi frps non ha mai bisogno di root né di CAP_NET_BIND_SERVICE. Per questo non bisogna configurare il vhost sulla porta 80 e lasciare che sia nginx a gestirla.

Scrivere /etc/systemd/system/frps.service:

[Unit]
Description=frp reverse tunnel server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true

[Install]
WantedBy=multi-user.target
# on the VPS
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo journalctl -u frps -n 20 --no-pager

Il log dovrebbe mostrare entrambi i listener. Gli indirizzi sono più importanti delle porte:

frps tcp listen on 0.0.0.0:7000
http service listen on 127.0.0.1:8080

ProtectSystem=strict rende di sola lettura l'intero filesystem per questo servizio. frps lo gestisce senza problemi perché, per impostazione predefinita, scrive il log sullo standard output e journald lo acquisisce. Se si imposta log.to su un percorso di file, il servizio non riesce a scriverci finché non si aggiunge una riga ReadWritePaths= corrispondente. Lasciare quindi l'impostazione predefinita.

Firewall: aprire una porta, non un intervallo

# on the VPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7000/tcp
sudo ufw enable
sudo ufw status numbered

Quattro regole, una delle quali serve soltanto per il rinnovo dei certificati. La porta 22 è SSH. La porta 80 reindirizza alla 443 e risponde alla challenge ACME (ambiente per la gestione automatica dei certificati). La porta 443 pubblica tutte le applicazioni instradate tramite tunnel. La porta 7000 è la porta di controllo di frp ed è l’unica porta che un client deve raggiungere.

Le guide che indicano di aprire un intervallo come sudo ufw allow 20000:30000/tcp descrivono l’altro modello, in cui ogni servizio usa una propria porta TCP pubblica. Qui non è necessario, perché tutto arriva sulla porta 443 e frp instrada le richieste in base al nome host. Se in seguito ti serve una porta TCP realmente pubblica, ripristina proxyBindAddr su 0.0.0.0 e aggiungi limitazioni per consentire a un client di usare soltanto le porte specificate:

allowPorts = [
  { start = 20000, end = 20010 }
]
maxPortsPerClient = 5

La maggior parte dei provider gestisce anche un firewall di rete nel pannello di controllo, separato da ufw sul server. Una regola che appare corretta in sudo ufw status ma le cui connessioni continuano ad andare in timeout è solitamente bloccata da quel firewall. Le regole ufw effettivamente necessarie su un VPS illustra la configurazione con criterio predefinito di negazione adottata in questa sezione.

Terminare HTTPS sul VPS con un certificato valido

Punta un record A per home.example.com all'indirizzo IP pubblico del VPS. Non a casa tua. La tua rete domestica non ha un indirizzo a cui puntare, ed è proprio questo il problema che stai risolvendo.

# on the VPS
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx

Crea /etc/nginx/sites-available/home.example.com iniziando con un blocco sulla porta 80, in modo che certbot abbia un server_name corrispondente su cui operare:

server {
    listen 80;
    listen [::]:80;
    server_name home.example.com;
    location / { return 404; }
}
# on the VPS
sudo ln -s /etc/nginx/sites-available/home.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --nginx -d home.example.com

nginx -t stampa nginx: configuration file /etc/nginx/nginx.conf test is successful quando i file sono sintatticamente validi. Eseguilo prima di ogni reload. Se un reload non riesce, nginx mantiene attiva la configurazione precedente; quindi una modifica non valida può sembrare una modifica che non ha prodotto effetti.

Gli upgrade WebSocket richiedono una map a livello http. Inseriscila in /etc/nginx/conf.d/upgrade.conf:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

Ora sostituisci il file del sito con quello definitivo:

server {
    listen 80;
    listen [::]:80;
    server_name home.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name home.example.com;

    ssl_certificate     /etc/letsencrypt/live/home.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;

    client_max_body_size 512m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        $connection_upgrade;
        proxy_read_timeout 3600s;
    }
}

proxy_set_header Host $host; è obbligatorio in questo caso. Il vhost HTTP di frp instrada le richieste in base all'header Host, confrontandolo con l'elenco customDomains nella configurazione del client. Se ometti quell'header, nginx invia Host: 127.0.0.1, frp non trova alcun proxy per quel nome e il visitatore riceve un 404 vuoto da frp invece della pagina dell'applicazione. Spiegazione di ogni riga di un blocco reverse proxy nginx descrive il funzionamento degli altri header.

# on the VPS
sudo nginx -t && sudo systemctl reload nginx
sudo certbot renew --dry-run

Il dry run dimostra che il rinnovo funzionerà tra novanta giorni, quando non starai controllando il sistema. Richiede che la porta 80 sia raggiungibile, ed è per questo che esiste quella regola ufw.

Il lato domestico: frpc come servizio senza privilegi

Installa frpc sul computer di casa esattamente come hai installato frps, usando la stessa versione e la stessa procedura di verifica del checksum, quindi crea lo stesso utente frp e la directory /etc/frp. Scrivi /etc/frp/frpc.toml:

serverAddr = "vps.example.com"
serverPort = 7000

auth.method = "token"
auth.token = "PASTE_THE_SAME_TOKEN_HERE"

transport.tls.enable = true
loginFailExit = false

proxies = [
  { name = "home-app", type = "http", localIP = "127.0.0.1", localPort = 3000, customDomains = ["home.example.com"] }
]

L’ordine delle chiavi in questo file è importante, e non per motivi di stile. TOML assegna ogni chiave successiva a un’intestazione di tabella alla tabella corrispondente. Di conseguenza, un’impostazione di primo livello come serverAddr, se scritta sotto l’intestazione di una tabella proxy, diventa silenziosamente un’impostazione del proxy che frp ignora. Scrivere l’elenco dei proxy come array inline, come mostrato sopra, evita il problema: ogni chiave di primo livello rimane chiaramente al primo livello.

type = "http" instrada questo proxy tramite il listener vhost invece di assegnargli una porta TCP pubblica dedicata. Per questo il firewall è rimasto con quattro regole. customDomains deve contenere il nome host che nginx inoltra nell’header Host, quindi deve essere home.example.com e non l’indirizzo IP del VPS.

loginFailExit = false è più importante di quanto sembri. Il valore predefinito è true, che fa terminare frpc se il primo tentativo di accesso non riesce. Su un computer di casa che completa l’avvio prima che il collegamento ISP sia disponibile, il servizio rimane quindi inattivo finché non te ne accorgi. Impostalo su false: frpc continuerà a riprovare finché il VPS non risponde.

Scrivi /etc/systemd/system/frpc.service:

[Unit]
Description=frp reverse tunnel client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=always
RestartSec=10s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target
# on the home box
sudo chown root:frp /etc/frp/frpc.toml
sudo chmod 640 /etc/frp/frpc.toml
sudo -u frp frpc verify -c /etc/frp/frpc.toml
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo journalctl -u frpc -n 20 --no-pager

Un client che ha stabilito la connessione registra un run id:

login to server success, get run id [3a1f9c2b7d4e5f60]

Apri https://home.example.com in un browser. Dovresti visualizzare l’applicazione che risiede su 127.0.0.1:3000 a casa. Restart=always sul client è intenzionale: le connessioni domestiche possono interrompersi e il servizio deve tornare operativo senza interventi manuali.

Mantieni la dashboard fuori dall'interfaccia pubblica

Con webServer.addr = "127.0.0.1" la dashboard risponde soltanto sul VPS stesso. Raggiungila dal laptop con un port forwarding locale invece di aprire una porta:

# on your laptop
ssh -N -L 7500:127.0.0.1:7500 you@vps.example.com

Apri http://127.0.0.1:7500 e accedi con webServer.user e webServer.password indicati in frps.toml. La pagina elenca ogni client connesso e i contatori del traffico per ciascun proxy. È il modo più rapido per verificare se il dispositivo di casa è effettivamente connesso in quel momento. Chiudi la sessione SSH e la dashboard torna a essere irraggiungibile.

Cosa non fa il tunnel

Leggete questa parte due volte, perché è il punto in cui si verificano gli incidenti più gravi. Il tunnel rende un servizio privato raggiungibile da Internet. Non autentica le persone che vi accedono. Quando https://home.example.com risolve, gli scanner lo individueranno entro pochi giorni, indipendentemente dal fatto che abbiate comunicato o meno il nome. I log di certificate transparency pubblicano ogni hostname per cui emettete un certificato, quindi il nome diventa pubblico non appena certbot termina correttamente.

Qualsiasi servizio esposto deve gestire autonomamente l'autenticazione. Se l'applicazione dispone di un login reale con rate limiting, va bene. Se usa un'unica password condivisa oppure non dispone di alcun login, configurate un proxy che gestisca l'autenticazione davanti all'applicazione sul VPS. Un oauth2-proxy davanti all'applicazione è la soluzione abituale e si inserisce tra nginx e il virtual host di frp senza modificare nessuna delle due estremità del tunnel.

Il token in frps.toml protegge il tunnel, non le applicazioni. Impedisce a un estraneo di registrare un proprio proxy sul VPS. Non ha alcun effetto su una richiesta che arriva sulla porta 443 per un hostname pubblicato intenzionalmente.

È opportuno mantenere due abitudini. Ruotate il token modificando entrambi i file e riavviando entrambi i servizi, perché non scade automaticamente. Inoltre, mantenete frp aggiornato: questo binario è il punto di ingresso pubblico del server e le note della versione v0.71.0 elencano un panic del server provocato da un valore non valido inviato da un client. È una classe di bug da correggere con una patch, non da analizzare a posteriori.

Modalità di errore e stringhe visualizzate

Il client non si connette mai. journalctl -u frpc si ripete connect to server error:, seguito da un timeout della connessione. Nessun dato raggiunge la porta 7000. Controllare ufw sul VPS, quindi il firewall di rete del provider nel pannello di controllo. Verificare infine la risoluzione del nome con getent hosts vps.example.com.

Il token non è corretto. Il client lo indica esplicitamente:

login to the server failed: token in login doesn't match token from configuration

Copiare di nuovo il token. Quasi tutti questi errori sono causati da un newline finale oppure da un $ in una stringa shell non racchiusa tra virgolette, che viene espanso in una stringa vuota. Per questo l'output di openssl rand -base64 32 deve essere racchiuso tra virgolette nel file TOML.

Il tunnel è attivo, ma il browser riceve un 404 senza contenuto. frpc ha registrato un accesso riuscito e la dashboard mostra il proxy, ma la pagina restituisce 404 senza alcuno stile dell'applicazione. Questo indica che frp non ha un proxy per questo header Host. Testare direttamente il vhost sul VPS, bypassando nginx e TLS:

# on the VPS
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: home.example.com' http://127.0.0.1:8080/

Un 404 restituito da questo comando indica che customDomains non è corretto. Qualsiasi altro codice indica che la richiesta non ha ricevuto da nginx il Host corretto.

502 da nginx. nginx risponde, mentre frp non lo fa. sudo ss -lntp | grep 8080 sul VPS dovrebbe mostrare frps in ascolto su 127.0.0.1:8080. Un output vuoto indica che frps è arrestato oppure che vhostHTTPPort non è impostato in frps.toml.

L'applicazione considera locali tutti i visitatori. I log dell'applicazione riportano 127.0.0.1 per ogni richiesta. frp imposta X-Forwarded-For e nginx lo aggiunge, quindi l'indirizzo reale del client si trova in quell'header. Configurare l'applicazione perché si fidi di questo header. Non saltare questo passaggio se l'applicazione applica il rate limiting in base all'indirizzo IP, perché al momento tutti i visitatori su Internet condividono lo stesso bucket.

Le richieste lunghe vengono interrotte dopo 60 secondi. I caricamenti o le risposte in streaming si interrompono prima del completamento. Questo dipende dal valore predefinito di nginx, proxy_read_timeout, non dal tunnel. Il blocco precedente lo aumenta a 3600s. client_max_body_size è il limite corrispondente per la dimensione dei caricamenti; il valore predefinito di 1 MB rifiuta i body più grandi con un errore 413.

Tutto funziona, poi smette dopo il riavvio del router. Restart=always nell'unità frpc, insieme a loginFailExit = false, gestisce questo caso. Verificare con sudo systemctl is-enabled frpc, che deve stampare enabled.

FAQ

Come posso sapere se sono dietro CGNAT?

Confronta l'indirizzo WAN nella pagina di amministrazione del router con quello che curl -4 -s https://ifconfig.me restituisce dalla stessa rete. Se sono diversi e l'indirizzo WAN del router rientra in 100.64.0.0/10, il provider utilizza il NAT di livello carrier. Quello è lo spazio di indirizzi condivisi RFC 6598, previsto proprio per questo scopo. Alcuni provider usano invece 10.0.0.0/8 sul lato WAN, con lo stesso risultato. Se i due indirizzi coincidono, hai un IP pubblico: inoltra la porta e hai finito.

Mi serve un nome di dominio per un tunnel inverso?

Per la configurazione HTTPS descritta qui, sì. Un certificato viene emesso per un hostname e il vhost HTTP di frp instrada le richieste in base all'header Host, quindi entrambe le estremità devono concordare su un nome. Un proxy TCP puro su una porta numerica funziona usando direttamente l'IP del VPS, senza alcun dominio, ma in questo caso non hai né un certificato né l'instradamento basato sull'hostname: una sola porta pubblica serve esattamente un servizio.

È sicuro eseguire frp su un VPS pubblico?

È sicuro quando la porta di controllo è l'unica esposta ed è autenticata. Imposta auth.token su un valore casuale in entrambe le estremità e transport.tls.force = true sul server. Imposta quindi proxyBindAddr = "127.0.0.1", in modo che nessuna porta aperta da frp per un proxy sia esposta a Internet, e mantieni la dashboard su webServer.addr = "127.0.0.1", raggiungendola tramite un forward locale SSH. Aggiorna il binario quando vengono rilasciate nuove versioni, perché è il processo in ascolto sul tuo indirizzo pubblico.

Perché nessuno riesce a raggiungere la porta inoltrata ssh -R?

sshd viene fornito con GatewayPorts no, quindi un forward remoto si associa soltanto all'interfaccia di loopback del VPS. curl eseguito direttamente sul VPS funziona, mentre curl da qualsiasi altra posizione va in timeout. La correzione consiste nel lasciare il forward sulla loopback e mettere nginx sulla porta 443 davanti a esso. Impostare GatewayPorts yes pubblica una porta TCP pura senza certificato e senza TLS, creando un problema maggiore di quello che risolve.

Devo usare frp oppure una VPN mesh come Tailscale o WireGuard?

Usa una VPN mesh quando devono accedere soltanto i tuoi dispositivi, perché in questo modo non viene pubblicato nulla e non esiste un hostname pubblico che chiunque possa analizzare. Usa frp quando ti serve un indirizzo HTTPS pubblico caricabile da qualsiasi browser, ad esempio per un ricevitore di webhook o una pagina da condividere con persone che non installeranno un client VPN. Le due soluzioni possono funzionare insieme senza problemi su un unico VPS, usando porte diverse e svolgendo funzioni diverse.

#frp#cgnat#nat#tunnel#reverse-proxy