Cloudreve icon indicating copy to clipboard operation
Cloudreve copied to clipboard

[Feature Request]个人私有部署,基于IPv6和P2P通信的网络架构设计

Open yixinin opened this issue 6 months ago • 2 comments

网络架构图如下 Image

一共有3种访问Cloudreve方式:

  1. 当客户端不支持IPv6时,通过Cloudflare的tunnel访问IPv4域名
  2. 客户端通过IPv6域名直接访问
  3. 借助Stun打洞P2P访问

Cloudreve的改动:

  1. 需要实现信令服务器功能 (HTTP,因为tunnel服务总是可以访问的,stun借助公共服务器或自建)。
  2. UDP打洞成功后创建QUIC连接,并提供HTTP服务。

该部署方式需要自己的域名域名,并托管到cloudflare。

部署:

  1. 本地运行cloudreve,此时cloudreve位于nat之内,外网无法访问。
  2. 到cloudflare创建tunnel,并在本地运行,代理cloudreve,此时可以通过ipv4/ipv6访问tunnel代理的域名,但是访问速度较慢。
  3. 关闭本地的IPv6防火墙,并打开路由器下所有设备的IPv6防火墙(有风险,请自行评估)
  4. 防火墙打开cloudreve端口,添加IPv6域名解析到cloudreve

如何打洞: 当客户端无法访问IPv6域名时,借助公共stun服务器进行端口发现,并通过cloudflare代理的域名进行peer地址交换完成打洞。

HTTPS和证书: 可以借助Caddy循环申请免费的HTTPS证书,由于运营商默认屏蔽了家庭网络的80和443端口,所以IPv6域名无法通过80/443访问。

yixinin avatar Jun 11 '25 07:06 yixinin

该方案完全免费(域名除外),并能够支持大部分网络下的高速访问(在完全对称网络下打洞可能失败)。

yixinin avatar Jun 11 '25 07:06 yixinin

我听不太懂啥意思,欢迎其他人贡献。

HFO4 avatar Jun 11 '25 13:06 HFO4

signal server应该由cloudreve实现吗?signal server也应该是另一个公网服务器提供,cloudreve只需要支持对接signal server接发offer/answer,除非是希望手动同步offer了. P2P这里作为应用层不应该太多改动吧,支持quic原生udp http都相当少见了

wintbiit avatar Jun 17 '25 10:06 wintbiit

signal server应该由cloudreve实现吗?signal server也应该是另一个公网服务器提供,cloudreve只需要支持对接signal server接发offer/answer,除非是希望手动同步offer了. P2P这里作为应用层不应该太多改动吧,支持quic原生udp http都相当少见了

我认为应该由cloudreve实现,实际上server的udp端口是可以固定的,定时向stun获取/维持公网地址,并不需要实现完整的signal服务,只需接收client公网地址后告诉client当前server的公网地址,1对N服务。

对于WEB端,我不确定是否能够主动发起UDP连接(http/3 quic), 可以考虑go-wasm的方式实现,如果不行可能需要借助webrtc来实现UDP通信。

yixinin avatar Jun 17 '25 16:06 yixinin

https://github.com/cloudreve/cloudreve/pull/2507

rust client 示例: https://github.com/yixinin/p2p-client-rs

yixinin avatar Jun 17 '25 16:06 yixinin

看起来应该在网络协议层里实现,在服务端和客户端部署网络中间件实现连接,而不是让应用来做这个事。

Candinya avatar Jun 21 '25 02:06 Candinya

看起来应该在网络协议层里实现,在服务端和客户端部署网络中间件实现连接,而不是让应用来做这个事。

移动端网络中间件实现起来可能比较麻烦?具体不是很了解Android和iOS的权限控制,也许可以做类似vpn的网络代理?

yixinin avatar Jun 23 '25 08:06 yixinin

看起来应该在网络协议层里实现,在服务端和客户端部署网络中间件实现连接,而不是让应用来做这个事。

移动端网络中间件实现起来可能比较麻烦?具体不是很了解Android和iOS的权限控制,也许可以做类似vpn的网络代理?

也不完全是,我是指单独维护一个 p2p 的网络工具专门用于实现这个需求,然后再将 cloudreve 或者其他需要这个功能的应用放在这个工具的后面,由工具来提供反向代理服务,而不是把这个需求直接集成到应用里面。算是一种解耦的思想,主要是为了避免在应用里引入和业务不相关的功能,同时如果未来要部署更多不同应用,就可以直接在工具里添加反向代理规则,而不是在每一个应用里都集成一套代码这样。

移动端实现的话,区分 IPv4 和 IPv6 的话可以使用 DNS 的条件解析(IPv4 使用 A 记录, IPv6 使用 AAAA 记录,但 CloudFlare 的 tunnel 我记得好像是 CNAME 形式提供的,或需要考虑结合一些其他的 DNS 条件解析方案,比如参考优选 IP 的接入方案之类的)。STUN 之类内网穿透打洞方案应该在语音通话之类的场景里也会有所涉及(以前部署 matrix 的时候稍微有看到过一些),如果实现一个针对这个工具开发的客户端的话或许可以避开系统级别的 VPN 配置。

Candinya avatar Jun 25 '25 06:06 Candinya

看起来应该在网络协议层里实现,在服务端和客户端部署网络中间件实现连接,而不是让应用来做这个事。

移动端网络中间件实现起来可能比较麻烦?具体不是很了解Android和iOS的权限控制,也许可以做类似vpn的网络代理?

也不完全是,我是指单独维护一个 p2p 的网络工具专门用于实现这个需求,然后再将 cloudreve 或者其他需要这个功能的应用放在这个工具的后面,由工具来提供反向代理服务,而不是把这个需求直接集成到应用里面。算是一种解耦的思想,主要是为了避免在应用里引入和业务不相关的功能,同时如果未来要部署更多不同应用,就可以直接在工具里添加反向代理规则,而不是在每一个应用里都集成一套代码这样。

移动端实现的话,区分 IPv4 和 IPv6 的话可以使用 DNS 的条件解析(IPv4 使用 A 记录, IPv6 使用 AAAA 记录,但 CloudFlare 的 tunnel 我记得好像是 CNAME 形式提供的,或需要考虑结合一些其他的 DNS 条件解析方案,比如参考优选 IP 的接入方案之类的)。STUN 之类内网穿透打洞方案应该在语音通话之类的场景里也会有所涉及(以前部署 matrix 的时候稍微有看到过一些),如果实现一个针对这个工具开发的客户端的话或许可以避开系统级别的 VPN 配置。

服务端:这样做是可行的,在cloudreve前挂一个reverse proxy,但是这样做会需要一个单独的signal server(也许reverse proxy或者cloudreve可以兼职一下),不好的点在于对于普通用户来讲部署起来较麻烦。 方案一:通过代理访问 方案二:Cloudreve应用内集成

客户端:

  • Windows/Linux/Macos:
    • 方案一:在宿主机运行一个Proxy,WEB和APP通过Proxy访问
    • 方案二:
      • APP:APP内实现p2p(stun)+quic(http/3)
      • WEB: 受限于浏览器(无法直接操作UDP套接字),借助WASM实现WEBRTC/DataChannel代理HTTP请求,所有的http请求通过WASM。(WASM也许可以在WEBRTC交换offer后直接建立QUIC连接,目前不确定,但借助WASM+WEBRTC应该是必须的)
  • Android/iOS
    • 方案一:在宿主机运行一个Proxy(VPN?),WEB和APP通过Proxy访问
    • 方案二:同Windows/Linux/Macos

优劣: 方案一: - 优点:和具体的应用解耦,扩展性较强 - 缺点:部署麻烦,需要维护多个组件,移动端权限不好控制 方案二: - 优点: 部署简单,维护简单 - 缺点:入侵了业务代码,提高了系统复杂度。

我个人还是倾向于方案二,作为一个面向非专业人员的开源项目,应该尽量减少用户的配置,做到开箱即用。

关于DNS解析和连接方式选择,建议的部署方案: Cloudflare tunnel对于大陆来讲访问速度较慢,只建议在没有IPv4公网地址或者无法配置端口转发的情况下采用. 前提是将域名托管到Cloudflare.

假设现在有域名 abc.com:

  1. 创建Cloudflare tunnel (自带免费https证书), 绑定子域名 drive.abc.com
  2. 如果你的服务器有IPv6地址,创建子域名drive6.abc.com, AAAA记录指向服务器地址(临时IPv6可以通过DDNS来动态更新,推荐ddns-go),家庭宽带无法使用80/443端口,只能使用其它非标端口例如8443,通过https://drive6.abc.com:8443 访问。证书可以使用Caddy来动态申请(免费)。

客户端可以通过当前网络环境来决定访问drive6.abc.com 还是drive.abc.com

yixinin avatar Jun 26 '25 07:06 yixinin

@yixinin 怎么感觉这个讨论串越来越复杂了……

咱会觉得CR是一个单独的服务端的程序,而不是一套商用云存储解决方案。 往本质的说,它只是网盘形状的CMS,除了通过HTTP(TCP)/套接字(socket)外, 用户具体是如何连接到它的,是包括Nginx/VPN在内的各种中间件该解决的问题。

至于你所倾向的方案二…… 诚然……CR面向的用户或许没有那么专业,如果真的支持开箱即用也确实很好。 但通常来说,非专业用户也不太会有机会折腾你所提到的复杂场景。 根据咱的偏见,CR的非专业用户大多还停留在和"宝塔面板部署后怎么提示502","XXX网盘为什么添加不了","你家CR怎么不能自动反映磁盘里的文件变化啊","为什么我在家能访问,在外面访问不了"这类问题斗智斗勇。 能考虑到这么复杂的使用场景的用户,应该有足够的能力完成方案一的配置,至少他们应该有能力通过上网搜索解决这些问题

至于家宽非标端口开服务这件事…… 合规与否先另说,这听起来并不是CR该关心的问题。 如果无论如何都要让CR的某一部分来解决的话,咱觉得由客户端来解决会更现实一些。 比如,DNS记录里面有一种叫做HTTPS记录的特殊SRV记录,它可以在DNS响应阶段提示客户端/浏览器HTTPS服务监听在哪个端口,可用接入点的IP地址一览之类的信息。 所以如果有人愿意开发一个第三方客户端,且计划充分活用这些DNS记录的话,会比让服务端更容易解决这个需求

hatsuyuki280 avatar Jun 26 '25 07:06 hatsuyuki280