go 实现端口扫描器 | go 技术论坛-380玩彩网官网入口
利用 go 批量扫描服务器端口
1、端口扫描器 v1 - 基本操作
package main
import (
"fmt"
"net"
"time"
"unsafe"
)
func main() {
tcpscan("127.0.0.1", 1, 65535)
}
func tcpscan(ip string, portstart int, portend int) {
start := time.now()
// 参数校验
isok := verifyparam(ip, portstart, portend)
if isok == false {
fmt.printf("[exit]\n")
}
for i := portstart; i <= portend; i {
address := fmt.sprintf("%s:%d", ip, i)
conn, err := net.dial("tcp", address)
if err != nil {
fmt.printf("[info] %s close \n", address)
continue
}
conn.close()
fmt.printf("[info] %s open \n", address)
}
cost := time.since(start)
fmt.printf("[tcpscan] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
netip := net.parseip(ip)
if netip == nil {
fmt.println("[error] ip type is must net.ip")
return false
}
fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
if portstart < 1 || portend > 65535 {
fmt.println("[error] port is must in the range of 1~65535")
return false
}
fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
return true
}
2、端口扫描器 v2 - 使用 goroutine
package main
import (
"fmt"
"net"
"sync"
"time"
"unsafe"
)
func main() {
tcpscanbygoroutine("127.0.0.1", 1, 65535)
}
func tcpscanbygoroutine(ip string, portstart int, portend int) {
start := time.now()
// 参数校验
isok := verifyparam(ip, portstart, portend)
if isok == false {
fmt.printf("[exit]\n")
}
var wg sync.waitgroup
for i := portstart; i <= portend; i {
wg.add(1)
go func(j int) {
defer wg.done()
address := fmt.sprintf("%s:%d", ip, j)
conn, err := net.dial("tcp", address)
if err != nil {
fmt.printf("[info] %s close \n", address)
return
}
conn.close()
fmt.printf("[info] %s open \n", address)
}(i)
}
wg.wait()
cost := time.since(start)
fmt.printf("[tcpscanbygoroutine] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
netip := net.parseip(ip)
if netip == nil {
fmt.println("[error] ip type is must net.ip")
return false
}
fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
if portstart < 1 || portend > 65535 {
fmt.println("[error] port is must in the range of 1~65535")
return false
}
fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
return true
}
3、端口扫描器 v3 - 利用 goroutine channel
package main
import (
"fmt"
"net"
"sync"
"time"
"unsafe"
)
func main() {
tcpscanbygoroutinewithchannel("127.0.0.1", 1, 65535)
}
func handleworker(ip string, ports chan int, wg *sync.waitgroup) {
for p := range ports {
address := fmt.sprintf("%s:%d", ip, p)
conn, err := net.dial("tcp", address)
if err != nil {
fmt.printf("[info] %s close \n", address)
wg.done()
continue
}
conn.close()
fmt.printf("[info] %s open \n", address)
wg.done()
}
}
func tcpscanbygoroutinewithchannel(ip string, portstart int, portend int) {
start := time.now()
// 参数校验
isok := verifyparam(ip, portstart, portend)
if isok == false {
fmt.printf("[exit]\n")
}
ports := make(chan int, 100)
var wg sync.waitgroup
for i := 0; i < cap(ports); i {
go handleworker(ip, ports, &wg)
}
for i := portstart; i <= portend; i {
wg.add(1)
ports <- i
}
wg.wait()
close(ports)
cost := time.since(start)
fmt.printf("[tcpscanbygoroutinewithchannel] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
netip := net.parseip(ip)
if netip == nil {
fmt.println("[error] ip type is must net.ip")
return false
}
fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
if portstart < 1 || portend > 65535 {
fmt.println("[error] port is must in the range of 1~65535")
return false
}
fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
return true
}
4 端口扫描器 v4 - 引入两个 channel
// package
package main
import (
"fmt"
"net"
"sort"
"time"
"unsafe"
)
func main() {
tcpscanbygoroutinewithchannelandsort("127.0.0.1", 1, 65535)
}
// the function handles checking if ports are open or closed for a given ip address.
func handleworker(ip string, ports chan int, results chan int) {
for p := range ports {
address := fmt.sprintf("%s:%d", ip, p)
conn, err := net.dial("tcp", address)
if err != nil {
// fmt.printf("[debug] ip %s close \n", address)
results <- (-p)
continue
}
// fmt.printf("[debug] ip %s open \n", address)
conn.close()
results <- p
}
}
func tcpscanbygoroutinewithchannelandsort(ip string, portstart int, portend int) {
start := time.now()
// 参数校验
isok := verifyparam(ip, portstart, portend)
if isok == false {
fmt.printf("[exit]\n")
}
ports := make(chan int, 50)
results := make(chan int)
var openslice []int
var closeslice []int
// 任务生产者-分发任务 (新起一个 goroutinue ,进行分发数据)
go func(a int, b int) {
for i := a; i <= b; i {
ports <- i
}
}(portstart, portend)
// 任务消费者-处理任务 (每一个端口号都分配一个 goroutinue ,进行扫描)
// 结果生产者-每次得到结果 再写入 结果 chan 中
for i := 0; i < cap(ports); i {
go handleworker(ip, ports, results)
}
// 结果消费者-等待收集结果 (main中的 goroutinue 不断从 chan 中阻塞式读取数据)
for i := portstart; i <= portend; i {
resport := <-results
if resport > 0 {
openslice = append(openslice, resport)
} else {
closeslice = append(closeslice, -resport)
}
}
// 关闭 chan
close(ports)
close(results)
// 排序
sort.ints(openslice)
sort.ints(closeslice)
// 输出
for _, p := range openslice {
fmt.printf("[info] %s:%-8d open\n", ip, p)
}
// for _, p := range closeslice {
// fmt.printf("[info] %s:%-8d close\n", ip, p)
// }
cost := time.since(start)
fmt.printf("[tcpscanbygoroutinewithchannelandsort] cost %s second \n", cost)
}
func verifyparam(ip string, portstart int, portend int) bool {
netip := net.parseip(ip)
if netip == nil {
fmt.println("[error] ip type is must net.ip")
return false
}
fmt.printf("[info] ip=%s | ip type is: %t | ip size is: %d \n", netip, netip, unsafe.sizeof(netip))
if portstart < 1 || portend > 65535 {
fmt.println("[error] port is must in the range of 1~65535")
return false
}
fmt.printf("[info] port start:%d end:%d \n", portstart, portend)
return true
}
本作品采用《cc 协议》,转载必须注明作者和本文链接
明天我们吃什么 悲哀藏在现实中
tacks
本帖由系统于 1年前 自动加精
循序渐进 这个好
好文收藏
写的真不错
好,写的真好
好活当赏