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") }
以上所述就是本文的全部内容了,希望大家能够喜欢。
相关文章
- 这篇文章主要介绍了Go语言压缩和解压缩tar.gz文件的方法,实例分析了使用Go语言压缩文件与解压文件的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03
- 大家有没有遇到过在开启本地服务时,有这么一种情况:当前端口已经被另一个项目使用了,导致服务开启失败。那么接下来,我们通过简简单单的示例代码来检测端口是否已经被占用。有需要的朋友们可以参考借鉴。...2016-10-02
- 这篇文章主要介绍了go语言使用RC4加密的方法,实例分析了RC4加密的技巧与实现方法,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-07
- 这篇文章主要介绍了Go语言图片处理和生成缩略图的方法,涉及Go语言针对图片操作的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03
- 这篇文章主要介绍了创建第一个Go语言程序Hello,Go!本文详细的给出项目创建、代码编写的过程,同时讲解了GOPATH、Go install等内容,需要的朋友可以参考下...2020-05-01
- 这篇文章主要介绍了C#端口转发用法,以实例形式较为详细的分析了C#实现端口转发的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了Go语言创建、初始化数组的常见方式,实例汇总了Go语言操作数组的常见技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-01
- 这篇文章主要介绍了go语言实现文件分割的方法,实例分析了Go语言操作文件的技巧,需要的朋友可以参考下...2020-05-05
- 这篇文章主要介绍了Go语言通过http抓取网页的方法,实例分析了Go语言通过http操作页面的技巧,需要的朋友可以参考下...2020-05-05
- 这篇文章主要介绍了go语言简单的处理http请求的函数,实例分析了Go语言处理http请求的技巧,需要的朋友可以参考下...2020-05-07
- 这篇文章主要介绍了Go语言实现socket的方法,实例分析了socket客户端与服务器端的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03
- 这篇文章主要介绍了Go语言里的new函数用法,实例分析了new函数的功能及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03
- 这篇文章主要介绍了Go语言实现简单留言板的方法,涉及数据库、模板页面元素等留言板相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03
- 这篇文章主要为大家介绍了Go语言的网络编程,其中包含了Socket编程,Http编程以及RPC编程,本篇文章是Go语言七篇入门系列文章,有需要的朋友可以借鉴下...2021-11-10
- 这篇文章主要介绍了Go语言扫描目录并获取相关信息的方法,实例分析了Go语言操作目录及文件的技巧,需要的朋友可以参考下...2020-05-05
- 这篇文章主要介绍了Go语言操作mysql数据库简单例子,本文包含插入数据和查询代码实例,需要的朋友可以参考下...2020-05-01
- 这篇文章主要介绍了Go语言计算指定年月天数的方法,实例分析了Go语言操作时间的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-05
- 这篇文章主要介绍了Zabbix系统端口监控状态,可以使用zabbix自带的key进行监控...2021-05-07
- 这篇文章主要介绍了Go语言获取本机逻辑CPU数量的方法,实例分析了runtime库的操作技巧,需要的朋友可以参考下...2020-05-05
- 这篇文章主要介绍了nginx 代理80端口转443端口的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-06