端口掃描設計過程(三)
概述
在上一篇做了對SYN掃描的用戶素材分析,得出了掃描過程。而在這一篇中,將使用Jpcap實現。同時在過程化實現中,我們又會發現新的需求,這將改變我們對軟件的理解和下一步開發的方式。
適宜讀者
本文適於大部分網絡編程愛好者,不過我的目的是希望對軟件設計和開發方法的任何人都對此文感興趣,所以本文側重於對軟件的開發方法上的討論,不過你如果對下面的概念熟悉,將有助於你對本文的理解。
l ARP協議
l 數據的封裝和OSI
l Jpcap、Java
實現之路
過程化複習
我們首先回顧一下上一篇提到的主要過程。爲了發送SYN包並通過返回響應數據包獲得端口狀態信息的過程描述如下:
第一步 通過ARP協議獲取對方MAC地址
第二步 封裝TCP SYN數據包,併發送
第三步 接受響應包並解析相應包,分析得出結論。
詳細分析
不難發現,程序需要發送兩個包,ARP請求包和TCP SYN請求包。需要接受,ARP迴應包和TCP SYN響應包。爲了發送或接受數據包肯定需要網卡,在使用網卡之前,肯定先要確定哪個是自己需要的網卡(即使電腦只有一個真實網卡,但可能有很多虛擬網卡)。所以,我們發現了第一個新需求:確定使用的網卡。馬上,我們就有個臨時的解決方案:選擇與目標IP同一子網下的網卡。
參考代碼:
public static NetworkInterface getNetWorkInterfaceInSameSubnet(InetAddress ip){
NetworkInterface[] devices=JpcapCaptor.getDeviceList();
NetworkInterface device=null;
loop: for(NetworkInterface d:devices){
for(NetworkInterfaceAddress addr:d.addresses){
if(!(addr.address instanceof Inet4Address)) continue;
byte[] bip=ip.getAddress();
byte[] subnet=addr.subnet.getAddress();
byte[] bif=addr.address.getAddress();
for(int i=0;i<4;i++){
bip[i]=(byte)(bip[i]&subnet[i]);
bif[i]=(byte)(bif[i]&subnet[i]);
}
if(Arrays.equals(bip,bif)){
device=d;
break loop;
}
}
}
return device;
}
對於不在同一子網,但只要是可訪問(能夠ping通),實現起來並不困難。但對於互聯網上的計算機需要接入互聯網才能訪問,所以這將依賴於接入互聯網技術。注意,JPcap所依賴於的WinPcap不支持PPPoE技術,這將讓我們大量使用PPPoE接入互聯網的方式無法使用完全依賴於WinPcap技術的端口掃描。目前爲止,常見的解決方案就是使用系統調用。
性能太差
最簡單的方法可以把上述過程全部寫在一個方法裏。實現方案用表格描述。
方法參數 |
InetAddress IP ,int Port |
方法返回類型 |
Boolean |
方法體 |
上述三個過程實現 |
用該方案實現不論性能上還是重用上以及調試上都不利,只有簡單性。接下來有必要考慮代碼重構。
重構
l 把ARP協議提前
方法中參數有IP和Port,這意味着,對同一個IP會有過多沒必要的ARP協議。所以ARP協議有必要在獲得目標IP或確認目標IP的主機是開啓的情況下執行ARP協議。
l 對於結果,不應該僅是一個Boolean類型,因爲端口的狀態可能不僅僅是開啓或關閉,(可能還有是被過濾的,意味着可能被防火牆處理過而無法確定是不是開啓。)對於Java可以考慮使用枚舉類型封裝結果。
l 應該注意,依據RFC793的規定。類似的掃描技術還可以有FIN、Xmas、Null掃描等。他們與SYN掃描相比僅是封裝發送數據包和解析迴應數據包的參數上存在微小區別,完全可以考慮重用代碼。
實現重構
l 爲了提前批量執行ARP協議,我們將需要一個IP地址列表,推薦使用線性表實現(參見Java集合框架中List接口)。執行完ARP協議,用詞典返回(參見Java集合框架Map接口)
l 對於結果,我們除了注意應該使用枚舉類型存儲更多的可能性外,還應該注意。針對不同的掃描方式,會有不同的解析方式。即針對SYN掃描可能,因爲迴應包返回的SYN/ACK而說明端口是開啓的而對返回RST包說明端口是關閉的。而對於Null掃描可能因爲迴應RST包說明端口是關閉的,而不迴應說明端口是開啓的(實際上,系統並不一定遵守RFC793)。可以考慮使用策略設計模式來實現代碼的可擴展性。
l 對於發送包。並不方便使用策略設計模式。我推薦使用的是分層來實現。即數據鏈路層、網絡層、傳輸層都在不同的地方針對同一個包來封裝。雖然這會加大實現的難度。但可以最大程度的重用代碼。而且每一層的封裝都可以並行執行。
小結
本篇通過對SYN實現,發現了許多新的需求,需要更多的數據結構和算法,在下一篇將繼續討論SYN掃描實現,而且我們還會發現更多的需求,並提出更多的概念。
討論
本篇文檔提出了一個疑問希望大家的見教。
如何在Windows環境下,以PPPoE接入互聯網,不使用系統調用的情況下,實現SYN掃描。
反饋
歡迎大家提供反饋意見,以讓文檔不斷完善,從而使文檔自身具有生命力。你可以通過[email protected]聯繫到作者。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/ruyun126/archive/2009/10/19/4700752.aspx