简单来说,就是用 Deno deploy 这个跑 V8 的平台做建立点对点连接时打洞用的公共服务器。实现主要归功于 Deno deploy 的以下特性:
具体可以参见我边缘函数的实现。
噱头归噱头,我也是真心想做一个比市面上已有的命令行文件传输更好用的工具。现有的工具设计时大部分是考虑传文件给他人的场景,但对于我来说,更多是在自己的不同服务器 /设备间传文件的场景。因此,大可不必每次传输都要求用户复制粘贴一段随机代号,身份验证信息可以提前存储到每台设备上。
acp 使用体验上尽量贴近 cp ,发送端指定文件,接收端不需要指定任何信息。并且启动无分先后,两边都就绪后即开始协商建立连接传输。
安装脚本详见 README(就下载个可执行文件然后初始化配置)
最后忍不住说一句,边缘函数干这个实在是太适合了,轻量低成本低延迟,还颇有拆手机锂电池用来生火的风味。
1
v2wtf 2023-01-16 09:20:42 +08:00
问一下,多人同时使用的情况下,是如何判断谁发给谁的?是需要事先登录同一个账号?
|
2
Contextualist OP @v2wtf 对于每个人的第一台设备,acp 在初始化配置 (acp --setup) 时会生成一个随机 ID ,随后的设备初始化配置会导入这个 ID (acp --setup-with '{"id":"... )。使用时会配对相同 ID 发起的、时间上最接近的两个请求。本来这个设计是给每个人自己给自己传文件用的,如果多个人间使用导入相同的配置也行,不过不太适合群发或者临时分享给陌生人。
|
3
AS4694lAS4808 2023-01-16 09:35:27 +08:00
如果是自己的服务器间传文件,用已经信任的密钥+scp+zerotier 应该也挺方便吧?
我是写了个 shell 脚本,接受的参数是(服务器名,源文件 /文件夹地址,远程目录)。。 |
4
haoxuexiaoyao 2023-01-16 09:37:26 +08:00
安全么 经过服务器么
|
5
haoxuexiaoyao 2023-01-16 09:37:35 +08:00
可以局域网部署么
|
6
duke807 2023-01-16 10:48:13 +08:00 via Android
“边缘函数” 是什么意思?
|
7
Contextualist OP @AS4694lAS4808 诚然,scp 的地位无可替代,跟它相比,acp 主要是为了省去打服务器名和远程目录的功夫。我自己的使用场景是:我登上一台机器,在其中某个目录深处工作到一半,需要把一些文件拷到当前目录下,作为接收只需要运行个不带参数的 acp ,然后发送端运行 acp path/to/files 即可。
@haoxuexiaoyao 服务只用来做 TCP 打洞的信息交换,真正的文件通过点对点直连传输。所以服务端接收发送的数据只有两边的 ID 和 IP 地址端口。部署到 Deno Deploy 同时也是为了利用他们全球分布的节点,服务端就一个 Deno TypeScript 文件,理论上来说你在任意 vm 上拿 Deno 也能跑。 |
8
Contextualist OP @duke807 边缘函数类似云函数,用户托管的代码只需要包含一个处理 HTTP 请求的函数。相比一般的云函数,边缘函数的运行时是 V8 (Chrome 和 Node.js 的 Javascript 引擎) 而不是完整的容器,因而部署成本低并且冷启动非常快。
|
9
Actrace 2023-01-16 12:19:04 +08:00
这个项目太棒了!
|
10
lysS 2023-01-16 12:28:23 +08:00
我只知道 UDP 打洞的原理,TCP 打洞是不是要 root 权限发送 raw ip 包?
|
11
duke807 2023-01-16 12:34:27 +08:00 via Android
|
12
novolunt 2023-01-16 13:27:35 +08:00
没配置吗? receiver 怎么接收指定的 sender ,没看到配置
建议使用 zstd 压缩,性能比 gzip 好 |
13
novolunt 2023-01-16 13:42:24 +08:00
测试了下,可以穿透内外网,很棒。
|
14
AS4694lAS4808 2023-01-16 13:53:18 +08:00 via Android
@duke807 公有云提供的服务,你把代码传上去,不用管运行环境,公有云提供软硬件运行你的代码
|
15
Contextualist OP @lysS 其实原理跟 UDP 打洞差不多,大概都是两边先各自跟第三方建立连接,再重用端口尝试互相连接。随着路由和设备支持的逐渐完善,现在 TCP 打洞成功率还是挺高的。不需要 root ,TCP socket 可以设置 SO_REUSEADDR 和 SO_REUSEPORT ,使同一个端口像 UDP 那样能同时被多个 socket 绑定。
@duke807 云函数基本就是你把代码交给平台,运维完全交给他们,平台根据请求数量伸缩实例数量,按照实际运行消耗的 CPU 时间和内存计费,没请求时不收费。边缘函数平台的 V8 比普通 Node.js 增加了权限隔离和横向伸缩等等,基本上像一个不带操作系统的容器了。 @novolunt 谢谢建议!我去看看 |
16
gogf 2023-01-16 17:22:57 +08:00
反馈个问题:
Win10: acp --setup 之后,acp 发送文件,报错:failed to communicate with the bridge: io: read/write on closed pipe Linux 下正常 而且 Windows 下貌似换个文件夹重新 setup ,id 、psk 就变了 |
17
Contextualist OP @gogf 谢谢反馈!我找了台 Windows 的机子,没法复现,这两个现象我暂时没头绪,不过我可以尝试解释一下。
> 报错:failed to communicate with the bridge: io: read/write on closed pipe 能连上配对的公共服务,但是收发信息时连接断开了,不过我在服务端也没看见报错日志。 > 貌似换个文件夹重新 setup ,id 、psk 就变了 这就很奇怪,acp --setup 会去找 %APPDATA%\acp\config.json 配置在不在,找不到才会重新生成。你的 %APPDATA% 环境变量有发生改变吗?你能在那个位置找到配置吗? acp --setup 有其他报错吗? |
18
gogf 2023-01-16 19:00:38 +08:00
@Contextualist
环境变量没有发生变化,acp --setup 也没有报错信息,我后面测试正常了,配置文件存在 不过我可以确定两次生成的参数确实不一样,应该是第一次因为某些原因没写进去 收发文件的问题还存在 |
19
Contextualist OP @gogf 我盯着代码又仔细想了一下,很有可能在连接配对公共服务时就出错了,但是这个错误没有被及时检查,被后来的收发信息错误覆盖了。所以可以快速尝试的事是看看你在终端里能不能正常访问 https://acp.deno.dev/get ,类似用 curl 发个 get 请求。如果这个也是正常的,你又不嫌麻烦,我明天修了这个报错顺序的问题,你再看看有没有新的错误信息。总之,感谢你的反馈!
|
20
gogf 2023-01-17 10:15:47 +08:00
@Contextualist
确实无法访问,浏览器与 curl 都无法访问,挂了代理就行,移动宽带 curl 报错:curl: (35) schannel: failed to receive handshake, SSL/TLS connection failed 终端在可以正常 get “https://acp.deno.dev/get“的前提下,acp 还是无法正常使用,同样的报错内容 |
21
Contextualist OP @gogf
我大概明白了,你是在用 HTTPS_PROXY 之类的环境变量吗?这个目前的实现会无视代理的环境变量。我修了这个问题后自己试了一下,发现用代理时建立不了 P2P 连接,你如果想试一下可以试试目前最新提交的 CI artifacts: https://github.com/Contextualist/acp/actions/runs/3935796582 这个页面最底下可以下载。我得花时间想想这个问题是不是能解决的。 如果一定需要代理,我自己试了一下目前那种基于 fake IP 的真全局代理(比如 ClashX Pro 的增强模式)是可以用的。 |
22
gogf 2023-01-17 14:01:09 +08:00
@Contextualist
我原本是没有设置代理的,我的意思是设置了 HTTPS_PROXY 才能访问 “ https://acp.deno.dev/get ” 另外,https://github.com/Contextualist/acp/actions/runs/3935796582 这里好像并不能下载最新版,不知道没有权限还是什么,没用过 GitHub Actions... |
23
Contextualist OP @gogf 嗯,我需要研究一下怎么样正确支持 HTTPS_PROXY ,等到时候有结果了跟你说。
看了一下,GitHub Actions 好像需要登录才能下载 artifacts ,任意账户都行。如果不行,你也可以用我下载下来的这个: https://t.wss.ink/f/aa11yspjrlv |
24
Contextualist OP @gogf 实在是抱歉!我折腾了半天,还是没能解决跟代理一起使用的兼容问题,下面是初步结论(但感觉解释不太清楚
对于使用代理的一方,只有代理服务器连接 acp.deno.dev 时使用的 IP 端口是对外可见的,但是这个 IP 端口实际上并不能被其他连接重用。 如果另一方没使用代理并且有公网,那或许可以连接上,但是实际测试发现,使用代理的一方不能设置端口重用(似乎是 Go 的 bug )。 对此,剩下的选择是你自己部署服务端(参见 https://github.com/Contextualist/acp/blob/main/docs/advanced.md#host-the-rendezvous-service-yourself ),在 Deno Deploy 上或者自己的服务器上都行,然后绑定一个自己的域名。 |
25
sbilly 2023-01-29 16:35:12 +08:00
@Contextualist Linux/Windows/macOS 都支持吗?
|
26
Contextualist OP @sbilly 都支持的,并且有相应的持续集成测试
|