内网穿透简介

互联网上两个不同的主机进行通信首先需要知道对方 IP。根据 IP 协议,只有分配了公网IP的设备才能在互联网上通信和传输数据。而中国人口/设备众多,分配到的IPv4资源又少,因此绝大部分情况是通过路由器/交换机转换公网IP后才上网。

位于路由器/交换机后的设备一般是内网设备,分配的IP地址以 192.168/172.16/10.0 开头,属于内网 IP。要让内网设备对外提供服务,就需要进行内网穿透。

常见穿透工具包括:FRP, ZeroTier 等,本文仅介绍 FRP 的使用。


FRP 简介

FRP(Fast Reverse Proxy)是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。

基本原理:

  • 在带有公网 ip 的云服务器上部署 frp 的服务端 frps
  • 在需要穿透的内网服务器上部署 frp 的客户端 frpc
  • 每个客户端都会有一个配置文件用于和服务器连接
  • 公网服务器充当代理服务器,用户访问 公网ip + 端口时,公网服务器的 frps 服务会根据端口号,自动转发到对应的内网服务器上,从而访问到内网服务

FRP 配置及使用

服务端和客户端使用的都是同一份文件,只是配置文件和启动文件不同。因此只需要下载一份文件,并按类型分成两份。下载地址:https://github.com/fatedier/frp/releases。服务器上输入`uname -m`是 x86_64 架构,因此下载 linux_amd64 版本。通过命令行下载并解压:

1
2
3
wget -c https://github.com/fatedier/frp/releases/download/v0.53.2/frp_0.53.2_linux_amd64.tar.gz
tar -xvf frp_0.53.2_linux_amd64.tar.gz
mv frp_0.53.2_linux_amd64 frp

查看目录:

1
2
3
4
5
6
.
├── frpc
├── frpc.toml
├── frps
├── frps.toml
└── LICENSE

这些文件分成两部分。

  1. 客户端,也即内网的服务器,需要 frpc 和 frpc.toml
  2. 服务端,也即公网的服务器,需要 frps 和 frps.toml
  3. 剩下的是LICENSE,可以不用管

将两类文件分别打包

1
2
3
mkdir client server
mv frpc* client
mv frps* server

服务端配置

server 目录上传到公网服务器任意路径。如果需要自动启动,看下一节。如下编辑 frps.toml,参数见注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[common]
# frp监听的端口,默认是7000,可修改
bindAddr = "0.0.0.0"
bindPort = 7000

# 开启Dashboard用于管理和查看服务状态。Dashboard端口、用户名和密码,请改成更复杂的。
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin123456"

# 授权码,请改成更复杂的,这个token之后在客户端会用到
auth.method = "token"
auth.token = "e10adc3949ba59abbe56e057f20f883e"

# 去除访问限速
transport.tcpMux = false

# frp日志配置
log.to = "./frps.log"
log.level = "info"
log.maxDays = 3

这里有几个参数需要根据需要手动修改:

  1. bindPort:frp 服务端监听的端口,也即服务入口,建议修改
  2. auth.token:授权码,这个授权码之后在客户端还会用到
  3. webServer.port:监控流量页面的端口,建议修改
  4. webServer.user:监控流量页面的用户名
  5. webServer.password:监控流量页面的密码
  6. log.to:日志文件路径,根据需要修改

其中认证token可以用 pwgen 命令来生成,这个授权码之后在客户端还会用到。

1
2
sudo apt install pwgen -y
pwgen -s 32 1

运行服务:

1
./frps -c frps.toml

记得防火墙打开云服务器的7500端口和其他所有提到的端口,这些端口可以用’,'分割,在一个规则中同时打开。然后网页输入 公网IP:7500,输入设置的Dashboard账户和密码,登录后即可看到 frp 的状态。(这里可以将 公网IP:7500 通过nginx转发,使用域名访问,这样可以少开一个7500端口,更安全)

客户端与服务端自启动(推荐)

把 frps 添加为系统服务,这一来当系统重启时,Frps 服务会自动启动,并且不需要手动再次启动。客户端同理,将下方出现的frps改成frpc即可。

然后云服务端新建文件:frps.service

1
2
cd /etc/systemd/system
sudo vim frps.service

内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=frps service
After=network.target syslog.target
Wants=network.target

[Service]
Type=simple
ExecStart=/home/user/software/frp/frps -c /home/user/software/frp/frps.toml
Restart=always
RestartSec=15s

[Install]
WantedBy=multi-user.target

设置自启动,并启动服务:

1
2
3
sudo systemctl enable frps  # 允许自启动
# 执行成功会提示“Created symlink /etc/systemd/system/multi-user.target.wants/frps.service → /usr/lib/systemd/system/frps.service.”
sudo systemctl start frps # 启动客户端服务

后续如果更改了配置文件,执行下边命令重启服务:

1
2
sudo systemctl daemon-reload
sudo systemctl restart frps

查看服务状态:

1
sudo systemctl status frps  # 查看服务状态

注:以上为云服务端配置,内网客户端也需要配置

客户端配置

client 目录上传到内网服务器,原来frpc.toml的内容删了,按照如下编辑 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
[common]
# 服务端公网IP、监听端口bind_port
serverAddr = "公网IP地址"
serverPort = 7000

webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "username"
webServer.password = "password"

# 授权码
auth.method = "token"
auth.token = "e10adc3949ba59abbe56e057f20f883e"

# 去除访问限速
transport.tcpMux = false

# frp日志配置
log.to = "./frpc.log"
log.level = "info"
log.maxDays = 3

[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 2288

# name 为服务名称,下方解释:访问frp服务端的2288端口时,等同于通过中转服务器访问127.0.0.1的22端口。
# type 为连接的类型,此处为tcp
# localIP 为中转客户端实际访问的IP
# localPort 为目标端口
# remotePort 为远程端口,记得服务端的防火墙打开这个端口

同样地,本地执行 ./frpc -c frpc.toml 即可启动客户端。

注:frpc.toml可以改名;frpc.toml每一行内容的后面不可以加注释,否则会报错。建议使用 tmux 在后台启动服务
内网服务器一定要能够访问外网(如果是校园网,网络断开的话要重新登陆才行,否则服务也会断开

回到服务器的dashboard界面,找到tcp端口,可以看到2288端口已经是online状态,即绑定成功。以上所有相当于公网IP:2288对应127.0.0.1:22

访问内网其他服务

在上面的client端,也就是frpc.toml文件末尾添加:

1
2
3
4
5
6
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 9800
remotePort = 9000

心跳设置

如不设置心跳,FRP 创建的连接可能在间隔较长时间后会断开,重新连接需刷新几次才能成功。


服务端输入 crontab -e,添加定时任务:

1
* * * * * curl localhost:2288 --max-time 5  >/dev/null 2>&1

2288为服务端的一个remoteport

如果未生效或者担心心跳是否设置成功,可以查看cron日志:

1
2
3
4
5
6
# 如果要查看crontab日志,需要将服务端的指令修改为:
* * * * * curl localhost:2288 --max-time 5 > /var/log/cron 2>&1
# 修改好后需要2min后生效,这时候可以输入下面这行使cron立即生效
sudo service cron restart
# 输入下面的指令查看日志
sudo tail -f /var/log/cron

注:

  1. 将/var/log下的cron文件权限改成可写,chmod 777 /var/log/cron 即可。
  2. 将云服务端的2288端口打开

请注意,使用 crontab 的方法并不是最优的解决方案,因为它可能会给服务器带来不必要的负担,尤其是当服务不需要这么频繁的心跳检测时。优先考虑使用 FRP 自带的心跳机制。如果你认为 FRP 的心跳机制不足以维持连接,再考虑使用 crontab

域名绑定

使用备案好的域名访问使用FRP进行内网穿透的服务,你需要配置FRP服务端(frps)、客户端(frpc)以及进行域名解析。以下是各配置的示例:
FRP服务端配置,frps.toml文件最后添加下面的内容:

1
2
3
4
5
6
# HTTP和HTTPS服务监听的端口(用于域名访问的HTTP和HTTPS请求,防火墙打开这两个端口)
vhost_http_port = 80
vhost_https_port = 443

# 使用的域名(将一级域名替换yourdomain.com,就是你购买的域名)
subdomain_host = yourdomain.com

FRP客户端配置,frpc.toml文件最后添加下面的内容:

1
2
3
4
5
6
7
8
[[proxies]]
name = "domin"
# 使用http类型
type = http
localIP = "127.0.0.1"
localPort = 8080
# 自定义域名前缀,完整域名将是 service.yourdomain.com
subdomain = service

域名解析设置

  • 登录到你的域名管理控制台。
  • 进入DNS管理或域名解析设置页面。
  • 添加A记录,指向FRP服务端的公网IP地址。

假设你的域名是yourdomain.com,你希望通过service.yourdomain.com来访问内网服务,那么你需要添加如下的解析记录:

  • 记录类型:A
  • 主机记录:service
  • 解析线路:默认
  • 记录值:your_public_ip(FRP服务端的公网IP)
  • TTL(生存时间):根据需要设置,通常是默认值或最短值

完成以上配置后,你需要重启FRP服务端和客户端以应用新的配置。在FRP服务端和客户端成功启动并连接后,你应该可以通过域名service.yourdomain.com来访问你的内网服务。

请确保服务器的防火墙或云服务器的安全组设置允许外部访问上述配置的端口,特别是HTTP和HTTPS端口(80和443)。同时,记得检查内网服务的防火墙设置,确保FRP客户端能够访问到内网服务的端口。

注:域名解析可能需要一些时间才能生效,这取决于DNS提供商和TTL设置。一旦DNS解析生效,且FRP配置正确无误,你就可以通过你的域名来访问内网服务了。笔者刚设置完上边的frps,frpc以及域名解析,访问不了,去食堂吃个饭回来就可以访问了,大概十几分钟。

现在既可以通过IP+Port访问,也可以通过域名访问,快去爽吧。

域名备案的一些知识点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
哪里买的,哪里进行备案。笔者使用的是阿里的域名和云
备案是国内对网络(网站)的一种管理机制。其实就是向有关部门提交一下域名使用人员活公司的实名信息。比如说这个域名主要是用来做什么的,然后负责人的联系方式是什么。只有备案了的域名才能被正常的DNS解析,也就是只有备案的域名才能被正常的访问。如果你的DNS解析服务器在国外,那么也可以不备案,但是不建议这么做。备案以后会少很多麻烦。传统的备案时间较长,可能有20-30天,现在腾讯或者阿里的小程序备案只要7个工作日基本就能搞定了。

备案流程:进入备案小程序--->填写备案信息--->云审核--->管局审核--->备案成功
有问题云这边会有工作人员call你,帮你修改好有问题的地方。

阿里云有很多新人优惠,第一次买1块钱一年。笔者买了个玩玩,买好后进行域名认证。域名认证一般官方提示需要22min(节假日也是这个时间,其实会快一点)。

填写备案域名和相关信息
网站名称:个人新站
网站服务内容:其他
备注:个人作品展示,个人信息展示
最后是人脸验证等。

提交后云那边有小姐姐帮你审核,如果有问题,会给你打电话,告诉你怎么改。这段时间记得看手机。如果没问题,他们会帮你提交到相应的管局,然后你会收到一条带验证码的短信,你需要在24h内核验链接,验证你的手机号,否则管局会驳回你的备案申请。不过驳回了也没啥事,小姐姐会帮你重新提交。如果这个没问题,应该就等管局那边审核了,几个工作日就好。等通过了会收到短信,再提示你公安部备案,如果你是个人网站或者小型网站,就不用了,因为很麻烦。

好了,就先记录这么多。

小结

随笔整理。又重新整理了一下。亲自实验过,非常好用,欢迎点赞收藏。