This note describes the process to use FRP as a self-hosted reverse proxy.
The goal is to allow connections to a firewalled server by using a "middleman" server. I've used this to access my home server when away from home by proxying requests through a public VPS.
The process has two parts to it, the "client" and the "server" (to make things confusing, both are servers in this scenario):
- The server acts as the "man in the middle"
- The client acts as the final destination for incoming requests
- It is the "client" of the "man in the middle" server
Install
- Download binary
wget https://github.com/fatedier/frp/releases/download/v0.42.0/frp_0.42.0_linux_amd64.tar.gz
Change the version as necessary
- Extract & install
tar -xf frp_0.42.0_linux_amd64.tar.gz
mv frp_0.42.0_linux_amd64.tar.gz/frpc frp_0.42.0_linux_amd64.tar.gz/frps /usr/sbin/
Make sure to change file paths as necessary if a different version was downloaded
Setup server
The server acts as a "man in the middle" for connections going to the "protected" server.
First setup the frps.ini
file to something like this:
[common]
bind_port = 80
The bind_port
is the port the client will connect to. It serves as a protocol port. In this case I am using port 80 to avoid it being blocked. But any port will do.
Then run the frp
server with the following command:
frps -c frps.ini
Setup client
The client now has to be configured to connect to the server and setup routes.
Create a frpc.ini
file with the following content:
[common]
server_addr = 123.123.123.123
server_port = 80
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 443
Make sure to change the server IP as necessary.
In the [common]
area, define the server IP and the protocol port to use (bind_port
in the frps.ini
file).
The [ssh]
section defines as specific "route" that the client is exposing via the server.
- The
type
defines the connection type (e.g. tcp
, udp
, etc) - The
local_ip
is usually 127.0.0.1
, but could be something else to forward the connection to another system on the network - The
local_port
is the port any incoming connections get sent to - The
remote_port
is the port that the server will expose for this connection (make sure the port you choose is not blocked by the server firewall)- In this case I am using port 443 to avoid it being blocked
With the above config, I can start the client with the following command:
./frpc -c frpc.ini
Token Authentication
docs
Setting up tokens adds an extra layer of protection by only allowing "clients" with the correct token to connect to a given "server".This does not protect user connections that are forwarded to the "protected" server, only the link between the FRP "client" and "server".
To enable token-based authentication add the following properties to both the server and the client:
[common]
authentication_method = token
token = 123abc
Make sure to change the token value and ensure it matches on the server & client.
Use Proxy
Once that is up and running, I can SSH into the "protected" server by running:
ssh <username>@<server ip> -p 443
The connection going to port 443 on the "server" gets forwarded down the frpc
connection to the "client". It then gets forwarded on to port 22 on the "client" (i.e. the protected server).
SSH Tunnel
If you have SSH access to the FRP client machine (i.e. the server you actually want to connect to), you only really need to expose one port with FRP. The rest can be exposed using an SSH tunnel.
For example, to expose port 8080
:
ssh <username>@<server ip> -p 443 -L 8080:localhost:8080