通过frp进行内网穿透实现星露谷多人局域网联机

posts/%E9%80%9A%E8%BF%87frp%E8%BF%9B%E8%A1%8C%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E5%AE%9E%E7%8E%B0%E6%98%9F%E9%9C%B2%E8%B0%B7%E5%A4%9A%E4%BA%BA%E5%B1%80%E5%9F%9F%E7%BD%91%E8%81%94%E6%9C%BA

环境

星露谷游戏平台:Steam

服务器配置(服务端):Ubuntu 20.04.1 LTS x86_64(确保所需要用到的端口号全部开启)

游戏主持主机(客户端):Ubuntu 20.10 x86_64

联机测试主机:Windows 10 家庭版 x64

开始前需要了解的东西

星露谷局域网联机的端口号

我们都知道游戏多人联机是需要通过端口进行相连的,在进行内网穿透前我们需要搞清楚星露谷局域网联机的端口号是多少。

不像 Terraria 一样,星露谷并没有提供多人游戏的端口号,但是想获取星露谷的端口号也很简单。

netstat 查看端口占用获取星露谷端口号

启动星露谷多人游戏

打开 steam->打开 Stardew Valley->多玩家->多人游戏->主持

在选项中找到多玩家先将服务器模式改为离线

打开终端使用netstat查看星露谷端口占用情况

$ netstat -tunlp | grep Stardew
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
udp        0      0 0.0.0.0:57560           0.0.0.0:*                           56045/./StardewVall

发现星露谷开放了一个端口号为57560udp协议端口,不清楚是不是局域网游戏的端口(毕竟游戏模式是离线)

再将服务器模式改为仅朋友

再使用netstat查看星露谷端口占用情况

$ netstat -tunlp | grep Stardew
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
udp        0      0 0.0.0.0:24642           0.0.0.0:*                           56045/./StardewVall
udp        0      0 0.0.0.0:57560           0.0.0.0:*                           56045/./StardewVall

发现星露谷又开放了一个端口号为24642的 udp 端口(由于开启了多人游戏所以推测24642是局域网多人游戏的端口)

记住24642这个端口号,一会使用 frp 进行内网穿透时会用到,还有走的udp协议

什么是内网穿透(NAT 穿透)

内网穿透可以说是 NAT 穿透,如果你在 Wikipedia 上搜索内网穿透的话搜索页面会被重定向到NAT 穿透,那么什么是NAT

NAT

NAT 即(Network Address Translation)中文译为网络地址转换。是在计算机网络中是一种在 IP 数据包通过路由器或防火墙时重写来源 IP 地址或目的 IP 地址的技术。这种技术被普遍使用在有多台主机但只通过一个公有 IP 地址访问互联网的私有网络中。它是一个方便且得到了广泛应用的技术。当然,NAT 也让主机之间的通信变得复杂,导致了通信效率的降低。

基本网络地址转换(Basic NAT)

这一种也可称作 NAT 或“静态 NAT”,在 RFC 2663 中提供了信息。它在技术上比较简单,仅支持地址转换,不支持端口映射。Basic NAT 要求对每一个当前连接都要对应一个公网 IP 地址,因此要维护一个公网的地址池。宽带(broadband)路由器通常使用这种方式来允许一台指定的设备去管理所有的外部链接,甚至当路由器本身只有一个可用外部 IP 时也如此,这台路由器有时也被标记为 DMZ 主机。由于改变了 IP 源地址,在重新封装数据包时候必须重新计算校验和,网络层以上的只要涉及到 IP 地址的头部校验和都要重新计算。

Basic NAT 要维护一个无端口号 NAT 表,结构如下:

内网 IP外网 IP
192.168.1.55219.152.168.222
192.168.1.59219.152.168.223
192.168.1.155219.152.168.224
网络地址端口转换(NAPT)

这种方式支持端口的映射,并允许多台主机共享一个公网 IP 地址。支持端口转换的 NAT 又可以分为两类:源地址转换和目的地址转换。前一种情形下发起连接的计算机的 IP 地址将会被重写,使得内网主机发出的数据包能够到达外网主机。后一种情况下被连接计算机的 IP 地址将被重写,使得外网主机发出的数据包能够到达内网主机。实际上,以上两种方式通常会一起被使用以支持双向通信。

NAPT 维护一个带有 IP 以及端口号的 NAT 表,结构如下:

内网 IP外网 IP
192.168.1.55:5566219.152.168.222:9200
192.168.1.59:80219.152.168.223:9201
192.168.1.155:4465219.152.168.224:9202

现在你应经知道了 NAT 可以转换 IP 地址和 IP 地址及其端口了,通过上述所说 NAT 这些功能所实现的技术可称之为内网穿透了。那么如何实现内网穿透?我们需要使用的是一款基于 Go 语言编写的开源软件frp

frp 使用

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

下载

在 frp 的 github 仓库release页面找到对应的客户端和服务端版本进行下载

解压

$ tar -zxvf frp_0.34.3_linux_amd64.tar.gz
frp_0.34.3_linux_amd64/
frp_0.34.3_linux_amd64/frps
frp_0.34.3_linux_amd64/frps.ini
frp_0.34.3_linux_amd64/LICENSE
frp_0.34.3_linux_amd64/frpc.ini
frp_0.34.3_linux_amd64/frps_full.ini
frp_0.34.3_linux_amd64/frpc_full.ini
frp_0.34.3_linux_amd64/systemd/
frp_0.34.3_linux_amd64/systemd/[email protected]
frp_0.34.3_linux_amd64/systemd/[email protected]
frp_0.34.3_linux_amd64/systemd/frpc.service
frp_0.34.3_linux_amd64/systemd/frps.service
frp_0.34.3_linux_amd64/frpc

你会发现存在着 frps 和 frpc 这两类文件分别是服务端文件(frpServer)和客户端文件(frpClient)

服务端文件一览

服务端完整所需的文件是这样的

$ tree
.
├── frps
├── frps.ini
└── systemd
    ├── frps.service
    └── [email protected]

1 directory, 5 files

客户端文件一览

客户端完整所需的文件是这样的

$ tree
.
├── frpc
├── frpc.ini
└── systemd
    ├── frpc.service
    └── [email protected]

1 directory, 5 files

将服务端文件通过scp命令上传至服务器,客户端文件通过cp保存到本地。

配置

服务端配置

通过 vim 打开 frps.ini

[common]
bind_port = 7000

添加tokendashboard_portdashboard_userdashboard_pwd参数

frps.ini 参数说明
参数说明
bind_portfrp 服务端与客户端访问绑定端口
token访问验证令牌需要服务端与客户端一致(安全性建议添加)
dashboard_portfrp 的仪表盘网页界面(可不选)
dashboard_userfrp 的仪表盘网页登陆用户名界面(可不选)
dashboard_pwdfrp 的仪表盘网页登陆密码界面(可不选)

添加参数后的 frps.ini

[common]
bind_port = 7000
token = example_token
dashboard_port = 7500
dashboard_user = example_user
dashboard_pwd = example_password

客户端配置

通过 vim 打开 frpc.ini

[common]
server_addr = 127.0.0.1
server_port = 7000

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
  1. 修改common项中server_addr参数,并添加token参数(应与服务端 token 保持一致),删除 ssh 所有的参数
  2. 添加stardewValleytype参数为tcplocal_ip参数为127.0.0.1local_port参数为24642remote_port参数为24642
frpc.ini 参数说明
参数说明
server_addrfrp 服务端 ip 地址
server_portfrp 客户端与服务端访问绑定端口
token访问验证令牌需要服务端与客户端一致(安全性建议添加)
type连接类型
local_ip本地被转发 ip 地址
local_port本地被转发 ip 地址对应端口
remote_port远程开放访问监听端口

修改参数后的 frpc.ini

[common]
server_addr = example.com
server_port = 7000
token = example_token

[stardewValley]
type = udp
local_ip = 127.0.0.1
local_port = 24642
remote_port = 24642

在这里你会发现type对应的是之前netstat查看星露谷端口的udp协议

local_port 是netstat查看的星露谷端口号24642

由于星露谷加入多人游戏时不像 Terraria 一样会可以让用户选择输入端口,星露谷的端口是固定的(你在加入局域网游戏时输入 ip 地址后会自动附加 24642 这个端口),所以remote_port应填24642

启动

服务端启动

通过screen -S frp建立一个新的窗口

启用frps

$ ./frps -c frps.ini

看到终端显示如下表示运行成功

$ ./frps -c frps.ini
2021/01/05 16:05:27 [I] [service.go:190] frps tcp listen on 0.0.0.0:7000
2021/01/05 16:05:27 [I] [service.go:289] Dashboard listen on 0.0.0.0:7500
2021/01/05 16:05:27 [I] [root.go:215] start frps success

客户端启动

通过screen -S frp建立一个新的窗口

启用frpc

$ ./frpc -c frpc.ini

看到终端显示如下表示运行成功

$ ./frpc -c frpc.ini
2021/01/05 16:06:55 [I] [service.go:288] [b5d1240fd9b4a92b] login to server success, get run id [b5d1240fd9b4a92b], server udp port [0]
2021/01/05 16:06:55 [I] [proxy_manager.go:144] [b5d1240fd9b4a92b] proxy added: [stardewValley]
2021/01/05 16:06:55 [I] [control.go:180] [b5d1240fd9b4a92b] [stardewValley] start proxy success
2021/01/05 16:06:56 [I] [proxy.go:478] [b5d1240fd9b4a92b] [stardewValley] incoming a new work connection for udp proxy, example.com:7000

服务端与客户端连接

在服务器上重新使用screen -R frp进入原有的frp窗口如果查看以下输出表示服务端与客户端连接成功

2021/01/05 16:06:55 [I] [service.go:444] [b5d1240fd9b4a92b] client login info: ip [your.ip:37869] version [0.34.3] hostname [] os [linux] arch [amd64]
2021/01/05 16:06:55 [I] [udp.go:84] [b5d1240fd9b4a92b] [stardewValley] udp proxy listen port [24642]
2021/01/05 16:06:55 [I] [control.go:446] [b5d1240fd9b4a92b] new proxy [stardewValley] success
2021/01/05 16:06:56 [I] [proxy.go:103] [b5d1240fd9b4a92b] [stardewValley] get a new work connection: [your.ip:37869]

进行多人局域网游戏

现在就可以小伙伴打开星露谷在局域网联机的 ip 地址框(不需要输入端口号)输入你的服务器地址和你进行多人联机了~