路由器通常会有多个端口,而多个端口的ip可能又处在不同的网段中,以实现不同网段间的数据转发。对于特定路由拓扑的发现,探测路由的端口还是有一定价值的。
路由器通常会有多个端口,而多个端口的ip可能又处在不同的网段中,以实现不同网段间的数据转发。对于特定路由拓扑的发现,探测路由的端口还是有一定价值的。
编程思路:
在已经知道路由的某个端口下,构造一个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;
}
}