Complete Guide to FRP Reverse Proxy Deployment

This article details the core features and deployment solutions for FRP reverse proxy service, including various deployment methods for server (frps) and client (frpc) using Docker and Kubernetes, with complete configuration templates and network architecture diagrams.

This article was published 988 days ago, some content may be outdated. If you have any questions, please leave a comment.

What is frp?

frp is a high-performance reverse proxy application specialized in intranet penetration. It supports multiple protocols including TCP, UDP, HTTP, HTTPS, and features P2P communication capabilities. Using frp, you can securely and conveniently expose internal network services to the public network through relay nodes with public IP addresses.

Why choose frp?

By deploying an frp server on a node with a public IP, you can easily penetrate internal services to the public network while enjoying these professional features:

  • Multi-protocol Support: Client-server communication supports TCP, QUIC, KCP, Websocket, and other protocols.
  • TCP Connection Stream Multiplexing: Carry multiple requests over a single connection to reduce connection setup time and lower request latency.
  • Load Balancing between proxy groups.
  • Port Multiplexing: Multiple services can be exposed through the same server port.
  • P2P Communication: Traffic bypasses server relay, maximizing bandwidth utilization.
  • Client Plugins: Provides natively supported client plugins for static file viewing, HTTPS/HTTP protocol conversion, HTTP/SOCKS5 proxies, and more.
  • Server Plugin System: Highly extensible plugin system for custom functional expansion.
  • User-Friendly UI: Server and client interfaces for simplified configuration and monitoring.

frps

FRPS is the server part of frp, which needs a public IP and opens port 12345.

  • docker-compose.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
  services:
    frps:
      image: fatedier/frps:v0.61.0
      container_name: frps
      restart: always
      working_dir: /etc/frps/
      command: ["-c", "./config.toml"]
      volumes:
        - /etc/localtime:/etc/localtime:ro
        - ./:/etc/frps/
      network_mode: host
  • config.toml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
  bindAddr = "0.0.0.0"
  bindPort = 12345
  
  vhostHTTPPort = 12380
  vhostHTTPSPort = 12343
  
  webServer.addr = "0.0.0.0"
  webServer.port = 12375
  webServer.user = "admin"
  webServer.password = "******"
  
  enablePrometheus = true
  
  log.to = "./logs/frps.log"
  log.level = "debug"
  log.maxDays = 7
  log.disablePrintColor = false
  
  auth.method = "token"
  auth.token = "******"
  
  custom404Page = "./404.html"
  • 404.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Not Found</title>
      <style>
          body {
              font-family: Arial, sans-serif;
              text-align: center;
              margin-top: 100px;
          }
          h1 {
              font-size: 50px;
              margin-bottom: 10px;
          }
          p {
              font-size: 20px;
              margin-top: 0;
          }
      </style>
  </head>
  <body>
  
      <h1>404</h1>
      <p>Page not found</p>
      
  </body>
  </html>

frpc

docker deployment

  • docker-compose.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
  services:
    net-tunnel:
      image: "harbor.example.com/devops/kube-net-tunnel:standalone"
      container_name: "net-tunnel"
      restart: "always"
      network_mode: "bridge"
      working_dir: /etc/net-tunnel/
      volumes:
        - "/etc/localtime:/etc/localtime:ro"
        - "./:/etc/net-tunnel/"
      command: ["-c", "/etc/net-tunnel/config.toml"]
  • config.toml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  user = "test"
  
  serverAddr = "*.*.*.*"
  serverPort = 12345
  
  auth.method = "token"
  auth.token = "******"
  
  log.to = "./logs/frpc.log"
  log.level = "debug"
  log.maxDays = 3
  log.disablePrintColor = false
  
  webServer.addr = "127.0.0.1"
  webServer.port = 12346
  webServer.user = "admin"
  webServer.password = "******"
  
  [[proxies]]
  name = "admin_ui"
  type = "tcp"
  localIP = "127.0.0.1"
  localPort = 12346
  remotePort = 12440
  
  [[proxies]]
  name = "ssh"
  type = "tcp"
  localIP = "172.17.0.1" # Windows or MacOS: "host.docker.internal"
  localPort = 22
  remotePort = 12441

K8s deployment

kube-net-tunnel.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-net-tunnel-config
  namespace: kube-system
data:
  config.toml: |
    user="test"
    serverAddr = "*.*.*.*"
    serverPort = 12345

    auth.method = "token"
    auth.token = "******"

    log.to = "console"
    log.level = "debug"
    log.maxDays = 3
    log.disablePrintColor = false

    webServer.addr = "127.0.0.1"
    webServer.port = 7400
    webServer.user = "admin"
    webServer.password = "******"

    [[proxies]]
    name = "admin"
    type = "tcp"
    localIP = "127.0.0.1"
    localPort = 7400
    remotePort = 12431

    [[proxies]]
    name = "ssh"
    type = "tcp"
    localIP = "10.19.31.7"
    localPort = 22
    remotePort = 12432


---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kube-net-tunnel
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kube-net-tunnel
  template:
    metadata:
      labels:
        app: kube-net-tunnel
    spec:
      containers:
        - name: kube-net-tunnel
          image: harbor.example.com/devops/kube-net-tunnel:standalone
          imagePullPolicy: IfNotPresent
          args: ["-c", "/etc/kube-net-tunnel/config.toml"]
          volumeMounts:
            - name: config-volume
              mountPath: /etc/kube-net-tunnel/config.toml
              subPath: config.toml
      volumes:
        - name: config-volume
          configMap:
            defaultMode: 0755
            name: kube-net-tunnel-config
            items:
              - key: config.toml
                path: config.toml
Facing the sea with spring blossoms.
Built with Hugo
Theme Stack designed by Jimmy