端口扫描介绍
端口扫描可以收集目的主机的提供服务端口的信息,可以对于目的主机的信息进行收集。
端口扫描的程序每次会向目的主机特定端口发送一条请求,如果请求得到回应则可以判断是否本端口在对外开放,通过这种方法可以探知目的主机的弱点。
扫描器可以不留痕迹的进行扫描的工作,可以发现远程服务器的各种TCP端口的分配及提供的服务和它们的软件版本。
在linux中,/etc/services存储了端口号和关键字的对应关系。同时常见的端口一般不会更改服务。如:ftp(21)telnet(23)www(80)pop3(110)etc。
本程序实现了简单的端口扫描程序:可以指定目的主机的端口和需要扫描的端口的范围进行扫描,如果对应端口打开,则输出该端口,否则指示该端口不开启。
程序流程如下:
程序代码:
#include<cstdio>
#include<cstdlib>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#include<cstring>
#define CHKADDRESS(_saddr_)\
{\
u_char *p=(u_char*)&(_saddr_);\
if((p[0]==10)||(p[0]==168&&16<=p[1]&&p[1]<=31)||(p[0]==192&&p[1]==168))\
;\
else{\
fprintf(stderr,"ip address error!\n");\
exit(EXIT_FAILURE);\
}\
}
enum{ CMD_NAME,DST_IP,START_PORT,LAST_PORT};
enum{ CONNECT,NOCONNECT};
int tcpscanport(u_int dst_ip,int dst_port);
int main(int argc,char** argv)
{
u_int dst_ip; //扫描端口的主机IP地址
int dst_port; //终端端口号
int start_port; //初始端口号
int last_port; //结束端口号
if(argc!= 4)
{
fprintf(stderr,"usage:%s dst_ip port last_port\n",argv[CMD_NAME]);
exit(EXIT_FAILURE);
}
//设置执行的参数
dst_ip=inet_addr(argv[DST_IP]);
start_port=atoi(argv[START_PORT]);
last_port=atoi(argv[LAST_PORT]);
for(dst_port=start_port;dst_port<last_port;dst_port++)
{
printf("scan port%d",dst_port);
fflush(stdout);
if(tcpscanport(dst_ip,dst_port)==CONNECT)
{
struct servent *sp;
sp=getservbyport(htons(dst_port)," tcp");
printf("%5d %-20s\n",dst_port,(sp==NULL)?"unknown":sp->s_name);
}
else
{
printf(" noconnect\n");
}
}
return EXIT_SUCCESS;
}
/*
在指定端口建立tcp连接
*/
int tcpscanport(u_int dst_ip,int dst_port)
{
struct sockaddr_in dest;
int s;
int ret;
memset((char*)&dest,0,sizeof(sockaddr_in));
dest.sin_family=AF_INET;
dest.sin_port=htons(dst_port);
dest.sin_addr.s_addr=dst_ip;
//检查地址是否合法
CHKADDRESS(dest.sin_addr.s_addr);
//创建tcp socket
if((s=socket(AF_INET,SOCK_STREAM,0))<0)
{
perror("socket");
exit(EXIT_FAILURE);
}
//建立连接
if(connect(s,(struct sockaddr*)&dest,sizeof(dest))<0)
{
ret=NOCONNECT;
}
else
{
ret=CONNECT;
}
close(s);
return ret;
}