Linux下UDP端口扫描

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/gamer727/article/details/47728333

由于UDP协议是非面向连接的,对UDP端口的探测也就不可能像TCP端口的探测那样依赖于连接建立过程,这也使得UDP端口扫描的可靠性不高。所以虽然UDP协议较之TCP协议显得简单,但是对UDP端口的扫描却是相当困难的。下面具体介绍一下UDP扫描方案:
        方案1:利用ICMP端口不可达报文进行扫描
        本方案的原理是当一个UDP端口接收到一个UDP数据报时,如果它是关闭的,就会给源端发回一个ICMP端口不可达数据报,ICMP协议中的类型字段为3(目的站点不可达)和代码字段为3(表示端口不可达);如果它是开放的,那么就会忽略这个数据报,也就是将它丢弃而不返回任何的信息,这里可以设置超时来进行判断。

        优点:
        可以完成对UDP端口的探测。
        缺点:
        需要系统管理员的权限。扫描结果的可靠性不高。因为当发出一个UDP数据报而没有收到任何的应答时,有可能因为这个UDP端口是开放的,也有可能是因为这个数据报在传输过程中丢失了。另外,扫描的速度很慢。原因是在RFC1812的中对ICMP错误报文的生成速度做出了限制。例如Linux就将ICMP报文的生成速度限制为每4秒钟80个,当超出这个限制的时候,还要暂停1/4秒。   
        方案2:UDP   recvfrom()和write()扫描   
        本方案实际上是对前一个方案的一些改进,目的在于解决方案1中所需要的系统管理员的权限问题。由于只有具备系统管理员的权限才可以查看ICMP错误报文,那么在不具备系统管理员权限的时候可以通过使用recvfrom( )和write( )这两个系统调用来间接获得对方端口的状态。对一个关闭的端口第二次调用write()的时候通常会得到出错信息。而对一个UDP端口使用recvfrom调用的时候,如果系统没有收到ICMP的错误报文通常会返回一个EAGAIN错误,错误类型码13,含义是“再试一次(Try   Again)”;如果系统收到了ICMP的错误报文则通常会返回一个ECONNREFUSED错误,错误类型码111,含义是“连接被拒绝(Connect   refused)”。通过这些区别,就可以判断出对方的端口状态如何。
        优点:
        不需要系统管理员的权限。
        缺点:
        除去解决了权限的问题外,其他问题依然存在。


实现代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <strings.h>
#include <errno.h>


#define MAXPACKET 4096
#define DEFAULT_TIMEOUT 10
#define DEFAULT_RESEND 6


void start_scanning(const char* ipaddress,unsigned short port)
{
unsigned int timeout=4, maxretry=3;
struct sockaddr_in myudp;
int udpsock, rawsock, retry, retval,iplen;
fd_set r;
struct timeval mytimeout;
struct icmp *packet;
struct ip *iphdr;
struct servent *service;
unsigned char recvbuff[MAXPACKET];




if((udpsock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
{
perror("socket()");
exit(-1);
}


if((rawsock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0)
{
perror("socket()");
exit(-1);
}
mytimeout.tv_sec = timeout;
mytimeout.tv_usec = 0;
retry = 0;


myudp.sin_addr.s_addr = inet_addr(ipaddress);
myudp.sin_family = AF_INET;
myudp.sin_port = htons(port);


while(retry++ < maxretry)
{
FD_ZERO(&r);
FD_SET(rawsock,&r);
if((sendto(udpsock,"  ",2,0,(struct sockaddr *)&myudp,sizeof(myudp))) < 0)
{
perror("sendto");
exit(-1);
}
retval = select((rawsock+1),&r,NULL,NULL,&mytimeout);
if(retval ==1)
{//some data reach
if((recvfrom(rawsock,recvbuff,sizeof(recvbuff),0x0,NULL,NULL)) < 0)
{
perror("Recv");
exit(-1);
}
iphdr = (struct ip *)recvbuff;
iplen = iphdr->ip_hl * 4;
packet = (struct icmp *)(recvbuff + iplen);
printf("the icmp type is=%d, code=%d \n",packet->icmp_type,packet->icmp_code);
if((packet->icmp_type == ICMP_UNREACH) && (packet->icmp_code == ICMP_UNREACH_PORT))
break;
} //end if(retval ==1)
else if(retval ==0)
{
printf("time out! the port may be availed !\n");
continue;
}
else
{
printf("occur some errors! scan udp failed !\n");
return ;
}
} //end while(1)


if(retry >= maxretry)
{
if((service = getservbyport(htons(port),"udp")) == NULL)
fprintf(stdout,"Unknown port %u, open.\n",port);
else
fprintf(stdout,"UDP service %s open.\n",service->s_name);
fflush(stdout);
}
else
{
printf("the port:%d is unavailable!\n",port);
}


}


int main(int argc,char **argv)
{
start_scanning("192.168.2.1",27015);
printf("scan over\n");
return 0;




}


 



展开阅读全文

C# udp端口扫描的问题

04-15

做一个简单的UDP端口扫描程序,如下。rn使用wireshark抓包后,发现udp的包成功送出后,有返回给我的主机ICMP的报文。rn但是在调用socket.receiveFrom的时候,receiveBuff里面什么都没有收到。rn经过debug后发现,socket的端口赋值有问题,详情见代码。rn请指教,谢谢。rn[code=C#]using System;rnusing System.Collections.Generic;rnusing System.Linq;rnusing System.Text;rnusing System.Net;rnusing System.Net.Sockets;rnrnnamespace UDPscanModulernrn class Programrn rn static void Main(string[] args)rn rn for (int i = 11000; i < 21000; i++)rn rnrn UdpClient udpClient = new UdpClient(i);rn IPAddress ipAddress = Dns.Resolve("www.baidu.com").AddressList[0];rn IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 11004);rn EndPoint remoteEndPoint = (ipEndPoint);rn Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");rnrnrn Console.WriteLine();rn Console.WriteLine("ready...");rnrn tryrn rn Console.WriteLine("try to send udp package...");rn //发送udp给远端,特定端口rn udpClient.Send(sendBytes, sendBytes.Length, ipEndPoint);rn rn catch (Exception e)rn rn Console.WriteLine(e.ToString());rn rnrn //本机的ip地址,其中i是我设定的本机的发送端口rn IPEndPoint ipMyEndPoint = new IPEndPoint(IPAddress.Parse("59.78.50.32"), i);rn EndPoint myEndPoint = (ipMyEndPoint);rn Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);rn rn socket.Bind(ipMyEndPoint);//绑定socket,问题:DEBUG的时候,ipMyEndPoint的端口号为i的值rn //但是socket.bind之后,socket的端口仍是0,为什么呢?rnrn Console.WriteLine("we are waiting for ICMP...");rn Byte[] ReceiveBuffer = new Byte[256];rn socket.ReceiveTimeout = 500;rn rn tryrn rn var nBytes = socket.ReceiveFrom(ReceiveBuffer, ref myEndPoint);rn rn catch (Exception e)rn rn //Console.WriteLine(e.ToString());rn Console.WriteLine("exception");rn rn Console.WriteLine("complete");rn if (ReceiveBuffer[20] == 3)//ICMP TYPE= DELIVERY FAILEDrn rn rn Console.WriteLine("Delivery failed");rn Console.WriteLine("Returned by: " + myEndPoint.ToString());rn Console.WriteLine("Destination: " + ReceiveBuffer[44] + "." + ReceiveBuffer[45] + "." + ReceiveBuffer[46] + "." + ReceiveBuffer[47]);rn Console.WriteLine("---------------");rn rn elsern rn Console.WriteLine("Some (not delivery failed) ICMP packet ignored");rn rn //udpClient.Close();rn rnrn rn rn[/code]rn 论坛

没有更多推荐了,返回首页