FRP User Guide: SSH Tunneling Through Public Server
Introduction#
FRP (Fast Reverse Proxy) is a high-performance reverse proxy application that helps you expose a local server behind a NAT or firewall to the internet. This guide focuses on using FRP to create SSH tunnels, allowing you to securely access your local servers through a public IP server.
What is FRP?#
FRP consists of two main components:
- frps (FRP Server): Runs on a server with a public IP address
- frpc (FRP Client): Runs on your local machine behind NAT/firewall
How FRP Works for SSH Tunneling#
-
Traditional SSH Access Problem
Internet → [Firewall/NAT] → Local Server (192.168.1.100:22)
When your local server is behind a NAT or firewall, it’s not directly accessible from the internet.
-
FRP Solution
Internet → Public Server (frps) → Tunnel → Local Server (frpc) → Local SSH (192.168.1.100:22)
FRP creates a secure tunnel between your local server and the public server, allowing external connections to reach your local services.
How SSH Tunneling Works with FRP#
Step-by-Step Process#
- Client Connection: External user connects to
public_server:6000
- FRP Server: Receives connection and forwards it through the tunnel
- FRP Client: Receives forwarded connection and routes to
127.0.0.1:22
- Local SSH: Handles the SSH connection normally
Network Flow Diagram#
External User
↓ SSH to public_server:6000
Public Server (frps)
↓ Tunnel (port 7000)
Local Server (frpc)
↓ Forward to 127.0.0.1:22
Local SSH Service
SSH Tunneling Usage#
Here is the SSH Tunneling Example, actually FRP can be used for more than just SSH:
- Web Services: Expose local web applications
- Database Access: Secure database connections
- File Sharing: Access local file servers
- Development: Share local development servers
for more usage, pls see details
Prerequisites#
# Download FRP from the latest release page, get the binary and default config files
wget https://github.com/fatedier/frp/releases/download/v0.65.0/frp_xxx.tar.gz
tar -xzf frp_xxx.tar.gz
# Move the binaries and configuration files accordingly
sudo mv frp_xxx/frps /usr/local/bin/
sudo mv frp_xxx/frps.toml /etc/systmd/system/
sudo mv frp_xxx/frpc /usr/local/bin/
sudo mv frp_xxx/frpc.toml /etc/systmd/system/
update the config files as below
Public Server With Static IP#
-
frps.toml (on public server)
# FRP server listening port bindPort = 7000 # Dashboard (optional) webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "admin" webServer.password = "your_password" # Authentication token (recommended) auth.token = "your_secure_token_here" # Logging log.to = "/var/log/frps.log" log.level = "info" log.maxDays = 3
-
systemd service file for frps (on public server)
[Unit] Description=FRP Server After=network.target [Service] Type=simple User=frp ExecStart=/usr/local/frps -c /etc/systemd/system/frps.toml Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
Private Server Behind NAT/Firewall#
-
frpc.toml (on local server)
# Public server address and port serverAddr = "your_public_server_ip" serverPort = 7000 # Authentication token (must match server) auth.token = "your_secure_token_here" # SSH tunnel configuration [[proxies]] name = "ssh" type = "tcp" localIP = "127.0.0.1" localPort = 22 remotePort = 6000
-
systemd service file for frpc (on local server)
[Unit] Description=FRP Client After=network.target [Service] Type=simple User=frp ExecStart=/usr/local/frpc -c /etc/systemd/system/frpc.toml Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
FRP’s Design Philosophy#
Client-Driven Configuration Model#
FRP follows a client-driven configuration philosophy where the client (frpc) tells the server (frps) what services it wants to expose and on which ports. This design choice has several important implications:
Why remotePort
is in frpc.toml, not frps.toml#
This is one of the most common points of confusion for new FRP users. Here’s why:
- Dynamic Service Registration: Services are registered dynamically when clients connect, not pre-configured on the server
- Multiple Client Support: Different clients can request different ports without server pre-configuration
- Client Control: Each client controls what it exposes and on which ports
- Server Simplicity: The server only needs to know the control port (7000), not all service ports
Port Separation Philosophy#
FRP clearly separates three types of ports:
serverPort
(7000): Communication between frps and frpc (control channel)remotePort
(6000): External traffic to the exposed service (data channel)localPort
(22): Local service on the client machine
As stated in the official documentation:
“The
localPort
(listened on the client) andremotePort
(exposed on the server) are used for traffic going in and out of the frp system, while theserverPort
is used for communication between frps and frpc.”
Benefits of This Design#
- Flexibility: Clients can expose multiple services on different ports
- Simplicity: Server configuration remains minimal
- Scalability: Easy to add new clients without server reconfiguration
- Dynamic Allocation: Ports are allocated when clients connect
- Client Autonomy: Each client manages its own service exposure
Example: Multiple Services from One Client#
# frpc.toml - One client exposing multiple services
serverAddr = "x.x.x.x"
serverPort = 7000
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
[[proxies]]
name = "web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 6001
[[proxies]]
name = "mysql"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3306
remotePort = 6002
The server automatically handles all these port allocations when the client connects, without any server-side configuration changes.