Frp (fast reverse proxy) is an open-source tunneling tool: a server with a public IP runs frps, machines behind NAT run frpc, and the two keep a persistent connection. Traffic hitting ports on the public server is forwarded through that connection to internal services. Typical use case: exposing a web service or SSH on your home machine to the outside world.

Configuration files use TOML (frps.toml / frpc.toml; the INI format is deprecated since v0.52+).

Server side (frps)

Unpack the frp release on your public server and edit frps.toml:

bindPort = 7000            # port frpc connects to

auth.token = "a long random secret"   # client must use the same value

webServer.addr = "0.0.0.0"  # built-in dashboard
webServer.port = 7500
webServer.user = "admin"
webServer.password = "dashboard password"

vhostHTTPPort = 8080        # entry port for HTTP proxies, enable as needed

Run it under systemd, /etc/systemd/system/frps.service:

[Unit]
Description = frp server
After = network.target

[Service]
Type = simple
ExecStart = /opt/frp/frps -c /opt/frp/frps.toml
Restart = on-failure
RestartSec = 5

[Install]
WantedBy = multi-user.target
sudo systemctl enable --now frps

Remember to open ports 7000 (frpc connection), 7500 (dashboard), and any proxy ports in your cloud provider’s security group — this is the most common cause of “it doesn’t connect”.

Client side (frpc)

On the internal machine, edit frpc.toml:

serverAddr = "server public IP"
serverPort = 7000
auth.token = "same secret as the server"

# Plain TCP: map internal port 22 to server port 6022
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6022

# HTTP site: served on vhostHTTPPort, routed by domain
[[proxies]]
name = "web"
type = "http"
localPort = 3000
customDomains = ["app.example.com"]

Start it:

frpc -c frpc.toml

Now ssh -p 6022 user@server-ip reaches the internal machine, and http://app.example.com:8080 opens internal port 3000 in a browser.

On Linux, run the client under systemd too (same unit file as above with frps replaced by frpc). On Windows, install with winget install fatedier.frp and schedule frpc -c frpc.toml to run at startup via Task Scheduler.

Troubleshooting

  • login to server failed: token in login doesn’t match token in configuration — the auth.token values differ, or the client is hitting a different frps instance.
  • Port unreachable — check whether the proxy registered in frps.log first, then the cloud security group and system firewall (ufw / firewalld).
  • HTTP proxy returns 404 — the customDomains must resolve to the server IP, and requests must hit vhostHTTPPort, not remotePort.
  • Need HTTPS — put nginx in front of frps for TLS termination, or use frp’s https2http plugin.