如何设置linux内核不发送RST_ACK,以便我可以在原始套接字内提供SYN_ACK

我想问一个关于raw socket编程和linux内核TCP处理的经典问题。 我已经做了一些相同的线程,如Linux原始套接字编程问题的研究 , 如何正确重现与原始套接字的TCP协议三方握手? 和TCP ACK欺骗 ,但仍然无法获得解决scheme。

我试图做一个服务器不听任何端口,但从远程主机嗅探SYN数据包。 服务器做一些计算后,会发回一个SYN_ACK包给对应的SYN包,这样我就可以手动创buildTCP连接,而不包括内核的操作。 我已经创build了原始套接字并将SYN_ACK发送给它,但数据包无法连接到远程主机。 当我服务器上的tcpdump(Ubuntu服务器10.04)和wireshark客户端(Windows 7)上,服务器返回RST_ACK而不是我的SYN_ACK数据包。 在做了一些研究之后,我得到的信息是我们无法抢占内核的TCP处理。

是否还有其他的方式来破解或设置内核不响应RST_ACK这些数据包? 我已经添加了一个防火墙到服务器的本地IP告诉内核,也许有防火墙后面正在等待数据包的东西,但仍然没有运气

你有没有尝试使用iptables删除RST?

iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP 

应该为你做这个工作。

我建议使用ip表,但是因为你问到关于内核的问题,下面是你如何做的解释(我使用内核4.1.20作为参考):

当收到一个数据包(sk_buff)时,IP协议处理程序将把它发送到注册的网络协议:

 static int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb) { ... ipprot = rcu_dereference(inet_protos[protocol]); if (ipprot) { ... ret = ipprot->handler(skb); 

假设协议是TCP,处理程序是tcp_v4_rcv:

 static const struct net_protocol tcp_protocol = { .early_demux = tcp_v4_early_demux, .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .no_policy = 1, .netns_ok = 1, .icmp_strict_tag_validation = 1, }; 

所以tcp_v4_cv被调用。 它会尝试找到接收到的skb的套接字,如果没有,它会发送复位:

 int tcp_v4_rcv(struct sk_buff *skb) { sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); if (!sk) goto no_tcp_socket; no_tcp_socket: if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) goto discard_it; tcp_v4_send_reset(NULL, skb); ... 

有很多不同的方法可以破解这个。 你可以去xfrm4_policy_check函数,并修改AF_INET的策略。 或者你可以简单的注释掉调用xfrm4_policy_check的那一行,这样代码总是会放到discard_it中,或者你可以直接注释掉调用tcp_v4_send_reset的那一行(尽管如此,这样会有更多的后果)。

希望这可以帮助。