-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
进一步讨论机制问题 #9
Comments
又有了一个更疯狂的想法。linux内核有个叫nfqueue的东西,可以直接把感兴趣的包发到用户态程序,修改之后再发回内核。具体操作参加 这样就可以利用一个普通的tcp socket通信,利用nfqueue在发出包时找出seq的最新值,然后在收到包时,把所有的ack都改为我们记录到的最新值。这样就变相废除了阻塞和重传机制。 |
@ccaapton |
欢迎s82kd92l。 2有个问题。如果原生的tcp socket不屏蔽掉,虽然可以用ttl让它发不出去数据,他会一直收到东西,占内核的处理资源。还有,在有丢包的情况下,这个原生tcp只要漏掉一个包,后续收到的数据就不能提交给上层。然后buffer会满。buffer满了后又一直收到新数据,丢的数据又重传不了,我担心内核会把他回收掉然后回复RTS 因为2的问题,1的优势也不明显了。 |
这个不错。我一直想找个类似的东西,用原生的tcp握手和发数据,然后干掉按序到达和拥塞控制。我先仔细看一下。 |
如果对方的ttl够小发不出,你又怎么会一直收到东西呢:) |
我是说对端的faketcp发来的数据包。ttl只是关掉了双方原生tcp的发送,没有关闭接收。对方rawsocket发来的tcp数据也会被原生tcp收到。 ==updated== |
你目前的实现里面,seq没有变化吧。这样内核默认这个是重传的包,应该不会丢给用户态的。 |
上面那个stackoverflow我随便搜的,这里好像有个更详细的blog: https://blog.talentica.com/2016/05/17/introduction-to-packet-interception-using-netfilter/ |
有变化。代码在int after_send_raw0(raw_info_t &raw_info) ,我用tcpdump抓包和真实tcp对比过,确认它是涨了的。 但是用--seq-mode 0可以关掉。 如果实现成不变的话,容易被运营商封。 |
想起个事,@ccaapton 我昨天修了个bug。修了以后icmp模式的速度彪满20m宽带了(上/下行都可以)。 = =。也许是偶然现象,我多用几天再下结论。 |
@linhua55 读了你的连接。
之前见过这个用法。只屏蔽掉发出去的RST。 然后我尝试在网上找这么做以后那个dummy tcp收到数据了的行为,什么也没找到。 我担心这个不确定的行为,所以最后选择了彻底屏蔽掉接受的方案。 |
这个思路我实现过,感觉没啥用其实,在 linux 上修改 iptables 太简单了。 |
最好是 彻底屏蔽掉接受,这样 本地内核 就不会产生RST包了。 如果是屏蔽掉输出,则是 本地内核产生RST包后,这样就浪费了CPU。 使用dummy TCP是为了 在接受输入的情况下(不使用iptables屏蔽) 不让 本地内核 产生RST包, 本地内核 产生RST包的几种情况: |
@ccsexyz 确实。 |
@linhua55 自己做TCP握手其实不是很麻烦,我觉得用raw socket的方式自己控制全部应该会更好,依赖一个其他东西的行为然后在上面打补丁可能会出难以预料的问题。 |
@wangyu- 对,这个确实没必要,也只有docker容器可能会用到(樱花docker不能使用iptables,但可以使用tcpdump(raw socket)),但现在提供docker服务的很少,暂时是没必要的 |
@linhua55 提供docker服务的一般都会在前端怼一个 haproxy 之类的代理,然后 fake-tcp 就根本不能工作了.不要问我是怎么知道的,我也是写完才发现自己好蠢,忽略了这一点. |
@ccsexyz 哦,哈哈,我这边udp有问题,看来我跟docker无缘了。 |
有的docker vps服务商在前端没有haproxy,而是用的iptables SNAT和DNAT。这种情况可以用raw socket。
现在我已经实现了简单的dummy socket,在server端可以不用添加iptables,可以在docker中运行而不产生RST,稳定性还有待考证(在我自己的环境上测试通过, #41 里面别人的环境也测试通过)。client端还是需要iptables。 更多信息参考:linhua55/lkl_study#11 |
最近发现一个可以利用的机制: 如果客户端发送的tcp包包含的ack > 服务器端期望的ack,那么服务器就会把这个包在内核处理阶段丢掉。反之亦然。 那么还是回到我最初的建议,开普通的tcp socket进行3次握手,握手结束后双方的udp2raw都用更高的seq/ack进行通信,那么就不再需要iptables了。 |
这个方案在server端已经实现了(不完美,server端会回复2个syn ack,但是不影响使用),client端还没有。 在这个帖子里有进一步的讨论,和tcpdump抓包数据: 这个方案的优点:
缺点:
之所以没实现,是因为没有足够的动力。 不过,多一个选择总是好的,如果有兴趣,可以PR。 这个方案已经加到了contribution guide里。 |
@wangyu- 如果client能摆脱iptables的依赖,很可能就能摆脱linux的依赖。 |
但是如果一个tcp socket一直收不到有效的包/一直收到序号不合法的包,2个小时后,这个socket会不会被系统回收掉呢,就是undocumented feature了。
这也是优点之一吧。 不过windows/mac上也有iptables的替代品。目前只支持linux,主要的原因不是因为对iptables的依赖,是没有人愿意移植。。。我自己目前也没有足够的动力移植。 |
@wangyu- 确实移植还不如用golang重写,我在看这个golang packet,好像对bpf/pcap各种支持都有,还有很多其他golang raw socket的库。有空我试试 你有没有什么不依赖openvpn之类轻量的测试代码可用于兼容性测试? |
golang的rawsocket和pcap可以参考一下kcpraw。
我自己也是用VPN来测试的,原来我一直用openvpn。现在我主要用自己写的那个tinyFecVPN测试,不需要证书,轻量很多。 |
补充一下,使用原生socket还有个好处,就是在建立fake tcp连接之前,利用原生的socket交换一些非常有用的信息,比如 |
这两个用目前的机制也可以实现。用udp2raw+VPN 和udp2raw+socks5也可以达到类似的效果,所以没有实现在udp2raw中。 |
@linhua55 @ccaapton pcap版的udp2raw实现了在client端用系统socket握手的功能: |
按类似思路实现了,但有几点问题:
|
你好,我是v站的s82kd92l,咱一起讨论过udp2raw细节问题。这两天看了下代码,也仔细回味了一下。架构上有些建议:
三次握手根本不需要我们自己完成,我们可以开一个普通的tcp socket和服务器进行初始握手,一切都由内核完成,之后再劫持这个socket进行隧道通信。
只要有个原生tcp socket,就不再需要"iptables -I INPUT" 这种dirty hack. 我们可以在本地利用setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,...)这种接口,让原生socket在握手之后发送的包ttl变小,这样原生socket无法收到对方发出的内容,也就不需要iptables了。
有新想法我再加
The text was updated successfully, but these errors were encountered: