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。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

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")

}

以上所述就是本文的全部内容了,希望大家能够喜欢。

本文链接:https://my.lmcjl.com/post/14940.html

展开阅读全文

4 评论

留下您的评论.