使用方法:command [options] addr
options:
-p 使用指定协议,如:tcp、udp,默认为tcp
-c 使用指定cpu数量,默认为1
-t 使用指定线程数,默认为1(使用多线程扫描,速度会更快)
-d 扫描单个端口超时控制,单位:秒,默认为5秒
package main
import (
"fmt"
"net"
"time"
"sync"
"flag"
"os"
"runtime"
)
type PortScan struct {
timeOut time.Duration
protocol string
cores int
threads int
addr string
availablePort []int
wasteTime int64
rwLocker sync.RWMutex
}
var protocol = flag.String("p", "tcp", "Use the specified protocol")
var cores = flag.Int("c", 1, "Use the specified core number")
var threads = flag.Int("t", 0, "Use the specified thread number")
var timeout = flag.Int("d", 5, "Use the specified duration")
func main() {
var portScanner *PortScan
portScanner = new(PortScan)
if err := portScanner.Scan(); err != nil {
fmt.Println(err)
}
}
func (ps *PortScan) Scan() error {
start := time.Now().Unix()
if err := ps.parse(); err != nil {
return err
}
fmt.Println("开始端口扫描...")
concurrent := make(chan bool, ps.threads)
ports := 65535
for port := 1; port <= ports; port ++ {
concurrent <- true
go ps.check(port, concurrent)
}
end := time.Now().Unix()
ps.wasteTime = end - start
fmt.Printf("扫描结束,耗时%d秒,%s:%s共扫描%d个可用端口\r\n", ps.wasteTime, ps.protocol, ps.addr, len(ps.availablePort))
return nil
}
func (ps *PortScan) appendAvailablePort(port int) {
ps.rwLocker.Lock()
defer ps.rwLocker.Unlock()
ps.availablePort = append(ps.availablePort, port)
}
func (ps *PortScan) check(port int, concurrent <-chan bool) {
ps.connect(port)
<-concurrent
}
func (ps *PortScan) connect(port int) {
cn := make(chan int, 1)
go func() {
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", ps.addr, port))
if err == nil {
conn.Close()
cn <- port
} else {
cn <- 0
}
}()
select {
case result := <-cn:
if result > 0 {
ps.appendAvailablePort(result)
ps.stdout(result)
}
case <-time.After(ps.timeOut):
}
return
}
func (ps *PortScan) parse() error {
flag.Parse()
if len(flag.Args()) == 0 {
flag.Usage()
os.Exit(1)
}
ps.protocol = *protocol
ps.cores = *cores
ps.threads = *threads
ps.timeOut = time.Duration(*timeout) * time.Second
ipAddr, err := net.ResolveIPAddr("ip", flag.Arg(0))
if err != nil {
return err
}
ps.addr = ipAddr.String()
if ps.threads > 0 {
if ps.cores > 0 {
if ps.cores <= runtime.NumCPU() {
runtime.GOMAXPROCS(ps.cores)
} else {
runtime.GOMAXPROCS(runtime.NumCPU())
}
} else {
runtime.GOMAXPROCS(1)
}
} else {
ps.threads = 1
}
return nil
}
func (ps *PortScan) stdout(port int) {
fmt.Println(port)
}