问题描述
我正在尝试使用原始套接字制作 tcp 服务器。通过这种方式,我可以了解更多关于 tcp 的信息。我的 tcp 服务器的问题是我在接收端(客户端)获得了不同的目标端口。服务器(源端口)正确,但目标端口不同。所以我的 telnet/nc 客户端一直在尝试连接。它无法连接并向拒绝连接的客户端提供错误。问题是我在目标系统上收到带有 SYN+ACK 的数据包,但端口不是客户端的源端口(我使用wireshark 在客户端上检查过)某些东西正在改变目标端口地址(客户端端口地址),或者我不是在原始套接字发送之前在原始服务器上正确分配它。我认为问题可能出在这条线上。我正在运行代码(客户端和服务器)在两个虚拟机 Linux 上
temp->dest=tcp->source;
tcp
是服务器端从客户端接收到的数据包的 tcp 头
temp->dest
是从服务器向客户端发送数据包的 tcp 客户端端口地址
//下面是main方法,它监听请求
// Packet length
#define PCKT_LEN 8192
int main(int argc,char *argv[])
{
int sd;
char buffer[PCKT_LEN];
int one = 1;
const int *val = &one;
memset(buffer,PCKT_LEN);
sd = socket(PF_INET,SOCK_RAW,IPPROTO_TCP);
if(sd < 0)
{
perror("socket() error");
exit(-1);
}
else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
if(setsockopt(sd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK\n");
struct sockaddr_in sa;
sa.sin_family=AF_INET;
sa.sin_port=htons(80);
sa.sin_addr.s_addr=inet_addr("0.0.0.0");
if(bind(sd,&sa,sizeof (sa))==0){
printf("Port Bound\n");
}
unsigned int count;
while(1)
{
char buffer1[8192];
struct sockaddr_in saddr;
int in_len;
if((recvfrom(sd,buffer1,sizeof (buffer1),&saddr,&in_len))!=-1){
connect1(saddr,buffer1);
sleep(5);
}//if recvfrom()
else{
int err=errno;
printf("recv error %s\n",errno);
}
sleep(2);
}
close(sd);
return 0;
}
//下面是发送响应(ACK+SYN)的方法
#define PCKT_LEN 100
void processBuffer(char buffer1[]);
int connect1(struct sockaddr_in sa,char buffer[]) {
printf("Connecting client...!\n");
char *c=inet_ntoa(sa.sin_addr);
// processBuffer(buffer);
int cp=ntohl(sa.sin_port);
printf("%s (%d)\n",c,cp);
struct iphdr *ip1=(struct iphdr *)buffer;
struct tcphdr *tcp=(struct tcphdr *)buffer;
sa.sin_port=tcp->source;
printf("%d %d --------- \n",tcp->source,ntohl(tcp->source));
printf("%d \n",ntohs(sa.sin_port));
int sd;
int one = 1;
const int *val = &one;
sd = socket(PF_INET,IPPROTO_TCP);
if(sd < 0)
{
perror("Connecting --socket() error");
exit(-1);
}
else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
if(setsockopt(sd,sizeof(one)) < 0)
{
perror("Connecting--setsockopt() error");
exit(-1);
}
else
printf("Connecting setsockopt() is OK\n");
if(bind(sd,sizeof (sa))==0){
printf("Port Bound\n");
}
char b[PCKT_LEN];
struct iphdr *i=(struct iphdr *)b;
struct tcphdr *t=(struct tcphdr *)(b+sizeof (struct iphdr));
ip(ip1,i);
sync_ack(tcp,t);
int ret=sendto(sd,&b,sizeof (b),sizeof (sa));
strerror("Error: ");
printf("%d\n",errno);
printf("%d\n",ret);
return 0;
}
//这就是我制作ip header的方式
int id=121333;
struct iphdr * ip(struct iphdr * ip,struct iphdr *temp)
{
temp->saddr=ip->daddr;
temp->daddr=ip->saddr;
temp->ihl=5;
temp->version=4;
temp->tos=0;
temp->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);
temp->id=htons(id);id++;
temp->frag_off = htons(16384);
temp->ttl = 64;
temp->protocol=IPPROTO_TCP;
temp->check=0;
temp->check = csum ((unsigned short *) temp,temp->tot_len >> 1);
return temp;
}
//接下来是我正在制作tcp header ACK+SYN
int seq=1105024978;
struct tcphdr * sync_ack(struct tcphdr * tcp,struct tcphdr *temp)
{
temp->source=htonl(80);
temp->dest=tcp->source;
temp->seq=htonl(seq);seq++;
temp->ack_seq=htonl(ntohl(tcp->seq)+1);
temp->doff = sizeof(struct tcphdr) / 4;
temp->fin=0;
temp->syn=1;
temp->ack=1;
temp->th_ack=tcp->seq;
temp->rst=0;
temp->psh=0;
temp->urg=0;
temp->window=htons ( 14600 );
temp->check = 0;
temp->urg_ptr = 0;
temp->check = csum( (unsigned short*) temp,sizeof (struct tcphdr));
return temp;
}
请检查代码有什么问题。我将处理重新传输,但我没有通过第一个数据包进入正确的端口地址。任何帮助将不胜感激
我在 Linux(特别是 Debian 5.9 版操作系统)上运行它
我之前就这个作品问过一个问题。 DOES router or linux kernel change the tcp headers and ip headers of packets 我怀疑这条线
temp->dest=tcp->source;
这是在服务器收到的wireshark信息,0.11是客户端ip,0.14是服务器ip。 80是服务器端口
iptables 更改后,syn+ack 正在发送,但客户端收到的数据包中的客户端端口不同。客户端端口线鲨鱼显示为 60
和之前问题更新图片
# iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)