=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的端口