GO語(yǔ)言編寫的TCP端口掃描器,本人的第一個(gè)GO程序。
Git@OSC:http://git.oschina.net/youshusoft/GoScanner
使用命令:
Scanner startIp [endIp] port thread
參數(shù)說(shuō)明:
startIp 開(kāi)始IP
endIp 結(jié)束IP,可選,不輸入表示只掃描startIp
port 掃描端口,單個(gè)端口:3389;多個(gè)端口:1433,3389;連續(xù)端口:135-3389
thread 最大并發(fā)線程數(shù),最高2048
掃描結(jié)果保存在同目錄下的 result.txt 中,每次啟動(dòng)都會(huì)清掉之前的內(nèi)容。
例子一:
Scanner 58.96.172.22 58.96.172.220 80 512
掃描58.96.172.22到58.96.172.220中的80端口,最大并發(fā)線程512。
例子二:
Scanner 58.96.172.22 58.96.172.220 21,5631 512
掃描58.96.172.22到58.96.172.220中的21和5631端口,最大并發(fā)線程512。
例子三:
Scanner 58.96.172.22 58.96.172.220 1-520 512
掃描58.96.172.22到58.96.172.220中的1到520端口,最大并發(fā)線程512。
例子四:
Scanner 58.96.172.22 1-520 512
掃描58.96.172.22中的1到520端口,最大并發(fā)線程512。
package main
import (
"fmt"
"strconv"
"flag"
"strings"
"net"
"os"
)
/**
掃描地址
*/
var ipAddrs chan string = make(chan string)
//掃描結(jié)果
var result chan string = make(chan string)
//線程數(shù)
var thread chan int = make(chan int)
var nowThread int;
//關(guān)閉程序
var clo chan bool = make(chan bool)
//保存結(jié)果
func writeResult(){
fileName := "result.txt"
fout,err := os.Create(fileName)
if err != nil{
//文件創(chuàng)建失敗
fmt.Println(fileName + " create error")
}
defer fout.Close()
s,ok := - result
for ;ok;{
fout.WriteString(s + "\r\n")
s,ok = - result
}
//通知進(jìn)程退出
clo - true;
}
//根據(jù)線程參數(shù)啟動(dòng)掃描線程
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{
//全部線程已終止,關(guān)閉結(jié)果寫入,退出程序
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{
//端口開(kāi)放
result - s
}
s,ok = -ipAddrs
}
fmt.Println("[thread-" + threadId + "] end")
thread - 0;
}
//獲取下一個(gè)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{
//進(jìn)位
ips[i] = "1"
}else{
//+1
n++
ips[i] = strconv.Itoa(n)
break
}
}
if i == -1{
//全部IP段都進(jìn)行了進(jìn)位,說(shuō)明此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
}
//處理參數(shù)
func processFlag(arg []string){
//開(kāi)始IP,結(jié)束IP
var startIp,endIp string
//端口
var ports []int = make([]int,0)
index := 0
startIp = arg[index]
si := net.ParseIP(startIp)
if si == nil{
//開(kāi)始IP不合法
fmt.Println("'startIp' Setting error")
return
}
index++
endIp = arg[index]
ei := net.ParseIP(endIp)
if(ei == nil){
//未指定結(jié)束IP,即只掃描一個(gè)IP
endIp = startIp
}else{
index++
}
tmpPort := arg[index]
if strings.Index(tmpPort,"-") != -1{
//連續(xù)端口
tmpPorts := strings.Split(tmpPort,"-")
var startPort,endPort int
var err error
startPort,err = strconv.Atoi(tmpPorts[0])
if err != nil || startPort 1 || startPort > 65535{
//開(kāi)始端口不合法
return
}
if len(tmpPorts) >= 2{
//指定結(jié)束端口
endPort,err = strconv.Atoi(tmpPorts[1])
if err != nil || endPort 1 || endPort > 65535 || endPort startPort{
//結(jié)束端口不合法
fmt.Println("'endPort' Setting error")
return
}
}else{
//未指定結(jié)束端口
endPort = 65535
}
for i := 0;startPort + i = endPort;i++{
ports = append(ports,startPort + i)
}
}else{
//一個(gè)或多個(gè)端口
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;
}
//傳送啟動(dòng)線程數(shù)
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{
//參數(shù)不合法
fmt.Println("Parameter error")
return
}
//獲取參數(shù)
args := make([]string,0,4)
for i := 0;i flag.NArg();i++{
args = append(args,flag.Arg(i))
}
//啟動(dòng)掃描線程
go runScan()
//啟動(dòng)結(jié)果寫入線程
go writeResult()
//參數(shù)處理
processFlag(args)
//等待退出指令
- clo;
fmt.Println("Exit")
}
以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。
您可能感興趣的文章:- Go語(yǔ)言實(shí)現(xiàn)的簡(jiǎn)單網(wǎng)絡(luò)端口掃描方法
- GO語(yǔ)言實(shí)現(xiàn)的端口掃描器分享
- go 實(shí)現(xiàn)簡(jiǎn)易端口掃描的示例