端口扫描器的实现

一。原理

端口扫描器是一种程序,它可以对目标主机的端口进行连接,并记录目标端口的应答。端口扫描器通过选用远程TCP/IP协议不同的端口的服务,记录目标计算机端口给予回答的方法,可以收集到很多关于目标计算机的各种有用信息(比如是否有端口在侦听,是否允许匿名登录,是否有可写的FTP目录,是否能用Telnet等)。

网络中的每一台计算机如同一座城堡,在这些城堡中,有的对外完全开放,有的却是紧锁城门。入侵者们是如何找到,并打开它们的城门的呢?这些城门究竟通向城堡的何处呢?在网络技术中,把这些城堡的“城门”称之为计算机的“端口”。端口扫描是入侵者搜集信息的几种常用手法之一。端口相当于两台计算机进程间的大门,可以随便定义,其目的只是为了让两台计算机能够找到对方的进程。计算机就像一座大楼,这个大楼有好多入口(端口),进到不同的入口中就可以找到不同的公司(进程)。如果要和远程主机A的程序通信,那么只要把数据发向A端口就可以实现通信了。
可见,端口与进程是一一对应的,如果某个进程正在等待连接,称之为该进程正在监听,那么就会出现与它相对应的端口。由此可见,通过扫描端口,便可以判断出目标计算机有哪些通信进程正在等待连接。

端口扫描的原理其实非常简单,只是简单的利用JAVA提供库函数Socket进行调用,与每一个感兴趣的目标计算机的端口进行连接。如果对方端口处于监听状态,那么连接就能成功。否则,这个端口不能用,既没有提供服务。这个技术的一个最大的优点是,不需要任何权限,系统中的任何用户都有权利使用这个调用。
引入多线程机制,利用多线程扫描的好处就是速度快,如果对每个目标端口以线性的方式使用单独的连接调用,那么将会花费相当长的时间。多线程同时打开多个套接字,从而加速扫描。在本设计中用户可以自定义线程的个数。此处用户还可以自定义扫描方式。

二。代码实现(为了深入理解 ,代码设置有错误,请勿直接使用,仅作参考)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
typedef struct _port_segment
{
     struct in_addr  dest_ip; //destination ip address;
     unsigned short int min_port; //begin port
     unsigned short int max_port;// end port
}port_segment;
 
void my_err(const char *err_string int line)
{
   fprintf(stderr, "line %d ",line);
   perror(error_string);
   exit(1);
}
//description scan one port on one ip
 
int do_scan(struct sockaddr_in serv_addr)
{
     int conn_fd;
     int ret;
     conn_fd=socket(AF_INET,SOCK_STREAM,0);
     if(conn_fd<0)
     {
        my_err("socket" ,__LINE__);
     }
     if((ret=connect(conn_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr)))<-)
     {
          if(errno==ECONNREUSED)  
          {
               //target port close
               close(conn_fd);
               return 0;
          }
          else
          {
              close(conn_fd);
              return -1
          }
     }else if(ret==0)
     {
         printf("port %d found in %s \n",ntohs(serv_addr.sin_port),inet_ntoa(serv_addr.sin_addr));
         close(conn_fd);
         return 1
     }
     return -1
}
 
void *scaner(void *arg)
{
    unsigned short int i;
    struct sockaddr_in serv_addr;
    port_segment portinfo;//port information
     
    memcpy(&portinfo,arg,sizeof(struct _port_segment));
    memset(&serv_addr,0,sizeof(struct sockaddr_in));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=portinfo.dest_ip.s_addr;
     
    for(i=portinfo.min_port;i<=portinfo.max_port;+i++)
    {
       serv_addr.sin_port=htons(i);
       if(do_scan(serv_addr)<0)
          continue;
    }
    return NULL;
     
}
int main(int argc, char **argv)
{
    pthread_t *thread;  //thread id
    int max_port;  //max port number  
    int thread_num;  //max thread number
    int seg_len;  //port  length
    struct in_addr dest_ip;//destination ip
     
    if(argc!=7)
    {
        printf("Usage :]-m [max_port] -a [serv_addr] -n thread_number\n");
        exit(1);
         
    }
     
    for(i=1;i<argc;i++)
    {
        if(strcmp("-m",argv[1]])==0)
        {
             max_port=atoi(argv[i+1]);
             if(max_port<||max_port>65535)
             {
                printf("Usage: invalid max destination port \n");
                exit(1);
             }
             continue;
        }
        if(strcmp("-a",argv[i])==0)
        {
            if(inet_aton(argv[i+1]),&dest_ip)==0)
            {
               printf("Ysage :invalid destination ip address \n");
               exit(1);
            }
            continue;
        }
        if(strcmp("-n",argv[i])==0)
        {
            thread_num=atoi(argv[i+1]);
            if(thread_num<=0)
            {
               printf("Usage invalid thread number \n");
               exit(1);
            }
            continue;
        }
         
    }
    if(max_port<thread_num)
    {
       thread_num=max_port;
    }
    seg_len=max_port; //
    if((max_port%thread_num)!=0)
    {
      thread_num+=1;
    }
    thread=(pthread_t *)malloc(thread_num*sizeof(pthread_t));
     
    for(i=0;i<pthread_num;i++)
    {
      port_segment portinfo;
      portinfo.dest_ip=dest_ip;
      portinfo.min_port=i*seg_len+1;
      if(i=pthread_num-1)
      {
           portinfo.max_port=max_port;
      }
      else
      {
           portinfo.max_port=portinfo.min_port+seg_len-1;
      }
      if(pthread_create(&thread[i],NULL,scanner,(void *)&portinfo)!=0)
      {
          my_err("thread create ",__LINE__);
           
      }
      //wait for child thread ended
   pthread_join(thread[i],NULL);
    }
     return 0;
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java端口扫描是一种用于检测目标主机上开放的网络端口的工具。它可以帮助网络管理员快速识别主机上的漏洞和弱点,以便及时进行修复和加固。下面是关于Java端口扫描的设计与实现。 首先,我们需要设计一个程序入口,用于接收用户输入的目标主机IP地址和要扫描的端口范围。然后,我们需要编写一个端口扫描函数,该函数接收目标主机IP和端口号作为参数,并尝试与目标主机建立连接。如果连接成功,表示该端口是开放的;如果连接失败,表示该端口是关闭的。 接下来,我们需要实现多线程并发扫描,以提高程序的效率。可以将端口扫描函数封装为一个Runnable对象,然后创建多个线程同时执行这些任务。这样可以并行地扫描目标主机的多个端口,加快扫描速度。 另外,我们还可以对扫描结果进行处理和展示。可以将扫描结果保存在文件中,或者直接在命令行或GUI界面上展示给用户。这样用户可以清楚地看到目标主机上哪些端口是开放的,哪些是关闭的。 最后,为了提高扫描的准确性和健壮性,我们可以添加一些异常处理和超时控制。例如,设置连接超时时间,以防止程序长时间等待连接结果而导致的阻塞。另外,还可以添加一些错误处理机制,及时处理因网络原因导致的连接失败或超时错误。 总的来说,设计和实现Java端口扫描需要考虑到用户友好性、效率和稳定性等方面,通过合理的并发处理和异常处理机制,可以使扫描更加实用和可靠。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值