1. 윈도우에서 Pcap을 테스트 하기 위해서는 Pcap이 설치 되어 있어야 한다.
- 설치파일 : https://www.winpcap.org/install/ 에서 인스톨파일 다운로드(WinPcap_4_1_3.exe)
- 다운로드한 WinPcap을 관리자권한으로 설치
2. Centos, Rocky Linux에서 pcap을 사용하려면 libpcap 설치
- Linux os버전에 따라 설치해야 할 항목은 다를 수 있다.
- 설치파일 : http://www.tcpdump.org/release/libpcap-1.10.1.tar.gz 에서 libpcap-1.10.1.tar.gz 파일을 다운로드
- 설치 방법
libpcap-1.10.4.tar.gz 수동 설치 할 경우 (Root 권한으로 진행) 1. 파일 다운로드 wget http://www.tcpdump.org/release/libpcap-1.10.1.tar.gz 2. 압축해제 tar -xzf libpcap-1.10.1.tar.gz 3. 압축해제된 폴더로 이동해서 설치 (configure 시 설치경로 /usr 지정) ./configure --prefix=/usr make make install 4. 설치 완료 후 설치 경로에 라이브러리 있는지 확인 ls /usr/include/pcap.h ls /usr/lib64/libpcap.so 5. /usr/include/pcap.h에 없고 /usr/local/include/pcap.h에 있으면 심볼 생성 ln -s /usr/local/include/pcap.h /usr/include/pcap.h 6. usr/lib64 path 설정 (다른 방법으로도 전역으로 생성하면 됨) echo 'export LD_LIBRARY_PATH=/usr/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc |
- pcap 설치 확인 및 테스트
간단하게 C로 인터페이스 출력하는 코드로 설치가 정상적으로 됐는지 확인 1. vi로 테스트 코드 작성 vi pcaptest.c 2. pcaptest.c 내용 #include <pcap.h> #include <stdio.h> int main() { pcap_if_t *alldevs, *dev; char errbuf[PCAP_ERRBUF_SIZE]; // 모든 네트워크 장치 목록을 가져옴 if (pcap_findalldevs(&alldevs, errbuf) == -1) { printf("Error finding devices: %s\n", errbuf); return 1; } // 첫 번째 장치를 선택 (기본 장치) dev = alldevs; if (dev == NULL) { printf("No devices found.\n"); pcap_freealldevs(alldevs); // 메모리 해제 return 1; } printf("Interface: %s\n", dev->name); // 장치 목록에서 사용한 메모리 해제 pcap_freealldevs(alldevs); return 0; } 3. pcaptest.c 컴파일 gcc -o pcaptest pcaptest.c -lpcap 4. pcaptest.c 컴파일을 하면 pcaptest 파일이 생성되면 실행이 정상적으로 되는지 확인 ./pcaptest 5. ./pcaptest 실행하면 나오는 경과 Interface: eth0 <---eth0은 서버 환경에 따라서 다를 수 있음 |
3. Java Spring 구현
- pom.xml에 pcap4j 라이브러리 Maven Dependency 추가
<dependency>
<groupId>org.pcap4j</groupId> <artifactId>pcap4j-core</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.pcap4j</groupId> <artifactId>pcap4j-packetfactory-static</artifactId> <version>1.7.4</version> </dependency> |
- PcapHandleWrapper.class 작성
import org.pcap4j.core.PcapHandle;
public class PcapHandleWrapper { private PcapHandle handle; public PcapHandleWrapper(PcapHandle handle) { this.handle = handle; } public PcapHandle getHandle() { return handle; } public void setHandle(PcapHandle handle) { this.handle = handle; } } |
- 테스트 샘플
import java.net.InetAddress;
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.pcap4j.core.BpfProgram; import org.pcap4j.core.PcapHandle; import org.pcap4j.core.PcapNetworkInterface; import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode; import org.pcap4j.core.Pcaps; import org.pcap4j.packet.EthernetPacket; import org.pcap4j.packet.IpV4Packet; import org.pcap4j.packet.Packet; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import egovframework.example.utils.PcapHandleWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; @Controller
@RequestMapping("/mactest") @RequiredArgsConstructor @Log4j2 public class MacAddrSampleController {
private static PcapHandleWrapper handleWrapper; @ResponseBody @GetMapping(value = {"/pcap4j"}) public String pcap4j5(HttpServletRequest req ,HttpServletResponse rep, //client IP @RequestParam(name = "targetIP", defaultValue = "192.168.35.224") String targetIP) throws Exception { //Was가 동작하고 있는 server IP String serverIP = "192.168.35.28"; ExecutorService executor = Executors.newSingleThreadExecutor(); try { //Was가 동작하고 있는 server IP InetAddress addr = InetAddress.getByName(serverIP); PcapNetworkInterface device = Pcaps.getDevByAddress(addr); if (device == null) { System.out.println("네트워크 인터페이스를 선택하지 않았습니다."); return "네트워크 인터페이스를 선택하지 않았습니다."; } // 캡처 설정 int snaplen = 65536; // 최대 캡처할 패킷 크기 PromiscuousMode mode = PromiscuousMode.PROMISCUOUS; // Promiscuous 모드 int timeout = 50; // 타임아웃 (단위: ms) PcapHandle handle = device.openLive(snaplen, mode, timeout); handleWrapper = new PcapHandleWrapper(handle); String filter = "ip host " + targetIP; handle.setFilter(filter, BpfProgram.BpfCompileMode.OPTIMIZE); executor.submit(() -> { try { while (true) { // 무한 루프 Packet packet = handleWrapper.getHandle().getNextPacket(); if (packet != null) { EthernetPacket ethernetPacket = packet.get(EthernetPacket.class); if (ethernetPacket != null) { // IP 패킷으로 변환 IpV4Packet ipV4Packet = packet.get(IpV4Packet.class); if (ipV4Packet != null) { // 목적지 MAC 주소 추출 String dstAddr = ipV4Packet.getHeader().getDstAddr().getHostAddress(); String dstMacAddrIp = ethernetPacket.getHeader().getDstAddr().toString(); if(dstAddr != null && targetIP.equals(dstAddr)) { System.out.println("Destination IP Address: " + dstAddr); System.out.println("Destination MAC Address: " + dstMacAddrIp); } } } } } } catch (Exception e) { e.printStackTrace(); } finally { handleWrapper.getHandle().close(); } }); // ExecutorService 종료 대기 Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { executor.shutdown(); if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); } })); } catch (Exception e) { e.printStackTrace(); } return "pcap 스레드 동작 중"; } } |
웹 프로젝트에서 테스트를 진행 했기 대문에 웹 호출로 스레드를 구동하고 나면 모니터링이 시작되고
웹페이지에 접속하는 클라이언트의 정보를 pcap으로 통해 가져 올 수 있다.
* 같은 망에서만 mac 정보를 가져올 수 있고 망이 다르면 가져올 수 없다.
https://kkubi-story.tistory.com/21
pcap 동작 원리
pcap(Packet Capture) 도구를 사용해도 망이 다르면 MAC 주소 정보를 가져올 수 없다. 이는 네트워크의 기본적인 동작 원리에 따른 것이다. 이유 설명 1. MAC 주소의 역할과 ARP 프로토콜
kkubi-story.tistory.com
'Development Story > Java' 카테고리의 다른 글
Spring Boot Batch Tibero Database 적용 (0) | 2024.08.30 |
---|---|
Spring boot 이클립스 디버깅 모드 Transaction 오류 (0) | 2024.08.30 |
spring Jxls 2.0 사용법 (1) | 2024.08.08 |
Spring 주입된 Bean을 Static에서 사용 (0) | 2024.08.08 |
egovframework 암호화/복호화 (0) | 2024.08.08 |