🚀 Hands-On Guide: Building a High-Speed Tunnel with VPS + Frp + Docker

1 min read

This tutorial aims to solve the following pain points: 1. Home broadband has no public IP, or ports 80/443 are blocked, so you cannot host a site directly. 2. Accessing home services in China from overseas is slow, and Cloudflare's free plan performs poorly inside China. 3. No ICP filing is required — use a VPS with a high-performance China-bound route for low-latency access.

🚀 Hands-On Guide: Building a High-Speed Tunnel with VPS + Frp + Docker

📖 Introduction

This tutorial aims to solve the following pain points:

  • Home broadband has no public IP, or ports 80/443 are blocked, so you cannot host a site directly.
  • Accessing domestic services from overseas is slow, and Cloudflare’s free plan does not perform well inside China.
  • No ICP filing is required — use a VPS with a high-performance route to achieve low-latency access.

Architecture:

User (HTTPS) -> VPS (Frp server) -> encrypted tunnel -> home server (Frp client) -> local Nginx (decrypt/respond)


🛠️ Prerequisites

  1. A VPS: ClawCloud is recommended (Hong Kong / Singapore / Japan) — optimized routes and generous bandwidth.
  2. A home server: with Docker and Nginx installed.
  3. A domain: hosted on Cloudflare/Alibaba Cloud, used to obtain an SSL certificate.
  4. Generate a token: run openssl rand -hex 16 in your terminal to generate a connection password.

Step 1: Server Deployment (ClawCloud VPS)

Environment: Ubuntu / Debian Goal: install frps, enable HTTPS listening, and configure auto-start on boot.

1. Download and Install

# Download the latest Frp (check the GitHub Release page for the latest version number)
wget https://github.com/fatedier/frp/releases/download/v0.58.1/frp_0.58.1_linux_amd64.tar.gz

# Extract and install
tar -zxvf frp_0.58.1_linux_amd64.tar.gz
sudo mv frp_0.58.1_linux_amd64/frps /usr/local/bin/
sudo chmod +x /usr/local/bin/frps

# Create the config directory
sudo mkdir -p /etc/frp

2. Configuration File (/etc/frp/frps.toml)

Ini, TOML

# frps internal communication port
bindPort = 7000

# [Key] Public-facing HTTPS port, receives public 443 traffic
vhostHTTPSPort = 443

# Authentication (replace with your own)
auth.method = "token"
auth.token = "a1b2c3d4e5f678901234567890abcdef"

# Dashboard configuration (optional)
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin123"

3. Configure Systemd Auto-Start (/etc/systemd/system/frps.service)

Ini, TOML

[Unit]
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml

[Install]
WantedBy=multi-user.target

4. Start the Service and Firewall

# Start the service
sudo systemctl daemon-reload
sudo systemctl enable frps --now

# Open the system firewall
sudo ufw allow 7000/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7500/tcp

⚠️ Note: Don’t forget to also allow these ports in your VPS provider’s web console (security group)!


Step 2: Client Deployment (Home Server)

Environment: Docker Goal: deploy frpc via Docker and pass HTTPS traffic through to the host machine’s Nginx.

1. Configuration File (~/frp/frpc.toml)

Ini, TOML

# Fill in the VPS public IP
serverAddr = "1.2.3.4"
serverPort = 7000

# Must match the server side
auth.method = "token"
auth.token = "a1b2c3d4e5f678901234567890abcdef"

# [Key] Enable TLS encryption to prevent the connection from being reset when crossing the firewall (Connection reset)
transport.tls.enable = true

# --- Forwarding rules ---
[[proxies]]
name = "home_web"
type = "https"  # https mode passes encrypted traffic through without decrypting it
customDomains = ["www.yourdomain.com"]

[proxies.plugin]
type = "https2http"
localAddr = "127.0.0.1:443" # points to the SSL port that the host machine's Nginx listens on

2. Docker Compose File (~/frp/docker-compose.yml)

version: '3.8'
services:
  frpc:
    image: snowdreamtech/frpc:latest
    container_name: frpc
    restart: always
    # [Key] Use host mode so the container can reach the host machine's Nginx port directly
    network_mode: "host"
    volumes:
      - ./frpc.toml:/etc/frp/frpc.toml

3. Start the Client

cd ~/frp
docker compose up -d

# Check the logs to confirm the connection succeeded (seeing "start proxy success" means success)
docker logs -f frpc

Step 3: Local Nginx Configuration (SSL Endpoint)

Because this is HTTPS passthrough, the SSL certificate must be configured on the home server’s Nginx.

Nginx Configuration Example

server {
    # Listen on local 443 (an ISP block on external 443 does not affect internal listening)
    listen 443 ssl;
    server_name www.yourdomain.com;

    # SSL certificate paths
    ssl_certificate /etc/nginx/cert/yourdomain.pem;
    ssl_certificate_key /etc/nginx/cert/yourdomain.key;

    location / {
        root /var/www/html;
        index index.html;
    }
}

💡 Tip: It is recommended to use acme.sh or Certbot with the DNS API method to obtain certificates, so you can auto-renew without port 80.


Step 4: DNS Resolution

Go to your domain provider (Cloudflare/Alibaba Cloud):

  1. Add an A record.
  2. Host record: www
  3. Value: the public IP of your ClawCloud VPS.
  4. (If using Cloudflare): Turn off the orange cloud (Proxy Status: DNS Only) so traffic connects directly to the VPS.

🚑 Troubleshooting

Q1: Startup error Connection lost before handshake?

  • Cause 1: The system times on the VPS and the home server are out of sync. Synchronize the time.
  • Cause 2: Blocked by GFW detection. Make sure transport.tls.enable = true is set in frpc.toml.

Q2: The web page returns 502 Bad Gateway?

  • The Frp connection is fine, but local Nginx cannot be found.
  • Check whether Docker uses network_mode: "host".
  • Check whether the localAddr port matches Nginx’s listen port.

Q3: The Dashboard (port 7500) won’t open?

  • Check whether webServer.addr = "0.0.0.0" is configured in frps.toml.
  • Key check: whether the security group in the Alibaba Cloud/ClawCloud web console allows port 7500.

Q4: Certificate error / privacy error?

  • Confirm that Nginx is configured with the correct certificate and that the domain matches the one being accessed. Frp is only the carrier; certificate errors are Nginx’s problem.

Comments