端口掃描--zmap

ZMap被設計用來針對整個IPv4地址空間或其中的大部分實施綜合掃描的工具。ZMap是研究者手中的利器,但在運行ZMap時,請注意,您頗有 可能正在以每秒140萬個包的速度掃描整個IPv4地址空間 。咱們建議用戶即便在實施小範圍掃描以前,也聯繫一下本地網絡的管理員並參考咱們列舉的最佳掃描體驗html

默認狀況下,ZMap會對於指定端口實施儘量大速率的TCP SYN掃描。較爲保守的狀況下,對10,000個隨機的地址的80端口以10Mbps的速度掃描,以下所示:linux

  1. $ zmap --bandwidth=10M --target-port=80 --max-targets=10000 --output-file=results.csv

或者更加簡潔地寫成:ios

  1. $ zmap -10M -80 -10000 -o results.csv

ZMap也可用於掃描特定子網或CIDR地址塊。例如,僅掃描10.0.0.0/8和192.168.0.0/16的80端口,運行指令以下:git

  1. zmap -80 -o results.csv 10.0.0.0/8 192.168.0.0/16

若是掃描進行的順利,ZMap會每秒輸出相似如下內容的狀態更新:github

  1. 0% (1h51m left); send: 28777 562 Kp/(560 Kp/s avg); recv: 1192 248 p/(231 p/s avg);hits: 0.04%
  2. 0% (1h51m left); send: 34320 554 Kp/(559 Kp/s avg); recv: 1442 249 p/(234 p/s avg);hits: 0.04%
  3. 0% (1h50m left); send: 39676 535 Kp/(555 Kp/s avg); recv: 1663 220 p/(232 p/s avg);hits: 0.04%
  4. 0% (1h50m left); send: 45372 570 Kp/(557 Kp/s avg); recv: 1890 226 p/(232 p/s avg);hits: 0.04%

這些更新信息提供了掃描的即時狀態並表示成:redis

  1. 完成進度% (剩餘時間); send: 發出包的數量 即時速率 (平均發送速率); recv: 接收包的數量 接收率 (平均接收率); hits: 命中率

若是您不知道您所在網絡能支持的掃描速率,您可能要嘗試不一樣的掃描速率和帶寬限制直到掃描效果開始降低,藉此找出當前網絡可以支持的最快速度。json

默認狀況下,ZMap會輸出不一樣IP地址的列表(例如,根據SYN ACK數據包的狀況),像下面這樣。其輸出結果還有幾種附加的格式(如,JSON和Redis),能夠用做生成程序可解析的掃描統計。 一樣,能夠指定附加的輸出字段並使用輸出過濾來過濾輸出的結果。緩存

  1. 115.237.116.119
  2. 23.9.117.80
  3. 207.118.204.141
  4. 217.120.143.111
  5. 50.195.22.82

咱們強烈建議您使用黑名單文件,以排除預留的/未分配的IP地址空間(如,RFC1918 規定的私有地址、組播地址),以及網絡中須要排除在您掃描以外的地址。默認狀況下,ZMap將採用位於 /etc/zmap/blacklist.conf的這個簡單的黑名單文件中所包含的預留和未分配地址。若是您須要某些特定設置,好比每次運行ZMap時的最大帶寬或黑名單文件,您能夠在文件/etc/zmap/zmap.conf中指定或使用自定義配置文件服務器

若是您正試圖解決掃描的相關問題,有幾個選項能夠幫助您調試。首先,您能夠經過添加--dryrun實施預掃,以此來分析包可能會發送到網絡的何處。此外,還能夠經過設置'--verbosity=n`來更改日誌詳細程度網絡

最佳掃描體驗

咱們爲針對互聯網進行掃描的研究者提供了一些建議,以此來引導養成良好的互聯網合做氛圍。

  • 密切協同本地的網絡管理員,以減小風險和調查
  • 確認掃描不會使本地網絡或上游供應商癱瘓
  • 在發起掃描的源地址的網頁和DNS條目中申明你的掃描是善意的
  • 明確解釋你的掃描中全部鏈接的目的和範圍
  • 提供一個簡單的退出掃描的方法並及時響應請求
  • 實施掃描時,不使用比研究對象需求更大的掃描範圍或更快的掃描頻率
  • 若是能夠,將掃描流量分佈到不一樣的時間或源地址上

即便不聲明,使用掃描的研究者也應該避免利用漏洞或訪問受保護的資源,並遵照其轄區內任何特殊的法律規定。

命令行參數

通用選項

這些選項是實施簡單掃描時最經常使用的選項。咱們注意到某些選項取決於所使用的探測模塊輸出模塊(如,在實施ICMP Echo掃描時是不須要使用目的端口的)。

-p, --target-port=port

要掃描的目標TCP端口號(例如,443)

-o, --output-file=name

將結果寫入該文件,使用-表明輸出到標準輸出。

-b, --blacklist-file=path

文件中被排除的子網使用CIDR表示法(如192.168.0.0/16),一個一行。建議您使用此方法排除RFC 1918地址、組播地址、IANA預留空間等IANA專用地址。在conf/blacklist.example中提供了一個以此爲目的示例黑名單文件。

掃描選項

-n, --max-targets=n

限制探測目標的數量。後面跟的能夠是一個數字(例如'-n 1000),或可掃描地址空間的百分比(例如,-n 0.1%`,不包括黑名單)

-N, --max-results=n

收到多少結果後退出

-t, --max-runtime=secs

限制發送報文的時間

-r, --rate=pps

設置發包速率,以包/秒爲單位

-B, --bandwidth=bps

以比特/秒設置傳輸速率(支持使用後綴G,M或K(如-B 10M就是速度10 mbps)的。設置會覆蓋--rate

-c, --cooldown-time=secs

發送完成後等待多久繼續接收回包(默認值= 8)

-e, --seed=n

地址排序種子。若是要用多個ZMap以相同的順序掃描地址,那麼就可使用這個參數。

--shards=n

將掃描分片/區,使其可多個ZMap中執行(默認值= 1)。啓用分片時,--seed參數是必需的。

--shard=n

選擇掃描的分片(默認值= 0)。n的範圍在[0,N),其中N爲碎片的總數。啓用分片時,--seed參數是必需的。

-T, --sender-threads=n

用於發送數據包的線程數(默認值= 1)

-P, --probes=n

發送到每一個IP的探測數(默認值= 1)

-d, --dryrun

用標準輸出打印出每一個包,而不是將其發送(用於調試)

網絡選項

-s, --source-port=port|range

發送數據包的源端口

-S, --source-ip=ip|range

發送數據包的源地址。能夠僅僅是一個IP,也能夠是一個範圍(如,10.0.0.1-10.0.0.9)

-G, --gateway-mac=addr

數據包發送到的網關MAC地址(用以防止自動檢測不工做的狀況)

-i, --interface=name

使用的網絡接口

探測選項

ZMap容許用戶指定並添加本身所須要的探測模塊。 探測模塊的職責就是生成要發送的探測包,並處理主機回覆的響應包。

--list-probe-modules

列出可用探測模塊(如tcp_synscan)

-M, --probe-module=name

選擇探測模塊(默認值= tcp_synscan)

--probe-args=args

向模塊傳遞參數

--list-output-fields

列出可用的輸出模塊

輸出選項

ZMap容許用戶指定和編寫他們本身的輸出模塊。輸出模塊負責處理由探測模塊返回的字段,並將它們輸出給用戶。用戶能夠指定輸出的字段,並過濾相應字段。

--list-output-modules

列出可用輸出模塊(如tcp_synscan)

-O, --output-module=name

選擇輸出模塊(默認值爲csv)

--output-args=args

傳遞給輸出模塊的參數

-f, --output-fields=fields

輸出的字段列表,以逗號分割

--output-filter

指定輸出過濾器探測模塊定義字段進行過濾

附加選項

-C, --config=filename

加載配置文件,能夠指定其餘路徑。

-q, --quiet

沒必要每秒刷新輸出

-g, --summary

在掃描結束後打印配置和結果彙總信息

-v, --verbosity=n

日誌詳細程度(0-5,默認值= 3)

-h, --help

打印幫助並退出

-V, --version

打印版本並退出

附加信息

TCP SYN 掃描

在執行TCP SYN掃描時,ZMap須要指定一個目標端口,也支持指定發起掃描的源端口範圍。

-p, --target-port=port

掃描的TCP端口(例如 443)

-s, --source-port=port|range

發送掃描數據包的源端口(例如 40000-50000)

警示! ZMap基於Linux內核使用RST包來應答SYN/ACK包響應,以關閉掃描器打開的鏈接。ZMap是在Ethernet層完成包的發送的,這樣作是爲了減小跟蹤打開的TCP鏈接和路由尋路帶來的內核開銷。所以,若是您有跟蹤鏈接創建的防火牆規則,如相似於-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT的netfilter規則,將阻止SYN/ACK包到達內核。這不會妨礙到ZMap記錄應答,但它會阻止RST包被送回,最終被掃描主機的鏈接會一直打開,直到超時後斷開。咱們強烈建議您在執行ZMap時,選擇一組主機上未使用且防火牆容許訪問的端口,加在-s後(如 -s '50000-60000' )。

ICMP Echo 請求掃描

雖然在默認狀況下ZMap執行的是TCP SYN掃描,但它也支持使用ICMP echo請求掃描。在這種掃描方式下ICMP echo請求包被髮送到每一個主機,並以收到ICMP應答包做爲答覆。實施ICMP掃描能夠經過選擇icmp_echoscan掃描模塊來執行,以下:

  1. $ zmap --probe-module=icmp_echoscan

UDP 數據報掃描

ZMap還額外支持UDP探測,它會發出任意UDP數據報給每一個主機,並接收UDP或ICMP不可達的應答。ZMap能夠經過使用--probe- args命令行選項來設置四種不一樣的UDP載荷。這些是:可在命令行設置可打印的ASCII 碼的‘text’載荷和十六進制載荷的‘hex’,外部文件中包含載荷的‘file’,和經過動態字段生成的載荷的‘template’。爲了獲得UDP 響應,請使用-f參數確保您指定的「data」字段處於輸出範圍。

下面的例子將發送兩個字節'ST',即PCAnwywhere的'status'請求,到UDP端口5632。

  1. $ zmap -M udp -5632 --probe-args=text:ST -100 -f saddr,data --

下面的例子將發送字節「0X02」,即SQL Server的'client broadcast'請求,到UDP端口1434。

  1. $ zmap -M udp -1434 --probe-args=hex:02 -100 -f saddr,data --

下面的例子將發送一個NetBIOS狀態請求到UDP端口137。使用一個ZMap自帶的載荷文件。

  1. $ zmap -M udp -1434 --probe-args=file:netbios_137.pkt -100 -f saddr,data --

下面的例子將發送SIP的'OPTIONS'請求到UDP端口5060。使用附ZMap自帶的模板文件。

  1. $ zmap -M udp -1434 --probe-args=file:sip_options.tpl -100 -f saddr,data --

UDP載荷模板仍處於實驗階段。當您在更多的使用一個以上的發送線程(-T)時可能會遇到崩潰和一個明顯的相比靜態載荷性能下降的表現。模板僅僅是 一個由一個或多個使用${}將字段說明封裝成序列構成的載荷文件。某些協議,特別是SIP,須要載荷來反射包中的源和目的包。其餘協議,如 portmapper和DNS,每一個請求包含的字段應該是隨機的,或下降被Zamp掃描的多宿主系統的風險。

如下的載荷模板將發送SIP OPTIONS請求到每個目的地:

  1. OPTIONS sip:${RAND_ALPHA=8}@${DADDR} SIP/2.0
  2. Via: SIP/2.0/UDP ${SADDR}:${SPORT};branch=${RAND_ALPHA=6}.${RAND_DIGIT=10};rport;alias
  3. From: sip:${RAND_ALPHA=8}@${SADDR}:${SPORT};tag=${RAND_DIGIT=8}
  4. To: sip:${RAND_ALPHA=8}@${DADDR}
  5. Call-ID: ${RAND_DIGIT=10}@${SADDR}
  6. CSeq: 1 OPTIONS
  7. Contact: sip:${RAND_ALPHA=8}@${SADDR}:${SPORT}
  8. Content-Length: 0
  9. Max-Forwards: 20
  10. User-Agent: ${RAND_ALPHA=8}
  11. Accept: text/plain

就像在上面的例子中展現的那樣,注意每行行末以\r\n結尾,請求以\r\n\r\n結尾,大多數SIP實現均可以正確處理它。一個能夠工做的例子放在ZMap的examples/udp-payloads目錄下 (sip_options.tpl).

當前實現了下面的模板字段:

  • SADDR: 源IP地址的點分十進制格式
  • SADDR_N: 源IP地址的網絡字節序格式
  • DADDR: 目的IP地址的點分十進制格式
  • DADDR_N: 目的IP地址的網絡字節序格式
  • SPORT: 源端口的ascii格式
  • SPORT_N: 源端口的網絡字節序格式
  • DPORT: 目的端口的ascii格式
  • DPORT_N: 目的端口的網絡字節序格式
  • RAND_BYTE: 隨機字節(0-255),長度由=(length) 參數決定
  • RAND_DIGIT: 隨機數字0-9,長度由=(length) 參數決定
  • RAND_ALPHA: 隨機大寫字母A-Z,長度由=(length) 參數決定
  • RAND_ALPHANUM: 隨機大寫字母A-Z和隨機數字0-9,長度由=(length) 參數決定

配置文件

ZMap支持使用配置文件來代替在命令行上指定全部要求的選項。配置中能夠經過每行指定一個長名稱的選項和對應的值來建立:

  1. interface "eth1"
  2. source-ip 1.1.1.4-1.1.1.8
  3. gateway-mac b4:23:f9:28:fa:2d # upstream gateway
  4. cooldown-time 300 # seconds
  5. blacklist-file /etc/zmap/blacklist.conf
  6. output-file ~/zmap-output
  7. quiet
  8. summary

而後ZMap就能夠按照配置文件並指定一些必要的附加參數運行了:

  1. $ zmap --config=~/.zmap.conf --target-port=443

詳細

ZMap能夠在屏幕上生成多種類型的輸出。默認狀況下,Zmap將每隔1秒打印出類似的基本進度信息。能夠經過設置--quiet來禁用。

  1. 0:01 12%; send: 10000 done (15.1 Kp/s avg); recv: 144 143 p/(141 p/s avg); hits:1.44%

ZMap一樣也能夠根據掃描配置打印以下消息,能夠經過'--verbosity`參數加以控制。

  1. Aug 11 16:16:12.813 [INFO] zmap: started
  2. Aug 11 16:16:12.817 [DEBUG] zmap: no interface provided. will use eth0
  3. Aug 11 16:17:03.971 [DEBUG] cyclic: primitive root: 3489180582
  4. Aug 11 16:17:03.971 [DEBUG] cyclic: starting point: 46588
  5. Aug 11 16:17:03.975 [DEBUG] blacklist: 3717595507 addresses allowed to be scanned
  6. Aug 11 16:17:03.975 [DEBUG] send: will send from 1 address on 28233 source ports
  7. Aug 11 16:17:03.975 [DEBUG] send: using bandwidth 10000000 bits/s, rate set to 14880pkt/s
  8. Aug 11 16:17:03.985 [DEBUG] recv: thread started

ZMap還支持在掃描以後打印出一個的可grep的彙總信息,相似於下面這樣,能夠經過調用--summary來實現。

  1. cnf target-port 443
  2. cnf source-port-range-begin 32768
  3. cnf source-port-range-end 61000
  4. cnf source-addr-range-begin 1.1.1.4
  5. cnf source-addr-range-end 1.1.1.8
  6. cnf maximum-packets 4294967295
  7. cnf maximum-runtime 0
  8. cnf permutation-seed 0
  9. cnf cooldown-period 300
  10. cnf send-interface eth1
  11. cnf rate 45000
  12. env nprocessors 16
  13. exc send-start-time Fri Jan 18 01:47:35 2013
  14. exc send-end-time Sat Jan 19 00:47:07 2013
  15. exc recv-start-time Fri Jan 18 01:47:35 2013
  16. exc recv-end-time Sat Jan 19 00:52:07 2013
  17. exc sent 3722335150
  18. exc blacklisted 572632145
  19. exc first-scanned 1318129262
  20. exc hit-rate 0.874102
  21. exc synack-received-unique 32537000
  22. exc synack-received-total 36689941
  23. exc synack-cooldown-received-unique 193
  24. exc synack-cooldown-received-total 1543
  25. exc rst-received-unique 141901021
  26. exc rst-received-total 166779002
  27. adv source-port-secret 37952
  28. adv permutation-gen 4215763218

結果輸出

ZMap能夠經過輸出模塊生成不一樣格式的結果。默認狀況下,ZMap只支持csv的輸出,可是能夠經過編譯支持redisjson 。可使用輸出過濾來過濾這些發送到輸出模塊上的結果。輸出模塊輸出的字段由用戶指定。默認狀況若是沒有指定輸出文件,ZMap將以csv格式返回結果,而不會生成特定結果。也能夠編寫本身的輸出模塊;請參閱編寫輸出模塊

-o, --output-file=p

輸出寫入文件地址

-O, --output-module=p

調用自定義輸出模塊

-f, --output-fields=p

以逗號分隔的輸出的字段列表

--output-filter=filter

對給定的探測指定字段輸出過濾

--list-output-modules

列出可用輸出模塊

--list-output-fields

列出給定的探測的可用輸出字段

輸出字段

除了IP地址以外,ZMap有不少字段。這些字段能夠經過在給定探測模塊上運行--list-output-fields來查看。

  1. $ zmap --probe-module="tcp_synscan" --list-output-fields
  2. saddr string: 應答包中的源IP地址
  3. saddr-raw int: 網絡字節格式的源IP地址
  4. daddr string: 應答包中的目的IP地址
  5. daddr-raw int: 網絡字節格式的目的IP地址
  6. ipid int: 應答包中的IP識別號
  7. ttl int: 應答包中的ttl(存活時間)值
  8. sport int: TCP 源端口
  9. dport int: TCP 目的端口
  10. seqnum int: TCP 序列號
  11. acknum int: TCP Ack
  12. window int: TCP 窗口
  13. classification string: 包類型
  14. success int: 是應答包成功
  15. repeat int: 是不是來自主機的重複響應
  16. cooldown int: 是不是在冷卻時間內收到的響應
  17. timestamp-str string: 響應抵達時的時間戳使用ISO8601格式
  18. timestamp-ts int: 響應抵達時的時間戳使用UNIX紀元開始的秒數
  19. timestamp-us int: 時間戳的微秒部分(例如 'timestamp-ts'的幾微秒)

能夠經過使用--output-fields=fields-f來選擇選擇輸出字段,任意組合的輸出字段能夠被指定爲逗號分隔的列表。例如:

  1. $ zmap -80 -"response,saddr,daddr,sport,seq,ack,in_cooldown,is_repeat,timestamp" -o output.csv

過濾輸出

在傳到輸出模塊以前,探測模塊生成的結果能夠先過濾。過濾是針對探測模塊的輸出字段的。過濾使用相似於SQL的簡單過濾語法寫成,經過ZMap的--output-filter選項來指定。輸出過濾一般用於過濾掉重複的結果,或僅傳輸成功的響應到輸出模塊。

過濾表達式的形式爲<字段名> <操做符> <值><值>的類型必須是一個字符串或一串無符號整數而且匹配<字段名>類型。對於整數比較有效的操做符是= !=, <, >, <=, >=。字符串比較的操做是=,!=。--list-output-fields能夠打印那些可供探測模塊選擇的字段和類型,而後退出。

複合型的過濾操做,能夠經過使用&&(邏輯與)和||(邏輯或)這樣的運算符來組合出特殊的過濾操做。

示例

書寫一則過濾僅顯示成功的、不重複的應答

  1. --output-filter="success = 1 && repeat = 0"

過濾出RST分類而且TTL大於10的包,或者SYNACK分類的包

  1. --output-filter="(classification = rst && ttl > 10) || classification = synack"

CSV

csv模塊將會生成以逗號分隔各個要求輸出的字段的文件。例如,如下的指令將生成名爲output.csv的CSV文件。

  1. $ zmap -80 -"response,saddr,daddr,sport,seq,ack,in_cooldown,is_repeat,timestamp" -o output.csv

  1. #響應, 源地址, 目的地址, 源端口, 目的端口, 序列號, 應答, 是不是冷卻模式, 是否重複, 時間戳
  2. response, saddr, daddr, sport, dport, seq, ack, in_cooldown, is_repeat, timestamp
  3. synack, 159.174.153.144, 10.0.0.9, 80, 40555, 3050964427, 3515084203, 0, 0,2013-08-1518:55:47.681
  4. rst, 141.209.175.1, 10.0.0.9, 80, 40136, 0, 3272553764, 0, 0,2013-08-15 18:55:47.683
  5. rst, 72.36.213.231, 10.0.0.9, 80, 56642, 0, 2037447916, 0, 0,2013-08-15 18:55:47.691
  6. rst, 148.8.49.150, 10.0.0.9, 80, 41672, 0, 1135824975, 0, 0,2013-08-15 18:55:47.692
  7. rst, 50.165.166.206, 10.0.0.9, 80, 38858, 0, 535206863, 0, 0,2013-08-15 18:55:47.694
  8. rst, 65.55.203.135, 10.0.0.9, 80, 50008, 0, 4071709905, 0, 0,2013-08-15 18:55:47.700
  9. synack, 50.57.166.186, 10.0.0.9, 80, 60650, 2813653162, 993314545, 0, 0,2013-08-1518:55:47.704
  10. synack, 152.75.208.114, 10.0.0.9, 80, 52498, 460383682, 4040786862, 0, 0,2013-08-1518:55:47.707
  11. synack, 23.72.138.74, 10.0.0.9, 80, 33480, 810393698, 486476355, 0, 0,2013-08-1518:55:47.710

Redis

Redis的輸出模塊容許地址被添加到一個Redis的隊列,而不是保存到文件,容許ZMap將它與以後的處理工具結合使用。

注意! ZMap默認不會編譯Redis功能。若是你從源碼構建ZMap,能夠在CMake的時候加上-DWITH_REDIS=ON來增長Redis支持。

JSON

JSON輸出模塊用起來相似於CSV模塊,只是以JSON格式寫入到文件。JSON文件能輕鬆地導入到其它能夠讀取JSON的程序中。

注意!,ZMap默認不會編譯JSON功能。若是你從源碼構建ZMap,能夠在CMake的時候加上-DWITH_JSON=ON來增長JSON支持。

黑名單和白名單

ZMap同時支持對網絡前綴作黑名單和白名單。若是ZMap不加黑名單和白名單參數,他將會掃描全部的IPv4地址(包括本地的,保留的以及組播地 址)。若是指定了黑名單文件,那麼在黑名單中的網絡前綴將再也不掃描;若是指定了白名單文件,只有那些網絡前綴在白名單內的纔會掃描。白名單和黑名單文件可 以協同使用;黑名單優先於白名單(例如:若是您在白名單中指定了10.0.0.0/8並在黑名單中指定了10.1.0.0/16,那麼10.1.0.0 /16將不會掃描)。白名單和黑名單文件能夠在命令行中指定,以下所示:

-b, --blacklist-file=path

文件用於記錄黑名單子網,以CIDR(無類域間路由)的表示法,例如192.168.0.0/16

-w, --whitelist-file=path

文件用於記錄限制掃描的子網,以CIDR的表示法,例如192.168.0.0/16

黑名單文件的每行都須要以CIDR的表示格式書寫,一行單一的網絡前綴。容許使用#加以備註。例如:

  1. # IANA(英特網編號管理局)記錄的用於特殊目的的IPv4地址
  2. # http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
  3. # 更新於2013-05-22
  4. 0.0.0.0/8 # RFC1122: 網絡中的全部主機
  5. 10.0.0.0/8 # RFC1918: 私有地址
  6. 100.64.0.0/10 # RFC6598: 共享地址空間
  7. 127.0.0.0/8 # RFC1122: 迴環地址
  8. 169.254.0.0/16 # RFC3927: 本地鏈路地址
  9. 172.16.0.0/12 # RFC1918: 私有地址
  10. 192.0.0.0/24 # RFC6890: IETF協議預留
  11. 192.0.2.0/24 # RFC5737: 測試地址1
  12. 192.88.99.0/24 # RFC3068: IPv6轉換到IPv4的任播
  13. 192.168.0.0/16 # RFC1918: 私有地址
  14. 192.18.0.0/15 # RFC2544: 檢測地址
  15. 198.51.100.0/24 # RFC5737: 測試地址2
  16. 203.0.113.0/24 # RFC5737: 測試地址3
  17. 240.0.0.0/4 # RFC1112: 預留地址
  18. 255.255.255.255/32 # RFC0919: 限制廣播地址
  19. # IANA記錄的用於組播的地址空間
  20. # http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
  21. # 更新於2013-06-25
  22. 224.0.0.0/4 # RFC5771: 組播/預留地址ed

若是您只是想掃描因特網中隨機的一部分地址,使用抽樣檢出,來代替使用白名單和黑名單。

注意!ZMap默認設置使用/etc/zmap/blacklist.conf做爲黑名單文件,其中包含有本地的地址空間和預留的IP空間。經過編輯/etc/zmap/zmap.conf能夠改變默認的配置。

速度限制與抽樣

默認狀況下,ZMap將以您當前網卡所能支持的最快速度掃描。以咱們對於經常使用硬件的經驗,這一般是理論上Gbit以太網速度的95-98%,這可能 比您的上游提供商可處理的速度還要快。ZMap是不會自動的根據您的上游提供商來調整發送速率的。您可能須要手動的調整發送速率來減小丟包和錯誤結果。

-r, --rate=pps

設置最大發送速率以包/秒爲單位

-B, --bandwidth=bps

設置發送速率以比特/秒(支持G,M和K後綴)。這會覆蓋--rate參數。

ZMap一樣支持對IPv4地址空間進行指定最大目標數和/或最長運行時間的隨機採樣。因爲每次對主機的掃描是經過隨機排序生成的,限制掃描的主機個數爲N就會隨機抽選N個主機。命令選項以下:

-n, --max-targets=n

探測目標上限數量

-N, --max-results=n

結果上限數量(累積收到這麼多結果後退出)

-t, --max-runtime=s

發送數據包時間長度上限(以秒爲單位)

-s, --seed=n

種子用以選擇地址的排列方式。使用不一樣ZMap執行掃描操做時將種子設成相同的值能夠保證相同的掃描順序。

舉個例子,若是您想要屢次掃描一樣的一百萬個互聯網主機,您能夠設定排序種子和掃描主機的上限數量,大體以下所示:

  1. zmap -443 -3 -1000000 -o results

爲了肯定哪一百萬主機將要被掃描,您能夠執行預掃,只打印數據包而非發送,並不是真的實施掃描。

  1. zmap -443 -3 -1000000 --dryrun | grep daddr
  2. | awk -F'daddr: ' '{print $2}' | sed 's/ |.*//;'

發送多個數據包

ZMap支持向每一個主機發送多個探測。增長這個數量既增長了掃描時間又增長了到達的主機數量。然而,咱們發現,增長的掃描時間(每一個額外掃描的增長近100%)遠遠大於到達的主機數量(每一個額外掃描的增長近1%)。

-P, --probes=n

向每一個IP發出的獨立探測個數(默認值=1)

示例應用

ZMap專爲向大量主機發起鏈接並尋找那些正確響應而設計。然而,咱們意識到許多用戶須要執行一些後續處理,如執行應用程序級別的握手。例如,用戶在80端口實施TCP SYN掃描也許想要實施一個簡單的GET請求,還有用戶掃描443端口可能但願完成TLS握手。

Banner獲取

咱們收錄了一個示例程序,banner-grab,伴隨ZMap使用可讓用戶從監聽狀態的TCP服務器上接收到消息。Banner-grab鏈接 到提供的服務器上,發送一個可選的消息,而後打印出收到的第一個消息。這個工具能夠用來獲取banner,例如HTTP服務的回覆的具體指 令,telnet登錄提示,或SSH服務的字符串。

下面的例子尋找了1000個監聽80端口的服務器,並向每一個發送一個簡單的GET請求,存儲他們的64位編碼響應至http-banners.out

  1. $ zmap -80 -1000 -10M -- | ./banner-grab-tcp -80 -500 -./http-req > out

若是想知道更多使用banner-grab的細節,能夠參考examples/banner-grab中的README文件。

注意! ZMap和banner-grab(如例子中)同時運行可能會比較顯著的影響對方的表現和精度。確保不讓ZMap佔滿banner-grab-tcp的並 發鏈接,否則banner-grab將會落後於標準輸入的讀入,致使阻塞ZMap的輸出寫入。咱們推薦使用較慢掃描速率的ZMap,同時提高 banner-grab-tcp的併發性至3000之內(注意 併發鏈接>1000須要您使用ulimit -SHn 100000ulimit -HHn 100000來增長每一個進程的最大文件描述符數量)。固然,這些參數取決於您服務器的性能、鏈接成功率(hit-rate);咱們鼓勵開發者在運行大型掃描以前先進行小樣本的試驗。

創建套接字

咱們也收錄了另外一種形式的banner-grab,就是forge-socket, 重複利用服務器發出的SYN-ACK,鏈接並最終取得banner。在banner-grab-tcp中,ZMap向每一個服務器發送一個SYN,並監聽服務器發回的帶有SYN+ACK的應答。運行ZMap主機的內核接受應答後發送RST,這樣就沒有與該包關聯活動鏈接。程序banner-grab必須在這以後建立一個新的TCP鏈接到從服務器獲取數據。

在forge-socket中,咱們利用內核中同名的模塊,使咱們能夠建立任意參數的TCP鏈接。能夠經過抑制內核的RST包,並重用SYN+ACK的參數取代該包而建立套接字,經過這個套接字收發數據和咱們平時使用的鏈接套接字並無什麼不一樣。

要使用forge-socket,您須要forge-socket內核模塊,從github上能夠得到。您須要git clone git@github.com:ewust/forge_socket.git至ZMap源碼根目錄,而後cd進入forge_socket目錄,運行make。以root身份運行insmod forge_socket.ko 來安裝該內核模塊。

您也須要告知內核不要發送RST包。一個簡單的在全系統禁用RST包的方法是使用iptables。以root身份運行iptables -A OUTPUT -p tcp -m tcp --tcp-flgas RST,RST RST,RST -j DROP便可,固然您也能夠加上一項--dport X將禁用侷限於所掃描的端口(X)上。掃描完成後移除這項設置,以root身份運行iptables -D OUTPUT -p tcp -m tcp --tcp-flags RST,RST RST,RST -j DROP便可。

如今應該能夠創建forge-socket的ZMap示例程序了。運行須要使用extended_fileZMap輸出模塊

  1. $ zmap -80 -1000 -10M -O extended_file -- | \
  2. ./forge-socket -500 -./http-req > ./http-banners.out

詳細內容能夠參考examples/forge-socket目錄下的README。


編寫探測和輸出模塊

ZMap能夠經過探測模塊來擴展支持不一樣類型的掃描,經過輸出模塊增長不一樣類型的輸出結果。註冊過的探測和輸出模塊能夠在命令行中列出:

--list-probe-modules

列出安裝過的探測模塊

--list-output-modules

列出安裝過的輸出模塊

輸出模塊

ZMap的輸出和輸出後處理能夠經過實現和註冊掃描器的輸出模塊來擴展。輸出模塊在接收每個應答包時都會收到一個回調。然而默認提供的模塊僅提供簡單的輸出,這些模塊一樣支持更多的輸出後處理(例如:重複跟蹤或輸出AS號碼來代替IP地址)。

經過定義一個新的output_module結構來建立輸出模塊,並在output_modules.c中註冊:

  1. typedef struct output_module {
  2. const char *name; // 在命令行如何引用輸出模塊
  3. unsigned update_interval; // 以秒爲單位的更新間隔
  4. output_init_cb init; // 在掃描器初始化的時候調用
  5. output_update_cb start; // 在掃描器開始的時候調用
  6. output_update_cb update; // 每次更新間隔調用,秒爲單位
  7. output_update_cb close; // 掃描終止後調用
  8. output_packet_cb process_ip; // 接收到應答時調用
  9. const char *helptext; // 會在--list-output-modules時打印在屏幕上
  10. } output_module_t;

輸出模塊必須有名稱,經過名稱能夠在命令行調用,而且一般會實現success_ip和常見的other_ip回調。process_ip的回調由每一個收到並經由probe module過濾的應答包調用。應答是否被認定爲成功並不肯定(好比,它能夠是一個TCP的RST)。這些回調必須定義匹配output_packet_cb定義的函數:

  1. int (*output_packet_cb) (
  2. ipaddr_n_t saddr, // 網絡字節格式的發起掃描主機IP地址
  3. ipaddr_n_t daddr, // 網絡字節格式的目的IP地址
  4. const char* response_type, // 發送模塊的數據包分類
  5. int is_repeat, // {0: 主機的第一個應答, 1: 後續的應答}
  6. int in_cooldown, // {0: 非冷卻狀態, 1: 掃描器處於冷卻中}
  7. const u_char* packet, // 指向IP包的iphdr結構體的指針
  8. size_t packet_len // 包的長度,以字節爲單位
  9. );

輸出模塊還能夠經過註冊回調,執行在掃描初始化的時候(諸如打開輸出文件的任務)、在掃描開始階段(諸如記錄黑名單的任務)、在掃描的常規間隔(諸如狀態更新的任務)、在關閉的時候(諸如關掉全部打開的文件描述符)。提供的這些回調能夠完整的訪問掃描配置和當前狀態:

  1. int (*output_update_cb)(struct state_conf*, struct state_send*, struct state_recv*);

這些定義在output_modules.h中。在src/outputmodules/modulecsv.c中有可用示例。

探測模塊

數據包由探測模塊構造,它能夠建立各類包和不一樣類型的響應。ZMap默認擁有兩個掃描模塊:tcp_synscanicmp_echoscan。默認狀況下,ZMap使用tcp_synscan來發送TCP SYN包並對每一個主機的響應分類,如打開時(收到SYN+ACK)或關閉時(收到RST)。ZMap容許開發者編寫本身的ZMap探測模塊,使用以下的API:

任何類型的掃描都必須經過開發和註冊send_module_t結構中的回調來實現:

  1. typedef struct probe_module {
  2. const char *name; // 如何在命令行調用掃描
  3. size_t packet_length; // 探測包有多長(必須是靜態的)
  4. const char *pcap_filter; // 對收到的響應實施PCAP過濾
  5. size_t pcap_snaplen; // libpcap 捕獲的最大字節數
  6. uint8_t port_args; // 設爲1,若是ZMap須要用戶指定--target-port
  7. probe_global_init_cb global_initialize; // 在掃描初始化會時被調用一次
  8. probe_thread_init_cb thread_initialize; // 每一個包緩存區的線程中被調用一次
  9. probe_make_packet_cb make_packet; // 每一個主機更新包的時候被調用一次
  10. probe_validate_packet_cb validate_packet; // 每收到一個包被調用一次,
  11. // 若是包無效返回0,
  12. // 非零則有效。
  13. probe_print_packet_cb print_packet; // 若是在預掃模式下被每一個包都調用
  14. probe_classify_packet_cb process_packet; // 由區分響應的接收器調用
  15. probe_close_cb close; // 掃描終止後被調用
  16. fielddef_t *fields // 該模塊指定的字段的定義
  17. int numfields // 字段的數量
  18. } probe_module_t;

在掃描操做初始化時會調用一次global_initialize,能夠用來實施一些必要的全局配置和初始化操做。然而,global_initialize並不能訪問包緩衝區,那裏是線程特定的。代替的,thread_initialize在 每一個發送線程初始化的時候被調用,提供對於緩衝區的訪問,能夠用來構建探測包和全局的源和目的值。此回調應用於構建主機不可知的包結構,甚至只有特定值 (如:目的主機和校驗和),須要隨着每一個主機更新。例如,以太網頭部信息在交換時不會變動(減去校驗和是由NIC硬件計算的)所以能夠事先定義以減小掃描 時間開銷。

調用回調參數make_packet是爲了讓被掃描的主機容許探測模塊更 新主機指定的值,同時提供IP地址、一個非透明的驗證字符串和探測數目(以下所示)。探測模塊負責在探測中放置儘量多的驗證字符串,即使當服務器返回的 應答爲空時,探測模塊也能驗證它的當前狀態。例如,針對TCP SYN掃描,tcp_synscan探測模塊會使用TCP源端口和序列號的格式存儲驗證字符串。響應包(SYN+ACK)將包含目的端口和確認號的預期 值。

  1. int make_packet(
  2. void *packetbuf, // 包的緩衝區
  3. ipaddr_n_t src_ip, // 網絡字節格式源IP
  4. ipaddr_n_t dst_ip, // 網絡字節格式目的IP
  5. uint32_t *validation, // 探測中的有效字符串
  6. int probe_num // 若是向每一個主機發送多重探測,
  7. // 該值爲咱們對於該主機
  8. // 正在發送的探測數目
  9. );

掃描模塊也應該定義pcap_filtervalidate_packetprocess_packet。只有符合PCAP過濾器的包纔會被掃描。舉個例子,在一個TCP SYN掃描的狀況下,咱們只想要調查TCP SYN / ACK或RST TCP數據包,並利用相似tcp && tcp[13] & 4 != 0 || tcp[13] == 18的過濾方法。validate_packet函數將會被每一個知足PCAP過濾條件的包調用。若是驗證返回的值非零,將會調用process_packet函數,並使用fields定義的字段和包中的數據填充字段集。舉個例子,以下代碼爲TCP synscan探測模塊處理了一個數據包。

  1. void synscan_process_packet(const u_char *packet, uint32_t len, fieldset_t *fs)
  2. {
  3. struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)];
  4. struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr
  5. + (sizeof(struct iphdr)));
  6. fs_add_uint64(fs, "sport", (uint64_t) ntohs(tcp->source));
  7. fs_add_uint64(fs, "dport", (uint64_t) ntohs(tcp->dest));
  8. fs_add_uint64(fs, "seqnum", (uint64_t) ntohl(tcp->seq));
  9. fs_add_uint64(fs, "acknum", (uint64_t) ntohl(tcp->ack_seq));
  10. fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->window));
  11. if (tcp->rst) { // RST packet
  12. fs_add_string(fs, "classification", (char*) "rst", 0);
  13. fs_add_uint64(fs, "success", 0);
  14. } else { // SYNACK packet
  15. fs_add_string(fs, "classification", (char*) "synack", 0);
  16. fs_add_uint64(fs, "success", 1);
  17. }
  18. }
相關文章
相關標籤/搜索