Работа над чтением pcap файлов

This commit is contained in:
serega6531
2020-04-05 23:55:29 +03:00
parent 459dbf0a02
commit a0ceda4cb4
9 changed files with 181 additions and 52 deletions

View File

@@ -1,20 +1,33 @@
package ru.serega6531.packmate; package ru.serega6531.packmate;
import org.pcap4j.core.PcapNativeException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import ru.serega6531.packmate.model.enums.CaptureMode;
import ru.serega6531.packmate.pcap.FilePcapWorker;
import ru.serega6531.packmate.pcap.LivePcapWorker;
import ru.serega6531.packmate.pcap.PcapWorker;
import ru.serega6531.packmate.service.ServicesService;
import ru.serega6531.packmate.service.StreamService;
import java.net.UnknownHostException;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableScheduling
@EnableWebSocket
public class ApplicationConfiguration extends WebSecurityConfigurerAdapter implements WebSocketConfigurer { public class ApplicationConfiguration extends WebSecurityConfigurerAdapter implements WebSocketConfigurer {
@Value("${account-login}") @Value("${account-login}")
@@ -30,6 +43,21 @@ public class ApplicationConfiguration extends WebSecurityConfigurerAdapter imple
this.webSocketHandler = webSocketHandler; this.webSocketHandler = webSocketHandler;
} }
@Bean(destroyMethod = "stop")
@Autowired
public PcapWorker pcapWorker(ServicesService servicesService,
StreamService streamService,
@Value("${local-ip}") String localIpString,
@Value("${interface-name}") String interfaceName,
@Value("${pcap-file}") String filename,
@Value("${capture-mode}") CaptureMode captureMode) throws PcapNativeException, UnknownHostException {
if(captureMode == CaptureMode.LIVE) {
return new LivePcapWorker(servicesService, streamService, localIpString, interfaceName);
} else {
return new FilePcapWorker(servicesService, streamService, localIpString, filename);
}
}
@Autowired @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() auth.inMemoryAuthentication()

View File

@@ -6,12 +6,9 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.EnableScheduling; import ru.serega6531.packmate.pcap.PcapWorker;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
@SpringBootApplication @SpringBootApplication
@EnableScheduling
@EnableWebSocket
public class PackmateApplication { public class PackmateApplication {
@Value("${enable-capture}") @Value("${enable-capture}")

View File

@@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.serega6531.packmate.model.enums.Protocol; import ru.serega6531.packmate.model.enums.Protocol;
import ru.serega6531.packmate.pcap.PcapWorker;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;

View File

@@ -0,0 +1,7 @@
package ru.serega6531.packmate.model.enums;
public enum CaptureMode {
LIVE, FILE
}

View File

@@ -1,25 +1,22 @@
package ru.serega6531.packmate; package ru.serega6531.packmate.pcap;
import com.google.common.collect.*; import com.google.common.collect.*;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutablePair;
import org.pcap4j.core.*; import org.pcap4j.core.PacketListener;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.packet.IpV4Packet; import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.Packet; import org.pcap4j.packet.Packet;
import org.pcap4j.packet.TcpPacket; import org.pcap4j.packet.TcpPacket;
import org.pcap4j.packet.UdpPacket; import org.pcap4j.packet.UdpPacket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import ru.serega6531.packmate.model.CtfService; import ru.serega6531.packmate.model.CtfService;
import ru.serega6531.packmate.model.enums.Protocol; import ru.serega6531.packmate.model.enums.Protocol;
import ru.serega6531.packmate.model.pojo.UnfinishedStream; import ru.serega6531.packmate.model.pojo.UnfinishedStream;
import ru.serega6531.packmate.service.ServicesService; import ru.serega6531.packmate.service.ServicesService;
import ru.serega6531.packmate.service.StreamService; import ru.serega6531.packmate.service.StreamService;
import javax.annotation.PreDestroy;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@@ -29,16 +26,14 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component
@Slf4j @Slf4j
public class PcapWorker implements PacketListener { public abstract class AbstractPcapWorker implements PcapWorker, PacketListener {
private final ServicesService servicesService; private final ServicesService servicesService;
private final StreamService streamService; private final StreamService streamService;
private final PcapNetworkInterface device; protected PcapHandle pcap = null;
private PcapHandle pcap = null; protected final ExecutorService listenerExecutorService;
private final ExecutorService listenerExecutorService;
private final InetAddress localIp; private final InetAddress localIp;
@@ -51,11 +46,9 @@ public class PcapWorker implements PacketListener {
private final SetMultimap<UnfinishedStream, ImmutablePair<Inet4Address, Integer>> fins = HashMultimap.create(); private final SetMultimap<UnfinishedStream, ImmutablePair<Inet4Address, Integer>> fins = HashMultimap.create();
private final SetMultimap<UnfinishedStream, ImmutablePair<Inet4Address, Integer>> acks = HashMultimap.create(); private final SetMultimap<UnfinishedStream, ImmutablePair<Inet4Address, Integer>> acks = HashMultimap.create();
@Autowired public AbstractPcapWorker(ServicesService servicesService,
public PcapWorker(ServicesService servicesService, StreamService streamService,
StreamService streamService, String localIpString) throws UnknownHostException {
@Value("${interface-name}") String interfaceName,
@Value("${local-ip}") String localIpString) throws PcapNativeException, UnknownHostException {
this.servicesService = servicesService; this.servicesService = servicesService;
this.streamService = streamService; this.streamService = streamService;
@@ -67,37 +60,6 @@ public class PcapWorker implements PacketListener {
BasicThreadFactory factory = new BasicThreadFactory.Builder() BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("pcap-worker-listener").build(); .namingPattern("pcap-worker-listener").build();
listenerExecutorService = Executors.newSingleThreadExecutor(factory); listenerExecutorService = Executors.newSingleThreadExecutor(factory);
device = Pcaps.getDevByName(interfaceName);
}
void start() throws PcapNativeException {
log.info("Using interface " + device.getName());
pcap = device.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 100);
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("pcap-worker-loop").build();
ExecutorService loopExecutorService = Executors.newSingleThreadExecutor(factory);
try {
log.info("Intercept started");
pcap.loop(-1, this, loopExecutorService);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
// выходим
} catch (Exception e) {
log.error("Error while capturing packet", e);
stop();
}
}
@PreDestroy
@SneakyThrows
private void stop() {
if (pcap != null && pcap.isOpen()) {
pcap.breakLoop();
pcap.close();
}
log.info("Intercept stopped");
} }
public void gotPacket(Packet rawPacket) { public void gotPacket(Packet rawPacket) {
@@ -241,7 +203,7 @@ public class PcapWorker implements PacketListener {
} }
@SneakyThrows @SneakyThrows
int closeTimeoutStreams(Protocol protocol, long timeoutMillis) { public int closeTimeoutStreams(Protocol protocol, long timeoutMillis) {
return listenerExecutorService.submit(() -> { return listenerExecutorService.submit(() -> {
int streamsClosed = 0; int streamsClosed = 0;

View File

@@ -0,0 +1,59 @@
package ru.serega6531.packmate.pcap;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.Packet;
import ru.serega6531.packmate.service.ServicesService;
import ru.serega6531.packmate.service.StreamService;
import java.io.EOFException;
import java.io.File;
import java.net.UnknownHostException;
@Slf4j
public class FilePcapWorker extends AbstractPcapWorker {
private final File file;
public FilePcapWorker(ServicesService servicesService,
StreamService streamService,
String localIpString,
String filename) throws UnknownHostException {
super(servicesService, streamService, localIpString);
file = new File(filename);
if(!file.exists()) {
throw new IllegalArgumentException("File " + file.getAbsolutePath() + " does not exist");
}
}
@SneakyThrows
@Override
public void start() {
pcap = Pcaps.openOffline(file.getAbsolutePath());
while (pcap.isOpen()) {
try {
final Packet packet = pcap.getNextPacketEx();
gotPacket(packet);
} catch (PcapNativeException e) {
log.error("Pcap read", e);
Thread.sleep(100);
} catch (EOFException e) {
stop();
break;
}
}
}
@SneakyThrows
public void stop() {
if (pcap != null && pcap.isOpen()) {
pcap.close();
}
log.info("Intercept stopped");
}
}

View File

@@ -0,0 +1,62 @@
package ru.serega6531.packmate.pcap;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.Pcaps;
import ru.serega6531.packmate.service.ServicesService;
import ru.serega6531.packmate.service.StreamService;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
public class LivePcapWorker extends AbstractPcapWorker {
private final PcapNetworkInterface device;
public LivePcapWorker(ServicesService servicesService,
StreamService streamService,
String localIpString,
String interfaceName) throws PcapNativeException, UnknownHostException {
super(servicesService, streamService, localIpString);
device = Pcaps.getDevByName(interfaceName);
if(device == null) {
throw new IllegalArgumentException("Device " + interfaceName + " does not exist");
}
}
public void start() throws PcapNativeException {
log.info("Using interface " + device.getName());
pcap = device.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 100);
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("pcap-worker-loop").build();
ExecutorService loopExecutorService = Executors.newSingleThreadExecutor(factory);
try {
log.info("Intercept started");
pcap.loop(-1, this, loopExecutorService);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
// выходим
} catch (Exception e) {
log.error("Error while capturing packet", e);
stop();
}
}
@SneakyThrows
public void stop() {
if (pcap != null && pcap.isOpen()) {
pcap.breakLoop();
pcap.close();
}
log.info("Intercept stopped");
}
}

View File

@@ -0,0 +1,12 @@
package ru.serega6531.packmate.pcap;
import org.pcap4j.core.PcapNativeException;
import ru.serega6531.packmate.model.enums.Protocol;
public interface PcapWorker {
void start() throws PcapNativeException;
void stop();
int closeTimeoutStreams(Protocol protocol, long timeoutMillis);
}

View File

@@ -15,6 +15,7 @@ spring:
enable-capture: true enable-capture: true
capture-mode: LIVE # LIVE, FILE
interface-name: enp0s31f6 interface-name: enp0s31f6
local-ip: "192.168.0.125" local-ip: "192.168.0.125"
account-login: BinaryBears account-login: BinaryBears