go语言制作端口扫描器
go语言编写的tcp端口扫描器,本人的第一个go程序。
git@osc:http://git.oschina.net/youshusoft/goscanner
使用命令:
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") }
以上所述就是本文的全部内容了,希望大家能够喜欢。
上一篇: Golang学习笔记(一):简介
下一篇: Go语言实现的最简单数独解法