我正在尝试使用原始套接字模拟TCP握手。为了测试,我在同一台机器上使用服务器和客户端。我使用原始套接字的代码是一个被动服务器,它监听SYN并响应SYN / ACK。但是,我无法从客户端获取ACK。我使用tcpdump来读取清楚地显示我的数据包离开服务器的痕迹。这是跟踪:
13:49:35.389518 IP (tos 0x0, ttl 64, id 51534, offset 0, flags [DF], proto TCP (6), length 60)
localhost.3333 > localhost.9999: Flags [S], cksum 0xfe30 (incorrect -> 0xd31d), seq 914929523, win 43690, options [mss 65495,sackOK,TS val 588877032 ecr 0,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c c94e 4000 4006 736b 7f00 0001 7f00 .<.N@.@.sk......
0x0020: 0001 0d05 270f 3688 b773 0000 0000 a002 ....'.6..s......
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 2319 ...0..........#.
0x0040: 8ce8 0000 0000 0103 0307 ..........
13:49:35.389642 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
localhost.9999 > localhost.3333: Flags [S.], cksum 0xf9cb (incorrect -> 0x9b6d), seq 584475847, ack 914929524, win 43690, options [mss 65495,sackOK,TS val 588877032 ecr 588877032,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00 .<..@.@.<.......
0x0020: 0001 270f 0d05 22d6 64c7 3688 b774 a012 ..'...".d.6..t..
0x0030: aaaa f9cb 0000 0204 ffd7 0402 080a 2319 ..............#.
0x0040: 8ce8 2319 8ce8 0103 0307 ..#.......
13:49:36.646081 IP (tos 0x0, ttl 64, id 29569, offset 0, flags [DF], proto TCP (6), length 60)
localhost.3333 > localhost.9999: Flags [S], cksum 0xfe30 (incorrect -> 0x7c87), seq 1169489315, win 43690, options [mss 65495,sackOK,TS val 588877346 ecr 0,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 7381 4000 4006 c938 7f00 0001 7f00 .<s.@.@..8......
0x0020: 0001 0d05 270f 45b4 fda3 0000 0000 a002 ....'.E.........
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 2319 ...0..........#.
0x0040: 8e22 0000 0000 0103 0307 ."........
13:49:37.645510 IP (tos 0x0, ttl 64, id 29570, offset 0, flags [DF], proto TCP (6), length 60)
localhost.3333 > localhost.9999: Flags [S], cksum 0xfe30 (incorrect -> 0x7b8d), seq 1169489315, win 43690, options [mss 65495,sackOK,TS val 588877596 ecr 0,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 7382 4000 4006 c937 7f00 0001 7f00 .<s.@.@..7......
0x0020: 0001 0d05 270f 45b4 fda3 0000 0000 a002 ....'.E.........
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 2319 ...0..........#.
0x0040: 8f1c 0000 0000 0103 0307 ..........
我明白不能简单地读取SYN数据包,因此我使用libpcap库来读取SYN数据包。我使用iptables来过滤RST,因为我没有人在服务器端监听(它是一个原始套接字)。当我试图用TCP的基本套接字函数模拟它并捕获它的跟踪它看起来与我的完全相同,除了我没有从客户端得到我的ACK。我不确定问题是什么。多年来一直坚持这一点。我发布了原始套接字创建的代码:
/ ** p_ip - SYN包的IP头| p_tcp - SYN包的TCP头| s_seq - SYN数据包的seq no * /
void send_syn_ack(int s_seq, struct ipheader *p_ip, struct tcpheader *p_tcp, __u8 *p_tcpopt)
{
printf("seq is: %lu\n", ntohl(s_seq));
char buffer[PKT_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));
struct tcp_options *tcpoptions = (struct tcp_options *) (buffer + sizeof(struct tcpheader) + sizeof(struct ipheader));
int one = 1;
const int *val = &one;
struct sockaddr_in sin;
memset(&buffer, 0, sizeof(buffer));
ip -> iph_ihl = 5;
ip -> iph_ver = 4;
ip -> iph_tos = 0;
ip -> iph_len = htons(sizeof(struct ipheader) + sizeof(struct tcpheader) + 20);
ip -> iph_ident = 0;
ip -> iph_offset = 0x40;
ip -> iph_ttl = 64;
ip -> iph_protocol = 6;
ip -> iph_chksum = 0;
ip -> iph_sourceip = p_ip -> iph_sourceip;
ip -> iph_destip = p_ip -> iph_destip;
//ip -> ip_sum = in_cksum((unsigned short *)&ip, sizeof(ip));
tcp -> tcph_srcport = p_tcp -> tcph_destport;
tcp -> tcph_destport = p_tcp -> tcph_srcport;
tcp -> tcph_seqnum = htonl(584475847);
tcp -> tcph_acknum = htonl(ntohl(p_tcp -> tcph_seqnum) + 1);
tcp -> tcph_hlen = 10;
tcp -> tcph_syn = 1;
tcp -> tcph_ack = 1;
tcp -> tcph_win = htons(43690);
//tcp -> tcph_chksum = (in_cksum_tcp( ntohl(ip -> iph_sourceip), ntohl(ip -> iph_destip), (buffer), 40));
tcp -> tcph_chksum = 0;
tcp -> tcph_urgptr = 0;
//tcp.th_sum = in_cksum_tcp(ip.ip_src.s_addr, ip.ip_dst.s_addr, (unsigned short *)&tcp, sizeof(tcp))
//ip -> iph_chksum = (in_cksum(buffer, sizeof(struct ipheader)));
ip -> iph_chksum = htons(0xfe30);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = (tcp -> tcph_srcport);
sin.sin_addr.s_addr = (ip -> iph_sourceip);
printf("Packet Information:\n");
printf("Source: %s.%u\nDestination: %s.%u\nPacket Length: %d \n", printIP(ip -> iph_sourceip), ntohs(tcp -> tcph_srcport), printIP(ip -> iph_destip), ntohs(tcp -> tcph_destport), ntohs(ip -> iph_len));
printf("Seq No: %lu \nAck No: %lu \n", ntohl(tcp -> tcph_seqnum), ntohl(tcp -> tcph_acknum));
struct tcp_options *tmpopts = readOptions(p_tcpopt);
memcpy(tcpoptions, tmpopts, 20);
//tcp -> tcph_chksum = in_cksum_tcp(ip -> iph_sourceip, ip -> iph_destip, buffer + 20, 40);
tcp -> tcph_chksum = htons(0xfe30);
if ((sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
perror("raw socket");
exit(1);
}
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("ERROR: setsockopt() can't be performed!");
exit(1);
}
else
printf(">> setsockopt() is OK\n");
int sent_length;
if ((sent_length = sendto(sd, buffer, 60, 0, (struct sockaddr *)&sin, sizeof(sin))) < 0) {
perror("sendto");
exit(1);
}
else
{
printf("Sent %d bytes\n", sent_length);
}
}
我多年来一直坚持这个问题。有些人可以找出我需要看的问题吗?
更新: iptables规则:
Chain INPUT (policy DROP 27 packets, 864 bytes)
pkts bytes target prot opt in out source destination
813 48600 DROP tcp -- any any anywhere anywhere tcp dpt:9999
173K 17M fail2ban-ssh tcp -- any any anywhere anywhere multiport dports ssh
3536K 720M ufw-before-logging-input all -- any any anywhere anywhere
3536K 720M ufw-before-input all -- any any anywhere anywhere
2745K 468M ufw-after-input all -- any any anywhere anywhere
55829 2150K ufw-after-logging-input all -- any any anywhere anywhere
55829 2150K ufw-reject-input all -- any any anywhere anywhere
55829 2150K ufw-track-input all -- any any anywhere anywhere
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ufw-before-logging-forward all -- any any anywhere anywhere
0 0 ufw-before-forward all -- any any anywhere anywhere
0 0 ufw-after-forward all -- any any anywhere anywhere
0 0 ufw-after-logging-forward all -- any any anywhere anywhere
0 0 ufw-reject-forward all -- any any anywhere anywhere
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP tcp -- any any anywhere anywhere tcp spt:9999flags: RST/RST
833K 1132M ufw-before-logging-output all -- any any anywhere anywhere
833K 1132M ufw-before-output all -- any any anywhere anywhere
61973 3938K ufw-after-output all -- any any anywhere anywhere
61973 3938K ufw-after-logging-output all -- any any anywhere anywhere
61973 3938K ufw-reject-output all -- any any anywhere anywhere
61973 3938K ufw-track-output all -- any any anywhere anywhere
正常套接字连接已建立跟踪:
13:50:13.739038 IP (tos 0x0, ttl 64, id 53527, offset 0, flags [DF], proto TCP (6), length 60)
localhost.3333 > localhost.4040: Flags [S], cksum 0xfe30 (incorrect -> 0x23fb), seq 732324684, win 43690, options [mss 65495,sackOK,TS val 588886619 ecr 0,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c d117 4000 4006 6ba2 7f00 0001 7f00 .<..@.@.k.......
0x0020: 0001 0d05 0fc8 2ba6 634c 0000 0000 a002 ......+.cL......
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 2319 ...0..........#.
0x0040: b25b 0000 0000 0103 0307 .[........
13:50:13.739050 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
localhost.4040 > localhost.3333: Flags [S.], cksum 0xfe30 (incorrect -> 0x1502), seq 2134096447, ack 732324685, win 43690, options [mss 65495,sackOK,TS val 588886619 ecr 588886619,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00 .<..@.@.<.......
0x0020: 0001 0fc8 0d05 7f33 ba3f 2ba6 634d a012 .......3.?+.cM..
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 2319 ...0..........#.
0x0040: b25b 2319 b25b 0103 0307 .[#..[....
13:50:13.739064 IP (tos 0x0, ttl 64, id 53528, offset 0, flags [DF], proto TCP (6), length 52)
localhost.3333 > localhost.4040: Flags [.], cksum 0xfe28 (incorrect -> 0xe746), seq 1, ack 1, win 342, options [nop,nop,TS val 588886619 ecr 588886619], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 d118 4000 4006 6ba9 7f00 0001 7f00 .4..@.@.k.......
0x0020: 0001 0d05 0fc8 2ba6 634d 7f33 ba40 8010 ......+.cM.3.@..
0x0030: 0156 fe28 0000 0101 080a 2319 b25b 2319 .V.(......#..[#.
0x0040: b25b .[
13:50:13.739084 IP (tos 0x0, ttl 64, id 53529, offset 0, flags [DF], proto TCP (6), length 58)
localhost.3333 > localhost.4040: Flags [P.], cksum 0xfe2e (incorrect -> 0xe76c), seq 1:7, ack 1, win 342, options [nop,nop,TS val 588886619 ecr 588886619], length 6
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003a d119 4000 4006 6ba2 7f00 0001 7f00 .:..@.@.k.......
0x0020: 0001 0d05 0fc8 2ba6 634d 7f33 ba40 8018 ......+.cM.3.@..
0x0030: 0156 fe2e 0000 0101 080a 2319 b25b 2319 .V........#..[#.
0x0040: b25b 4090 b5bc 097f .[@.....
13:50:13.739089 IP (tos 0x0, ttl 64, id 2075, offset 0, flags [DF], proto TCP (6), length 52)
localhost.4040 > localhost.3333: Flags [.], cksum 0xfe28 (incorrect -> 0xe740), seq 1, ack 7, win 342, options [nop,nop,TS val 588886619 ecr 588886619], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 081b 4000 4006 34a7 7f00 0001 7f00 .4..@.@.4.......
0x0020: 0001 0fc8 0d05 7f33 ba40 2ba6 6353 8010 .......3.@+.cS..
0x0030: 0156 fe28 0000 0101 080a 2319 b25b 2319 .V.(......#..[#.
0x0040: b25b .[
答案 0 :(得分:1)
您是否尝试使用您感兴趣的iptables过滤数据包?我的意思是,我不确定你遇到的这个问题,也许作为提示你可以使用iptables来过滤带有SYN标志的数据包,并查看数据包是否丢弃数据包。
由于您在同一台计算机上使用服务器和客户端,因此数据包不会发送到您的NIC,但是,数据包将被发送到虚拟环回接口(您可以在Google上找到&# 34; loopback iptables&#34;)。
这不是如何解决问题,但是,获得一些关于如何修复它的提示可能会有用。我从来没有使用过原始套接字,所以我能帮助的就是这些东西。另一点是,您尝试连接的端口号必须设置为接受新连接,这意味着必须&#34;绑定&#34;。
祝你好运。答案 1 :(得分:1)
我试图根据您发布的数据进行猜测:
首先,校验和不正确。如果您依靠NIC计算校验和,则不会对发往localhost的消息执行此操作。
其次,你能展示你正在使用的所有iptables规则吗?如果使用libpcap,则应使用将TCP消息丢弃到端口9999的规则。
第三,如果客户端使用AF_INET流套接字(&#34;普通&#34;套接字),请添加以下规则:
iptables -A INPUT -p tcp --dport 9999 -j DROP
删除其他DROP规则。