The go language makes port scanners

  • 2020-05-27 05:54:38
  • OfStack

GO language prepared by TCP port scanner, my first GO program.

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

Command to use:

Scanner startIp [endIp] port thread

Parameter description:

startIp began IP
endIp ends IP, optional, no input means only startIp is scanned
port scan port, single port: 3389; Multiple ports: 1433,3389; Continuous port: 135-3389
thread maximum number of concurrent threads, maximum 2048

The scan results are saved in result.txt in the same directory, and the previous contents are cleared every time you launch.

Example 1:
Scanner 58.96.172.22 58.96.172.220 80 512
Scan port 80 from 58.96.172.22 to 58.96.172.220 for maximum concurrent thread 512.

Example 2:
Scanner 58.96.172.22 58.96.172.220 21,5631 512
Scan ports 21 and 5631 from 58.96.172.22 to 58.96.172.220 for maximum concurrent threads 512.

Example 3:
Scanner 58.96.172.22 58.96.172.220 1-520 512
Scan ports 1 to 520 from 58.96.172.22 to 58.96.172.220 for maximum concurrent threads 512.

Example 4:
Scanner 58.96.172.22 1-520 512
Scan port 1 through 520 in 58.96.172.22, Max concurrent thread 512.


package main
import (
"fmt"
"strconv"
"flag"
"strings"
"net"
"os"
)
/**
   Scan the address 
*/
var ipAddrs chan string = make(chan string)
// Scan results 
var result chan string = make(chan string)
// The number of threads 
var thread chan int = make(chan int)
var nowThread int;
// Close the program 
var clo chan bool = make(chan bool)
// Save the result 
func writeResult(){
  fileName := "result.txt"
  fout,err := os.Create(fileName)
  if err != nil{
    // File creation failed 
    fmt.Println(fileName + " create error")
  }
  defer fout.Close()
  s,ok := <- result
  for ;ok;{
    fout.WriteString(s + "\r\n")
    s,ok = <- result
  }
  // Notification process exit 
  clo <- true; 
}
// Start the scan thread based on the thread parameter 
func runScan(){
  t,ok := <- thread
  nowThread = t;
  if ok{
    for i := 0;i < nowThread;i++{
    go scan(strconv.Itoa(i))
    }
  }
  // Waiting for thread termination 
  for;<-thread == 0;{
    nowThread--
    if nowThread == 0{
      // All threads have terminated , Close result write , Exit the program 
      close(result)
      break
    }
  }
}
/**
   Scan the thread 
*/
func scan(threadId string){
  s,ok := <-ipAddrs
  for;ok;{
    fmt.Println("[thread-" + threadId + "] scan:" + s)
    _,err := net.Dial("tcp",s)
    if err == nil{
      // The port is open 
      result <- s     
    }
    s,ok = <-ipAddrs
  }
  fmt.Println("[thread-" + threadId + "] end")
  thread <- 0;
}
// To obtain the 1 a 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{
      // carry 
      ips[i] = "1"  
    }else{
      //+1
      n++
      ips[i] = strconv.Itoa(n)
      break
    }
  }
  if i == -1{
    // all IP The segments are carried , Illustrate this IP It is out of scope 
    return "";
  }
  ip = ""
  leng := len(ips)
  for i := 0;i < leng;i++{
    if i == leng -1{
      ip += ips[i]
    }else{
      ip += ips[i] + "."
    }
  }
  return ip
}
// generate IP Address list 
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
}
// Processing parameters 
func processFlag(arg []string){
  // start IP, The end of the IP
  var startIp,endIp string
  // port 
  var ports []int = make([]int,0)
  index := 0
  startIp = arg[index]
  si := net.ParseIP(startIp)
  if si == nil{
    // start IP illegal 
    fmt.Println("'startIp' Setting error")
    return
  }
  index++
  endIp = arg[index]
  ei := net.ParseIP(endIp)
  if(ei == nil){
    // End not specified IP, The only scan 1 a IP
    endIp = startIp
  }else{
   index++
  }
  tmpPort := arg[index]
  if strings.Index(tmpPort,"-") != -1{
    // Serial port 
    tmpPorts := strings.Split(tmpPort,"-")
    var startPort,endPort int
    var err error
    startPort,err = strconv.Atoi(tmpPorts[0])
    if err != nil || startPort < 1 || startPort > 65535{
      // The start port is not valid 
      return
    }
    if len(tmpPorts) >= 2{
      // Specify end port 
      endPort,err = strconv.Atoi(tmpPorts[1])
      if err != nil || endPort < 1 || endPort > 65535 || endPort < startPort{
        // The end port is not valid 
        fmt.Println("'endPort' Setting error")
        return
      }
    }else{
      // An end port was not specified 
      endPort = 65535
    }
    for i := 0;startPort + i <= endPort;i++{
      ports = append(ports,startPort + i)
    }
  }else{
    //1 Two or more ports 
    ps := strings.Split(tmpPort,",")
    for i := 0;i < len(ps);i++{
      p,err := strconv.Atoi(ps[i])
      if err != nil{
        // Port illegal 
        fmt.Println("'port' Setting error")
        return
      }
      ports = append(ports,p)
    }
  }
  index++
  t,err := strconv.Atoi(arg[index])
  if(err != nil){
    // Thread illegal 
    fmt.Println("'thread' Setting error")
    return
  }
  // The biggest thread 2048
  if t < 1{
    t = 1;
  }else if t > 2048{
    t = 2048;
  }
  // Sends the number of startup threads 
  thread <- t
  // Generate the scan address list 
  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{
    // Parameter invalid 
    fmt.Println("Parameter error")
    return
  }
  // To obtain parameters 
  args := make([]string,0,4)
  for i := 0;i < flag.NArg();i++{
    args = append(args,flag.Arg(i))
  }
  // Start the scan thread 
  go runScan()
  // Start the result writing thread 
  go writeResult()
  // Processing parameters 
  processFlag(args)
  // Waiting for exit instruction 
  <- clo;
  fmt.Println("Exit")
}

That's all for this article, I hope you enjoy it.


Related articles: