全球主机交流论坛

标题: 改了一点realm, 顺便说说目前常见的转发工具 [打印本页]

作者: dunce    时间: 2021-4-29 23:49
标题: 改了一点realm, 顺便说说目前常见的转发工具
本帖最后由 dunce 于 2021-4-30 21:43 编辑

最近抽空学了一点rust(刚看完the book & async programming),  顺便研究了一下realm
作者 @zhboner 平时似乎不怎么上线(两周前合并了一个PR(关于TCP连接关闭的),这之前很长一段时间没有活动)
目前Issue区还有几个问题没解决,我就自己动手改了一下代码,希望可以帮到有需要的人(不知道还有人用没)

先说第一个问题(个人认为比较重要):https://github.com/zhboner/realm/issues/25

这个程序支持批量监听端口。程序启动以后会先单独启动一个线程用于解析域名,随后为每个端口分配一个异步任务,
在每个异步任务中又会开启两个线程用于转发UDP。当监听端口数量比较多的时候,会开启大量线程(用于UDP转发),
占用大量资源。这时候线程间频繁的上下文切换会产生不少额外开销(以及锁),况且大多数人的机器也就1个CPU
(顶多俩个),开这么多线程实在不值得。 Issue里也有人反映端口增加的时候 CPU/内存 占用飙升。

改动: 把线程全都改成异步任务(包括DNS解析),保留了锁。因为如果跑在多核的机器上,tokio就会开启多个线程。

第二个问题: UDP丢包 https://github.com/zhboner/realm/issues/26

UDP转发的逻辑有点暴力:绑定的端口接受到UDP包以后,依次记录来源。等到收到回复的时候再把包转发给之前记录的第一个来源。
只有假设 客户端发送一个包,服务器返回一个包,这种情况下才能正常转发。并且客户端只有一个,不然返回包发送顺序可能会乱。

改动:单独加了个UDP转发模块。每有一个不同的来源,就为其单独分配一个socket 负责跟服务端通讯,持续一段时间。
(应该能用,但是我不清楚这样做是否科学)

主要改动就以上这两个。仓库:https://github.com/zephyrchien/realm
https://github.com/zephyrchien/realm/releases/tag/v1.2.0

另外我单独开了一个分支,把程序改成了单线程的,去掉了锁,并且去掉了输出(因为是同步的,想好好打印日志就最好改成异步的)
随后研究了一下zero copy,和tfo。想要实现这些功能得亲自调用C api (或者用封装库),并且得亲自实现Future trait,
不如直接拿C++写一个
==================================================================================================
端口转发是个很简单的功能,很多工具都能拿来干这活。realm的好处就在于它足够简洁,开箱即用。
顺便我想借题发挥一下,说说目前常见的转发工具:

iptables: 工作于IP层,让内核负责转发。可惜享受不到TCP拥塞控制。

haproxy: 性能很好,功能性够强。支持配置入站/出站tls(以及sni, alpn),可以纯TCP转发,也可以处理HTTP(2),还可以用acl分流

nginx: 同上,但是我自己用的时候速度差强人意。<del>同样不支持UDP转发(一般也用不到)</del> (nginx可以转发UDP,加上udp关键字就行)

golang系列转发工具: 功能都很多,但是我自己基本用不上,有些配置比较复杂。(纯转发的话不如自己写个,开俩io.Copy()就行,自动实现零拷贝)

总体来说这些工具都够用,个人更倾向于稳定(haproxy) 或者短小精悍的(realm)。


作者: aipage    时间: 2021-4-29 23:50
支持大佬,虽然你说的这些我都看不懂。

作者: h20    时间: 2021-4-29 23:53
提示: 作者被禁止或删除 内容自动屏蔽
作者: qer    时间: 2021-4-29 23:53
大佬辛苦 已start
作者: 小蓝姐姐    时间: 2021-4-29 23:58
提示: 作者被禁止或删除 内容自动屏蔽
作者: yuanyuexiaoni    时间: 2021-4-30 00:00
本帖最后由 yuanyuexiaoni 于 2021-4-30 00:08 编辑

我也喜欢haproxy,还有一个是GOST搭配MMP-Go。端口复用必备
haproxy可以SNI分流(加了tls的),裸ws读取host头分流。转ws tls或者ws必备。而且转发到cf的话别人扫到你的端口也没法用。
MMP-Go解包分流。搭配GOST用起来相当舒服,转发到本地GOST监听端口加密隧道发过去,可以分流酸酸。
作者: dunce    时间: 2021-4-30 00:01
aipage 发表于 2021-4-29 23:50
支持大佬,虽然你说的这些我都看不懂。

感谢顶贴
作者: hostloc8888    时间: 2021-4-30 00:02
realm确实不错,配置起来相对简单,而且可以享受bbr。
作者: dunce    时间: 2021-4-30 00:09
qer 发表于 2021-4-29 23:53
大佬辛苦 已start

thx! (不过我不是大佬
作者: dunce    时间: 2021-4-30 00:14
h20 发表于 2021-4-29 23:53
会话的概念要有超时,否则内存会泄漏

我还是喜欢用rinetd

目前UDP的处理方式还是比较暴力。得等接受端口15分钟不活动,再唤醒负责清理的future,让分配的socket自鲨。这样处理超时的代价比较小,但是如果老是收到不同来源的UDP包,就没机会释放资源了
(话说论坛真是卡成dog了,我这回复好几次都发不出去
作者: dole    时间: 2021-4-30 00:17
支持大佬,虽然你说的这些我都看不懂。
作者: dunce    时间: 2021-4-30 00:17
yuanyuexiaoni 发表于 2021-4-30 00:00
我也喜欢haproxy,还有一个是GOST搭配MMP-Go。端口复用必备
haproxy可以SNI分流(加了tls的),裸ws读取hos ...

我目前中转机和落地机都用haproxy(落地机服务端分流grpc/ws/tcp/web),非常的舒适
作者: h20    时间: 2021-4-30 00:20
提示: 作者被禁止或删除 内容自动屏蔽
作者: dole    时间: 2021-4-30 00:23
h20 发表于 2021-4-30 00:20
GCP完蛋了耶

过期了 老婆要不来试试az或aws
作者: h20    时间: 2021-4-30 00:26
提示: 作者被禁止或删除 内容自动屏蔽
作者: dunce    时间: 2021-4-30 00:37
小蓝姐姐 发表于 2021-4-29 23:58
大佬,谈谈Brook和rinetd

= =没用过,不好说。而且不同的人之间使用环境千变万化,就算我用过也不好妄下定论。不过一般而言这些工具性能上差不了多少,我个人因为只需要TCP纯转发,相比之下更关心资源占用和配置简洁程度
//
rinted似乎是个纯转发,而brook功能很多。就Go和C本身而言,个人更倾向于C。Go在单核nat上发挥不出来goroutine的多线程调度优势,而且因为转发太方便,通常会支持一大堆我自己用不上的功能
//
golang依靠runtime检查fd是否就绪,调用的io.Copy()自带splice()实现(不过golang syscall代价挺大);C程序依靠epoll让内核通知fd就绪,要实现零拷贝也很容易。 论性能理论上是C更好,但是实际上这两者实在不会差多少 (我业余学编程也就一年时间,学的远远不够深入,不能保证前面说的都是对的)
作者: dunce    时间: 2021-4-30 00:39
dole 发表于 2021-4-30 00:17
支持大佬,虽然你说的这些我都看不懂。

感谢兹词,另外我不是大佬= =
作者: dunce    时间: 2021-4-30 00:41
论坛太卡了,回不动了
作者: IPLC    时间: 2021-4-30 00:53
亲测,流量大的时候,尤其是多人中转的时候,除了gost都是渣
作者: 优秀的苦瓜    时间: 2021-4-30 01:05
nginx stream 可以 UDP
作者: dunce    时间: 2021-4-30 01:10
优秀的苦瓜 发表于 2021-4-30 01:05
nginx stream 可以 UDP

感谢指正! 我不曾用过,误以为不支持。。原来只要加上udp关键字就可以了
作者: dunce    时间: 2021-4-30 01:18
本帖最后由 dunce 于 2021-4-30 01:25 编辑
IPLC 发表于 2021-4-30 00:53
亲测,流量大的时候,尤其是多人中转的时候,除了gost都是渣


这我不敢苟同。如果要一概而论的话,gc语言是绝对干不过系统语言的。具体而言,首先go程序并发依赖于goroutine(有栈),连接数特别多的时候会占用大量内存;而c程序依赖于内核调度(rust tokio封装了epoll kqueue iocp),性能和资源消耗绝对更优秀。其次go在垃圾回收的时候会挂起所有线程(stop the world)。最后gost封装了太多层接口 不知道是否失去了零拷贝优化(当然realm也没去实现零拷贝)
作者: gbadge    时间: 2021-4-30 01:22
mark学习一下。
作者: xiaoz    时间: 2021-4-30 08:13
1. nginx的stream支持UDP转发
作者: xiaoz    时间: 2021-4-30 08:14
2.golang开发的brook也停简单的
作者: ychx0719    时间: 2021-4-30 11:14
大佬可否编译一个win版?谢谢!
作者: 35954514    时间: 2021-4-30 11:27
realm 、gost
这2个我用了时间久了似乎有卡死的迹象
作者: KallyDev    时间: 2021-4-30 11:53
提示: 作者被禁止或删除 内容自动屏蔽
作者: ymcoming    时间: 2021-4-30 12:14
realm的配置格式能否改一下。目前的格式是:port1,port2,port3;sip1,sip2,sip3;dip1,dip2,dip3.......转发数量多了,眼晴都要看花,无法一一对应修改目标。能否改成:sip1,port1,dip1;sip2,port2,dip2....
作者: ychx0719    时间: 2021-4-30 13:17
KallyDev 发表于 2021-4-30 11:53
缘分,这几天刚好在用 Rust 写端口转发工具,主要涉及到基本的 TCP/UDP 转发、常见协议(SSH、BT、TLS 等) ...


劳烦大佬开发的时候也编译一个win版,最好支持DDNS,谢谢!
作者: KallyDev    时间: 2021-4-30 13:18
提示: 作者被禁止或删除 内容自动屏蔽
作者: dunce    时间: 2021-4-30 21:29
xiaoz 发表于 2021-4-30 08:14
2.golang开发的brook也停简单的

感谢指正
作者: taigt    时间: 2021-4-30 21:31
已阅,不懂,大佬继续表演
作者: dunce    时间: 2021-4-30 21:31
KallyDev 发表于 2021-4-30 11:53
缘分,这几天刚好在用 Rust 写端口转发工具,主要涉及到基本的 TCP/UDP 转发、常见协议(SSH、BT、TLS 等) ...

cool! 不过我才刚入门没多久,不一定帮的上忙。我目前打算先学O习一下page大佬的trojan-r
作者: KallyDev    时间: 2021-4-30 21:36
提示: 作者被禁止或删除 内容自动屏蔽
作者: dunce    时间: 2021-4-30 21:36
ymcoming 发表于 2021-4-30 12:14
realm的配置格式能否改一下。目前的格式是:port1,port2,port3;sip1,sip2,sip3;dip1,dip2,dip3.......转发 ...

我也觉得目前的配置文件不够清晰。但是如果连配置格式都改了,这还叫realm吗。。(除非作者来改)
作者: dunce    时间: 2021-4-30 21:48
35954514 发表于 2021-4-30 11:27
realm 、gost
这2个我用了时间久了似乎有卡死的迹象

程序运行的过程中总是会遇到千奇百怪的问题。。只能在写代码的时候尽量考虑周全了
作者: dunce    时间: 2021-4-30 21:50
ychx0719 发表于 2021-4-30 11:14
大佬可否编译一个win版?谢谢!

github actions里面有编译好的版本(刚刚把win给加上了)
作者: zhbone    时间: 2021-4-30 22:05
感谢楼主的贡献。我因为博士的最后一年很忙,realm没有时间管了。
作者: naiba    时间: 2021-4-30 22:07
支持
作者: dunce    时间: 2021-5-1 00:28
zhbone 发表于 2021-4-30 22:05
感谢楼主的贡献。我因为博士的最后一年很忙,realm没有时间管了。

客气了,我也只是做了点微不足道的事情。话说老哥你难得回归一次,我想借此机会提个PR(thread->task & udp fix)  晚点麻烦你review一下=-=
作者: dunce    时间: 2021-5-1 00:29
naiba 发表于 2021-4-30 22:07
支持

感谢大佬兹词!
作者: ychx0719    时间: 2021-5-1 11:50
dunce 发表于 2021-4-30 21:50
github actions里面有编译好的版本(刚刚把win给加上了)

我看到workflow有,但是怎样下载?谢谢!(我不太会用github actions)
作者: dunce    时间: 2021-5-1 13:22
ychx0719 发表于 2021-5-1 11:50
我看到workflow有,但是怎样下载?谢谢!(我不太会用github actions)

https://github.com/zephyrchien/realm/actions/runs/799590803
就在Artifacts里面
作者: ychx0719    时间: 2021-5-1 14:36
dunce 发表于 2021-5-1 13:22
https://github.com/zephyrchien/realm/actions/runs/799590803
就在Artifacts里面

下载了,解压后怎样运行?谢谢!
作者: IPLC    时间: 2021-5-4 19:52
dunce 发表于 2021-4-30 01:18
这我不敢苟同。如果要一概而论的话,gc语言是绝对干不过系统语言的。具体而言,首先go程序并发依赖于goro ...

具体怎么回事我不了解,但是我这是我生产环境的事实,不知你有没有优化realm的方法呢
作者: hanweizhe    时间: 2021-5-4 19:55
高手如云
作者: dunce    时间: 2021-5-4 22:46
IPLC 发表于 2021-5-4 19:52
具体怎么回事我不了解,但是我这是我生产环境的事实,不知你有没有优化realm的方法呢 ...

加大读写buffer。目前用的tokio::io::copy 硬编码了2kb的buffer,有点小。得自己单独实现个copy,把buffer加大至8k或者16k。这样每次系统调用的性价比会高很多
作者: buaachenhua    时间: 2021-5-4 22:52
yuanyuexiaoni 发表于 2021-4-30 00:00
我也喜欢haproxy,还有一个是GOST搭配MMP-Go。端口复用必备
haproxy可以SNI分流(加了tls的),裸ws读取hos ...

能否给个haproxy转WS的教材,找了好久没找到
作者: mfch666    时间: 2021-5-4 23:14
h20 发表于 2021-4-29 23:53
会话的概念要有超时,否则内存会泄漏

我还是喜欢用rinetd

rinetd 是方便 但是 监听端口数量非常有限
作者: 石原里美    时间: 2021-5-4 23:15
大佬辛苦了




欢迎光临 全球主机交流论坛 (https://lilynana.eu.org/) Powered by Discuz! X3.4