最近新入了一台小主机,家里还有个树莓派,索性想通过小主机跑点东西,然后通过外网访问家里的设备;不过鉴于大天朝内网环境,没有公网 IP 并且多层路由的情况下只能选择使用内网穿透方案,以下记录了一下使用 frp 进行内网穿透的过程
一、内网穿透原理
简单地说,内网穿透依赖于 NAT 原理,根据 NAT 设备不同大致可分为以下 4 大类(前3种NAT类型可统称为cone类型):
- 全克隆(Full Cone):NAT 把所有来自相同内部 IP 地址和端口的请求映射到相同的外部 IP 地址和端口上,任何一个外部主机均可通过该映射反向发送 IP 包到该内部主机
- 限制性克隆(Restricted Cone):NAT 把所有来自相同内部 IP 地址和端口的请求映射到相同的外部 IP 地址和端口;但是,只有当内部主机先给 IP 地址为 X 的外部主机发送 IP 包时,该外部主机才能向该内部主机发送 IP 包
- 端口限制性克隆(Port Restricted Cone):端口限制性克隆与限制性克隆类似,只是多了端口号的限制,即只有内部主机先向 IP 地址为 X,端口号为 P 的外部主机发送1个 IP 包,该外部主机才能够把源端口号为 P 的 IP 包发送给该内部主机
- 对称式NAT(Symmetric NAT):这种类型的 NAT 与上述3种类型的不同,在于当同一内部主机使用相同的端口与不同地址的外部主机进行通信时, NAT 对该内部主机的映射会有所不同;对称式 NAT 不保证所有会话中的私有地址和公开 IP 之间绑定的一致性;相反,它为每个新的会话分配一个新的端口号;导致此种 NAT 根本没法穿透
内网穿透的作用就是利用以上规则,创建一条从外部服务器到内部设备的 “隧道”,具体的 NAT 原理等可参考 内网打洞、网络地址转换NAT原理
二、环境准备
实际上根据以上 NAT 规则,基本上大部分家用设备和运营商上级路由等都在前三种规则之中,所以只需要借助成熟的内网穿透工具即可,以下为本次穿透环境
- 最新版本 frp
- 一台公网 VPS 服务器
- 内网一台服务器,最好 Linux 系统
三、服务端搭建
服务器作为公网访问唯一的固定地址,即作为 server 端;内网客户端作为 client 端,会主动向 server 端创建连接,此时再从 server 端反向发送数据即可实现内网穿透
1 2 3 4
| wget https://github.com/fatedier/frp/releases/download/v0.9.3/frp_0.9.3_linux_amd64.tar.gz tar -zxvf frp_0.9.3_linux_amd64.tar.gz cd frp_0.9.3_linux_amd64
|
编辑 frps.ini
如下
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
| [common]
bind_addr = 0.0.0.0 bind_port = 7000
vhost_http_port = 4080 vhost_https_port = 4443
dashboard_port = 7500 dashboard_user = admin dashboard_pwd = admin
log_file = /dev/stdout
log_level = info log_max_days = 3
privilege_mode = true
privilege_token = HE7qTtW8Lg83UDKY
privilege_allow_ports = 4000-50000
max_pool_count = 100
authentication_timeout = 900
subdomain_host = domain.com
[ssh] type = tcp auth_token = M4P2xsH6RuUkbP9d bind_addr = 0.0.0.0 listen_port = 6000
|
其他具体配置说明请参考frp README 文档
设置完成后执行 ./frps -c frps.ini
启动即可
四、客户端配置
客户端作为发起链接的主动方,只需要正确配置服务器地址,以及要映射客户端的哪些服务端口等即可
1 2 3 4
| wget https://github.com/fatedier/frp/releases/download/v0.9.3/frp_0.9.3_linux_amd64.tar.gz tar -zxvf frp_0.9.3_linux_amd64.tar.gz cd frp_0.9.3_linux_amd64
|
编辑 frpc.ini
文件
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
| [common]
server_addr = domain.com server_port = 7000
log_file = /dev/stdout log_level = info log_max_days = 3
auth_token = ouRRXE4tk69oNZ6f
privilege_token = VfJiyhDVJ38t7Qu6
[ssh] type = tcp local_ip = 127.0.0.1 local_port = 22
use_encryption = true
use_gzip = true
[web01] type = http local_ip = 127.0.0.1 local_port = 8000
privilege_mode = true use_encryption = true use_gzip = true
pool_count = 20
subdomain = test
|
最后使用 ./frpc -c frpc.ini
启动即可
五、测试
服务端和客户端同时开启完成后,即可访问 http://domain.com:7500
进入 frp 控制面板,如下
此时通过 ssh root@domain.com -p 6000
即可连接到内网服务器,通过访问 http://test.domain.com:4080
即可访问内网发布的位于 8000
端口服务
六、Systemd 管理
在较新的 Linux 系统中一经采用 Systemd 作为系统服务管理工具,以下为服务端作为服务方式运行的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| cp frps /usr/local/bin/frps mkdir /etc/frp cp frps.ini /etc/frp/frps.ini
vim /usr/lib/systemd/system/frps.service
[Unit] Description=frps After=network.target
[Service] TimeoutStartSec=30 ExecStart=/usr/local/bin/frps -c /etc/frp/frps.ini ExecStop=/bin/kill $MAINPID
[Install] WantedBy=multi-user.target
systemctl enable frps systemctl start frps systemctl status frps
|
客户端与此类似,这里不再重复编写,更多详细设置(如代理 https 等)请参考 frp 官方文档