The go language makes port scanners


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.