基于Go語言實(shí)現(xiàn)一個并發(fā)端口掃描器
一、實(shí)戰(zhàn)背景
端口掃描器是網(wǎng)絡(luò)安全領(lǐng)域常用的工具,它通過對目標(biāo)主機(jī)的端口進(jìn)行掃描,檢測目標(biāo)設(shè)備是否開放某些服務(wù)端口(如 HTTP、FTP、SSH 等)。常見的端口掃描場景包括:
- 安全審計(jì):檢測主機(jī)是否存在未授權(quán)服務(wù)
- 漏洞掃描:識別可能存在漏洞的服務(wù)端口
- 網(wǎng)絡(luò)診斷:排查服務(wù)器是否正常工作
傳統(tǒng)的端口掃描使用串行方式,一個端口一個端口地檢查,速度非常慢。而 Go 的并發(fā)編程可以極大地提升掃描效率。
二、實(shí)戰(zhàn)目標(biāo)
我們將實(shí)現(xiàn)一個并發(fā)端口掃描器,具備以下功能:
- 輸入目標(biāo)主機(jī) IP 和端口范圍
- 使用并發(fā)掃描多個端口
- 輸出每個端口的開放狀態(tài)
- 使用超時機(jī)制控制掃描時間,避免阻塞
三、完整代碼實(shí)現(xiàn)
1. 掃描器實(shí)現(xiàn)(scanner.go)
package main
import (
"fmt"
"net"
"strconv"
"sync"
"time"
)
func scanPort(ip string, port int, wg *sync.WaitGroup, resultCh chan<- string) {
defer wg.Done()
address := fmt.Sprintf("%s:%d", ip, port)
conn, err := net.DialTimeout("tcp", address, 1*time.Second) // 設(shè)置連接超時時間
if err != nil {
resultCh <- fmt.Sprintf("端口 %d: 關(guān)閉", port)
return
}
conn.Close()
resultCh <- fmt.Sprintf("端口 %d: 開放", port)
}
func main() {
var wg sync.WaitGroup
resultCh := make(chan string, 100) // 創(chuàng)建帶緩沖的 Channel,緩沖區(qū)大小為 100
fmt.Print("請輸入目標(biāo) IP 地址: ")
var ip string
fmt.Scanln(&ip)
fmt.Print("請輸入端口范圍(例如:80 100): ")
var startPort, endPort int
fmt.Scanln(&startPort, &endPort)
// 掃描指定范圍的端口
for port := startPort; port <= endPort; port++ {
wg.Add(1)
go scanPort(ip, port, &wg, resultCh)
}
// 等待所有掃描任務(wù)完成并關(guān)閉 Channel
go func() {
wg.Wait()
close(resultCh)
}()
// 打印掃描結(jié)果
fmt.Println("\n掃描結(jié)果:")
for result := range resultCh {
fmt.Println(result)
}
}
四、運(yùn)行方式
執(zhí)行端口掃描器
go run scanner.go
輸入示例:
請輸入目標(biāo) IP 地址: 192.168.1.1 請輸入端口范圍(例如:80 100): 80 90
輸出示例:
掃描結(jié)果: 端口 80: 開放 端口 81: 關(guān)閉 端口 82: 關(guān)閉 端口 83: 關(guān)閉 端口 84: 開放 端口 85: 關(guān)閉 端口 86: 開放 端口 87: 關(guān)閉 端口 88: 關(guān)閉 端口 89: 開放 端口 90: 關(guān)閉
五、關(guān)鍵技術(shù)點(diǎn)解析
1. 使用 Goroutine 并發(fā)掃描端口
每個端口的掃描任務(wù)都是由獨(dú)立的 Goroutine 執(zhí)行的。這樣可以最大化利用 CPU 核心,實(shí)現(xiàn)端口掃描的并發(fā)化。
go scanPort(ip, port, &wg, resultCh)
2. 使用 sync.WaitGroup 等待所有 Goroutine 完成
WaitGroup 用來等待所有掃描任務(wù)完成,確保在關(guān)閉結(jié)果通道之前所有掃描任務(wù)已經(jīng)結(jié)束。
var wg sync.WaitGroup wg.Add(1)
3. 使用 net.DialTimeout 設(shè)置連接超時
DialTimeout 可以在指定的超時時間內(nèi)完成連接,如果超時則返回錯誤。我們在這里設(shè)置了 1 秒的超時。
conn, err := net.DialTimeout("tcp", address, 1*time.Second)
4. 使用 channel 收集掃描結(jié)果
通過 Channel 傳遞每個端口的掃描結(jié)果,避免了主線程和 Goroutine 之間的數(shù)據(jù)競爭問題。
resultCh <- fmt.Sprintf("端口 %d: 開放", port)
5. 緩存掃描結(jié)果并打印
使用帶緩沖的 Channel resultCh 存儲掃描結(jié)果。所有任務(wù)完成后,我們關(guān)閉通道并打印掃描結(jié)果。
go func() {
wg.Wait()
close(resultCh)
}()
六、優(yōu)化和擴(kuò)展方向
| 優(yōu)化方向 | 說明 |
|---|---|
| 控制并發(fā)數(shù)量 | 使用令牌桶算法(Token Bucket)或 sem 控制并發(fā)掃描的 Goroutine 數(shù)量 |
| 支持輸入多個目標(biāo) IP | 擴(kuò)展支持一次掃描多個 IP 地址 |
| 掃描端口的協(xié)議支持 | 不僅支持 TCP 端口掃描,還可支持 UDP 掃描 |
| 日志記錄 | 將掃描結(jié)果輸出到日志文件,便于后期分析 |
| 進(jìn)度條顯示 | 添加掃描進(jìn)度顯示,提升用戶體驗(yàn) |
| 智能端口掃描 | 根據(jù)常見端口列表(如 80、443、21 等)進(jìn)行掃描 |
七、小結(jié)
通過本篇案例,你學(xué)會了如何用 Go 實(shí)現(xiàn)一個并發(fā)端口掃描器,掌握了以下關(guān)鍵技術(shù):
- 使用 Goroutine 實(shí)現(xiàn)并發(fā)任務(wù)處理
- 利用
sync.WaitGroup等待所有并發(fā)任務(wù)完成 - 使用
net.DialTimeout進(jìn)行超時控制,防止阻塞 - 使用 Channel 收集并傳遞任務(wù)結(jié)果
這個并發(fā)端口掃描器可以幫助你在網(wǎng)絡(luò)安全和系統(tǒng)維護(hù)中快速診斷目標(biāo)主機(jī)的開放端口。通過優(yōu)化,您還可以將其擴(kuò)展成更完整的網(wǎng)絡(luò)掃描工具。
以上就是基于Go語言實(shí)現(xiàn)一個并發(fā)端口掃描器的詳細(xì)內(nèi)容,更多關(guān)于Go并發(fā)端口掃描器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang 一次性定時器Timer用法及實(shí)現(xiàn)原理詳解
這篇文章主要為大家介紹了golang 一次性定時器Timer用法及實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Go編寫定時器與定時任務(wù)詳解(附第三方庫gocron用法)
當(dāng)需要每天執(zhí)行定時任務(wù)的時候就需要定時器來處理了,周期任務(wù),倒計(jì)時任務(wù),定點(diǎn)任務(wù)等,下面這篇文章主要給大家介紹了關(guān)于Go編寫定時器與定時任務(wù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07

