FRP 反向代理服务部署完整指南

本文详细介绍了FRP反向代理服务的核心特性与部署方案,包含服务端(frps)和客户端(frpc)的Docker、Kubernetes等多种部署方式,提供完整的配置文件模板和网络架构原理图。

这篇文章已发布 988 天,部分内容可能已过时。如有疑问,可在评论区留言。

frp 是什么?

frp 是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。使用 frp,您可以安全、便捷地将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转。

为什么选择 frp?

通过在具有公网 IP 的节点上部署 frp 服务端,您可以轻松地将内网服务穿透到公网,并享受以下专业特性:

  • 多种协议支持:客户端服务端通信支持 TCP、QUIC、KCP 和 Websocket 等多种协议。
  • TCP 连接流式复用:在单个连接上承载多个请求,减少连接建立时间,降低请求延迟。
  • 代理组间的负载均衡。
  • 端口复用:多个服务可以通过同一个服务端端口暴露。
  • P2P 通信:流量不必经过服务器中转,充分利用带宽资源。
  • 客户端插件:提供多个原生支持的客户端插件,如静态文件查看、HTTPS/HTTP 协议转换、HTTP、SOCKS5 代理等,以便满足各种需求。
  • 服务端插件系统:高度可扩展的服务端插件系统,便于根据自身需求进行功能扩展。
  • 用户友好的 UI 页面:提供服务端和客户端的用户界面,使配置和监控变得更加方便。

frps

frp 的服务端,需要有公网 IP,开通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 部署

  • 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 部署

  • 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
面朝大海,春暖花开。
使用 Hugo 构建
主题 StackJimmy 设计