又一个命令行文件传输,这次用边缘函数做 TCP 打洞

2023-01-16 08:17:23 +08:00
 Contextualist

简单来说,就是用 Deno deploy 这个跑 V8 的平台做建立点对点连接时打洞用的公共服务器。实现主要归功于 Deno deploy 的以下特性:

具体可以参见我边缘函数的实现

噱头归噱头,我也是真心想做一个比市面上已有的命令行文件传输更好用的工具。现有的工具设计时大部分是考虑传文件给他人的场景,但对于我来说,更多是在自己的不同服务器 /设备间传文件的场景。因此,大可不必每次传输都要求用户复制粘贴一段随机代号,身份验证信息可以提前存储到每台设备上。

acp 使用体验上尽量贴近 cp ,发送端指定文件,接收端不需要指定任何信息。并且启动无分先后,两边都就绪后即开始协商建立连接传输。

安装脚本详见 README(就下载个可执行文件然后初始化配置)

最后忍不住说一句,边缘函数干这个实在是太适合了,轻量低成本低延迟,还颇有拆手机锂电池用来生火的风味

项目在这: https://github.com/Contextualist/acp

3200 次点击
所在节点    分享创造
26 条回复
v2wtf
2023-01-16 09:20:42 +08:00
问一下,多人同时使用的情况下,是如何判断谁发给谁的?是需要事先登录同一个账号?
Contextualist
2023-01-16 09:34:12 +08:00
@v2wtf 对于每个人的第一台设备,acp 在初始化配置 (acp --setup) 时会生成一个随机 ID ,随后的设备初始化配置会导入这个 ID (acp --setup-with '{"id":"... )。使用时会配对相同 ID 发起的、时间上最接近的两个请求。本来这个设计是给每个人自己给自己传文件用的,如果多个人间使用导入相同的配置也行,不过不太适合群发或者临时分享给陌生人。
AS4694lAS4808
2023-01-16 09:35:27 +08:00
如果是自己的服务器间传文件,用已经信任的密钥+scp+zerotier 应该也挺方便吧?
我是写了个 shell 脚本,接受的参数是(服务器名,源文件 /文件夹地址,远程目录)。。
haoxuexiaoyao
2023-01-16 09:37:26 +08:00
安全么 经过服务器么
haoxuexiaoyao
2023-01-16 09:37:35 +08:00
可以局域网部署么
duke807
2023-01-16 10:48:13 +08:00
“边缘函数” 是什么意思?
Contextualist
2023-01-16 10:56:30 +08:00
@AS4694lAS4808 诚然,scp 的地位无可替代,跟它相比,acp 主要是为了省去打服务器名和远程目录的功夫。我自己的使用场景是:我登上一台机器,在其中某个目录深处工作到一半,需要把一些文件拷到当前目录下,作为接收只需要运行个不带参数的 acp ,然后发送端运行 acp path/to/files 即可。

@haoxuexiaoyao 服务只用来做 TCP 打洞的信息交换,真正的文件通过点对点直连传输。所以服务端接收发送的数据只有两边的 ID 和 IP 地址端口。部署到 Deno Deploy 同时也是为了利用他们全球分布的节点,服务端就一个 Deno TypeScript 文件,理论上来说你在任意 vm 上拿 Deno 也能跑。
Contextualist
2023-01-16 11:46:18 +08:00
@duke807 边缘函数类似云函数,用户托管的代码只需要包含一个处理 HTTP 请求的函数。相比一般的云函数,边缘函数的运行时是 V8 (Chrome 和 Node.js 的 Javascript 引擎) 而不是完整的容器,因而部署成本低并且冷启动非常快。
Actrace
2023-01-16 12:19:04 +08:00
这个项目太棒了!
lysS
2023-01-16 12:28:23 +08:00
我只知道 UDP 打洞的原理,TCP 打洞是不是要 root 权限发送 raw ip 包?
duke807
2023-01-16 12:34:27 +08:00
@Contextualist
云函数又是什么?
不用容器不就是经典的直接运行的 nodejs 之类的程序,不用 docker 而已么
novolunt
2023-01-16 13:27:35 +08:00
没配置吗? receiver 怎么接收指定的 sender ,没看到配置
建议使用 zstd 压缩,性能比 gzip 好
novolunt
2023-01-16 13:42:24 +08:00
测试了下,可以穿透内外网,很棒。
AS4694lAS4808
2023-01-16 13:53:18 +08:00
@duke807 公有云提供的服务,你把代码传上去,不用管运行环境,公有云提供软硬件运行你的代码
Contextualist
2023-01-16 14:12:17 +08:00
@lysS 其实原理跟 UDP 打洞差不多,大概都是两边先各自跟第三方建立连接,再重用端口尝试互相连接。随着路由和设备支持的逐渐完善,现在 TCP 打洞成功率还是挺高的。不需要 root ,TCP socket 可以设置 SO_REUSEADDR 和 SO_REUSEPORT ,使同一个端口像 UDP 那样能同时被多个 socket 绑定。

@duke807 云函数基本就是你把代码交给平台,运维完全交给他们,平台根据请求数量伸缩实例数量,按照实际运行消耗的 CPU 时间和内存计费,没请求时不收费。边缘函数平台的 V8 比普通 Node.js 增加了权限隔离和横向伸缩等等,基本上像一个不带操作系统的容器了。

@novolunt 谢谢建议!我去看看
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 就变了
Contextualist
2023-01-16 18:03:29 +08:00
@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 有其他报错吗?
gogf
2023-01-16 19:00:38 +08:00
@Contextualist
环境变量没有发生变化,acp --setup 也没有报错信息,我后面测试正常了,配置文件存在

不过我可以确定两次生成的参数确实不一样,应该是第一次因为某些原因没写进去

收发文件的问题还存在
Contextualist
2023-01-16 19:38:18 +08:00
@gogf 我盯着代码又仔细想了一下,很有可能在连接配对公共服务时就出错了,但是这个错误没有被及时检查,被后来的收发信息错误覆盖了。所以可以快速尝试的事是看看你在终端里能不能正常访问 https://acp.deno.dev/get ,类似用 curl 发个 get 请求。如果这个也是正常的,你又不嫌麻烦,我明天修了这个报错顺序的问题,你再看看有没有新的错误信息。总之,感谢你的反馈!
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 还是无法正常使用,同样的报错内容

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/909170

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX