当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > go语言制作端口扫描器

go语言制作端口扫描器

2017年12月08日  | 移动技术网IT编程  | 我要评论
go语言编写的tcp端口扫描器,本人的第一个go程序。 git@osc:http://git.oschina.net/youshusoft/goscanner 使用命令

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

git@osc

使用命令:

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")
}

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

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网