Túnel inverso con frp para evitar CGNAT usando un VPS
CGNAT impide abrir puertos sin IP pública. Configura frp en un VPS económico, inicia el túnel desde casa y termina HTTPS con un certificado real.
Por qué el reenvío de puertos no funciona detrás de CGNAT
Detrás de CGNAT (traducción de direcciones de red a escala de operador), la dirección WAN de tu router se comparte con otros abonados. Por tanto, no tienes una IP pública asignada ni un puerto que puedas reenviar. Un túnel inverso resuelve el problema: un VPS económico mantiene la IP pública, el equipo de tu casa inicia una conexión saliente al VPS y las peticiones entrantes regresan por la conexión que el equipo doméstico ya abrió. Conservas el hardware que ya tienes. Alquilas lo único que tu ISP no te ofrece: una dirección enrutable.
Todos los comandos siguientes indican en qué equipo deben ejecutarse. Necesitas dos equipos: el VPS con una IP pública y el equipo doméstico que ejecuta el servicio al que quieres acceder.
Cómo saber si realmente está detrás de CGNAT
Abra la página de administración del router y consulte la dirección WAN que muestra. Después, pregunte en Internet qué dirección detecta.
# on the home box
curl -4 -s https://ifconfig.me; echoSi las dos direcciones coinciden, tiene una IP pública y no necesita nada de esto. Redirija el puerto y deje de leer. Si la dirección WAN del router está dentro de 100.64.0.0/10, está detrás de CGNAT. Ese bloque es un espacio de direcciones compartido definido por RFC 6598 y reservado precisamente para este uso. Algunos ISP asignan 10.0.0.0/8 en el lado WAN; la situación es la misma, aunque tenga otra etiqueta.
Compruebe una cosa antes de alquilar nada. Muchos ISP que usan CGNAT asignan un prefijo IPv6 real. Si su equipo doméstico tiene una dirección IPv6 global, puede abrir el firewall en esa dirección y omitir el túnel por completo. Dejará de funcionar en cuanto un visitante use una red que solo admita IPv4, por lo que la mayoría de las personas termina aquí de todos modos.
Cómo funciona un túnel inverso en un VPS, iniciado desde dentro
CGNAT y los routers domésticos normales bloquean las conexiones entrantes no solicitadas. Los firewalls corporativos también. Ninguno bloquea las conexiones salientes, porque eso es lo que hacen durante todo el día los navegadores y los clientes de actualización. Cuando un dispositivo NAT detecta una conexión TCP saliente, crea un mapeo para ella y permite el tráfico de respuesta correspondiente. Ningún sistema externo puede iniciar una conexión con el equipo de su casa. Por tanto, el equipo doméstico la inicia y el túnel transporta el tráfico de vuelta por esa misma conexión, en la dirección contraria.
Ese es todo el mecanismo. El equipo doméstico se conecta al VPS a través de un puerto y mantiene abierta la conexión. El VPS acepta las solicitudes públicas y las envía por esa conexión existente. Nunca se intenta acceder a la dirección IP doméstica, por lo que no es necesario que sea accesible.
De aquí se derivan dos consecuencias, y ambas son útiles. El registro DNS apunta al VPS, nunca a su casa. Además, su dirección pública pasa a ser la del VPS. Por tanto, cualquier información que un observador obtenga mediante una consulta de IP corresponde a un servidor alquilado y no a su conexión doméstica.
Tres formas de montarlo
ssh -R: ya está instalado en ambos extremos y es adecuado para un único servicio o una demostración temporal. No ofrece un panel ni una lógica de reconexión que resulte útil.- frp: un servidor pequeño escrito en Go (
frps) y un cliente compatible (frpc). Es adecuado para una configuración permanente con varios servicios detrás de un mismo nombre de host. Esta es la opción principal de la guía. - Una VPN de malla: Tailscale o un servidor WireGuard administrado por usted. Es adecuada cuando quiere que sus propios dispositivos se comuniquen de forma privada, en lugar de publicar algo en Internet.
Elija la malla si su objetivo es acceder de forma privada desde dispositivos bajo su control. Tailscale Serve y Funnel explica cómo publicar servicios fuera de una tailnet, y una VPN WireGuard autohospedada en el mismo VPS ofrece la misma arquitectura sin que haya un servidor de coordinación de terceros en la ruta. Lea una de esas secciones y omita el resto de esta página. Todo lo que sigue presupone que quiere un nombre de host HTTPS público que cualquiera pueda cargar.
La versión rápida: ssh -R para un servicio
Suponga que el equipo de casa ejecuta una aplicación en 127.0.0.1:3000 y que ya tiene acceso 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 indica al sshd del VPS que escuche en su propio 127.0.0.1:8080 y envíe todo lo que llegue allí a 127.0.0.1:3000 en el equipo de casa. -N significa que no debe iniciar un shell. Las dos opciones ServerAlive hacen que ssh detecte un enlace caído en unos noventa segundos, en lugar de quedarse bloqueado en una conexión que ya no existe.
Ahora viene la parte que confunde a todo el mundo. Ese listener está en loopback, por lo que curl http://vps.example.com:8080 falla desde cualquier otro lugar. sshd se distribuye con GatewayPorts no, lo que significa que un reenvío remoto se enlaza sólo a la interfaz de loopback. No lo corrija estableciendo GatewayPorts yes. Mantenga el reenvío en loopback y coloque nginx delante, igual que en la configuración de frp que se muestra más abajo, de modo que el puerto público sea 443 con un certificado y el puerto del túnel nunca quede expuesto a Internet. Si no tiene claro qué está escuchando actualmente y en qué interfaz, un recorrido breve por los puertos y listeners de Linux merece diez minutos.
Si el puerto ya está ocupado en el VPS, ssh muestra esto, y ExitOnForwardFailure=yes hace que abandone en lugar de conectarse sin un túnel operativo:
Warning: remote port forwarding failed for listen port 8080La causa habitual es una sesión anterior que terminó sin que sshd lo detectara. Establezca ClientAliveInterval 30 y ClientAliveCountMax 3 en /etc/ssh/sshd_config del VPS para que las sesiones inactivas se eliminen y liberen el puerto. Ejecute todo el comando en una unidad de systemd con Restart=always y una clave dedicada, o use autossh. Para cualquier configuración con más de un servicio, deténgase aquí y use frp.
Instalar frp en el VPS y fijar una etiqueta
frp se distribuye como un binario estático de Go y no está disponible en los repositorios de Ubuntu ni Debian, por lo que debe descargar una versión y verificarla manualmente. Fije la versión. El formato de configuración cambió en v0.52.0 y los nombres de las opciones han cambiado desde entonces. Por eso, un tutorial antiguo puede indicarle claves que su binario no reconoce. Esta guía usa v0.71.0, publicada el 14 de agosto de 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.txtsha256sum debe mostrar exactamente una línea:
frp_0.71.0_linux_amd64.tar.gz: OK--ignore-missing es necesario porque el archivo de sumas de comprobación incluye los dieciocho archivos de la versión y usted ha descargado uno de ellos. Sin esa opción, sha256sum informa de que faltan los otros diecisiete y termina con un código distinto de cero. Esto parece una verificación fallida aunque no haya ningún 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 --versionfrps --version muestra 0.71.0. Sólo frps se instala en el VPS. frpc se instala en el equipo doméstico. Instalar ambos binarios en todos los equipos es una forma habitual de terminar ejecutando accidentalmente un servidor de túnel en casa.
La configuración de VPS: token, TLS obligatorio y listeners en loopback
Genere primero un token. Es lo único que separa su túnel de cualquiera que haga un escaneo de puertos en el VPS.
# on the VPS
openssl rand -base64 32Escriba ese valor en /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"Cuatro de esas líneas realizan el trabajo de seguridad. Revise cada una por separado.
auth.token debe coincidir con auth.token en el cliente. Sin esta coincidencia, frps acepta cualquier cliente que encuentre el puerto 7000. Ese cliente puede publicar lo que quiera a través del VPS y de su certificado.
transport.tls.force = true rechaza cualquier conexión de control que no use TLS (transport layer security). Los clientes tienen TLS habilitado de forma predeterminada desde v0.50.0. En la práctica, esto no le supone ningún coste y cierra el caso en que un cliente antiguo o creado manualmente se conecte sin cifrado sin avisarle.
proxyBindAddr = "127.0.0.1" es la línea que la mayoría de las guías omite. Por eso esta configuración se puede dejar activa de forma segura. Mueve todos los listeners que frp abre en nombre de un proxy, tanto el vhost HTTP como cualquier remotePort que solicite un cliente, a la interfaz de loopback. Internet no puede acceder a esos listeners. La única puerta pública es nginx en 443, que usted configura y controla.
webServer.addr = "127.0.0.1" mantiene el dashboard fuera de la interfaz pública. El dashboard ofrece un mapa completo de sus servicios privados y de su tráfico, protegido por una única contraseña de autenticación básica HTTP. Por tanto, no debe estar en 0.0.0.0.
Establezca el propietario para que el token no sea legible por todos los usuarios. Después, compruebe la sintaxis antes de iniciar nada:
# 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.tomlUn archivo válido muestra:
frps: the configuration file /etc/frp/frps.toml syntax is okUna nota sobre el formato que le ahorrará una hora. frp elige el parser a partir de la extensión del archivo y reconoce .toml, .yaml, .yml y .json. Los archivos .ini antiguos todavía se cargan mediante una ruta de conversión heredada, pero INI está obsoleto y las opciones nuevas sólo están documentadas para TOML. Si una guía muestra una sección [common] y server_addr = x.x.x.x, es anterior a v0.52.0 y sus nombres de clave no coincidirán con los del binario que acaba de instalar.
Ejecutar frps como un servicio sin privilegios
bindPort es 7000 y vhostHTTPPort es 8080. Ambos están por encima de 1024, por lo que frps nunca necesita root ni CAP_NET_BIND_SERVICE. Por eso no se debe poner el vhost en el puerto 80 y dejar que nginx lo gestione.
Escriba /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-pagerEl registro debe mostrar ambos escuchas. Las direcciones son más importantes que los puertos:
frps tcp listen on 0.0.0.0:7000
http service listen on 127.0.0.1:8080ProtectSystem=strict hace que todo el sistema de archivos sea de sólo lectura para este servicio. frps lo admite porque, de forma predeterminada, envía el registro a la salida estándar y journald lo captura. Si establece log.to en una ruta de archivo, el servicio no podrá escribir en ella hasta que añada una línea ReadWritePaths= equivalente. Por tanto, mantenga el valor predeterminado.
Firewall: abrir un puerto, no un rango
# 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 numberedCuatro reglas, y una de ellas sólo existe para la renovación de certificados. 22 es SSH. 80 redirige a 443 y responde al desafío ACME (automatic certificate management environment, entorno de gestión automática de certificados). 443 sirve todas las aplicaciones tunelizadas. 7000 es el puerto de control de frp y es el único puerto al que un cliente necesita conectarse.
Las guías que indican abrir un rango como sudo ufw allow 20000:30000/tcp describen el otro diseño, en el que cada servicio reclama su propio puerto TCP público. Aquí no es necesario, porque todo llega por 443 y frp lo enruta según el nombre de host. Si más adelante necesita un puerto TCP realmente público, cambie proxyBindAddr por 0.0.0.0 y añada límites para que un cliente sólo pueda reclamar los puertos que haya especificado:
allowPorts = [
{ start = 20000, end = 20010 }
]
maxPortsPerClient = 5La mayoría de los proveedores también ejecuta un firewall de red en el panel de control, independiente de ufw en el servidor. Una regla que parece correcta en sudo ufw status y aun así agota el tiempo de espera suele estar bloqueada allí. Reglas de ufw que necesita realmente un VPS explica la configuración de denegación predeterminada que asume esta sección.
Terminar HTTPS en el VPS con un certificado válido
Apunte un registro A de home.example.com a la IP pública del VPS. No a la de su casa. Su casa no tiene una dirección accesible para ese fin, que es precisamente el problema que está resolviendo.
# on the VPS
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginxCree /etc/nginx/sites-available/home.example.com con un bloque básico para el puerto 80. Así, certbot tendrá un server_name coincidente con el que trabajar:
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.comnginx -t muestra nginx: configuration file /etc/nginx/nginx.conf test is successful cuando los archivos se analizan correctamente. Ejecútelo antes de cada recarga. nginx mantiene activa la configuración anterior cuando falla una recarga, por lo que una modificación incorrecta puede parecer una modificación que no tuvo ningún efecto.
Las actualizaciones de WebSocket necesitan un map en el nivel http. Colóquelo en /etc/nginx/conf.d/upgrade.conf:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}Ahora sustituya el archivo del sitio por el archivo 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; es obligatorio en este caso. frp enruta el vhost HTTP mediante la cabecera Host y la compara con la lista customDomains de la configuración del cliente. Si omite esa cabecera, nginx envía Host: 127.0.0.1, frp no encuentra ningún proxy para ese nombre y el visitante recibe un 404 sin formato de frp en lugar de la página de la aplicación. Explicación de cada línea de un bloque de proxy inverso de nginx describe la función de las demás cabeceras.
# on the VPS
sudo nginx -t && sudo systemctl reload nginx
sudo certbot renew --dry-runLa ejecución de prueba confirma que la renovación funcionará dentro de noventa días, cuando usted no estará supervisándola. Necesita que el puerto 80 sea accesible. Por eso existe esa regla de ufw.
El lado doméstico: frpc como servicio sin privilegios
Instale frpc en el equipo doméstico exactamente como instaló frps, con la misma versión y el mismo paso de comprobación del checksum. Después, cree el mismo usuario frp y el mismo directorio /etc/frp. Escriba /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"] }
]El orden de las claves es importante en este archivo, y no por motivos de estilo. TOML asigna cada clave situada después de una cabecera de tabla a esa tabla. Por tanto, un ajuste de nivel superior como serverAddr escrito debajo de una cabecera de tabla de proxy se convierte silenciosamente en un ajuste del proxy que frp ignora. Al escribir la lista de proxies como una matriz en línea, tal como aparece arriba, se evita el problema: todas las claves de nivel superior permanecen claramente en ese nivel.
type = "http" encamina este proxy a través del listener de vhost en lugar de reservar su propio puerto TCP público. Por eso el firewall se mantuvo con cuatro reglas. customDomains debe contener el nombre de host que nginx reenvía en la cabecera Host, por lo que es home.example.com y nunca la dirección IP del VPS.
loginFailExit = false es más importante de lo que parece. El valor predeterminado es true, que hace que frpc termine si falla su primer intento de inicio de sesión. En un equipo doméstico que termina de arrancar antes de que esté disponible el enlace del ISP, el servicio queda detenido hasta que alguien lo detecta. Establézcalo en false para que frpc siga reintentando hasta que el VPS responda.
Escriba /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-pagerUn cliente que se ha conectado registra un ID de ejecución:
login to server success, get run id [3a1f9c2b7d4e5f60]Abra https://home.example.com en un navegador. Debería obtener la aplicación que se ejecuta en 127.0.0.1:3000 en casa. Restart=always en el cliente es intencionado: las conexiones domésticas se interrumpen y el servicio debe recuperarse sin intervención manual.
Mantenga el panel fuera de la interfaz pública
Con webServer.addr = "127.0.0.1", el panel sólo responde en el propio VPS. Acceda desde su portátil mediante un reenvío local en lugar de abrir un puerto:
# on your laptop
ssh -N -L 7500:127.0.0.1:7500 you@vps.example.comAbra http://127.0.0.1:7500 e inicie sesión con webServer.user y webServer.password de frps.toml. La página muestra todos los clientes conectados y los contadores de tráfico de cada proxy. Es la forma más rápida de comprobar si el equipo doméstico está conectado en ese momento. Cierre la sesión de SSH y el panel volverá a quedar inaccesible.
Lo que no hace el túnel
Lea esta parte dos veces, porque es donde se producen los problemas más graves. El túnel permite acceder a un servicio privado desde Internet público. No autentica a las personas que acceden a él. Cuando https://home.example.com se resuelva, los escáneres lo encontrarán en cuestión de días, tanto si informó a alguien del nombre como si no. Los registros de transparencia de certificados publican todos los nombres de host para los que emite un certificado, por lo que el nombre es público en cuanto certbot termina correctamente.
Todo lo que exponga debe tener su propia autenticación. Si la aplicación tiene un inicio de sesión real con limitación de tasa, está bien. Si usa una sola contraseña compartida o no tiene ningún inicio de sesión, coloque delante un proxy con autenticación en el VPS. Un oauth2-proxy delante de la aplicación es la opción habitual. Se coloca entre nginx y el vhost de frp sin cambiar ninguno de los extremos del túnel.
El token de frps.toml protege el túnel, no las aplicaciones. Impide que un desconocido registre su propio proxy en el VPS. No hace nada con una petición que llega al puerto 443 para un nombre de host que publicó deliberadamente.
Conviene mantener dos hábitos. Rote el token editando ambos archivos y reiniciando ambos servicios, porque no caduca por sí solo. Mantenga también frp actualizado: este binario es la puerta de entrada pública, y las notas de v0.71.0 indican un panic del servidor provocado por un valor incorrecto enviado por un cliente. Ese tipo de error debe corregirse con una actualización, no analizarse para decidir si puede ignorarse.
Modos de fallo y mensajes que verá
El cliente nunca se conecta. journalctl -u frpc repite connect to server error: y después se agota el tiempo de espera de conexión. No llega nada al puerto 7000. Compruebe ufw en el VPS, después el firewall de red del proveedor en el panel de control y, por último, confirme que el nombre se resuelve con getent hosts vps.example.com.
El token es incorrecto. El cliente lo indica claramente:
login to the server failed: token in login doesn't match token from configurationCopie el token de nuevo. Un salto de línea final o un $ en una cadena de shell sin comillas que se haya expandido a vacío provoca casi todos estos casos. Por eso la salida de openssl rand -base64 32 debe estar entre comillas en el archivo TOML.
El túnel está activo, pero el navegador recibe un 404 vacío. frpc registró un inicio de sesión correcto y el panel muestra el proxy, pero la página devuelve 404 sin ningún estilo de la aplicación. Esto significa que frp no tiene ningún proxy para esta cabecera Host. Pruebe el vhost directamente en el VPS, sin pasar por nginx ni 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 de ese comando significa que customDomains es incorrecto. Cualquier otro código significa que la petición no recibió el Host correcto de nginx.
502 de nginx. nginx responde y frp no. sudo ss -lntp | grep 8080 en el VPS debería mostrar que frps está escuchando en 127.0.0.1:8080. Una salida vacía significa que frps está detenido o que vhostHTTPPort no está definido en frps.toml.
La aplicación considera locales a todos los visitantes. Los registros de la aplicación muestran 127.0.0.1 en todas las peticiones. frp establece X-Forwarded-For y nginx lo añade, por lo que la dirección real del cliente está en esa cabecera. Configure la aplicación para confiar en ella. No omita este paso si la aplicación limita la tasa por dirección IP, porque en este momento todos los visitantes de Internet comparten el mismo límite.
Las peticiones largas se interrumpen a los 60 segundos. Las cargas o las respuestas de streaming se detienen a mitad. Ese es el valor predeterminado de nginx para proxy_read_timeout, no un problema del túnel. El bloque anterior lo aumenta a 3600s. client_max_body_size es el límite equivalente para el tamaño de carga y su valor predeterminado de 1 MB rechaza los cuerpos más grandes con un 413.
Todo funciona y después deja de funcionar al reiniciar el router. Restart=always en la unidad de frpc, junto con loginFailExit = false, cubre este caso. Confírmelo con sudo systemctl is-enabled frpc, que debe mostrar enabled.
FAQ
¿Cómo sé si estoy detrás de CGNAT?
Compare la dirección WAN que muestra la página de administración del router con la dirección que curl -4 -s https://ifconfig.me informa desde la misma red. Si son distintas y la dirección WAN del router está dentro de 100.64.0.0/10, su ISP utiliza NAT de nivel de operador. Ese rango es un espacio de direcciones compartido definido por RFC 6598 y existe para este fin. Algunos ISP utilizan 10.0.0.0/8 en el lado WAN, lo que significa lo mismo. Si las dos direcciones coinciden, tiene una IP pública: reenvíe el puerto y habrá terminado.
¿Necesito un nombre de dominio para un túnel inverso?
Para la configuración HTTPS descrita aquí, sí. Un certificado se emite para un nombre de host, y el vhost HTTP de frp enruta las solicitudes según la cabecera Host, por lo que ambos extremos necesitan un nombre en común. Un proxy TCP directo en un puerto numerado funciona con la IP pública del VPS sin ningún dominio, pero entonces no tiene certificado ni enrutamiento por nombre de host. Un solo puerto público sirve exactamente a un servicio.
¿Es seguro ejecutar frp en un VPS público?
Es seguro cuando el puerto de control es el único expuesto y está autenticado. Establezca auth.token con un valor aleatorio en ambos extremos y configure transport.tls.force = true en el servidor. Después, establezca proxyBindAddr = "127.0.0.1" para que ninguno de los elementos que frp abre para un proxy quede expuesto a Internet, y mantenga el panel en webServer.addr = "127.0.0.1", accesible mediante un reenvío local de SSH. Actualice el binario cuando se publiquen nuevas versiones, porque es el proceso que escucha en su dirección pública.
¿Por qué nadie puede acceder a mi puerto reenviado ssh -R?
sshd se distribuye con GatewayPorts no, por lo que un reenvío remoto sólo se enlaza a la interfaz de loopback del VPS. curl ejecutado directamente en el VPS funciona, pero curl ejecutado desde cualquier otro lugar agota el tiempo de espera. La solución correcta es mantener el reenvío en loopback y colocar nginx delante, escuchando en 443. Configurar GatewayPorts yes publica un puerto sin certificado ni TLS, lo que es peor que el problema que pretende resolver.
¿Debo usar frp o una VPN de malla como Tailscale o WireGuard?
Use una VPN de malla cuando sólo sus propios dispositivos necesiten acceso, porque así no se publica nada ni existe un nombre de host público que cualquiera pueda analizar. Use frp cuando necesite una dirección HTTPS pública que cualquier navegador pueda cargar, por ejemplo, para recibir webhooks o publicar una página que compartirán personas que no instalarán un cliente VPN. Ambas opciones pueden coexistir sin problemas en un mismo VPS, en puertos distintos y con funciones diferentes.