linux icmp 拓扑发现代码,Linux下用ICMP协议,进行路由多端口尝试探测

该博客介绍了一种通过构造UDP数据包并发送到路由器的不可用高端口来探测路由端口的方法,以发现特定路由拓扑。在接收到端口不可达的ICMP响应后,分析IP来识别其他端口。虽然这种方法存在局限,例如通常路由路径稳定,返回的ICMP通常是已知端口,但仍然是一个简单的探测技术。代码示例展示了如何实现这个过程,包括创建UDP和RAW套接字,发送和接收数据包,以及检查ICMP响应。
摘要由CSDN通过智能技术生成

路由器通常会有多个端口,而多个端口的ip可能又处在不同的网段中,以实现不同网段间的数据转发。对于特定路由拓扑的发现,探测路由的端口还是有一定价值的。

路由器通常会有多个端口,而多个端口的ip可能又处在不同的网段中,以实现不同网段间的数据转发。对于特定路由拓扑的发现,探测路由的端口还是有一定价值的。

a4f84e2d37b14ddc04b67c5f9803c371.png

编程思路:

在已经知道路由的某个端口下,构造一个udp数据包

将数据包发送到路由的某个不可用的高端口(使路由回复端口不可达的icmp数据包)

接收数据包,分析是否有端口不可达的icmp数据包

如果有,则检测是否是同一ip返回的数据,如果ip不同,则很大程度上认为此不同的ip即为另一端口(可以多次测量,并保证数据请求的单一性)

当然此种方法存在着很大的不足:

通常情况下,路由的路径相对稳定,,返回的icmp通常也就是原来的路由端口(已知)

代码说明:

只简易的实现了基本流程,没有对接收时的等待时间作限制,容易在此处卡掉

对于路由高端口的选择,也只是随机得挑了一个

这种测试方法,一般会对同一路由进行多次探测,而代码仅有一次流程

代码仅作参考

/**

* date:2015-03-15

* author:zhang mou ren

* purpose:use the udp and icmp to get router's names (IPs,ports);

*

* */

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAXPACKET 65535 //MAX size of ip packet

int check_packet(u_char *databuf,int buflen);

int main(int argc,char* argv[])

{

struct sockaddr_in hostaddr; //aim host address

struct sockaddr_in localaddr; //local host address

int sendsock,recvsock; //two socket

if(argc!=2)

{

printf("this programe need one argument:host ip\n");

return 0;

}

//fill aim host address

bzero(&hostaddr,sizeof(hostaddr));

hostaddr.sin_family=AF_INET;

hostaddr.sin_port=htons(55555);

//TEST port

hostaddr.sin_addr.s_addr=inet_addr(argv[1]);

//fill local host address

bzero(&localaddr,sizeof(localaddr));

localaddr.sin_family=AF_INET;

localaddr.sin_port=htons(55551);

//TEST port

localaddr.sin_addr.s_addr=htonl(INADDR_ANY);

//create send socket

if((sendsock=socket(AF_INET,SOCK_DGRAM,0))==-1)

{

printf("create send udp socket fail\n");

return 0;

}

if(bind(sendsock,(struct sockaddr *)&localaddr,sizeof(localaddr))==-1)

{

printf("create bind upd socket fail\n");

return 0;

}

//create receive socket

if((recvsock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))==-1)

{

printf("create receive socket fail,raw socket need root\n");

return 0;

}

//test a simple process

//create a udp

//receive the backdata

//analyse the backdata

//create a udp and send

char buf[40];

///test

memset(buf,0,sizeof(buf));

int n;

//int ttl=220;

//test

//set TTL

//if(setsockopt(sendsock,IPPROTO_IP,IP_TTL,(char *)&ttl,sizeof(ttl))==-1)

//{

//printf("set ttl fail\n");

//return 0;

//}

//send upd packet

if((n=sendto(sendsock,buf,40,0,(struct sockaddr *)&hostaddr,sizeof(struct sockaddr_in)))==-1)

{

printf("send packet fail\n");

return 0;

}

if(n!=40)

{

printf("send packet not complete\n");

return 0;

}

//receive the backdata

char databuf[MAXPACKET];

struct sockaddr_in from;

int len=sizeof(struct sockaddr_in);

printf("start receive data\n");

if((n=recvfrom(recvsock,databuf,MAXPACKET,0,(struct sockaddr *)&from,&len)) == -1)

{

printf("receive packet fail\n");

return 0;

}

//analyse the backdata

if(check_packet(databuf,sizeof(databuf))==1)

{

printf("analyse the host ip\n");

printf("host ip:%s\n",inet_ntoa(from.sin_addr));

}

return 0;

}

//check the icmp packet

int check_packet(u_char *databuf,int buflen)

{

struct ip *ip=(struct ip *)databuf;

int hlen=ip->ip_hl<<2; //total ip header length

if(ip->ip_p!=IPPROTO_ICMP)

{

printf("not icmp packet\n");

return 0;

}

struct icmp *icmp=(struct icmp *)(databuf+hlen);

printf("receive ICMP tpye = %d \n",icmp->icmp_type);

printf("receive ICMP code = %d \n",icmp->icmp_code);

//the port is unreachable

if(icmp->icmp_type==3 && icmp->icmp_code ==3)

{

printf("we get success!\n");

return 1;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值