使用 FRP 配置内网穿透访问内部服务

使用 FRP 配置内网穿透访问内部服务

所谓诚其意者 毋自欺也

本文将详细介绍如何利用流行的内网穿透工具 FRP (Fast Reverse Proxy),在拥有公网 IP 的服务器(我们称之为“控制面板服务器”)和位于内网的服务器(“目标服务器”)之间建立连接,从而实现通过公网域名访问部署在目标服务器内部的服务。本文将以轻量级导航站 van-nav 作为内部服务示例。

前提条件

在开始之前,请确保你满足以下条件:

  • 两台 Linux 服务器 (本文以两台 Ubuntu 22.04 为例):
    • 一台拥有公网 IP 的服务器,作为 控制面板服务器 (运行 frps)。示例 IP:18.138.249.128
    • 一台位于内网或防火墙后的服务器,作为 目标服务器 (运行 frpc 和内部服务)。示例 IP:35.212.231.21 (这是公网IP,但假设其上的服务需要穿透)
  • 目标服务器上运行的服务:需要一个通过 HTTP 协议访问的服务。本文以 Docker 容器运行的 van-nav 为例,监听在特定端口。也可以是直接运行的二进制程序。
  • 域名:一个你拥有管理权限的域名,需要将其解析到 控制面板服务器 的公网 IP。本文示例域名:nat1.status.aptzone.cc
  • FRP 程序:从 FRP GitHub Releases 下载适合你服务器架构(如 amd64, arm64)的最新版本。压缩包内同时包含服务端程序 frps 和客户端程序 frpc

配置步骤

接下来,我们将分步完成 FRP 的配置和运行。

1. 确定内网服务地址和端口

首先,你需要知道 目标服务器 上内部服务监听的 IP 地址和端口,以便 frpc 可以将流量转发给它。

  • 确定 IP 地址

    • 如果服务和 frpc 运行在同一台目标服务器上,通常可以使用 127.0.0.1 (localhost)。

    • 如果服务运行在 Docker 容器中,你可能需要使用 Docker 容器的内部 IP,或者更常见的是,使用目标服务器上可以访问该容器映射端口的网络接口 IP (例如,物理网卡 IP 或 Docker 网桥 IP)。

    • 你可以使用 ip addr show 命令查看目标服务器的网络接口和 IP 地址:

      1
      ip addr show
      输出示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
      inet 127.0.0.1/8 scope host lo
      valid_lft forever preferred_lft forever
      inet6 ::1/128 scope host
      valid_lft forever preferred_lft forever
      2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc mq state UP group default qlen 1000
      link/ether 42:01:0a:8a:00:04 brd ff:ff:ff:ff:ff:ff
      inet 10.138.0.4/32 metric 100 scope global dynamic ens4
      valid_lft 2138sec preferred_lft 2138sec
      inet6 fe80::4001:aff:fe8a:4/64 scope link
      valid_lft forever preferred_lft forever
      3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
      link/ether 02:42:5c:de:e0:39 brd ff:ff:ff:ff:ff:ff
      inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
      valid_lft forever preferred_lft forever
      inet6 fe80::42:5cff:fede:e039/64 scope link
      valid_lft forever preferred_lft forever
      你需要记下目标服务器上 `frpc` 可以访问到 `van-nav` 服务的那个 IP 地址。在本例中,我们将使用 `ens4` 接口的 IP `10.138.0.4`。
  • 确定端口:确认 van-nav 服务实际监听的端口号。

2. 运行内部服务 (以 van-nav Docker 为例)

目标服务器 上启动你的内部服务。以 van-nav Docker 容器为例:

1
2
# 确保你在一个合适的目录下执行,因为 -v $(pwd):/app/data 会映射当前目录
docker run -d --name van-nav --restart always -p 8080:6412 -v $(pwd):/app/data mereith/van-nav:latest
  • 命令解释
    • docker run -d: 在后台运行容器。
    • --name van-nav: 给容器命名为 van-nav
    • --restart always: 容器退出时自动重启。
    • -p 8080:6412: 将容器内部的 6412 端口映射到 目标服务器8080 端口。这意味着现在可以通过 目标服务器IP:8080 (即 10.138.0.4:8080) 访问 van-nav
    • -v $(pwd):/app/data: 将主机当前目录映射到容器内的 /app/data 目录,用于持久化数据。
    • mereith/van-nav:latest: 使用的 Docker 镜像。

替代方案:你也可以不使用 Docker,直接下载 van-nav 的二进制文件运行。具体步骤请参考其官方文档。关键是确保服务在目标服务器的某个 IP 和端口上运行。

3. 配置 FRP 服务端 (frps)

控制面板服务器 (公网服务器) 上,创建并编辑 frps 的配置文件。通常命名为 frps.toml (或 frps.ini,取决于你下载的版本和偏好,新版本推荐 TOML)。

将下载的 frps 可执行文件和配置文件(例如 frps.toml)放在服务器的某个目录下(例如 /root/frp/)。

编辑 frps.toml 文件:

1
2
3
4
5
# /root/frp/frps.toml 内容示例
bindPort = 7000 # frps 与 frpc 通信的端口
vhostHttpPort = 8080 # frps 监听 HTTP 请求的端口 (用于域名转发)
# 你还可以添加 token 进行身份验证等,提高安全性,例如:
# auth.token = "your_secure_token"
  • bindPort: frps 等待 frpc 连接的端口,需要确保防火墙已放行此端口 (TCP)。
  • vhostHttpPort: 当 frpc 配置了 type = http 时,frps 在此端口监听来自公网的 HTTP 请求,并通过 customDomains 进行转发。确保防火墙放行此端口 (TCP)。

4. 配置 FRP 客户端 (frpc)

目标服务器 (内网服务器) 上,创建并编辑 frpc 的配置文件。通常命名为 frpc.toml (或 frpc.ini)。

将下载的 frpc 可执行文件和配置文件(例如 frpc.toml)放在服务器的某个目录下(例如 /root/frp/)。

编辑 frpc.toml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
# /root/frp/frpc.toml 内容示例
serverAddr = "18.138.249.128" # 指向你的控制面板服务器的公网 IP
serverPort = 7000 # 必须与 frps.toml 中的 bindPort 一致
# 如果 frps 设置了 token,这里也需要配置:
# auth.token = "your_secure_token"

[[proxies]]
name = "van-nav-http" # 代理规则的名字,自定义,方便识别
type = "http" # 代理类型为 HTTP
localIP = "10.138.0.4" # 目标服务器上 van-nav 服务的 IP (第一步确定的)
localPort = 8080 # 目标服务器上 van-nav 服务监听的端口 (第二步映射的)
customDomains = ["nat1.status.aptzone.cc"] # 希望通过访问的域名 (需解析到控制面板服务器IP)
  • serverAddr: 你的 控制面板服务器 的公网 IP 地址。
  • serverPort: 连接 frpsbindPort
  • [[proxies]]: 定义一个具体的代理规则。
  • name: 代理规则的唯一标识。
  • type = "http": 表明这是一个 HTTP 类型的代理。frps 会使用 vhostHttpPort 来处理这类代理的请求。
  • localIP: 目标服务器上内部服务监听的 IP 地址。
  • localPort: 目标服务器上内部服务监听的端口。
  • customDomains: 指定将哪些域名的请求转发到这个 localIP:localPort。这个域名必须已经解析到你的 控制面板服务器 的公网 IP (18.138.249.128)。

5. 使用 systemd 运行 frp

为了让 frpsfrpc 在后台稳定运行并在服务器重启后自动启动,推荐使用 systemd 进行管理。

注意:以下步骤假设 frpsfrpc 及其配置文件位于 /root/frp/ 目录下。请根据你的实际路径修改 ExecStart 中的路径。

配置 frpssystemd 服务 (在控制面板服务器上)

  1. 创建 systemd 服务单元文件:

    1
    sudo vim /etc/systemd/system/frps.service
  2. 在文件中添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [Unit]
    Description=FRP Server Service
    After=network.target

    [Service]
    Type=simple
    User=root # 或者一个专门运行 frps 的非 root 用户
    Restart=on-failure
    ExecStart=/root/frp/frps -c /root/frp/frps.toml # 确保路径正确

    [Install]
    WantedBy=multi-user.target
  3. 保存并退出编辑器,然后重新加载 systemd 配置:

    1
    sudo systemctl daemon-reload
  4. 启动并设置开机自启 frps 服务:

    1
    2
    sudo systemctl start frps
    sudo systemctl enable frps

配置 frpcsystemd 服务 (在目标服务器上)

  1. 创建 systemd 服务单元文件:

    1
    sudo vim /etc/systemd/system/frpc.service
  2. 在文件中添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [Unit]
    Description=FRP Client Service
    After=network.target

    [Service]
    Type=simple
    User=root # 或者一个专门运行 frpc 的非 root 用户
    Restart=on-failure
    ExecStart=/root/frp/frpc -c /root/frp/frpc.toml # 确保路径正确

    [Install]
    WantedBy=multi-user.target
  3. 保存并退出编辑器,然后重新加载 systemd 配置:

    1
    sudo systemctl daemon-reload
  4. 启动并设置开机自启 frpc 服务:

    1
    2
    sudo systemctl start frpc
    sudo systemctl enable frpc

检查服务状态

你可以使用以下命令检查 frpsfrpc 服务的运行状态和日志:

1
2
3
4
5
6
7
# 在控制面板服务器上检查 frps
sudo systemctl status frps
journalctl -u frps -f --no-pager # 查看实时日志

# 在目标服务器上检查 frpc
sudo systemctl status frpc
journalctl -u frpc -f --no-pager # 查看实时日志

如果一切顺利,frpc 应该已经成功连接到 frps。此时,理论上,发送到 控制面板服务器 18.138.249.1288080 端口(vhostHttpPort)且 Host 头为 nat1.status.aptzone.cc 的 HTTP 请求,应该会被转发到 目标服务器10.138.0.4:8080

你可以尝试直接访问 http://18.138.249.128:8080 并在请求中指定 Host 头,或者更常见地,通过下一步配置的反向代理来访问。

6. 配置反向代理 (以 Nginx Proxy Manager 为例)

通常我们不希望用户通过 IP 和端口号(如 :8080)访问服务,而是直接通过标准的 HTTP (80) 或 HTTPS (443) 端口访问域名。这就需要一个反向代理服务器(如 Nginx、Caddy 或 Nginx Proxy Manager)部署在 控制面板服务器 上。

如果你正在使用 Nginx Proxy Manager (NPM),请在 NPM 中添加一个新的代理主机 (Proxy Host):

  • Domain Names: nat1.status.aptzone.cc (你在 frpc.toml 中配置的 customDomains)
  • Scheme: http
  • Forward Hostname / IP: 18.138.249.128 (或者 127.0.0.1,因为 NPM 和 frps 都在这台控制面板服务器上)
  • Forward Port: 8080 (你在 frps.toml 中配置的 vhostHttpPort)
  • (可选但推荐)SSL 选项卡中为此域名申请并启用 SSL 证书 (例如 Let’s Encrypt),实现 HTTPS 访问。

工作流程解释:

  1. 用户浏览器访问 https://nat1.status.aptzone.cc (假设配置了 SSL)。
  2. DNS 将域名解析到控制面板服务器的 IP 18.138.249.128
  3. 请求到达控制面板服务器的 443 端口,被 Nginx Proxy Manager 接收。
  4. NPM 根据域名 nat1.status.aptzone.cc 找到对应的代理规则。
  5. NPM 将请求 (解密后变为 HTTP) 转发给本机 (127.0.0.118.138.249.128) 的 8080 端口。
  6. frps8080 端口 (vhostHttpPort) 监听到这个请求。
  7. frps 检查请求的 Host 头 (nat1.status.aptzone.cc),找到与之关联的 frpc 客户端连接。
  8. frps 通过 bindPort (7000) 建立的隧道,将请求转发给目标服务器上对应的 frpc 实例。
  9. frpc 收到请求,将其转发给 localIP:localPort,即 10.138.0.4:8080 上的 van-nav 服务。
  10. van-nav 处理请求并将响应原路返回。

完成以上所有步骤后,你就应该能通过访问 http://nat1.status.aptzone.cchttps://nat1.status.aptzone.cc (如果配置了 SSL) 来访问部署在内网目标服务器上的 van-nav 服务了。

  • Title: 使用 FRP 配置内网穿透访问内部服务
  • Author:
  • Created at : 2024-08-11 12:07:39
  • Updated at : 2025-04-29 19:06:40
  • Link: https://xblog.aptzone.cc/2024/08/11/内网穿透配置/
  • License: All Rights Reserved © 凡
Comments