我想问一个关于原始套接字编程和linux内核TCP处理的经典问题。我已经完成了对linux raw socket programming question,How to reproduce TCP protocol 3-way handshake with raw sockets correctly?和TCP ACK spoofing等相同线程的研究,但仍无法得到解决方案。
我尝试制作一个不听任何端口的服务器,但是从远程主机嗅探SYN数据包。在服务器进行一些计算之后,它会将SYN_ACK数据包发送回相应的SYN数据包,这样我就可以手动创建TCP连接,而不包括内核的操作。我已创建原始套接字并在其上发送SYN_ACK,但数据包无法通过远程主机。当我在服务器(Ubuntu Server 10.04)上tcpdump和客户端(Windows 7)上的wireshark时,服务器返回RST_ACK而不是我的SYN_ACK数据包。在做了一些研究之后,我得到的信息是我们不能抢占内核的TCP处理。
还有其他方法可以破解或设置内核不响应RST_ACK到这些数据包吗? 我已经为服务器的本地ip添加了一个防火墙,告诉内核可能在防火墙后面有什么东西正在等待数据包,但仍然没有运气
答案 0 :(得分:4)
答案 1 :(得分:1)
我建议使用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找到套接字,如果没有,它将发送reset:
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的行(但这会产生更多后果)。
希望这有帮助。