目录结构
gscan
Nscan.go //设置扫描目标
scanfactory
Connect.go //连接目标
scanfactory.go //扫描目标
types //设置类型
示意图
运行go run nscan.go -ip=127.0.0.1
nscan.go文件下
首先是用flag 包实现命令行标签解析
在我们运行程序的时候,命令行没有携带参数或携带了-h时会打印解析
紧接着我们我们接收命令行中的ip参数,并用for循环遍历1-1024端口
然后就是开始扫描了,扫描函数是import导入进来的,import,我导入的包是放在工作目录下的src目录,也就是D:\go\gowork\src
scanfactory.go文件下
添加扫描目标,用connect函数进行连接
用通道实现子go程来并发运行,从而提高我们的运行效率
用for加select进行循环选择,连接成功返回值并打印出来,当扫描结束时在connect函数中让s.ok接收参数让并打印sacn over最后进行goto结束运行
connect.go文件下
进行连接,超时退出,结束后通道接收参数
gscan
nscan.go
package main
import (
"flag"
"fmt"
"scanfactory"
. "types"
"os"
)
var ipRange *string = flag.String("ip", "127.0.0.1", `IP range of scan. Example:
scah your-ip`)
var demo *string = flag.String("d", "scan ip=127.0.0.1 port=1-1024", `go run nscan.go -ip=your-ip`)
var help *string = flag.String("h", "help doc", "help doc")
func PortRange() (ports []Port) {
s:=1024
for i:=1;i!=s+1;i++{
ports = append(ports, Port(i))
}
return
}
func getIp(ipRange *string) (ips []Ip, err error) {
ips = append(ips, Ip(*ipRange))
return
}
func main() {
flag.Parse()
if len(os.Args) > 1 && os.Args[1] == "-h" ||
len(os.Args) == 1 {
flag.Usage()
os.Exit(-1)
}
ips, err := getIp(ipRange)
if err != nil {
os.Exit(-1)
}
ports:= PortRange()
fmt.Printf("current scan IP :%s:",ips[0])
fmt.Println("\n")
scan := scanfactory.NewScan(ips, ports)
scan.Scan()
}
scanfactory
scanfactory.go
package scanfactory
import (
"fmt"
. "types"
)
type Addrs struct {
ip []Ip
portList []Port
}
type Scan struct {
Addrs
ch chan Result
ok chan bool
results []Result
sumAddr int
}
func NewScan(ip []Ip, portList []Port) (scan *Scan) {
sumAddr := len(ip) * len(portList)
ch := make(chan Result, sumAddr)
ok := make(chan bool, sumAddr)
return &Scan{Addrs: Addrs{ip, portList}, ch: ch, ok: ok, sumAddr: sumAddr}
}
func (s *Scan) Scan() {
for _, ip := range s.ip {
for _, port := range s.portList {
addr := Addr{ip, port}
go connect(addr, s.ch, s.ok)
}
}
s.waitResults()
}
func (s *Scan) waitResults() {
var result Result
for {
select {
case result = <-s.ch:
s.results = append(s.results, result)
if result.Open {
fmt.Printf("port: %d open\n", result.Addr.Port)
}
case <-s.ok:
s.sumAddr--
if s.sumAddr == 0 {
fmt.Println("scan over")
goto LOOP
}
}
}
LOOP:
}
connect.go
package scanfactory
import (
"net"
"strconv"
"time"
. "types"
)
func connect(addr Addr, c chan Result, ok chan bool) {
remote := string(addr.Ip) + ":" + strconv.Itoa(int(addr.Port))
conn, err := net.DialTimeout("tcp", remote, 5*time.Second)
var result Result
if err == nil {
conn.Close()
result = Result{addr, true}
} else {
result = Result{addr, false}
}
c <- result
ok <- true
}
types
types.go
package types
type Ip string
type Port uint16
type Addr struct {
Ip Ip
Port Port
}
type Result struct {
Addr Addr
Open bool
}