SSD Nodes Learn 🎉 VPS vanaf $5.50/mnd
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-21

Eigen server bereikbaar maken achter CGNAT met een VPS

Krijgt u geen toegang tot uw thuisserver door CGNAT? Gebruik een reverse tunnel met frp op een VPS om uw eigen publieke IP-adres te omzeilen en HTTPS veilig te ontsluiten.

Waarom port forwarding niet werkt achter CGNAT

Achter CGNAT (carrier-grade network address translation) wordt het WAN-adres van uw router gedeeld met andere abonnees. U beschikt dus niet over een publiek IP-adres en er is geen poort die u kunt forwarden. Een reverse tunnel lost dit op: een goedkope VPS fungeert als het publieke IP-adres, uw thuisserver maakt verbinding met de VPS, en inkomende verzoeken worden via de reeds geopende verbinding teruggeleid naar uw thuisnetwerk. U behoudt de hardware die u al bezit. U huurt het enige dat uw ISP u niet kan leveren: een routeerbaar adres.

Elk commando hieronder is voorzien van een aanduiding voor de machine waarop het moet worden uitgevoerd. Hiervoor zijn twee machines nodig: de VPS met een publiek IP-adres en de thuisserver waarop de service draait die u wilt bereiken.

Hoe u vaststelt of u zich achter CGNAT bevindt

Open de beheerpagina van uw router en lees het WAN-adres dat daar wordt weergegeven. Vraag vervolgens aan het internet welk adres het ziet.

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

Als de twee adressen overeenkomen, beschikt u over een publiek IP-adres en is deze procedure niet nodig. Stuur de poort door en u kunt stoppen met lezen. Als het WAN-adres van de router zich binnen 100.64.0.0/10 bevindt, bevindt u zich achter CGNAT. Dat blok is de RFC 6598 gedeelde adresruimte, die specifiek voor dit doel is gereserveerd. Sommige ISP's plaatsen in plaats daarvan 10.0.0.0/8 aan de WAN-zijde, wat in feite dezelfde situatie is onder een andere noemer.

Controleer één ding voordat u iets huurt. Veel CGNAT-ISP's verstrekken een echt IPv6-prefix. Als uw thuisnetwerk over een globaal IPv6-adres beschikt, kunt u de firewall op dat adres openen en de tunnel volledig overslaan. Dit werkt echter niet zodra een bezoeker zich op een netwerk bevindt dat alleen IPv4 ondersteunt; dat is de reden waarom de meeste mensen uiteindelijk toch hier terechtkomen.

Hoe een VPS-reverse tunnel werkt, opgezet vanuit het interne netwerk

CGNAT en standaard thuisrouters blokkeren ongevraagde inkomende verbindingen. Bedrijfsfirewalls doen dit eveneens. Geen van deze blokkeert uitgaande verbindingen, aangezien uitgaand verkeer de standaard is voor elke browser en elke update-client. Een NAT-apparaat dat een uitgaande TCP-verbinding ziet, maakt hiervoor een mapping aan en staat vervolgens het retourverkeer over die verbinding toe. Niets van buitenaf kan een verbinding met uw thuisnetwerk starten. Daarom start de machine thuis de verbinding, waarna de tunnel het verkeer via diezelfde verbinding in de andere richting terugvoert.

Dat is het volledige mechanisme. De machine thuis maakt verbinding met de VPS op een specifieke poort en houdt deze verbinding open. De VPS accepteert publieke verzoeken en geeft deze door via de bestaande verbinding. Er wordt nooit geprobeerd om uw thuis-IP-adres te bereiken, dus dat is ook niet nodig.

Hieruit volgen twee nuttige consequenties. Uw DNS-record verwijst naar de VPS, nooit naar uw huisadres. Bovendien is uw publieke adres nu het adres van de VPS; wat een waarnemer ook leert via een IP-lookup, het betreft de gehuurde server in plaats van uw thuisverbinding.

Drie manieren om dit op te bouwen

  1. ssh -R: reeds geïnstalleerd aan beide kanten en geschikt voor één service of een tijdelijke demo. Het biedt geen dashboard en geen noemenswaardige logica voor het herstellen van verbindingen.
  2. frp: een kleine Go-server (frps) en een bijbehorende client (frpc). Geschikt voor een permanente opstelling met meerdere services achter één hostnaam. Dit vormt het grootste deel van deze handleiding.
  3. Een mesh VPN: Tailscale, of een WireGuard-server die u zelf beheert. Geschikt wanneer u wilt dat uw eigen apparaten elkaar privé kunnen bereiken in plaats van iets te publiceren op het openbare internet.

Kies voor de mesh als uw doel privétoegang is vanaf apparaten die u zelf beheert. Tailscale Serve en Funnel behandelt het publiceren vanuit een tailnet, en een zelfgehoste WireGuard VPN op dezelfde VPS biedt u dezelfde structuur zonder een externe coördinatieserver in het pad. Lees een van deze opties en sla de rest van deze pagina over. Alles hieronder gaat ervan uit dat u een openbare HTTPS-hostnaam wilt die door iedereen geladen kan worden.

De beknopte versie: ssh -R voor één service

Stel dat uw thuisserver een applicatie draait op 127.0.0.1:3000 en u heeft al SSH-toegang tot de 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 instrueert de sshd van de VPS om op zijn eigen 127.0.0.1:8080 te luisteren en alles wat daar binnenkomt door te sturen naar 127.0.0.1:3000 op de thuisserver. -N betekent dat er geen shell wordt gestart. De twee ServerAlive-opties zorgen ervoor dat ssh een verbroken verbinding na ongeveer negentig seconden opmerkt, in plaats van te blijven hangen op een verbinding die niet meer bestaat.

Nu het onderdeel dat voor verwarring zorgt. Die listener bevindt zich op de loopback-interface, dus curl http://vps.example.com:8080 vanaf een andere locatie zal falen. sshd wordt geleverd met GatewayPorts no, wat betekent dat een remote forward alleen aan de loopback-interface bindt. Los dit niet op door GatewayPorts yes in te stellen. Laat de forward op loopback staan en plaats nginx ervoor, op dezelfde manier als bij de onderstaande frp-configuratie. Hierdoor is de publieke poort 443 voorzien van een certificaat en is de tunnelpoort nooit direct verbonden met het internet. Als u niet zeker weet wat er momenteel luistert en op welke interface, is een korte rondleiding langs poorten en listeners op Linux tien minuten van uw tijd waard.

Als de poort al in gebruik is op de VPS, toont ssh deze melding en zorgt ExitOnForwardFailure=yes ervoor dat het proces stopt in plaats van verbinding te maken zonder werkende tunnel:

Warning: remote port forwarding failed for listen port 8080

De gebruikelijke oorzaak is een vorige sessie die is beëindigd zonder dat sshd dit heeft opgemerkt. Stel ClientAliveInterval 30 en ClientAliveCountMax 3 in het bestand /etc/ssh/sshd_config van de VPS in, zodat dode sessies worden opgeruimd en de poort vrijgeven. Verpak het volledige commando in een systemd-unit met Restart=always en een specifieke sleutel, of gebruik autossh. Voor alles met meer dan één service kunt u hier stoppen en frp gebruiken.

frp installeren op de VPS, vastgezet op een specifieke tag

frp wordt geleverd als een statisch Go-binary en zit niet in de Ubuntu- of Debian-repositories, dus u downloadt een release en verifieert deze zelf. Zet de versie vast. Het configuratieformaat is gewijzigd bij v0.52.0 en optienamen zijn sindsdien verplaatst, waardoor een verouderde handleiding u sleutels kan geven die uw binary niet herkent. Deze handleiding gebruikt v0.71.0, gepubliceerd op 14 augustus 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 hoort precies één regel te tonen:

frp_0.71.0_linux_amd64.tar.gz: OK

--ignore-missing is nodig omdat het checksum-bestand alle achttien release-assets bevat en u er slechts één heeft gedownload. Zonder die vlag rapporteert sha256sum de andere zeventien als ontbrekend en sluit af met een non-zero exitcode, wat lijkt op een mislukte verificatie terwijl er niets aan de hand is.

# 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 toont 0.71.0. Alleen frps gaat op de VPS. frpc gaat op de thuiscomputer. Door beide binaries overal te installeren, eindigen mensen er vaak mee dat ze per ongeluk een tunnelserver thuis draaien.

De VPS-configuratie: token, geforceerde TLS, loopback-listeners

Genereer eerst een token. Dit is de enige beveiliging tussen uw tunnel en iedereen die de VPS scant op open poorten.

# on the VPS
openssl rand -base64 32

Schrijf die waarde naar /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"

Vier van deze regels verzorgen de beveiliging; loop ze daarom één voor één na.

auth.token moet overeenkomen met auth.token op de client. Zonder deze instelling accepteert frps elke client die poort 7000 vindt, waarna die client alles kan publiceren via uw VPS en uw certificaat.

transport.tls.force = true weigert elke controleverbinding die geen TLS (transport layer security) gebruikt. Clients hebben TLS standaard ingeschakeld sinds v0.50.0, dus dit kost u in de praktijk niets en voorkomt dat een verouderde of zelfgebouwde client onversleuteld verbinding maakt zonder dat u dit merkt.

proxyBindAddr = "127.0.0.1" is de regel die in de meeste handleidingen ontbreekt, en het is de reden waarom deze opstelling veilig is om permanent te draaien. Het verplaatst elke listener die frp opent namens een proxy, zowel de HTTP vhost als elke remotePort waar een client om vraagt, naar de loopback-interface. Het internet kan deze listeners op geen enkele wijze bereiken. De enige publieke ingang is nginx op poort 443, die u zelf configureert en beheert.

webServer.addr = "127.0.0.1" houdt het dashboard weg van de publieke interface. Het dashboard is een volledig overzicht van uw privé-services en het bijbehorende verkeer, beveiligd door slechts één HTTP basic auth-wachtwoord; het hoort daarom niet thuis op 0.0.0.0.

Stel de rechten zo in dat het token niet leesbaar is voor andere gebruikers en controleer vervolgens de syntaxis voordat u iets opstart:

# 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

Een geldig bestand geeft de volgende uitvoer:

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

Een opmerking over het formaat die u veel tijd zal besparen. frp kiest de parser op basis van de bestandsextensie en herkent .toml, .yaml, .yml en .json. Oude .ini-bestanden laden nog steeds via een legacy-conversiepad, maar INI is verouderd en nieuwe opties worden uitsluitend voor TOML gedocumenteerd. Als een handleiding u een [common]-sectie en server_addr = x.x.x.x toont, is deze van vóór v0.52.0 en zullen de sleutelnamen niet overeenkomen met de binary die u zojuist heeft geïnstalleerd.

frps uitvoeren als een service zonder privileges

bindPort is 7000 en vhostHTTPPort is 8080. Beide poorten liggen boven 1024, waardoor frps nooit root-rechten nodig heeft en nooit CAP_NET_BIND_SERVICE vereist. Dit is de reden om de vhost niet op poort 80 te plaatsen en dit in plaats daarvan door Nginx te laten afhandelen.

Schrijf /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

Het logbestand hoort beide listeners te tonen, waarbij de adressen belangrijker zijn dan de poorten:

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

ProtectSystem=strict maakt het volledige bestandssysteem alleen-lezen voor deze service. frps staat dit toe omdat het logbestand standaard naar de standaarduitvoer wordt geschreven en journald dit opvangt. Als u log.to instelt op een bestandspad, zal de service falen om hiernaar te schrijven totdat u een bijbehorende ReadWritePaths=-regel toevoegt; laat de standaardinstelling daarom ongewijzigd.

Firewall: open één poort, geen bereik

# 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

Er zijn vier regels, waarvan er één uitsluitend bestaat voor de vernieuwing van certificaten. 22 is voor SSH. 80 leidt door naar 443 en beantwoordt de ACME-challenge (automatic certificate management environment). 443 bedient elke getunnelde applicatie. 7000 is de frp-controlepoort; dit is de enige poort die een client ooit hoeft te bereiken.

Handleidingen die adviseren om een bereik zoals sudo ufw allow 20000:30000/tcp te openen, beschrijven een ander ontwerp waarbij elke service zijn eigen publieke TCP-poort opeist. Dat is hier niet nodig, omdat al het verkeer binnenkomt op 443 en frp het doorstuurt op basis van de hostnaam. Mocht u later toch één echt publieke TCP-poort nodig hebben, zet proxyBindAddr dan terug naar 0.0.0.0 en voeg limieten toe zodat een client alleen poorten kan claimen die u heeft aangewezen:

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

De meeste providers hanteren ook een netwerkfirewall in het configuratiescherm, los van ufw op de server zelf. Een regel die correct lijkt in sudo ufw status maar toch een time-out geeft, wordt meestal daar geblokkeerd. De ufw-regels die een VPS daadwerkelijk nodig heeft doorloopt de default-deny-configuratie waarvan deze sectie uitgaat.

Beëindig HTTPS op de VPS met een geldig certificaat

Wijs een A-record voor home.example.com toe aan het publieke IP-adres van de VPS. Niet aan uw thuisadres. Uw thuisnetwerk heeft geen publiek adres waarheen verwezen kan worden; dat is precies het probleem dat u hier oplost.

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

Maak /etc/nginx/sites-available/home.example.com aan met eerst een eenvoudig blok voor poort 80, zodat certbot een bijpassende server_name heeft om mee te werken:

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 geeft nginx: configuration file /etc/nginx/nginx.conf test is successful weer wanneer de bestanden correct zijn geparseerd. Voer dit uit vóór elke herlaadactie. nginx blijft de oude configuratie uitvoeren als een herlaadactie mislukt; een foutieve wijziging lijkt daardoor op een wijziging die geen effect heeft gehad.

WebSocket-upgrades vereisen een map op het http-niveau. Plaats deze in /etc/nginx/conf.d/upgrade.conf:

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

Vervang nu het site-bestand door het definitieve exemplaar:

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; is hier niet optioneel. De HTTP vhost van frp routeert op basis van de Host-header en vergelijkt deze met de customDomains-lijst in de clientconfiguratie. Laat u deze header weg, dan verstuurt nginx Host: 127.0.0.1, vindt frp geen proxy voor die naam en krijgt uw bezoeker een kale 404-foutmelding van frp in plaats van de pagina van de applicatie. Elke regel van een nginx reverse proxy-blok uitgelegd behandelt de functie van de overige headers.

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

De dry run bewijst dat de vernieuwing over negentig dagen zal werken, wanneer u niet meekijkt. Hiervoor moet poort 80 bereikbaar zijn; dat is de reden waarom die ufw-regel aanwezig is.

De thuiszijde: frpc als een service zonder privileges

Installeer frpc op de thuiscomputer op exact dezelfde wijze als u frps heeft geïnstalleerd, met dezelfde versie en dezelfde checksum-stap. Maak vervolgens dezelfde frp-gebruiker en /etc/frp-directory aan. Schrijf /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"] }
]

De volgorde van de keys in dit bestand is van belang, en niet alleen voor de leesbaarheid. TOML wijst elke key na een tabel-header toe aan die tabel. Een instelling op het hoogste niveau, zoals serverAddr, die onder een proxy-tabel-header wordt geschreven, wordt stilletjes een proxy-instelling die door frp wordt genegeerd. Door de proxylijst als een inline array te schrijven, zoals hierboven getoond, vermijdt u deze valkuil: elke key op het hoogste niveau blijft ondubbelzinnig op het hoogste niveau staan.

type = "http" routeert deze proxy via de vhost-listener in plaats van een eigen publieke TCP-poort op te eisen; dit is de reden waarom de firewall op vier regels bleef staan. customDomains moet de hostnaam bevatten die nginx doorstuurt in de Host-header, dus het is home.example.com en nooit het IP-adres van de VPS.

loginFailExit = false is belangrijker dan het lijkt. De standaardwaarde is true, waardoor frpc afsluit als de eerste inlogpoging mislukt. Op een thuiscomputer die sneller opstart dan de internetverbinding tot stand komt, resulteert dit in een service die dood blijft totdat u het toevallig opmerkt. Stel dit in op false en frpc blijft het opnieuw proberen totdat de VPS antwoordt.

Schrijf /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

Een client die verbinding heeft gemaakt, logt een run id:

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

Open https://home.example.com in een browser en u zou de applicatie moeten zien die op 127.0.0.1:3000 thuis draait. Restart=always op de client is een bewuste keuze: thuisverbindingen verbreken wel eens, en de service moet automatisch herstellen zonder dat u hoeft in te grijpen.

Houd het dashboard buiten de publieke interface

Met webServer.addr = "127.0.0.1" reageert het dashboard alleen op de VPS zelf. Benader het vanaf uw laptop met een lokale forward in plaats van een poort open te stellen:

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

Open http://127.0.0.1:7500 en meld u aan met de webServer.user en webServer.password uit frps.toml. De pagina toont elke verbonden client en de verkeerstellers voor elke proxy; dit is de snelste manier om de vraag "is de thuis-box op dit moment wel verbonden" te beantwoorden. Sluit de ssh-sessie en het dashboard is direct weer onbereikbaar.

Wat de tunnel niet doet

Lees dit gedeelte twee keer, want hier gaat het vaak mis. De tunnel maakt een private service bereikbaar vanaf het publieke internet. Het authenticeert niet de personen die de service bereiken. Zodra https://home.example.com is opgelost, zullen scanners de service binnen enkele dagen vinden, ongeacht of u de naam aan iemand heeft doorgegeven. Certificate transparency logs publiceren elke hostnaam waarvoor u een certificaat aanvraagt; de naam is dus openbaar zodra certbot slaagt.

Alles wat u blootstelt, moet over eigen authenticatie beschikken. Als de applicatie een volwaardige login met rate limiting heeft, is dat prima. Als de login uit één gedeeld wachtwoord bestaat, of als er helemaal geen login is, plaats dan een authenticerende proxy voor de applicatie op de VPS. Een oauth2-proxy voor de applicatie plaatsen is de gebruikelijke oplossing; deze wordt tussen nginx en de frp vhost geplaatst zonder dat er aan beide uiteinden van de tunnel iets hoeft te veranderen.

Het token in frps.toml beveiligt de tunnel, niet de applicaties. Het voorkomt dat een vreemde een eigen proxy op uw VPS registreert. Het doet niets tegen een verzoek dat op poort 443 binnenkomt voor een hostnaam die u bewust heeft gepubliceerd.

Twee gewoontes zijn aan te raden. Roteer het token door beide bestanden te bewerken en beide services te herstarten, omdat het token niet uit zichzelf verloopt. Houd frp bovendien actueel: dit binaire bestand is uw publieke voordeur. De release notes van v0.71.0 vermelden een server panic die werd veroorzaakt door een ongeldige waarde vanuit een client; dit is het type bug dat u liever gepatcht ziet dan dat u erover moet nadenken.

Foutmodi en de bijbehorende meldingen

De client maakt geen verbinding. journalctl -u frpc herhaalt connect to server error:, gevolgd door een dial timeout. Er bereikt niets poort 7000. Controleer ufw op de VPS, controleer daarna de netwerkfirewall van de provider in het configuratiescherm en bevestig vervolgens dat de naam correct wordt omgezet met getent hosts vps.example.com.

Het token is onjuist. De client geeft dit expliciet aan:

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

Kopieer het token opnieuw. Een afsluitende newline, of een $ in een niet-gequote shell-string die naar niets expandeerde, is de oorzaak van bijna al deze problemen. Daarom hoort de openssl rand -base64 32-output tussen aanhalingstekens in het TOML-bestand te staan.

De tunnel is actief, maar de browser geeft een kale 404. frpc meldt een succesvolle login en het dashboard toont de proxy, maar de pagina geeft een 404 zonder de styling van de applicatie. Dit betekent dat frp geen proxy heeft voor deze Host-header. Test de vhost rechtstreeks op de VPS, waarbij u zowel nginx als TLS omzeilt:

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

Een 404-foutmelding bij dit commando betekent dat customDomains onjuist is. Elke andere code betekent dat het verzoek nooit de juiste Host van nginx heeft ontvangen.

502-foutmelding van nginx. nginx antwoordt wel, maar frp niet. sudo ss -lntp | grep 8080 op de VPS zou moeten tonen dat frps luistert op 127.0.0.1:8080. Een lege output betekent dat frps is gestopt, of dat vhostHTTPPort niet is ingesteld in frps.toml.

De applicatie ziet elke bezoeker als lokaal. Uw applicatie logt 127.0.0.1 voor elk verzoek. frp stelt X-Forwarded-For in en nginx voegt hieraan toe, dus het werkelijke clientadres staat in die header. Configureer de applicatie om deze te vertrouwen. Sla dit niet over als de applicatie rate limiting toepast op basis van IP-adres, omdat op dit moment elke bezoeker op internet in dezelfde categorie valt.

Lange verzoeken worden na 60 seconden afgebroken. Uploads of streaming-antwoorden stoppen halverwege. Dit is de standaard proxy_read_timeout van nginx, niet de tunnel. Het bovenstaande blok verhoogt deze naar 3600s. client_max_body_size is de bijbehorende limiet voor de uploadgrootte; de standaardwaarde van 1 MB wijst grotere bestanden af met een 413-foutmelding.

Alles werkt, maar valt uit na een herstart van de router. Restart=always in de frpc-unit plus loginFailExit = false dekt dit scenario af. Controleer dit met sudo systemctl is-enabled frpc, wat enabled moet weergeven.

FAQ

Hoe weet ik of ik achter CGNAT zit?

Vergelijk het WAN-adres op de beheerpagina van uw router met wat curl -4 -s https://ifconfig.me rapporteert vanuit hetzelfde netwerk. Als deze verschillen en het WAN-adres van de router binnen 100.64.0.0/10 valt, gebruikt uw ISP carrier-grade NAT. Dat bereik is RFC 6598 gedeelde adresruimte en bestaat specifiek voor dit doel. Sommige ISP's gebruiken 10.0.0.0/8 aan de WAN-zijde, wat hetzelfde betekent. Als de twee adressen overeenkomen, heeft u een publiek IP-adres: stuur de poort door en u bent klaar.

Heb ik een domeinnaam nodig voor een reverse tunnel?

Voor de hier beschreven HTTPS-configuratie wel. Een certificaat wordt uitgegeven voor een hostnaam en de HTTP vhost van frp routeert verzoeken op basis van de Host-header, dus beide uiteinden moeten een naam hebben waarover ze het eens zijn. Een pure TCP-proxy op een genummerd poortnummer werkt tegen het kale IP-adres van de VPS zonder domein, maar dan heeft u geen certificaat en geen hostnaam-routing, waardoor één publieke poort precies één service bedient.

Is het veilig om frp op een publieke VPS te draaien?

Het is veilig wanneer de control-poort het enige is dat wordt blootgesteld en deze is geauthenticeerd. Stel auth.token in op een willekeurige waarde aan beide kanten en transport.tls.force = true op de server. Stel vervolgens proxyBindAddr = "127.0.0.1" zo in dat niets wat frp opent voor een proxy direct naar het internet is gericht, en houd het dashboard op webServer.addr = "127.0.0.1", bereikbaar via een SSH local forward. Update het binaire bestand wanneer er nieuwe releases verschijnen, omdat dit het proces is dat op uw publieke adres luistert.

Waarom kan niemand mijn ssh -R doorgestuurde poort bereiken?

sshd wordt geleverd met GatewayPorts no, waardoor een remote forward alleen bindt aan de loopback-interface van de VPS. curl uitgevoerd op de VPS zelf werkt, maar curl vanaf elke andere locatie krijgt een time-out. De juiste oplossing is om de forward op loopback te laten staan en nginx op poort 443 ervoor te plaatsen. Het instellen van GatewayPorts yes publiceert een onbeveiligde poort zonder certificaat en zonder TLS, wat slechter is dan het probleem dat het oplost.

Moet ik frp gebruiken of een mesh VPN zoals Tailscale of WireGuard?

Gebruik een mesh VPN wanneer alleen uw eigen apparaten toegang nodig hebben, omdat er dan niets wordt gepubliceerd en er geen publieke hostnaam is die iemand kan scannen. Gebruik frp wanneer u een publiek HTTPS-adres nodig heeft dat elke browser kan laden, zoals een webhook-ontvanger of een pagina die u deelt met mensen die geen VPN-client zullen installeren. De twee kunnen prima naast elkaar bestaan op één VPS, op verschillende poorten, waarbij ze verschillende taken uitvoeren.

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