=Start=
缘由:
用看代码、改代码的方式学习Go 语言。
正文:
参考解答:
放一个网上找到的,既容易理解,效果也不错的代码:
package main
import (
"context"
"fmt"
"net"
"os/exec"
"strconv"
"strings"
"sync"
"time"
"golang.org/x/sync/semaphore"
)
/*
https://medium.com/@KentGruber/building-a-high-performance-port-scanner-with-golang-9976181ec39d
*/
// 将对IP的端口扫描抽象成 PortScanner 结构体
type PortScanner struct {
ip string
lock *semaphore.Weighted // 加权信号量
}
// 通过 os/exec 模块调用命令 `ulimit -n` 并将它输出作为返回
func Ulimit() int64 {
out, err := exec.Command("ulimit", "-n").Output()
if err != nil {
panic(err)
}
s := strings.TrimSpace(string(out))
i, err := strconv.ParseInt(s, 10, 64)
if err != nil {
panic(err)
}
return i
}
// 扫描原理的核心逻辑——使用 net.DialTimeout 进行连接尝试
func ScanPort(ip string, port int, timeout time.Duration) {
target := fmt.Sprintf("%s:%d", ip, port)
conn, err := net.DialTimeout("tcp", target, timeout)
if err != nil {
if strings.Contains(err.Error(), "too many open files") {
time.Sleep(timeout)
ScanPort(ip, port, timeout)
} else {
fmt.Println(port, "closed")
}
return
}
conn.Close()
fmt.Println(port, "open")
}
func (ps *PortScanner) Start(f, l int, timeout time.Duration) {
wg := sync.WaitGroup{}
defer wg.Wait()
for port := f; port <= l; port++ {
ps.lock.Acquire(context.TODO(), 1) // 对每一个 ScanPort 调用都加锁处理
wg.Add(1)
go func(port int) {
defer ps.lock.Release(1)
defer wg.Done()
ScanPort(ps.ip, port, timeout)
}(port)
}
}
func main() {
start_time := time.Now()
ps := &PortScanner{
ip: "127.0.0.1",
lock: semaphore.NewWeighted(Ulimit()),
}
ps.Start(1, 65535, 500*time.Millisecond)
fmt.Printf("Spend %v seconds.\n", time.Since(start_time).Seconds())
}
参考链接:
- 用Go 语言构建一个高性能的端口扫描器 #nice
https://gist.github.com/picatz/9c0028efd7b3ced3329f7322f41b16e1.go - https://github.com/w8rbt/netscan
https://github.com/anvie/port-scanner
https://github.com/gabbifish/golang-port-scanner - PortScan 端口扫描器多种语言实现方案(Golang/Python)
https://thief.one/2018/05/17/1/ - https://golang.org/pkg/sync/#example_WaitGroup
https://golang.org/pkg/net/#JoinHostPort - golang编写的网络端口扫描器
- Golang 写一个端口扫描器 #代码有问题,不能直接用
- 【golang】tcp syn scanner
=END=
《 “Go语言学习#18-实现一个端口扫描器” 》 有 5 条评论
context包定义Context上下文类型,它跨API边界和进程之间传递截止日期、取消信号和其他请求作用域值。
即使函数允许,也不要传递nil上下文。如果还不确定要使用哪个上下文,那就先使用context.TODO。
https://golang.org/pkg/context/#TODO
semaphore包提供了一个加权信号量的实现
https://www.godoc.org/golang.org/x/sync/semaphore
https://github.com/golang/sync/blob/master/semaphore/semaphore.go
深入理解 sync.RWMutex:解决读者-写者问题
https://studygolang.com/articles/14760?fr=sidebar
Golang安全资源合集
https://github.com/re4lity/Hacking-With-Golang
`
# 扫描工具
blacksheepwall – Go语言编写的域名信息搜集工具
amass – Go语言编写的子域名收集工具
vuls – Go语言编写的Linux/FreeBSD漏洞扫描器
gryffin – 大规模Web安全扫描平台
Gobuster – Kai下敏感目录扫描工具
OnionScan – Go语言编写的暗网扫描仪
x-crack – Go语言编写的弱口令扫描器
kraken – Go语言编写的YARA跨平台扫描器
# 网络工具
GoReplay – Go语言编写HTTP流量记录重放工具
NATBypass – LCX/Htran在Golang下的实现
ngrok – 反向代理/内网穿透工具
brook – Go语言编写的一款跨平台代理应用
Hyperfox – HTTP/HTTPS流量监控工具
gost – Go语言编写多功能网络代理转发工具
gomitmproxy – Go语言实现的Mitmproxy
`
Go 基于 Redis 通用频率控制的实现
https://mp.weixin.qq.com/s/OKRZKM3McOhCWMJTaB1hFg
Ngrok内网穿透简单上手
https://blog.mythsman.com/post/5d9aac622db8a452e9b7085a/
无法扫描UDP的端口