当前位置 博文首页 > go语言制作端口扫描器

    go语言制作端口扫描器

    作者:admin 时间:2021-02-15 21:06

    GO语言编写的TCP端口扫描器,本人的第一个GO程序。

    Git@OSC:http://git.oschina.net/youshusoft/GoScanner

    使用命令:

    Scanner startIp [endIp] port thread

    参数说明:

    startIp  开始IP
    endIp  结束IP,可选,不输入表示只扫描startIp
    port  扫描端口,单个端口:3389;多个端口:1433,3389;连续端口:135-3389
    thread  最大并发线程数,最高2048

    扫描结果保存在同目录下的 result.txt 中,每次启动都会清掉之前的内容。

    例子一:
    Scanner 58.96.172.22 58.96.172.220 80 512
    扫描58.96.172.22到58.96.172.220中的80端口,最大并发线程512。

    例子二:
    Scanner 58.96.172.22 58.96.172.220 21,5631 512
    扫描58.96.172.22到58.96.172.220中的21和5631端口,最大并发线程512。

    例子三:
    Scanner 58.96.172.22 58.96.172.220 1-520 512
    扫描58.96.172.22到58.96.172.220中的1到520端口,最大并发线程512。

    例子四:
    Scanner 58.96.172.22 1-520 512
    扫描58.96.172.22中的1到520端口,最大并发线程512。

    package main
    import (
    "fmt"
    "strconv"
    "flag"
    "strings"
    "net"
    "os"
    )
    /**
      扫描地址
    */
    var ipAddrs chan string = make(chan string)
    //扫描结果
    var result chan string = make(chan string)
    //线程数
    var thread chan int = make(chan int)
    var nowThread int;
    //关闭程序
    var clo chan bool = make(chan bool)
    //保存结果
    func writeResult(){
      fileName := "result.txt"
      fout,err := os.Create(fileName)
      if err != nil{
        //文件创建失败
        fmt.Println(fileName + " create error")
      }
      defer fout.Close()
      s,ok := <- result
      for ;ok;{
        fout.WriteString(s + "\r\n")
        s,ok = <- result
      }
      //通知进程退出
      clo <- true; 
    }
    //根据线程参数启动扫描线程
    func runScan(){
      t,ok := <- thread
      nowThread = t;
      if ok{
        for i := 0;i < nowThread;i++{
        go scan(strconv.Itoa(i))
        }
      }
      //等待线程终止
      for;<-thread == 0;{
        nowThread--
        if nowThread == 0{
          //全部线程已终止,关闭结果写入,退出程序
          close(result)
          break
        }
      }
    }
    /**
      扫描线程
    */
    func scan(threadId string){
      s,ok := <-ipAddrs
      for;ok;{
        fmt.Println("[thread-" + threadId + "] scan:" + s)
        _,err := net.Dial("tcp",s)
        if err == nil{
          //端口开放
          result <- s     
        }
        s,ok = <-ipAddrs
      }
      fmt.Println("[thread-" + threadId + "] end")
      thread <- 0;
    }
    //获取下一个IP
    func nextIp(ip string) string{
      ips := strings.Split(ip,".")
      var i int;
      for i = len(ips) - 1;i >= 0;i--{
        n,_ := strconv.Atoi(ips[i])
        if n >= 255{
          //进位
          ips[i] = "1"  
        }else{
          //+1
          n++
          ips[i] = strconv.Itoa(n)
          break
        }
      }
      if i == -1{
        //全部IP段都进行了进位,说明此IP本身已超出范围
        return "";
      }
      ip = ""
      leng := len(ips)
      for i := 0;i < leng;i++{
        if i == leng -1{
          ip += ips[i]
        }else{
          ip += ips[i] + "."
        }
      }
      return ip
    }
    //生成IP地址列表
    func processIp(startIp,endIp string) []string{
      var ips = make([]string,0)
      for ;startIp != endIp;startIp = nextIp(startIp){
        if startIp != ""{
          ips = append(ips,startIp)
        }
      }
      ips = append(ips,startIp)
      return ips
    }
    //处理参数
    func processFlag(arg []string){
      //开始IP,结束IP
      var startIp,endIp string
      //端口
      var ports []int = make([]int,0)
      index := 0
      startIp = arg[index]
      si := net.ParseIP(startIp)
      if si == nil{
        //开始IP不合法
        fmt.Println("'startIp' Setting error")
        return
      }
      index++
      endIp = arg[index]
      ei := net.ParseIP(endIp)
      if(ei == nil){
        //未指定结束IP,即只扫描一个IP
        endIp = startIp
      }else{
       index++
      }
      tmpPort := arg[index]
      if strings.Index(tmpPort,"-") != -1{
        //连续端口
        tmpPorts := strings.Split(tmpPort,"-")
        var startPort,endPort int
        var err error
        startPort,err = strconv.Atoi(tmpPorts[0])
        if err != nil || startPort < 1 || startPort > 65535{
          //开始端口不合法
          return
        }
        if len(tmpPorts) >= 2{
          //指定结束端口
          endPort,err = strconv.Atoi(tmpPorts[1])
          if err != nil || endPort < 1 || endPort > 65535 || endPort < startPort{
            //结束端口不合法
            fmt.Println("'endPort' Setting error")
            return
          }
        }else{
          //未指定结束端口
          endPort = 65535
        }
        for i := 0;startPort + i <= endPort;i++{
          ports = append(ports,startPort + i)
        }
      }else{
        //一个或多个端口
        ps := strings.Split(tmpPort,",")
        for i := 0;i < len(ps);i++{
          p,err := strconv.Atoi(ps[i])
          if err != nil{
            //端口不合法
            fmt.Println("'port' Setting error")
            return
          }
          ports = append(ports,p)
        }
      }
      index++
      t,err := strconv.Atoi(arg[index])
      if(err != nil){
        //线程不合法
        fmt.Println("'thread' Setting error")
        return
      }
      //最大线程2048
      if t < 1{
        t = 1;
      }else if t > 2048{
        t = 2048;
      }
      //传送启动线程数
      thread <- t
      //生成扫描地址列表
      ips := processIp(startIp,endIp)
      il := len(ips)
      for i := 0; i < il;i++{
        pl := len(ports)
        for j := 0;j < pl;j++{
          ipAddrs <- ips[i] + ":" + strconv.Itoa(ports[j]) 
        }
      }
      close(ipAddrs)
    }
    func main(){
      flag.Parse()
      if flag.NArg() != 3 && flag.NArg() != 4{
        //参数不合法
        fmt.Println("Parameter error")
        return
      }
      //获取参数
      args := make([]string,0,4)
      for i := 0;i < flag.NArg();i++{
        args = append(args,flag.Arg(i))
      }
      //启动扫描线程
      go runScan()
      //启动结果写入线程
      go writeResult()
      //参数处理
      processFlag(args)
      //等待退出指令
      <- clo;
      fmt.Println("Exit")
    }
    

    以上所述就是本文的全部内容了,希望大家能够喜欢。

    js
    下一篇:没有了