“更新说明(2026-03-16)”

本文已根据实际部署与排障过程进行修订,主要更新内容包括:

  1. 修正 FRP 服务端/客户端配置说明;
  2. 补充 Sunshine 自定义端口族与多客户端并存的配置逻辑;
  3. 新增 Moonlight certificate mismatchunexpected end of stream、端口检测异常等问题的排查说明;
  4. 修正部分端口开放与服务暴露建议。

网络检测

带宽

对于串流被控端需要有足够的上行带宽,例如4K 60FPS一般需要50Mbps,如果要排除一些网络不稳定状态,可能还需要有1/3的冗余带宽;同理,对于串流控制端需要有足够的下行带宽,也需要大致50Mbps。我们这里可以用 speedtest 等软件进行测量。

延迟

对于一些高交互性,竞技性的游戏,串流进行游戏不建议,毕竟有一个服务器的往返时间差,吃力不讨好。对于一些如逆转裁判,GAL等非即时交互的游戏可以有一个比较好的体验,总而言之对于远程串流而言,时延越低体验越好。一般来说,60ms 以内仍可接受,超过 100ms 后,在高交互场景中更容易出现明显的输入迟滞、音画不同步等问题。这边可以用ping来测试服务器时延,但是需要*2。

丢包率

如果网络质量比较差,丢包就会导致视频流,音频流不稳定,画面出现花屏,模糊,断裂,严重影响使用体验,这边也可以用ping来测量。

NAT

NAT的层级对于我们串流方式的选择也有很大的影响,一般划分NAT为4个层级,NAT1、NAT2、NAT3、NAT4,对于想要实现NAT穿越的用户来说,NAT 类型会影响串流方案的选择。若双方网络条件较好,可以尝试点对点连接;若处于严格 NAT 或运营商网络环境下,通常更稳妥的做法是通过具备公网 IP 的中继服务器进行转发,例如使用 FRP。在NAT3与NAT4的环境中,内部网络的设备通过路由器共享同一个公网IP地址,外部的设备无法直接访问内网中的设备。为了让外部设备能够访问内网设备,需要通过路由器进行端口转发或者使用中继服务器;在NAT1与NAT2环境下,由于路由器允许更加自由的连接和端口映射,内网设备可以直接与外网设备之间直接建立联系,即P2P打洞,实现更加好的网络性能。
我们这边使用FRP进行终端流量转播来实现流量的转播。 你可以使用一些在线网站 MyNat NatTypeTester 等一些工具查看你现在使用网络的NAT类型。

FRP穿透

FRP 是一个用于内网穿透的反向代理应用,将服务器端部署在具有公网IP的机器上,客户端部署在内网或者防火墙内的机器上,通过访问暴露在服务器上的端口,反向代理到处于内网的服务。

FRPS

Sunshine 默认端口族

Sunshine 默认以 47989 为基准端口,相关端口族如下:

## Sunshine 默认端口族

- TCP
  - 47984:HTTPS
  - 47989:HTTP
  - 47990:Web UI
  - 48010:RTSP

- UDP
  - 47998:Video
  - 47999:Control
  - 48000:Audio
  - 48002:Mic(通常未使用)

Sunshine 官方文档说明,修改 port 后,其它端口会按固定偏移整体变化;Moonlight 官方文档也把 47984、47989、48010(TCP)以及 47998、47999、48000、48002、48010(UDP)列为 Sunshine 场景下需要关注的联网端口。

服务器端口开放

# FRP
sudo ufw allow 7000/tcp
sudo ufw allow 7500/tcp

# Sunshine A(默认端口族,基础端口 47989)
sudo ufw allow 47984/tcp
sudo ufw allow 47989/tcp
sudo ufw allow 48010/tcp

sudo ufw allow 47998/udp
sudo ufw allow 47999/udp
sudo ufw allow 48000/udp
sudo ufw allow 48002/udp
sudo ufw allow 48010/udp

# 查看规则
sudo ufw status numbered

我们需要在购置的服务器的外部配置网站上开放FRP以及Moonlight与Sunshine的服务通讯端口。

frps.toml

我们首先需要下载 frp的打包软件 ,这里用的是0.67.0的版本。解压下来可以并编辑我们的frps.toml服务端frp配置

/usr/bin/frps/frps.toml 15 lines
bindPort = 7000

auth.method = "token"
auth.token = "YOUR_TOKEN"

webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "YOUR_ADMIN"
webServer.password = "YOUR_PASSWORD"

transport.tcpMux = true

allowPorts = [
  { start = 47984, end = 48010 }
]

/etc/systemd/system/frps.service 14 lines
[Unit]
Description=FRP Server (frps)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/frps -c /etc/frp/frps.toml
Restart=always
RestartSec=3
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

我这边的配置是将解压下来的软件包换了个位置,具体需要按自己的情况修改frps.toml和frps位置。

sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo systemctl status frps --no-pager

可以通过以上指令进行frps服务自启动

FRPC

同样的,我们需要在被控端使用frp中frpc服务。

/etc/frp/frpc.toml 63 lines
serverAddr = "服务器公网IP"
serverPort = 7000

auth.method = "token"
auth.token = "YOUR_TOKEN"

user = "pc-a"

[[proxies]]
name = "sunshine-https"
type = "tcp"
localIP = "127.0.0.1"
localPort = 47984
remotePort = 47984

[[proxies]]
name = "sunshine-http"
type = "tcp"
localIP = "127.0.0.1"
localPort = 47989
remotePort = 47989

[[proxies]]
name = "sunshine-rtsp-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 48010
remotePort = 48010

[[proxies]]
name = "sunshine-video"
type = "udp"
localIP = "127.0.0.1"
localPort = 47998
remotePort = 47998

[[proxies]]
name = "sunshine-control"
type = "udp"
localIP = "127.0.0.1"
localPort = 47999
remotePort = 47999

[[proxies]]
name = "sunshine-audio"
type = "udp"
localIP = "127.0.0.1"
localPort = 48000
remotePort = 48000

[[proxies]]
name = "sunshine-mic"
type = "udp"
localIP = "127.0.0.1"
localPort = 48002
remotePort = 48002

[[proxies]]
name = "sunshine-rtsp-udp"
type = "udp"
localIP = "127.0.0.1"
localPort = 48010
remotePort = 48010

如果需要配置被控端自启动,linux就用service,windows就用bat,看自己使用情况。

多客户端情况

如果只接入一台 Sunshine 主机,直接使用默认端口族即可。
如果要同时接入多台 Sunshine 主机,frpc.toml则需要满足以下条件:

  1. 每台客户端使用不同的 user
  2. 每台客户端的代理 name 唯一;
  3. 每台客户端占用不同的 remotePort
  4. 如果某台主机修改了 Sunshine 基础端口,则该主机的 localPort 也必须对应新的端口族。

假设第二台 Sunshine 主机将基础端口改为 48989,则其本地端口族会变为:

- TCP
  - 48984
  - 48989
  - 48990
  - 49010

- UDP
  - 48998
  - 48999
  - 49000
  - 49002
  - 49010

/etc/frp/frpc-b.toml 63 lines
serverAddr = "服务器公网IP"
serverPort = 7000

auth.method = "token"
auth.token = "YOUR_TOKEN"

user = "pc-b"

[[proxies]]
name = "sunshine-b-https"
type = "tcp"
localIP = "127.0.0.1"
localPort = 48984
remotePort = 48984

[[proxies]]
name = "sunshine-b-http"
type = "tcp"
localIP = "127.0.0.1"
localPort = 48989
remotePort = 48989

[[proxies]]
name = "sunshine-b-rtsp-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 49010
remotePort = 49010

[[proxies]]
name = "sunshine-b-video"
type = "udp"
localIP = "127.0.0.1"
localPort = 48998
remotePort = 48998

[[proxies]]
name = "sunshine-b-control"
type = "udp"
localIP = "127.0.0.1"
localPort = 48999
remotePort = 48999

[[proxies]]
name = "sunshine-b-audio"
type = "udp"
localIP = "127.0.0.1"
localPort = 49000
remotePort = 49000

[[proxies]]
name = "sunshine-b-mic"
type = "udp"
localIP = "127.0.0.1"
localPort = 49002
remotePort = 49002

[[proxies]]
name = "sunshine-b-rtsp-udp"
type = "udp"
localIP = "127.0.0.1"
localPort = 49010
remotePort = 49010

frps 端口白名单(多客户端)

如果第二台主机使用 48989 这一组端口,则服务端的 allowPorts 和防火墙规则也需要同步增加:

/usr/bin/frps/frps.toml 4 lines
allowPorts = [
  { start = 47984, end = 48010 },
  { start = 48984, end = 49010 }
]

服务端防火墙也可以写成:

sudo ufw allow 48984/tcp
sudo ufw allow 48989/tcp
sudo ufw allow 49010/tcp

sudo ufw allow 48998/udp
sudo ufw allow 48999/udp
sudo ufw allow 49000/udp
sudo ufw allow 49002/udp
sudo ufw allow 49010/udp

Sunshine & Moonlight

Sunshine Moonlight 是串流的游戏流媒体服务端以及客户端,我们需要在被控电脑端配置Sunshine,在控制端配置Moonlight。 Sunshine直接下载Release中适合自己版本并打包好的软件即可,一般打开后访问 192.168.1.5:47990 。第一次访问需要设置用户名与密码,之后等待Moonlight端发起串流请求并在PIN选项卡中输入Moonlight给出的PIN码即可。
Moonlight需要你控制端如平板,手机,笔记本电脑等上安装,之后填入服务器的公网IP,如果配置了第二台客户端,需要填入公网IP:48989,以此类推,就会返回一个PIN码,在Sunshine中输入即可建立串流。
Sunshine还需要配置自启动,这个也需要根据被控端的系统来设置。

参考

Moonlight 远程串流 + 远程开机全流程搭建(低成本方案)
体验较好的低延迟串流方案 | MoonLight+Sunshine+Tailscale
Server搭建过程-5.Frp穿透介绍和P2P