手把手教你用Go語言打造一款簡易TCP埠掃描器

2021-01-11 51CTO

 前言

Hey,大家好呀,我是碼農,星期八。

這次呢, 咱們來實現一個簡單的TCP埠掃描器!

也來體驗一下黑客的風採!

TCP掃描本質

我們在使用TCP進行連接時,需要知道對方機器的ip:port

正常握手

連接成功的話,流程如下。


連接失敗

有正常,就有失敗,如果被連接方關閉的話,流程如下。


如果有防火牆

還有一種可能是,埠開放,但是防火牆攔截,流程如下。


代碼

本質理解之後,就可以開始擼代碼了。

在Go中,我們通常使用net.Dial進行TCP連接

它就兩種情況

成功:返回conn。 失敗:err != nil。

普通版

相對來說,剛開始時,我們可能都不是太膽大,都是先寫原型,也不考慮性能。

代碼

package main  import (     "fmt"     "net" )  func main() {     var ip = "192.168.43.34"     for i := 21; i <= 120; i++ {         var address = fmt.Sprintf("%s:%d", ip, i)         conn, err := net.Dial("tcp", address)         if err != nil {             fmt.Println(address, "是關閉的")             continue         }         conn.Close()         fmt.Println(address, "打開")   } } 

執行結果


但是這個過程是非常緩慢的。

因為net.Dial如果連接的是未開放的埠,一個埠可能就是20s+,所以,我們為什麼學習多線程懂了把!!!

多線程版

上述是通過循環去一個個連接ip:port的,那我們就知道了,在一個個連接的位置,讓多個人去幹就好了。

所以,多線程如下。

代碼

package main  import (     "fmt"     "net"     "sync"     "time" )  func main() {      var begin =time.Now()     //wg     var wg sync.WaitGroup     //ip     var ip = "192.168.99.112"     //var ip = "192.168.43.34"     //循環     for j := 21; j <= 65535; j++ {         //添加wg         wg.Add(1)         go func(i int) {             //釋放wg             defer wg.Done()             var address = fmt.Sprintf("%s:%d", ip, i)             //conn, err := net.DialTimeout("tcp", address, time.Second*10)             conn, err := net.Dial("tcp", address)             if err != nil {                 //fmt.Println(address, "是關閉的", err)                 return             }             conn.Close()             fmt.Println(address, "打開")         }(j) }     //等待wg     wg.Wait()     var elapseTime = time.Now().Sub(begin)     fmt.Println("耗時:", elapseTime) } 

執行結果

 

其實是同時開啟了6W多個線程,去掃描每個ip:port。

所以耗時最長的線程結束的時間,就是程序結束的時間。

感覺還行,20s+掃描完6w多個埠!!!

線程池版

上面我們簡單粗暴的方式為每個ip:port都創建了一個協程。

雖然在Go中,理論上協程開個幾十萬個都沒問題,但是還是有一些壓力的。

所以我們應該採用一種相對節約的方式進行精簡代碼,一般採用線程池方式。

本次使用的線程池包:gohive

地址:https://github.com/loveleshsharma/gohive

簡單介紹


代碼

package main  //線程池方式 import (     "fmt"     "github.com/loveleshsharma/gohive"     "net"     "sync"     "time" )  //wg var wg sync.WaitGroup  //地址管道,100容量 var addressChan = make(chan string, 100)  //工人 func worker() {     //函數結束釋放連接     defer wg.Done()     for {         address, ok := <-addressChan         if !ok {             break         }         //fmt.Println("address:", address)         conn, err := net.Dial("tcp", address)         //conn, err := net.DialTimeout("tcp", address, 10)         if err != nil {             //fmt.Println("close:", address, err)             continue         }         conn.Close()         fmt.Println("open:", address) } } func main() {     var begin = time.Now()     //ip     var ip = "192.168.99.112"     //線程池大小     var pool_size = 70000     var pool = gohive.NewFixedSizePool(pool_size)      //拼接ip:埠     //啟動一個線程,用於生成ip:port,並且存放到地址管道種     go func() {         for port := 1; port <= 65535; port++ {             var address = fmt.Sprintf("%s:%d", ip, port)             //將address添加到地址管道             //fmt.Println("<-:",address)             addressChan <- address         }         //發送完關閉 addressChan 管道         close(addressChan) }()     //啟動pool_size工人,處理addressChan種的每個地址     for work := 0; work < pool_size; work++ {         wg.Add(1)         pool.Submit(worker) }     //等待結束     wg.Wait()     //計算時間     var elapseTime = time.Now().Sub(begin)     fmt.Println("耗時:", elapseTime) } 

執行結果


我設置的線程池大小是7w個,所以也是一下子開啟6w多個協程的,但是我們已經可以進行線程大小約束了。

假設現在有這樣的去求,有100個ip,需要掃描每個ip開放的埠,如果採用簡單粗暴開線程的方式.

那就是100+65535=6552300,600多w個線程,還是比較消耗內存的,可能系統就會崩潰,如果採用線程池方式。

將線程池控制在50w個,或許情況就會好很多。

但是有一點的是,在Go中,線程池通常需要配合chan使用,可能需要不錯的基礎。

總結

本篇更偏向於樂趣篇,了解一下好玩的玩意。

其實還可以通過net.DialTimeout連接ip:port,這個可以設置超時時間,比如超時5s就判定埠未開放。

此處就不做舉例了。

咱們主要使用三種方式來實現功能。

正常版,沒有並發,速度很慢。 多協程版,並發,性能很高,但是協程太多可能會崩潰。 協程池版,並發,性能高,協程數量可控。

通常情況下,如果基礎可以,更推薦使用協程池方式。

用微笑告訴別人,今天的我比昨天強,今後也一樣。

【編輯推薦】

【責任編輯:

姜華

TEL:(010)68476606】

點讚 0

相關焦點

  • [Python黑帽] 三.編程實現IP及埠掃描器、實現多線程C段掃描器
    Python黑帽第三篇文章將分享網絡掃描基礎知識,編程實現IP及埠掃描器、實現多線程C段掃描器。
  • 如何使用zenmap掃描你的伺服器埠
    可以用來掃描伺服器的開放埠,首先,平出你需要掃描埠的伺服器,然後打開zenmap,把IP丟進目標中。接下來還有多種掃描方式,這裡我選擇默認的強烈掃描。Nmap done: 1 IP address (1 host up) scanned in 161.96 seconds接下來你就可以看到
  • 埠掃描技術,Namp工具的使用介紹
    :21Telnet(遠程登錄)協議代理伺服器常用埠號:23HTTP伺服器,默認埠號為80/tcp(木馬Executor開放此埠)HTTPS(securely transferring web pages)伺服器,默認埠號為443/tcp
  • 使用netcat [nc]命令對Linux和Unix進行埠掃描
    我如何在自己的伺服器上找出哪些埠是開放的?如何使用 nc 命令進行埠掃描來替換 Linux 或類 Unix 中的 nmap 命令? nmap (「Network Mapper」)是一個用於網絡探測和安全審核的開源工具。
  • 網絡防火牆詳解:記錄(Log)與埠
    通常對於防火牆的TCP/UDP埠掃描有哪些? 本節講述通常TCP/UDP埠掃描在防火牆記錄中的信息。記住:並不存在所謂ICMP埠。如果你對解讀ICMP數據感興趣,請參看本文的其它部分。 0 通常用於分析作業系統。這一方法能夠工作是因為在一些系統中「0」是無效埠,當你試圖使用一種通常的閉合埠連接它時將產生不同的結果。
  • 你看到了什麼 解釋防火牆Log與埠
    (一) 通常對於防火牆的TCP/UDP埠掃描有哪些? 本節講述通常TCP/UDP埠掃描在防火牆記錄中的信息。記住:並不存在所謂ICMP埠。如果你對解讀ICMP數據感興趣,請參看本文的其它部分。 0 通常用於分析作業系統。這一方法能夠工作是因為在一些系統中「0」是無效埠,當你試圖使用一種通常的閉合埠連接它時將產生不同的結果。
  • 解Bug之路-NAT引發的性能瓶頸|埠|tcp|nginx|ip|ack_網易訂閱
    合作方的多臺機器用NAT將多個源ip映射成同一個出口ip 20.1.1.1,而我們內網將多個Nginx映射成同一個目的ip 30.1.1.1。沒效果在一開始筆者沒有搞明白LVS那個詭異的曲線的時候,筆者並不知道在埠復用的情況下,LVS會表現出"親和性"。於是想著,如果擴容Nginx後,根據負載均衡原則,正好落到有這個TIME_WAIT五元組的概率會降低,所以嘗試著另擴容了一倍的Nginx。但由於之前所說的LVS在埠號復用下的親和性,反而加大了TIME_WAIT段!
  • Go語言愛好者周刊:第 23 期
    3、做 github 最好用的 http client 庫,讓你體會到還沒有爽玩,活已經幹玩。4、用 Go 編寫的 XMPP 伺服器。)大神是如何學習 Go 語言之淺入淺出接口的原理4)大神是如何學習 Go 語言之寫出優雅的 Go 代碼3、使用多年的 go pprof 檢查內存洩漏的方法居然是錯的?!
  • 手把手教你拿下班主任電腦(考試開掛的萬能方法,學生党進來看看)
    第二步:對目標概況做完信息收集後,確定老師的郵箱地址(重要)第三步:利用msf模塊生成後門文件,並做雙編碼免殺(一旦被殺軟查出來你就廢了,所以這一步非常重要)第四步:受害者在PC端運行木馬後,你也就拿到的shell,接下來你要做的最重要的事是記錄下班主任的IP位址,主機名,開啟文件共享服務,並利用hashdump參數導出班主任電腦密碼的hash值(如果有密碼的話
  • 高級掃描技術及原理介紹
    一、高級ICMP掃描技術  Ping就是利用ICMP協議走的,我們在這裡主要是利用ICMP協議最基本的用途:報錯,根據網絡協議,如果按照協議出現了錯誤,那麼接收端將產生一個ICMP的錯誤報文。這些錯誤報文並不是主動發送的,而是由於錯誤,根據協議自動產生。
  • 下載 | 《手把手教你學51單片機-C語言版》
    編輯推薦《手把手教你學51單片機(C語言版)》的創作,目的就是改變當前「51單片機」教學與自學的模式:國內首創「手把手教你學」——集理論知識、視頻教程可以預見,《手把手教你學51單片機(C語言版)》將引領一場單片機教學的革命!作者簡介宋雪松 ,國內知名單片機培訓專家,嵌入式產品技術顧問。擁有近十年產品研發經驗,曾主持研發通信類、虛擬儀器等多款產品,在硬體電路設計和嵌入式軟體設計方向有豐富的項目實戰經驗。
  • 白帽子黑客教你:如何高效率掃描資產?
    一、主角(nmap&&masscan)簡介1.1 Masscan,其採用了無狀態的掃描技術。l 基本功能:主機發現,開放埠掃描,支持多埠、多網段,可對目標域名進行掃描;l 識別功能:識別埠服務類型及版本、作業系統、設備類型等;l 掃描模式:TCP SYN scan、TCP connectscan、UDP scan、No Ping scan等;
  • 手把手教你用PyTorch實現圖像分類器(第一部分)
    通過3篇短文,介紹如何實現圖像分類器的概念基礎——這是一種能夠理解圖像內容的算法。本文的目標不是提供手把手的指導,而是幫助理解整個過程。如果你正在考慮學習機器學習或人工智慧,你將不得不做類似的項目,並理解本系列文章中介紹的概念。文章主要進行概念上的解釋,不需要知道如何編寫代碼。
  • 埠·木馬·安全·掃描應用知識概覽
    一、 埠  一)、埠的一般含義  說到埠,這確實是個老話題,但一切都是從它開始的,不得不說。何謂埠,打個比方,你住在一座房子裡,想讓別人來拜訪你,得在房子上開個大門,你養了個可愛的小貓,為了它的進出,專門給它修了個小門,為了到後花園,又開了個後門……所有這些為了進到這所房子裡而開的門我們叫它埠,這些為了別人進來而開的埠稱它為'服務埠'。
  • Tcptraceroute:基於TCP數據包的路由跟蹤器
    儘管如此,許多情況下,防火牆會準許反向(inbound)TCP數據包通過防火牆到達指定埠,這些埠是主機內防火牆背後的一些程序和外界連接用的。通過發送TCP SYN數據包來代替UDP或者ICMP應答數據包,tcptraceroute可以穿透大多數防火牆。
  • 如何防止外網ip埠掃描,防止埠掃描的方法
    在說明如何防止埠掃描之前首先我們要先了解什麼是埠掃描,埠掃描其實就是通過對計算機每個常用埠發送數據包,通過返回的數據包來分析其弱點加以攻擊。了解了這些之後下一步如何進行防範呢?其實最簡單的辦法就是關閉不用的埠,減低埠掃描風險,然後在對開啟的埠做好防範措施,下面我們來具體說明一下。1、在此電腦上方點擊右鍵,在彈出的菜單中點擊屬性。2、在系統窗口左上角找到並點擊控制面板主頁。3、在控制面板下方找到並點擊Windows Defender 防火牆進入。
  • 掃描全能王領銜六款高效學習APP,打造專屬學術型APP
    掃描全能王領銜六款高效學習APP,打造專屬學術型APP開學快要兩個月啦,買來的iPad是不是也不可避免地變成「買前生產力,買後愛奇藝」了呢?手把手教你如何把你的iPad從頭武裝到牙齒,成為一個無情的學習利器!
  • [網絡安全] 二.Web滲透信息收集之域名、埠、服務、指紋、旁站、CDN和敏感信息
    娜璋AI安全之家於2020年8月18日開設,將專注於Python和安全技術,主要分享Web滲透、系統安全、人工智慧、大數據分析、圖像識別、惡意代碼檢測、CVE復現、威脅情報分析等文章。真心想把自己近十年的所學所做所感分享出來,與大家一起進步。這篇文章重構作者CSDN的系列,也參考了B站、謝公子和Agan兄的文章,真心推薦白帽、謝公子和Agan兄的文章,真的寫得棒。
  • TCP與UDP區別趣圖 小技巧:快速判斷udp,tcp埠是否同通暢
    一:TCP 和 UDP 之間的區別↓↓↓
  • 手把手教你用Java打造一款簡單故事書(上篇)
    後臺回復「Java」即可獲贈Java學習資料一、項目背景