Implement intranet penetration using frp
frp
is a fast reverse proxy to expose a local server behind a network address translation (NAT) or firewall to the internet. This article introduces how to use frp
to establish a SSH connection with a server that does not have a public IP address, even if two servers are not in same local area network (LAN).
What is intranet penetration?
The technology of communication between hosts in different LANs via the Internet is called intranet penetration. The figure below illustrates that when Host A communicates with Host B, which belongs to a different LAN, Host A cannot directly access Host B's private IP address of 110.111.1.2. To enable communication between two hosts, port mapping must be established between the public network IP address 15.16.17.2 in LAN ② and Host B's private IP address. This allows Host A to automatically forward IP datagrams to Host B by sending them to the destination address of 15.16.17.2.
However, public IP addresses are a limited resource, and you may need to get assigned a static public IP address from the ISP by applying. Therefore, this article uses frp
to achieve intranet penetration, to make the local server be accessible without a public IP address.
Server configuration
First, download the corresponding release of frp
in its Github repository. After unzipping, you will get two types of files. One is frps
, which s
means server; one is frpc
, which c
indicates client. frp.ini
is the config file, and the description of parameters are shown in frp_full.ini
.
# download
wget https://github.com/fatedier/frp/releases/download/v0.46.0/frp_0.46.0_linux_amd64.tar.gz
# unzip
tar -zxvf frp_0.46.0_linux_amd64.tar.gz
mv frp_0.46.0_linux_amd64 frp && cd frp
# (optional) remove client files
rm frpc*
Then you can start editing the config file frps.ini
. Actually, you only need to configure the port, but I add the token for security.
[common]
bind_port = PORT
# auth token
token = TOKEN_VALUE
Add a daemon by performing sudo vim /lib/systemd/system/frps.service
. The USERNAME
and PATH
should be changed based on your cases.
[Unit]
Description=Frp Server Service
After=network.target
[Service]
Type=simple
User=USERNAME
Restart=on-failure
RestartSec=5s
ExecStart=PATH/frps -c PATH/frps.ini
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
# start and enable service
sudo systemctl start frps.service
sudo systemctl enable frps.service
Client configuration
The configuration in client side is similar with server side.
# download
wget https://github.com/fatedier/frp/releases/download/v0.46.0/frp_0.46.0_linux_amd64.tar.gz
# unzip
tar -zxvf frp_0.46.0_linux_amd64.tar.gz
mv frp_0.46.0_linux_amd64 frp && cd frp
# (optional) remove server files
rm frps*
Edit frpc.ini
by filling in the values of the server's IP, port, and token. Then change REMOTE_PORT
to your SSH connection port.
[common]
server_addr = SERVER_IP
server_port = PORT
token = TOKEN_VALUE
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = REMOTE_PORT
Add a daemon using sudo vim /lib/systemd/system/frps.service
.
[Unit]
Description=Frp Client Service
After=network.target
[Service]
Type=simple
User=USERNAME
Restart=on-failure
RestartSec=5s
ExecStart=PATH/frpc -c PATH/frpc.ini
ExecReload=PATH/frpc reload -c PATH/frpc.ini
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
# start and enable service
sudo systemctl start frps.service
sudo systemctl enable frps.service
Now the client can be operated by connecting the predefined port (i.e., REMOTE_PORT
) of the server's IP using ssh
.
By default, communication between server and client through frp
is in plaintext. While this is not a problem for SSH, frp
can also be used to enable users to access services on a local server via TCP forwarding, resulting in insecure communication. In the future, I will introduce how to enable HTTPS for a local HTTP(S) service to encrypt traffic.
Update: The article about how to enable TLS communication between frps and frpc was uploaded here.