Ethernet сниффер на Java
Сниффер или анализатор трафика в Ethernet сети тема довольно обширная и ее нереально осветить в одном посте. Достаточно проанализировать работу и возможности общеизвестного анализатора трафика Wireshark и станет ясно насколько серъезна данная тема. И тем не менее все же попробуем сделать несколько шагов в данном направлении используя технологию Java.
Эта тема интересна не только для анализа трафика в Ethernet сети но и для построения десктопного приложения по приему и обработке так называемых 'сырых' Ethernet пакетов на Java, которое может работать в любой опереационной системе как есть. Итак, известно, что Wireshark работает в связке с популярной Windows библиотекой WinPcap. В Java также есть подобная библиотека, вернее так называемая обертка Java для WinPcap Jnetpcap, которая имеет развернутую документацию и множество примеров ее применения.
На официальном сайте библиотеки Jnetpcap имеются примеры ее использования, но каждый из примеров поясняет только общую концепцию ее применения с кодом в методе main(). Данный пост это собственно тоже небольшой пример использования библиотеки Jnetpcap но на базе простейшей десктопной формы, где представлен механизм запуска отлова безпротокольных Ethernet фреймов с использованием классов потока, формы с входящими в нее классами и лисенерами, а также хендлера в котором собственно и формируются данные отловленного фрейма. На базе приведенного примера вполне можно развивать тему приема и обработки безпротокольных Ethernet пакетов в любом требуемом направлении. Ниже приведен Java код примера с обильными комментами.
package javaethcapturer;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
public class JavaEthCapturer {
// Will be filled with NICs
List alldevs = new ArrayList();
// For any error msgs
StringBuilder errbuf = new StringBuilder();
//Getting a list of devices
int r = Pcap.findAllDevs(alldevs, errbuf);
int adp;
int nbpct;
boolean pc = false;
// массив строк адаптеров
String [] nbAdapterStrings = {"0", "1"};
String [] nbAdpStrings = {"0", "1"};
int bufrdCount;
// Capture all packets, no trucation
int snaplen = 64 * 1024;
// capture all packets
int flags = Pcap.MODE_PROMISCUOUS;
// пакеты только на выбранный адаптер
// static int flags = Pcap.MODE_NON_PROMISCUOUS;
// Timeout mc
// static int timeout = 10000;
int timeout = 100;
//----------------------------------------------------------------------
// создание объектов
private JButton stop = new JButton("Stop");
private JButton start = new JButton("Start");
private static JTextArea input = new JTextArea("input");
private JScrollPane scrollPaneInput = new JScrollPane(input);
private JLabel label1 = new JLabel("Select an adapter");
private JLabel label2 = new JLabel("Test1");
private JLabel label3 = new JLabel("Test2");
private JComboBox adapterList = new JComboBox();
static private Pcap pcap = new Pcap();
//----------------------------------------------------------------------
// Десктопная форма
public class Form extends JFrame{
String dv = "";
// конструктор класса Form (должен иметь тоже имя Form)
public Form() {
System.out.println(r);
System.out.println(r);
if (r != Pcap.OK) {
System.err.printf("Can't read list of devices, error is %s", errbuf
.toString());
return;
}
System.out.println("Network devices found:");
int i = 0;
for (Iterator it = alldevs.iterator(); it.hasNext();) {
PcapIf device = (PcapIf) it.next();
String description =
(device.getDescription() != null) ? device.getDescription()
: "No description available";
// записать название адаптера в строку
nbAdapterStrings[i] = description + "\n";
nbAdpStrings[i] = description;
dv = dv + nbAdapterStrings[i];
// список адаптеров в adapterList
adapterList.addItem(nbAdapterStrings[i]);
i++;
}
// список адаптеров в input
input.setText(dv);
// инициализация компонентов
initComponents();
}
// метод инициализации компонентов формы
private void initComponents(){
// положение на экране
setBounds(15,30,800,600);
// размер формы
setSize(830, 600);
// Закрытие формы
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Контейнер для размещения компонентов формы
Container container = getContentPane();
// установить разметку
container.setLayout(null);
container.setBounds(5,5,800,600);
//----------------------------------------------------------------------
// JTextArea
// Добавление JTextArea input
input.setLineWrap(true);
input.setColumns(20);
input.setRows(5);
input.setBounds(10,220,790,300);
container.add(input);
// Добавление скрола
scrollPaneInput.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPaneInput.setBounds(10,220,800,300);
container.add(scrollPaneInput);
scrollPaneInput.setViewportView(input);
//----------------------------------------------------------------------
// JComboBox
adapterList.setBounds(10,25,300,20);
// зарегистрировать экземпляр класса обработчика события
adapterList.addActionListener(new ethListEventListener());
adapterList.setEnabled(true);
container.add(adapterList);
//----------------------------------------------------------------------
// JLabel
// добавление метки состояния COM порта
label1.setBounds(10,5,300,20);
// прозрачный фон
label1.setOpaque(true);
label1.setForeground(Color.red);
container.add(label1);
//
label2.setBounds(10,190,300,20);
label2.setText("Lenght of packet");
container.add(label2);
//
label3.setBounds(20,530,250,20);
label3.setText("Frame number");
container.add(label3);
//----------------------------------------------------------------------
// JButton
// зарегистрировать экземпляр класса обработчика события start
start.addActionListener(new startEventListener());
// добавить кнопку и ее положение
start.setBounds(440,155,80,25);
start.setEnabled(false);
container.add(start);
// зарегистрировать экземпляр класса обработчика события stop
stop.addActionListener(new stopEventListener());
stop.setBounds(730,155,80,25);
stop.setEnabled(false);
container.add(stop);
}
// клас имплементации события нажатия start
class startEventListener implements ActionListener {
@Override
// обработка события нажатия на button start
public void actionPerformed(ActionEvent e) {
// дезактивировать выбор адаптеров
adapterList.setEnabled(false);
// Флаг открытия pcap
pc = true;
stop.setEnabled(true);
}
}
// клас имплементации события нажатия stop
class stopEventListener implements ActionListener {
@Override
// обработка события нажатия на button stop
public void actionPerformed(ActionEvent e) {
// Флаг закрытия pcap
pc = false;
System.out.println(adp + " device close");
label1.setOpaque(true);
label1.setForeground(Color.red);
label1.setText("Select an adapter");
//Close the pcap
pcap.close();
start.setEnabled(false);
adapterList.setEnabled(true);
stop.setEnabled(false);
}
}
// обработка события изменения JComboBox comList
class ethListEventListener implements ActionListener {
String op = "Opened";
@Override
public void actionPerformed(ActionEvent e) {
// comName - выбранная строка в JComboBox comList
JComboBox cb = (JComboBox)e.getSource();
// получить номер выбранного адаптера
adp = cb.getSelectedIndex();
// выбор адаптера
PcapIf device = (PcapIf) alldevs.get(adp);
// отрыть выбранный адаптер
pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);
if (pcap == null) {
input.setText("Error while opening device for capture: "
+ errbuf.toString());
}
// выбранный адаптер в окне input
input.setText(nbAdpStrings[adp] + " " + op);
// прозрачность label1 с послед. уст. цвета
label1.setOpaque(true);
label1.setForeground(Color.MAGENTA);
label1.setText(nbAdapterStrings[adp]);
start.setEnabled(true);
}
}
}
//----------------------------------------------------------------------
// Хендлер метод
PcapPacketHandler jpacketHandler = new PcapPacketHandler() {
// строка данных
String readData;
// буфер данных
byte[] bufrd = new byte [2000];
@Override
public void nextPacket(PcapPacket packet, String user) {
// данные фрейма data
byte[] data = packet.getByteArray(0, packet.size());
// номер фрейма
nbpct = (int) packet.getFrameNumber();
input.setText("");
readData = "";
// количество байт фрейма
label2.setText(String.format("Lenght of packet %d bytes", data.length));
label3.setText(String.format("Frame number %d ", packet.getFrameNumber()));
// перенос данных фрейма в форматированную строку
for (int i = 0; i < data.length; i++){
bufrd[i] = data[i];
readData = readData + String.format("%02X ", bufrd[i]);
}
// данные фрейма в окно input
input.setText(readData);
}
};
// Поток с pcap.loop
public class PcapLoopThread extends Thread {
// переопределение метода run
@Override
public void run() {
while(true)
{
try{
//Приостанавливает поток 1мс
sleep(1);
if(pc) {
// отлов одного пакета если был Start
pcap.loop(1, jpacketHandler, "jnetpcap rocks!");
}
}catch(InterruptedException e){}
}
}
}
//----------------------------------------------------------------------
// Main
public static void main(String[] args) {
// создание объектов
JavaEthCapturer javaEthTest = new JavaEthCapturer();
JavaEthCapturer.Form form = javaEthTest.new Form();
JavaEthCapturer.PcapLoopThread pcapLoopThread = javaEthTest.new PcapLoopThread();
// по зарытию формы
form.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Запуск формы
form.setVisible(true);
// Запуск потока
pcapLoopThread.start();
}
}
Для порядка кратко опишем работу приложения.
1. При запуске приложения прежде всего необходимо определиться со списком сетевых адаптеров и выбрать тот с которым программа будет работать. Список адаптеров формируется в конструкторе класса формы Form() и отображается в окне JTextArrea и в списке выбора JComboBox. Кроме того в лисененре ethListEventListener производится операция открытия выбранного адаптера pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);
2. После выбора нужного адаптера и его открытия становится доступной кнопка Start по нажатию которой, в лисененре startEventListener, производится установка флага запуска метода отлова пакетов pcap.loop(1, jpacketHandler, "jnetpcap rocks!"); Отлов пакетов производится в потоке PcapLoopThread() который запускается при запуске приложения в методе main()
Вот собственно и все. В окне JTextArea input будут мелькать данные всех входящих и исходящих пакетов. Над окном и под ним будут мелькать циферки указывающие на количество байт в отловленном пакете и порядковый номер фрейма соответственно. Полезно обратить внимание на начальные установки типа int timeout = 100; - таймаут перед отловом каждого последующего пакета, int flags = Pcap.MODE_PROMISCUOUS; - режим отлова пакетов который может быть MODE_NON_PROMISCUOUS - отлов только тех пакетов которые имеют адрес назначения совпадающий с МАС адресом выбранного адаптера. Порядок передачи переменных из класса в класс и механизм взаимодействия объектов в приложении можно проследить просмотрев код программы. По ссылке ниже по тексту собственно архив проекта с библиотекой Jnetpcap для Net Beans 7.2. Не забывайте оставлять свои комменты, замечания и предложения по теме.
P.s. Поскольку библиотека jnetpcap это всего лишь обертка библиотеки winpcap то для правильной работы приложения в Windows должна быть установлена нативная (родная для операционной системы) библиотека WinPcap и в системную папку ...:\WINDOWS\system32\ помещен файл библиотеки jnetpcap jnetpcap.dll
Электроника :
- Техника электроника (11)
- Полезная электроника (4)
- Электроника для всех (5)
- Техника для дома (6)
- Cхемотехника ПЛИС (11)
- Пректирование PCAD (4)
Программирование :
- Микроконтроллеры (9)
- ПЛИС VHDL Verilog (29)
- C++ Builder (7)
- Visual Studio C++ C# (7)
- Java programming (7)
- Matlab programming (4)
Сайтостроение :
- Сайтостроение HTML (5)
- Сайтостроение PHP (8)
- PHP CMS на файлах (3)
- Web инструменты (9)
- Полезное вебмастеру (11)
- SEO раскрутка сайта (4)
- PHP скрипты (3)
Реклама :
Книги и учебники :
- Шаблоны сайтов (6)
- Книги и учебники (2)
Компьютер и интернет :
Поиск по сайту :
Реклама :
Облако меток :
Бесплатная подписка :
Статистика :
- Популярность (3)
- Посещаемость (3)
- Поисковые запросы (3)