内网穿透工具 - frp

温馨提醒

简介

frp 是一款高性能的反向代理软件,专注于内网穿透,支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,通过 frp,可以安全、便捷的将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转。

中文官网

英文官网

工作原理

frp 由两个组件组成:客户端(frpc)和服务端(frps),服务端部署在具有公网 IP 地址的机器上,而客户端部署在需要穿透的内网服务所在的机器上。

由于内网服务器缺乏公网 IP 地址,因此无法直接被非局域网内的用户访问,用户通过访问服务端的 frps,frp 负责根据请求的端口或其他信息将请求路由到相应的内网机器,从而实现通信。

代理类型

TCP:提供纯粹的 TCP 端口映射,使用服务端能根据不同的端口将请求路由到不同的内网服务;

UDP:提供纯粹的 UDP 端口映射,与 TCP 代理类似,但用于 UDP 流量;

HTTP:专为 HTTP 应用设计,支持修改 Host Header 和增加鉴权等额外功能

HTTPS:类似于 HTTP 代理,但专门用于处理 HTTPS 流量;

STCP:提供安全的 TCP 内网代理,要求在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口;

SUDP:提供安全的 UDP 内网代理,与 STCP 类似,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口;

XTCP:点对点内网穿透代理,与 STCP 类似,但流量不需要经过服务器中转;

TCPMUX:支持服务端 TCP 端口的多路复用,允许通过同一端口访问不同的内网服务。

内网穿透教程

客户端:本地部署的飞牛 NAS,内网 IP:192.168.200.101,端口:5666

服务端:使用华为云的 ECS,公网 IP:116.204.45.64,端口:9998

服务端 frps 安装和配置

  • 下载安装包

    官方Github地址

  • 解压

    1
    2
    
    mkdir /usr/local/frps
    tar xf frp_0.61.2_linux_amd64.tar.gz -C /usr/local/frps/
  • 修改配置文件

    vim /usr/local/frp_0.61.2_linux_amd64/frps.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
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    
    # 服务器监听的地址
    bindAddr = '0.0.0.0'
    
    # frps 监听的端口,frpc 需要连接此端口
    bindPort = 7000
    
    # kcp 协议使用udp端口,可以和bindPort相同
    kcpBindPort = 7000
    
    # 使用 quic 协议时监听的端口,如果不设置,则不会启用 quic
    quicBindPort = 7002
    
    # frps 代理服务器监听的地址,默认与 bindAddr 相同
    proxyBindAddr = "0.0.0.0"
    
    # 每个代理允许的最大连接池数量
    transport.maxPoolCount = 5
    
    # 是否启用 tcp 多路复用,默认为 true
    transport.tcpMux = true
    
    # 是否强制 TLS 传输加密,默认 false
    transport.tls.force = false
    
    # TLS 证书文件路径
    # transport.tls.certFile = "server.crt"
    
    # TLS 私钥文件路径
    # transport.tls.keyFile = "server.key"
    
    # CA 证书路径
    # transport.tls.trustedCaFile = "ca.crt"
    
    # 日志路径
    log.to = "/var/log/frps/frps.log"
    
    # 日志级别,可选 trace、debug、info、warn、error
    log.level = "info"
    
    # 日志保留天数
    log.maxDays = 3
    
    # frps 用于 Http 代理的端口
    vhostHTTPPort = 9998
    # frps 用于 https 代理的端口
    vhostHTTPSPort = 8443
    
    # 是否启用 http connect 隧道复用,默认为0(禁用)
    tcpmuxHTTPConnectPort = 5337
    
    # 是否开启 tcp 隧道直通模式,默认 false(开启流量修改)
    tcpmuxPassthrough = false
    
    # 启用管理面板
    webServer.addr = "0.0.0.0"
    webServer.port = 7500
    webServer.user = "admin"
    webServer.password = "admin"
    webServer.pprofEnable = false
    
    # 是否启用 prometheus 监控
    enablePrometheus = true
    
    # 身份验证
    auth.method = "token"
    auth.token = "admin"
    
    # 限制 frpc (客户端)可用的端口范围
    allowPorts = [
      { start = 2000, end = 3000 },		# 允许 2000-3000
      { single = 3001 },					# 允许 3001
      { single = 3003 },					# 允许 3003
      { start = 4000, end = 50000 }		# 允许 4000-50000
    ]
    
    # 每个客户端最多可用的端口数,0表示无限制
    maxPortsPerClient = 0
    
    # 子域名支持
    subDomainHost = "domain.com"	# 客户端配置 subdomain = "test",则访问 test.domain.com 将路由到该客户端
    custom404Page = "/path/to/404.html"		# 自定义 404 错误页面路径
    
    # 设置 udp 数据包大小,默认1500字节
    udpPacketSize = 1500
    
    # NAT 穿透数据的保留时间(小时)
    natholeAnalysisDataReserveHours = 168
  • 创建启动脚本

    vim /usr/lib/systemd/system/frps.service

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    [Unit]
    # 服务名称,可自定义
    Description = frp server
    After = network.target syslog.target
    Wants = network.target
    
    [Service]
    Type = simple
    # 启动frps的命令,需修改为您的frps的安装路径
    ExecStart = /usr/local/frp_0.61.2_linux_amd64/frps -c /usr/local/frp_0.61.2_linux_amd64/frps.toml
    
    [Install]
    WantedBy = multi-user.target
  • 启动服务

    1
    2
    
    systemctl daemon-reload
    systemctl enable --now frps

客户端 frpc 安装和配置

  • 与服务端在同一个安装包

  • 修改配置文件

    vim /usr/local/frp_0.61.2_linux_amd64/frpc.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
    32
    33
    34
    35
    36
    
    # frps 的外网地址和端口
    serverAddr = "116.204.45.64"
    serverPort = 7000
    
    # 日志配置
    log.to = "/var/log/frpc/frpc.log"
    
    # 日志级别,可选 trace、debug、info、warn、error
    log.level = "info"
    
    # 日志保留天数
    log.maxDays = 3
    
    # 身份验证方式,token 要与 frps 配置的一样
    loginFailExit = true
    auth.method = "token"
    auth.token = "admin"
    
    # 启用 管理面板
    webServer.addr = "0.0.0.0"
    webServer.port = 7400
    webServer.user = "admin"
    webServer.password = "admin"
    
    # 连接 frp 服务器的协议,支持 tcp、kcp、quic、websocket、wss
    transport.protocol = "tcp"
    transport.connectServerLocalIP = "0.0.0.0"
    
    # http 代理
    [[proxies]]
    name = "test"
    type = "http"					# 代理类型	
    localIP = "192.168.200.101"		# 内网服务器地址
    localPort = 5666				# 内网服务器端口
    subdomain = "test"				# 使用子域名访问 test.chenji.org.cn
    customDomains = ["test.domain.com"]
  • 其他代理配置

     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
    
    # https 代理
    [[proxies]]
    name = "web02"
    type = "https"
    localIP = "127.0.0.1"
    localPort = 8000
    customDomains = ["web02.yourdomain.com"]	# 访问 web02.yourdomain.com 时,frps 会转发请求到本地 127.0.0.1:8000
    
    # ssh 代理
    [[proxies]]
    name = "ssh"			# 代理名称
    type = "tcp"			# 代理类型
    localIP = "127.0.0.1"	# 本地需要转发的服务 IP
    localPort = 22			# 本地端口
    remotePort = 6001		# 服务器上开放的端口,外部可通过该端口访问 ssh
    
    # socks5 代理
    [[proxies]]
    name = "plugin_socks5"
    type = "tcp"
    remotePort = 6005		# 远程开放的端口,客户端可以使用 frps:6005 使用 socks5 代理
    [proxies.plugin]
    type = "socks5"			# 代理 socks5 代理,提供匿名代理服务
    username = "abc"
    password = "abc"
    
    # stcp 内网穿透
    [[proxies]]
    name = "secret_tcp"
    type = "stcp"
    secretKey = "abcdefg"		# 访问密钥
    localIP = "127.0.0.1"
    localPort = 22
  • 创建启动脚本

    vim /usr/lib/systemd/system/frpc.service

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    [Unit]
    # 服务名称,可自定义
    Description = frp server
    After = network.target syslog.target
    Wants = network.target
    
    [Service]
    Type = simple
    # 启动frps的命令,需修改为您的frps的安装路径
    ExecStart = /usr/local/frp_0.61.2_linux_amd64/frpc -c /usr/local/frp_0.61.2_linux_amd64/frpc.toml
    
    [Install]
    WantedBy = multi-user.target
  • 启动服务

    1
    2
    
    systemctl daemon-reload
    systemctl enable --now frpc

用浏览器访问 http://116.204.45.64:9998 时,就会将请求转发到内网的 192.168.200.101:5666 上