← 回到 nvnda.dev EN
閱讀時間 9 分鐘

Part 2: nmap 解剖 — 別還沒開始就被發現

你的掃描在封包層實際做了什麼,以及為什麼預設旗標並不像聽起來那麼隱匿。

在 第一部分,我們談了 nmap 是什麼、為什麼被廣泛使用,也停在了深度與隱匿的取捨上。第二部分要深入到 wire 層級:它怎麼判斷目標是否還活著、封包怎麼抵達目標,以及不同權限下掃描會有什麼不同。

一旦你理解 nmap 底層到底在做什麼,就不只是更會用它——你還會開始意識到,什麼時候其他工具或手法反而才是正確選擇。接下來會比較技術性,請有心理準備。

掃描前:nmap 要先搞清楚什麼?

前一節讓我們看到設定掃描旗標要謹慎的代價。但如果你只學哪些旗標會觸發比較少警報,那其實還只是在背答案。

nmap 這個工具依賴的是 TCP/UDP 的行為,這些大致上是標準化的。但目標會怎麼回應,取決於兩件事:

這些因素都比 TCP/UDP 層更深,也遠遠超出 nmap 的範疇。這也是為什麼了解網路拓撲和 ARP 運作方式,能讓從業者理解「host seems down」或某個 port 莫名其妙顯示為 filtered 背後的原因。也或許,能讓你找到「盲目切換 nmap 旗標」以外的其他辦法。

為了保持簡單,我把 nmap 掃描分成兩個大情境:一個是掃描同一個子網路裡的目標,另一個是掃描不同子網路的目標。

情境 1:目標在同一個子網路

掃描端和目標都在同一個子網路(10.0.1.0/24)。掃描端(10.0.1.10)和目標(10.0.1.25)共用同一個本地網路,可以不透過路由器直接通訊。

/24 是什麼意思?

像 10.0.1.10 這樣的 IP 位址,其實由兩部分組成:網路部分與主機部分。CIDR 記法中的 /24 就是告訴你這個分界線在哪。24 代表前 24 bit 是網路(10.0.1),剩下的 8 bit 是主機(.10)。任何共用 10.0.1 前綴的機器,都屬於同一個本地子網路,不需要經過 gateway 就能到達。

改變數字,邊界就會跟著移動:/16 會把網路擴大到 65,536 台主機,/30 則縮小到只有 4 台。這個數字,就是 OS 在判斷要直接 ARP 還是透過 gateway 繞路時會檢查的。

same subnet

步驟 1:查詢路由表

還記得第一部分的封閉式社區比喻嗎?路由表就像社區入口的那本通訊錄,告訴你要找的那戶是在自己社區內,還是得從大門(gateway)出去。

在送任何東西之前,掃描端的 OS 會先翻開這本通訊錄。它的 eth0 介面設定在 10.0.1.10/24,代表 10.0.1.0-10.0.1.255 範圍內的都是本地。10.0.1.25 落在這個範圍內,因此不需要 gateway,直接 ARP 就行。

步驟 2:ARP 廣播確認對方是否活著

知道可以直接在本地網路做 ARP ping 後,掃描端就往本地網路內所有裝置(ff:ff:ff:ff:ff:ff)發出廣播,問:「誰是 10.0.1.25?」

ARP 是什麼?為什麼要用?

如果 IP 位址是社區和門牌號碼,那 MAC 位址就是住在裡面的人的那張臉。ARP (Address Resolution Protocol) 的工作就是把位址和臉對應起來,把 IP 對應到 MAC。

網路是分層的。Layer 2 處理本地的硬體位址,使用 MAC 和 frame;Layer 3 負責 IP 路由,使用 packet。ARP 運作在 Layer 2,所以它送出的是 frame 而不是 packet,而且只能在本地網路運作。

這也意味著像 iptables 這種 IP 層級的防火牆沒辦法擋 ARP,因為它們只能在 Layer 3 以上做過濾。(ARP 還是可以在 Layer 2 被過濾,例如用 arptables 或交換器上的 Dynamic ARP Inspection,但對一般終端主機來說不常見。)

步驟 3:ARP 回應

如果目標還活著,它會直接回應自己的 MAC 位址。nmap 現在就知道主機是活的,以及要把 port 掃描封包送去哪。如果沒收到回應,nmap 就會下「host seems down」的結論,並在這裡停下。

步驟 4:Port 掃描

有了必要資訊(目的 IP、MAC,以及 port)後,掃描端就能開始組裝並送出封包,判斷每個 port 的狀態。

這一步,port 掃描封包會直接送到目標的 MAC 位址(ff:ee:dd:44:55:66),完全不經過 gateway。因為 gateway 沒參與,你的掃描不會離開本地網段,代表子網路之間的路由器、防火牆或 IDS(Intrusion Detection System,入侵偵測系統)都看不到這個掃描,因此本質上更隱匿。下一節我們討論跨子網路的情境時,情況就不一樣了,請記住這點。

情境 2:目標在不同的子網路

掃描端和目標在不同子網路,必須透過 gateway 通訊。跟情境 1 不同,這裡 ARP 回應只告訴我們 gateway 是活的,所以我們需要另一個探測來確認目標主機是否活著。

different subnet

步驟 1:查詢路由表

路由表還是扮演一樣的角色:告訴掃描端該怎麼到達目標。只是這次答案不同——它告訴掃描端 61.170.20.9 不在任何本地子網路,必須透過 gateway(192.168.1.1)、從 wlan0 介面出去。

步驟 2:ARP 廣播找 gateway

現在掃描端必須倚賴 gateway 把封包轉給目標。所以它不會直接廣播找目標,而是廣播找 gateway,因為機器只能在本地子網路做 ARP。

步驟 3:Gateway 的 ARP 回應

如果 gateway 是活的,它會從 eth0 介面收到這個廣播,並直接回傳自己的 MAC 位址給掃描端。如果沒有收到回應,封包根本出不了本地網路,nmap 會回報「host seems down」。但這種情況下,意思可能是 gateway 本身不通,不一定代表目標離線。

步驟 4:掃描端將封包送到 gateway

掃描端這時可以組出一個主機探測封包:目的 IP 是目標的 IP(61.170.20.9),目的 MAC 是 gateway 的 MAC(98:96:8d:20:21:4a)。MAC 負責把封包帶到 gateway 的門口,而目的 IP 才是 gateway 用來決定要把它轉送到哪裡的依據。

步驟 5:Gateway 把封包路由到目標

封包抵達 gateway 時,gateway 會拆掉 Ethernet frame(包含 MAC 位址的那一層),讀取裡面的 IP 標頭,看到目的 IP 是 61.170.20.9。接著 gateway 會查自己的路由表(和掃描端的路由表不同),再把封包從它的 wlan0 介面送往目標。

步驟 6:主機偵測完成,開始 port 掃描

如果目標有回應,nmap 就能確認主機還活著,開始掃 port。從這裡開始,每一個掃描封包都會走一樣的路徑:經過 gateway、經過任何介於其間的設備,包括防火牆或 IDS。這就是為什麼跨子網路掃描本質上比本地掃描更容易暴露。

主機活著了,但是不是 root 有差嗎?

這裡我想特別區分兩個 nmap 掃描旗標:-sS 和 -sT。兩者都做 TCP port 掃描,但一個需要 root 權限,另一個不需要。

簡單複習一下 TCP:一個連線透過三向握手 (three-way handshake) 建立:客戶端送 SYN、伺服器回 SYN-ACK、客戶端再回 ACK 確認。RST 則是強制中斷連線。兩種掃描都仰賴這個交握流程,只是使用方式不同。

我們先看兩者的流程,再來比較差異。

-sT — 走 OS 的 connect() 系統呼叫。下面每一步都是 kernel 在做,不是 nmap。

-sT workflow

-sS — 開啟 raw socket,自己驅動整個掃描,完全掌控連線。

-sS workflow

這兩個流程之間的差別,歸結到三個實務上的面向:

comparison

有了上表作為差異的骨架,再補幾個值得一提的機制細節:

來源 port。 因為 -sS 會自己組出整個 TCP 標頭,它能自訂任何來源 port。像 --source-port 53 這種手法可以把掃描流量偽裝成 DNS,但這只對 stateless 的 ACL 有效。現代的 stateful 防火牆會追蹤連線狀態,單靠偽造來源 port 是騙不過去的。

速度。 -sS 透過 raw socket 一次送出大量 SYN 封包,並非同步收集回應。-sT 則被卡在每一次 connect() 握手,要等它完成或 timeout 才能跳下一個 port。

可見性。 -sT 在 socket 關閉後,連線狀態還會留在 OS 表中一段時間,讓監控工具有機會看到它們。-sS 則完全繞過 OS,這也是為什麼它需要 root 才能開 raw socket。但躲得過 OS 不代表躲得過網路本身:現代 IDS(像 Snort、Suricata、Zeek)對半開掃描的模式通常一眼就能識破。

話說回來,-sT 也不是一無是處。它是沒有 root 時唯一的選擇;而且因為它會完成完整握手,對於藏在 load balancer 或 proxy 後面的目標,反而能取得更準確的結果。有些 IDS 甚至會把不完整的握手標記為掃描特徵,這時候完整的 connect() 看起來反而比較不可疑。

每次掃描前我會問自己的兩個問題

我跟目標之間有什麼? 同一個子網路:流量留在本地。不同子網路:一切都會經過 gateway 以及任何監看它的裝置,包括防火牆或 IDS。

我是 root 嗎? 有 root,你有得選;沒有 root,就只剩 -sT。有選擇的時候,選哪個取決於上面第一個問題的答案。


還有一件事我後來開始做:思考 nmap 到底是不是正確的工具。Netdiscover 可以被動地(加 -p)偵聽本地子網路上的 ARP 流量,完全不需要送出探測封包。Hping3 則讓你可以自己逐一組出每一個 header,對封包擁有完整掌控。重點不是要把所有工具背下來,而是理解機制後你就能挑對工具。

nmap 的第一個封包本身就是一個決定。好好地做這個決定。