go语言制作端口扫描器
GO语言编写的TCP端口扫描器,本人的第一个GO程序。
Git@OSC:http://git.oschina.net/youshusoft/GoScanner
使用命令:
ScannerstartIp[endIp]portthread
参数说明:
startIp 开始IP
endIp 结束IP,可选,不输入表示只扫描startIp
port 扫描端口,单个端口:3389;多个端口:1433,3389;连续端口:135-3389
thread 最大并发线程数,最高2048
扫描结果保存在同目录下的result.txt中,每次启动都会清掉之前的内容。
例子一:
Scanner58.96.172.2258.96.172.22080512
扫描58.96.172.22到58.96.172.220中的80端口,最大并发线程512。
例子二:
Scanner58.96.172.2258.96.172.22021,5631512
扫描58.96.172.22到58.96.172.220中的21和5631端口,最大并发线程512。
例子三:
Scanner58.96.172.2258.96.172.2201-520512
扫描58.96.172.22到58.96.172.220中的1到520端口,最大并发线程512。
例子四:
Scanner58.96.172.221-520512
扫描58.96.172.22中的1到520端口,最大并发线程512。
packagemain
import(
"fmt"
"strconv"
"flag"
"strings"
"net"
"os"
)
/**
扫描地址
*/
varipAddrschanstring=make(chanstring)
//扫描结果
varresultchanstring=make(chanstring)
//线程数
varthreadchanint=make(chanint)
varnowThreadint;
//关闭程序
varclochanbool=make(chanbool)
//保存结果
funcwriteResult(){
fileName:="result.txt"
fout,err:=os.Create(fileName)
iferr!=nil{
//文件创建失败
fmt.Println(fileName+"createerror")
}
deferfout.Close()
s,ok:=<-result
for;ok;{
fout.WriteString(s+"\r\n")
s,ok=<-result
}
//通知进程退出
clo<-true;
}
//根据线程参数启动扫描线程
funcrunScan(){
t,ok:=<-thread
nowThread=t;
ifok{
fori:=0;i<nowThread;i++{
goscan(strconv.Itoa(i))
}
}
//等待线程终止
for;<-thread==0;{
nowThread--
ifnowThread==0{
//全部线程已终止,关闭结果写入,退出程序
close(result)
break
}
}
}
/**
扫描线程
*/
funcscan(threadIdstring){
s,ok:=<-ipAddrs
for;ok;{
fmt.Println("[thread-"+threadId+"]scan:"+s)
_,err:=net.Dial("tcp",s)
iferr==nil{
//端口开放
result<-s
}
s,ok=<-ipAddrs
}
fmt.Println("[thread-"+threadId+"]end")
thread<-0;
}
//获取下一个IP
funcnextIp(ipstring)string{
ips:=strings.Split(ip,".")
variint;
fori=len(ips)-1;i>=0;i--{
n,_:=strconv.Atoi(ips[i])
ifn>=255{
//进位
ips[i]="1"
}else{
//+1
n++
ips[i]=strconv.Itoa(n)
break
}
}
ifi==-1{
//全部IP段都进行了进位,说明此IP本身已超出范围
return"";
}
ip=""
leng:=len(ips)
fori:=0;i<leng;i++{
ifi==leng-1{
ip+=ips[i]
}else{
ip+=ips[i]+"."
}
}
returnip
}
//生成IP地址列表
funcprocessIp(startIp,endIpstring)[]string{
varips=make([]string,0)
for;startIp!=endIp;startIp=nextIp(startIp){
ifstartIp!=""{
ips=append(ips,startIp)
}
}
ips=append(ips,startIp)
returnips
}
//处理参数
funcprocessFlag(arg[]string){
//开始IP,结束IP
varstartIp,endIpstring
//端口
varports[]int=make([]int,0)
index:=0
startIp=arg[index]
si:=net.ParseIP(startIp)
ifsi==nil{
//开始IP不合法
fmt.Println("'startIp'Settingerror")
return
}
index++
endIp=arg[index]
ei:=net.ParseIP(endIp)
if(ei==nil){
//未指定结束IP,即只扫描一个IP
endIp=startIp
}else{
index++
}
tmpPort:=arg[index]
ifstrings.Index(tmpPort,"-")!=-1{
//连续端口
tmpPorts:=strings.Split(tmpPort,"-")
varstartPort,endPortint
varerrerror
startPort,err=strconv.Atoi(tmpPorts[0])
iferr!=nil||startPort<1||startPort>65535{
//开始端口不合法
return
}
iflen(tmpPorts)>=2{
//指定结束端口
endPort,err=strconv.Atoi(tmpPorts[1])
iferr!=nil||endPort<1||endPort>65535||endPort<startPort{
//结束端口不合法
fmt.Println("'endPort'Settingerror")
return
}
}else{
//未指定结束端口
endPort=65535
}
fori:=0;startPort+i<=endPort;i++{
ports=append(ports,startPort+i)
}
}else{
//一个或多个端口
ps:=strings.Split(tmpPort,",")
fori:=0;i<len(ps);i++{
p,err:=strconv.Atoi(ps[i])
iferr!=nil{
//端口不合法
fmt.Println("'port'Settingerror")
return
}
ports=append(ports,p)
}
}
index++
t,err:=strconv.Atoi(arg[index])
if(err!=nil){
//线程不合法
fmt.Println("'thread'Settingerror")
return
}
//最大线程2048
ift<1{
t=1;
}elseift>2048{
t=2048;
}
//传送启动线程数
thread<-t
//生成扫描地址列表
ips:=processIp(startIp,endIp)
il:=len(ips)
fori:=0;i<il;i++{
pl:=len(ports)
forj:=0;j<pl;j++{
ipAddrs<-ips[i]+":"+strconv.Itoa(ports[j])
}
}
close(ipAddrs)
}
funcmain(){
flag.Parse()
ifflag.NArg()!=3&&flag.NArg()!=4{
//参数不合法
fmt.Println("Parametererror")
return
}
//获取参数
args:=make([]string,0,4)
fori:=0;i<flag.NArg();i++{
args=append(args,flag.Arg(i))
}
//启动扫描线程
gorunScan()
//启动结果写入线程
gowriteResult()
//参数处理
processFlag(args)
//等待退出指令
<-clo;
fmt.Println("Exit")
}
以上所述就是本文的全部内容了,希望大家能够喜欢。