mirror of
https://git.freestone.net/cramer/pcapmirror.git
synced 2025-12-31 12:00:40 +01:00
Compare commits
20 Commits
0.5beta1
...
0.6-rocky1
| Author | SHA1 | Date | |
|---|---|---|---|
| 255f1d0773 | |||
| ce6e5ec9a8 | |||
| 66b45a06f2 | |||
| 6ca07a3f6a | |||
| 316f792927 | |||
| 65f3e923c1 | |||
| 204b636727 | |||
| 3f58677aa0 | |||
| 5dd567ee20 | |||
| 626b379a54 | |||
| 4d25135e58 | |||
| 0d41857e52 | |||
| ebcd9f697d | |||
| d2133f7531 | |||
| c202697f7b | |||
| 9fcac378ae | |||
| 87d74f0db9 | |||
| 6baf639a9c | |||
| e3097eec3a | |||
| a2c0ad8bfb |
199
.gitlab-ci.yml
199
.gitlab-ci.yml
@@ -1,11 +1,10 @@
|
|||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- publish
|
- publish
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
VERSION: 0.5
|
VERSION: 0.6
|
||||||
|
|
||||||
build-bookworm:
|
build-bookworm:
|
||||||
stage: build
|
stage: build
|
||||||
@@ -13,7 +12,8 @@ build-bookworm:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-bookworm:v1
|
||||||
script:
|
script:
|
||||||
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
- apt-get update && apt-get install -y libpcap-dev
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
@@ -34,11 +34,45 @@ publish-bookworm:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
script:
|
script:
|
||||||
- apt-get update && apt-get install -y curl
|
|
||||||
- ls -la build
|
- ls -la build
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/bookworm/pcapmirror_$VERSION-1_amd64.deb'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/bookworm/pcapmirror_$VERSION-deb12_amd64.deb'
|
||||||
|
|
||||||
|
build-trixie:
|
||||||
|
stage: build
|
||||||
|
needs: []
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
|
script:
|
||||||
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
|
- dpkg-buildpackage -uc -us
|
||||||
|
- mkdir -p build
|
||||||
|
- mv ../pcapmirror*.* build/
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build
|
||||||
|
|
||||||
|
publish-trixie:
|
||||||
|
stage: publish
|
||||||
|
needs:
|
||||||
|
- build-trixie
|
||||||
|
dependencies:
|
||||||
|
- build-trixie
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
|
script:
|
||||||
|
- ls -la build
|
||||||
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/trixie/pcapmirror_$VERSION-deb13_amd64.deb'
|
||||||
|
|
||||||
build-sid:
|
build-sid:
|
||||||
stage: build
|
stage: build
|
||||||
@@ -46,7 +80,8 @@ build-sid:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- sid
|
- docker-generic
|
||||||
|
image: debian-package-builder-sid:v1
|
||||||
script:
|
script:
|
||||||
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
- apt-get update && apt-get install -y libpcap-dev
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
@@ -67,11 +102,48 @@ publish-sid:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
script:
|
script:
|
||||||
- apt-get update && apt-get install -y curl
|
|
||||||
- ls -la build
|
- ls -la build
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/sid/pcapmirror_$VERSION-1_amd64.deb'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/sid/pcapmirror_$VERSION-sid_amd64.deb'
|
||||||
|
|
||||||
|
build-rocky10:
|
||||||
|
stage: build
|
||||||
|
needs: []
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: rockylinux-package-builder-10:v1
|
||||||
|
script:
|
||||||
|
- dnf install -y libpcap-devel
|
||||||
|
- mkdir -p /root/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
|
- tar -czf /root/rpmbuild/SOURCES/pcapmirror-v${VERSION}.tar.gz --exclude=debian --exclude=.git .
|
||||||
|
- cp -r * /root/rpmbuild/BUILD
|
||||||
|
- rpmbuild -ba pcapmirror.spec
|
||||||
|
- mkdir -p build
|
||||||
|
- mv /root/rpmbuild/RPMS/x86_64/pcapmirror*.* build/
|
||||||
|
- mv /root/rpmbuild/SRPMS/pcapmirror*.* build/
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build
|
||||||
|
|
||||||
|
publish-rocky10:
|
||||||
|
stage: publish
|
||||||
|
needs:
|
||||||
|
- build-rocky10
|
||||||
|
dependencies:
|
||||||
|
- build-rocky10
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
|
script:
|
||||||
|
- ls -la build
|
||||||
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror-$VERSION-*.el10.x86_64.rpm ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/rockylinux10/pcapmirror-$VERSION-1.el10.x86_64.rpm'
|
||||||
|
|
||||||
build-rocky9:
|
build-rocky9:
|
||||||
stage: build
|
stage: build
|
||||||
@@ -79,11 +151,12 @@ build-rocky9:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- rocky9
|
- docker-generic
|
||||||
|
image: rockylinux-package-builder-9:v1
|
||||||
script:
|
script:
|
||||||
- dnf install -y libpcap-devel
|
- dnf install -y libpcap-devel
|
||||||
- mkdir -p /root/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
- mkdir -p /root/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
- tar -czf /root/rpmbuild/SOURCES/pcapmirror-v$VERSION.tar.gz --exclude=debian --exclude=.git .
|
- tar -czf /root/rpmbuild/SOURCES/pcapmirror-v${VERSION}.tar.gz --exclude=debian --exclude=.git .
|
||||||
- cp -r * /root/rpmbuild/BUILD
|
- cp -r * /root/rpmbuild/BUILD
|
||||||
- rpmbuild -ba pcapmirror.spec
|
- rpmbuild -ba pcapmirror.spec
|
||||||
- mkdir -p build
|
- mkdir -p build
|
||||||
@@ -103,11 +176,11 @@ publish-rocky9:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
script:
|
script:
|
||||||
- apt-get update && apt-get install -y curl
|
|
||||||
- ls -la build
|
- ls -la build
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror-$VERSION-*.el9.x86_64.rpm ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/rockylinux9/pcapmirror-$VERSION-1.el8.x86_64.rpm'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror-$VERSION-*.el9.x86_64.rpm ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/rockylinux9/pcapmirror-$VERSION-1.el9.x86_64.rpm'
|
||||||
|
|
||||||
build-rocky8:
|
build-rocky8:
|
||||||
stage: build
|
stage: build
|
||||||
@@ -115,11 +188,12 @@ build-rocky8:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- rocky8
|
- docker-generic
|
||||||
|
image: rockylinux-package-builder-8:v1
|
||||||
script:
|
script:
|
||||||
- dnf install -y libpcap-devel
|
- dnf install -y libpcap-devel
|
||||||
- mkdir -p /root/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
- mkdir -p /root/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
- tar -czf /root/rpmbuild/SOURCES/pcapmirror-v$VERSION.tar.gz --exclude=debian --exclude=.git .
|
- tar -czf /root/rpmbuild/SOURCES/pcapmirror-v${VERSION}.tar.gz --exclude=debian --exclude=.git .
|
||||||
- cp -r * /root/rpmbuild/BUILD
|
- cp -r * /root/rpmbuild/BUILD
|
||||||
- rpmbuild -ba pcapmirror.spec
|
- rpmbuild -ba pcapmirror.spec
|
||||||
- mkdir -p build
|
- mkdir -p build
|
||||||
@@ -139,9 +213,9 @@ publish-rocky8:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
script:
|
script:
|
||||||
- apt-get update && apt-get install -y curl
|
|
||||||
- ls -la build
|
- ls -la build
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror-$VERSION-*.el8.x86_64.rpm ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/rockylinux8/pcapmirror-$VERSION-1.el8.x86_64.rpm'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror-$VERSION-*.el8.x86_64.rpm ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/rockylinux8/pcapmirror-$VERSION-1.el8.x86_64.rpm'
|
||||||
|
|
||||||
@@ -151,7 +225,8 @@ build-pios12:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- pios12
|
- docker-generic
|
||||||
|
image: pios-package-builder-bookworm:v1
|
||||||
script:
|
script:
|
||||||
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
- apt-get update && apt-get install -y libpcap-dev
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
@@ -172,11 +247,11 @@ publish-pios12:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
script:
|
script:
|
||||||
- apt-get update && apt-get install -y curl
|
|
||||||
- ls -la build
|
- ls -la build
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_armhf.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/bookworm/pcapmirror_$VERSION-1_armhf.deb'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_armhf.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/bookworm/pcapmirror_$VERSION-piso12_armhf.deb'
|
||||||
|
|
||||||
build-pios12-64:
|
build-pios12-64:
|
||||||
stage: build
|
stage: build
|
||||||
@@ -184,7 +259,8 @@ build-pios12-64:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- pios12-64
|
- docker-generic
|
||||||
|
image: pios-package-builder-bookworm:64-v1
|
||||||
script:
|
script:
|
||||||
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
- apt-get update && apt-get install -y libpcap-dev
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
@@ -205,8 +281,77 @@ publish-pios12-64:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- bookworm
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
script:
|
script:
|
||||||
- apt-get update && apt-get install -y curl
|
|
||||||
- ls -la build
|
- ls -la build
|
||||||
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_arm64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/bookworm/pcapmirror_$VERSION-1_arm64.deb'
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_arm64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/bookworm/pcapmirror_$VERSION-pios12_arm64.deb'
|
||||||
|
|
||||||
|
build-plucky:
|
||||||
|
stage: build
|
||||||
|
needs: []
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: ubuntu-package-builder-plucky:v1
|
||||||
|
script:
|
||||||
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
|
- dpkg-buildpackage -uc -us
|
||||||
|
- mkdir -p build
|
||||||
|
- mv ../pcapmirror*.* build/
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build
|
||||||
|
|
||||||
|
publish-plucky:
|
||||||
|
stage: publish
|
||||||
|
needs:
|
||||||
|
- build-plucky
|
||||||
|
dependencies:
|
||||||
|
- build-plucky
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
|
script:
|
||||||
|
- ls -la build
|
||||||
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/trixie/pcapmirror_$VERSION-ubu25.04_amd64.deb'
|
||||||
|
|
||||||
|
build-noble:
|
||||||
|
stage: build
|
||||||
|
needs: []
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: ubuntu-package-builder-noble:v1
|
||||||
|
script:
|
||||||
|
- tar -czf ../pcapmirror_$VERSION.orig.tar.gz --exclude=debian .
|
||||||
|
- apt-get update && apt-get install -y libpcap-dev
|
||||||
|
- dpkg-buildpackage -uc -us
|
||||||
|
- mkdir -p build
|
||||||
|
- mv ../pcapmirror*.* build/
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- build
|
||||||
|
|
||||||
|
publish-noble:
|
||||||
|
stage: publish
|
||||||
|
needs:
|
||||||
|
- build-noble
|
||||||
|
dependencies:
|
||||||
|
- build-noble
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
tags:
|
||||||
|
- docker-generic
|
||||||
|
image: debian-package-builder-trixie:v1
|
||||||
|
script:
|
||||||
|
- ls -la build
|
||||||
|
- 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/pcapmirror_$VERSION-1_amd64.deb ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/pcapmirror/trixie/pcapmirror_$VERSION-ubu24.04_amd64.deb'
|
||||||
|
|
||||||
|
|||||||
5
Makefile
5
Makefile
@@ -24,6 +24,9 @@ PREFIX = /usr
|
|||||||
# Default rule
|
# Default rule
|
||||||
all: $(TARGET) man
|
all: $(TARGET) man
|
||||||
|
|
||||||
|
static: $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) -static $(OBJS) -o $(TARGET) $(LIBS) -ldbus-1 -lsystemd -lcap
|
||||||
|
|
||||||
# Create executable
|
# Create executable
|
||||||
$(TARGET): $(OBJS)
|
$(TARGET): $(OBJS)
|
||||||
$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) $(LIBS)
|
$(CC) $(CFLAGS) $(OBJS) -o $(TARGET) $(LIBS)
|
||||||
@@ -37,7 +40,7 @@ man:
|
|||||||
|
|
||||||
# Clean up object files and executable
|
# Clean up object files and executable
|
||||||
clean:
|
clean:
|
||||||
rm -f -f $(OBJS) $(TARGET)
|
rm -f -f $(OBJS) $(TARGET) pcapmirror.8.gz
|
||||||
|
|
||||||
# Install the executable
|
# Install the executable
|
||||||
install: $(TARGET)
|
install: $(TARGET)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# pcapmirror
|
# pcapmirror
|
||||||

|

|
||||||
|
|
||||||
pcapmirror is a command-line tool for capturing network traffic and mirroring it to a remote destination using [TZSP encapsulation](https://en.wikipedia.org/wiki/TZSP). It leverages the `libpcap` library for packet capture and provides options for filtering traffic based on BPF syntax. This tool is useful for network monitoring, intrusion detection, and remote packet analysis.
|
pcapmirror is a command-line tool for capturing network traffic and mirroring it to a remote destination using [TZSP encapsulation](https://en.wikipedia.org/wiki/TZSP) or [ERSPAN](https://datatracker.ietf.org/doc/html/draft-foschiano-erspan-01). It leverages the `libpcap` library for packet capture and provides options for filtering traffic based on BPF syntax. This tool is useful for network monitoring, intrusion detection, and remote packet analysis.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -16,6 +16,9 @@ pcapmirror [options]
|
|||||||
* -f <filter> Specify the capture filter (BPF syntax)
|
* -f <filter> Specify the capture filter (BPF syntax)
|
||||||
* -r <host/ipv4/ipv6> Specify the destination host (required)
|
* -r <host/ipv4/ipv6> Specify the destination host (required)
|
||||||
* -p <port> Specify the destination port (default: 37008)
|
* -p <port> Specify the destination port (default: 37008)
|
||||||
|
* -e Use ERSPAN encapsulation (default: TZSP)
|
||||||
|
* -s <source_ip> Specify the source IP address (required for ERSPAN)
|
||||||
|
* -S <session_id> Specify the session ID (default: 42, must be between 0 and 1023)
|
||||||
* -4 Force IPv4 host lookup
|
* -4 Force IPv4 host lookup
|
||||||
* -6 Force IPv6 host lookup
|
* -6 Force IPv6 host lookup
|
||||||
* -l List available network interfaces.
|
* -l List available network interfaces.
|
||||||
|
|||||||
8
debian/changelog
vendored
8
debian/changelog
vendored
@@ -1,3 +1,11 @@
|
|||||||
|
pcapmirror (0.6-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Erspan Encapsulation support
|
||||||
|
* added option -e to set the encapsulation type
|
||||||
|
* added option -S to set ERSPAN session id
|
||||||
|
|
||||||
|
-- Matthias Cramer <cramer@freestone.net> Sun, 20 Apr 2025 16:50:00 +0200
|
||||||
|
|
||||||
pcapmirror (0.5-1) unstable; urgency=medium
|
pcapmirror (0.5-1) unstable; urgency=medium
|
||||||
|
|
||||||
* new option -c to count matching packets (overrides verbose mode)
|
* new option -c to count matching packets (overrides verbose mode)
|
||||||
|
|||||||
4
debian/control
vendored
4
debian/control
vendored
@@ -11,7 +11,7 @@ Architecture: any
|
|||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libpcap0.8
|
Depends: ${shlibs:Depends}, ${misc:Depends}, libpcap0.8
|
||||||
Description: A simple packet mirroring tool using libpcap
|
Description: A simple packet mirroring tool using libpcap
|
||||||
pcapmirror is a command-line tool for capturing network traffic and
|
pcapmirror is a command-line tool for capturing network traffic and
|
||||||
mirroring it to a remote destination using TZSP encapsulation. It
|
mirroring it to a remote destination using TZSP or ERSPAN encapsulation.
|
||||||
leverages the libpcap library for packet capture and provides options
|
It leverages the libpcap library for packet capture and provides options
|
||||||
for filtering traffic based on BPF syntax. This tool is useful for
|
for filtering traffic based on BPF syntax. This tool is useful for
|
||||||
network monitoring, intrusion detection, and remote packet analysis.
|
network monitoring, intrusion detection, and remote packet analysis.
|
||||||
165
main.c
165
main.c
@@ -38,6 +38,19 @@ struct tzsp_tagged {
|
|||||||
unsigned char type; // Tag type
|
unsigned char type; // Tag type
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// GRE Header Structure
|
||||||
|
struct gre_header {
|
||||||
|
uint16_t flags; // GRE flags
|
||||||
|
uint16_t protocol; // Protocol type (0x88BE for ERSPAN)
|
||||||
|
};
|
||||||
|
|
||||||
|
// ERSPAN Header Structure
|
||||||
|
// ERSPAN Type II Header Structure
|
||||||
|
struct erspan_header {
|
||||||
|
uint32_t ver_vlan_cos_en_t_session; // Ver (4 bits), VLAN (12 bits), COS (3 bits), En (1 bit), T (1 bit), Session ID (10 bits)
|
||||||
|
uint32_t reserved_index; // Reserved (12 bits), Index (20 bits)
|
||||||
|
};
|
||||||
|
|
||||||
// Add this structure for ARP header parsing
|
// Add this structure for ARP header parsing
|
||||||
struct arp_header {
|
struct arp_header {
|
||||||
uint16_t htype; // Hardware type
|
uint16_t htype; // Hardware type
|
||||||
@@ -51,12 +64,6 @@ struct arp_header {
|
|||||||
uint8_t tpa[4]; // Target protocol address
|
uint8_t tpa[4]; // Target protocol address
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to check if the system is little-endian
|
|
||||||
int is_little_endian() {
|
|
||||||
volatile unsigned int i=0x01234567;
|
|
||||||
return (((unsigned char*)&i)[0] == 0x67);
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_interfaces() {
|
void list_interfaces() {
|
||||||
pcap_if_t *alldevs;
|
pcap_if_t *alldevs;
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
@@ -119,6 +126,9 @@ void print_usage(const char *program_name) {
|
|||||||
printf(" -f <filter> Specify the capture filter (BPF syntax)\n");
|
printf(" -f <filter> Specify the capture filter (BPF syntax)\n");
|
||||||
printf(" -r <host/ipv4/ipv6> Specify the destination host (required)\n");
|
printf(" -r <host/ipv4/ipv6> Specify the destination host (required)\n");
|
||||||
printf(" -p <port> Specify the destination port (default: %d)\n", DEFAULT_DEST_PORT);
|
printf(" -p <port> Specify the destination port (default: %d)\n", DEFAULT_DEST_PORT);
|
||||||
|
printf(" -e Use ERSPAN encapsulation (default: TZSP)\n");
|
||||||
|
printf(" -s <source_ip> Specify the source IP address (required for ERSPAN)\n");
|
||||||
|
printf(" -S <session_id> Specify the session ID (default: 42, must be between 0 and 1023)\n");
|
||||||
printf(" -4 Force IPv4 host lookup\n");
|
printf(" -4 Force IPv4 host lookup\n");
|
||||||
printf(" -6 Force IPv6 host lookup\n");
|
printf(" -6 Force IPv6 host lookup\n");
|
||||||
printf(" -l List available network interfaces\n");
|
printf(" -l List available network interfaces\n");
|
||||||
@@ -145,6 +155,10 @@ int main(int argc, char *argv[]) {
|
|||||||
int count_packets = 0; // Flag for counting packets
|
int count_packets = 0; // Flag for counting packets
|
||||||
unsigned long long int packet_count = 0; // Counter for matching packets (64bit)
|
unsigned long long int packet_count = 0; // Counter for matching packets (64bit)
|
||||||
|
|
||||||
|
int use_erspan = 0; // Flag for ERSPAN encapsulation
|
||||||
|
char *source_address = NULL; // Source IP address, default is NULL
|
||||||
|
uint32_t session_id = 42; // Session ID (10 bits)
|
||||||
|
|
||||||
// Socket variables
|
// Socket variables
|
||||||
int sockfd;
|
int sockfd;
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints, *res;
|
||||||
@@ -185,6 +199,18 @@ int main(int argc, char *argv[]) {
|
|||||||
} else if (strcmp(argv[i], "-c") == 0) {
|
} else if (strcmp(argv[i], "-c") == 0) {
|
||||||
count_packets = 1; // Enable packet counting
|
count_packets = 1; // Enable packet counting
|
||||||
verbose = 0; // Disable verbose mode if -c is set
|
verbose = 0; // Disable verbose mode if -c is set
|
||||||
|
} else if (strcmp(argv[i], "-e") == 0) {
|
||||||
|
use_erspan = 1; // Enable ERSPAN encapsulation
|
||||||
|
} else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) {
|
||||||
|
source_address = argv[i + 1]; // Set source IP from command line
|
||||||
|
i++; // Skip the source IP value
|
||||||
|
} else if (strcmp(argv[i], "-S") == 0 && i + 1 < argc) {
|
||||||
|
session_id = atoi(argv[i + 1]); // Set session ID from command line
|
||||||
|
if (session_id > 1023) { // Validate session ID (must fit in 10 bits)
|
||||||
|
fprintf(stderr, "Error: Session ID must be between 0 and 1023.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
i++; // Skip the session ID value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +232,12 @@ int main(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the interface is specified
|
||||||
|
if (dev_name == NULL) {
|
||||||
|
fprintf(stderr, "Error: Interface must be specified\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve the destination address
|
// Resolve the destination address
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
|
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
|
||||||
@@ -233,13 +265,32 @@ int main(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create UDP socket
|
if (use_erspan) {
|
||||||
|
// Create a raw socket for ERSPAN
|
||||||
|
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_GRE);
|
||||||
|
if (sockfd == -1) {
|
||||||
|
perror("socket");
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the IP_HDRINCL option to include the IP header in the packet
|
||||||
|
int optval = 1;
|
||||||
|
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) {
|
||||||
|
perror("setsockopt");
|
||||||
|
close(sockfd);
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create a UDP socket for TZSP
|
||||||
sockfd = socket(res->ai_family, SOCK_DGRAM, 0);
|
sockfd = socket(res->ai_family, SOCK_DGRAM, 0);
|
||||||
if (sockfd == -1) {
|
if (sockfd == -1) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memset(&dest_addr, 0, sizeof(dest_addr));
|
memset(&dest_addr, 0, sizeof(dest_addr));
|
||||||
|
|
||||||
@@ -308,6 +359,7 @@ int main(int argc, char *argv[]) {
|
|||||||
struct ip6_hdr *ip6_header; // Declare ip6_header
|
struct ip6_hdr *ip6_header; // Declare ip6_header
|
||||||
int ip_protocol = 0;
|
int ip_protocol = 0;
|
||||||
struct timeval current_time, last_count;
|
struct timeval current_time, last_count;
|
||||||
|
static uint32_t sequence_number = 0; // Sequence number for ERSPAN packets
|
||||||
|
|
||||||
gettimeofday(&last_count, NULL);
|
gettimeofday(&last_count, NULL);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -394,6 +446,104 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encapsulation logic
|
||||||
|
if (use_erspan) {
|
||||||
|
// ERSPAN Encapsulation
|
||||||
|
struct ip ip_header;
|
||||||
|
struct gre_header gre;
|
||||||
|
struct erspan_header erspan;
|
||||||
|
|
||||||
|
// Set IP header fields
|
||||||
|
memset(&ip_header, 0, sizeof(ip_header));
|
||||||
|
ip_header.ip_hl = 5; // Header length (5 * 4 = 20 bytes)
|
||||||
|
ip_header.ip_v = 4; // IPv4
|
||||||
|
ip_header.ip_tos = 0; // Type of Service
|
||||||
|
ip_header.ip_len = htons(sizeof(ip_header) + sizeof(gre) + sizeof(sequence_number) + sizeof(erspan) + header.caplen);
|
||||||
|
ip_header.ip_id = htons(0); // Identification
|
||||||
|
ip_header.ip_off = 0; // Fragment offset
|
||||||
|
ip_header.ip_ttl = 64; // Time to live
|
||||||
|
ip_header.ip_p = IPPROTO_GRE; // Protocol (GRE)
|
||||||
|
ip_header.ip_dst.s_addr = ((struct sockaddr_in *)&dest_addr)->sin_addr.s_addr;
|
||||||
|
|
||||||
|
if (source_address != NULL) {
|
||||||
|
if (inet_pton(AF_INET, source_address, &(ip_header.ip_src)) != 1) {
|
||||||
|
fprintf(stderr, "Error: Invalid source IP address '%s'\n", source_address);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ip_header.ip_src.s_addr = inet_addr("192.168.1.1"); // Default source IP
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_header.ip_src.s_addr = inet_addr("192.168.1.1"); // Replace with your source IP
|
||||||
|
|
||||||
|
// Set GRE header fields
|
||||||
|
gre.flags = htons(0x1000); // GRE flags (S bit set for Sequence Number Present)
|
||||||
|
gre.protocol = htons(0x88BE); // ERSPAN protocol type
|
||||||
|
|
||||||
|
// Set ERSPAN header fields
|
||||||
|
uint32_t version = 1; // Version (4 bits)
|
||||||
|
uint32_t vlan = 100; // VLAN ID (12 bits)
|
||||||
|
uint32_t cos = 5; // Class of Service (3 bits)
|
||||||
|
uint32_t en = 0; // Trunk Encapsulation Type (2 bit)
|
||||||
|
uint32_t t = 1; // Truncated (1 bit)
|
||||||
|
|
||||||
|
// Combine fields into the 32-bit ver_vlan_cos_en_t_session field
|
||||||
|
erspan.ver_vlan_cos_en_t_session =
|
||||||
|
((version & 0xF) << 28) | // Version (4 bits, shifted to bits 28-31)
|
||||||
|
((vlan & 0xFFF) << 16) | // VLAN ID (12 bits, shifted to bits 16-27)
|
||||||
|
((cos & 0x7) << 13) | // Class of Service (3 bits, shifted to bits 13-15)
|
||||||
|
((en & 0x3) << 11) | // Trunk Encapsulation Type (2 bit, bit 12)
|
||||||
|
((t & 0x1) << 10) | // Truncated (1 bit, bit 11)
|
||||||
|
(session_id & 0x3FF); // Session ID (10 bits, bits 0-9)
|
||||||
|
|
||||||
|
// Convert to network byte order
|
||||||
|
erspan.ver_vlan_cos_en_t_session = htonl(erspan.ver_vlan_cos_en_t_session);
|
||||||
|
|
||||||
|
// Set the reserved and index fields
|
||||||
|
uint32_t reserved = 0; // Reserved (12 bits)
|
||||||
|
uint32_t index = 12345; // Index (20 bits)
|
||||||
|
|
||||||
|
// Combine fields into the 32-bit reserved_index field
|
||||||
|
erspan.reserved_index =
|
||||||
|
((reserved & 0xFFF) << 20) | // Reserved (12 bits, bits 20-31)
|
||||||
|
(index & 0xFFFFF); // Index (20 bits, bits 0-19)
|
||||||
|
|
||||||
|
// Convert to network byte order
|
||||||
|
erspan.reserved_index = htonl(erspan.reserved_index);
|
||||||
|
|
||||||
|
// Calculate total length
|
||||||
|
unsigned short total_length = sizeof(ip_header) + sizeof(gre) + sizeof(sequence_number) + sizeof(erspan) + header.caplen;
|
||||||
|
|
||||||
|
// Allocate memory for ERSPAN packet
|
||||||
|
unsigned char *erspan_packet = (unsigned char *)malloc(total_length);
|
||||||
|
if (erspan_packet == NULL) {
|
||||||
|
perror("malloc");
|
||||||
|
continue; // Skip this packet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy IP header, GRE header, sequence number, ERSPAN header, and packet data into the new buffer
|
||||||
|
unsigned char *ptr = erspan_packet;
|
||||||
|
memcpy(ptr, &ip_header, sizeof(ip_header));
|
||||||
|
ptr += sizeof(ip_header);
|
||||||
|
memcpy(ptr, &gre, sizeof(gre));
|
||||||
|
ptr += sizeof(gre);
|
||||||
|
uint32_t seq_num_network_order = htonl(sequence_number++);
|
||||||
|
memcpy(ptr, &seq_num_network_order, sizeof(sequence_number));
|
||||||
|
ptr += sizeof(sequence_number);
|
||||||
|
memcpy(ptr, &erspan, sizeof(erspan));
|
||||||
|
ptr += sizeof(erspan);
|
||||||
|
memcpy(ptr, packet, header.caplen);
|
||||||
|
|
||||||
|
// Send packet via raw socket
|
||||||
|
if (sendto(sockfd, erspan_packet, total_length, 0, (struct sockaddr *)&dest_addr, dest_addr_size) == -1) {
|
||||||
|
perror("sendto");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(erspan_packet); // Free allocated memory
|
||||||
|
printf("Sent ERSPAN packet with sequence number: %u\n", sequence_number - 1);
|
||||||
|
} else {
|
||||||
|
// TZSP Encapsulation
|
||||||
|
|
||||||
// Create TZSP Header
|
// Create TZSP Header
|
||||||
struct tzsp_header tzsp;
|
struct tzsp_header tzsp;
|
||||||
tzsp.version = 1; // TZSP Version 1
|
tzsp.version = 1; // TZSP Version 1
|
||||||
@@ -430,6 +580,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
free(tzsp_packet); // Free allocated memory
|
free(tzsp_packet); // Free allocated memory
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pcap_freecode(&fp);
|
pcap_freecode(&fp);
|
||||||
pcap_close(handle);
|
pcap_close(handle);
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ Specify the destination host (required).
|
|||||||
.B \-p \fIport\fR
|
.B \-p \fIport\fR
|
||||||
Specify the destination port (default: 37008).
|
Specify the destination port (default: 37008).
|
||||||
.TP
|
.TP
|
||||||
|
.B \-e
|
||||||
|
Use ERSPAN encapsulation.
|
||||||
|
.TP
|
||||||
|
.B \-s \fIsource_ip\fR
|
||||||
|
Specify the source IP address (required for ERSPAN).
|
||||||
|
.TP
|
||||||
|
.B \-S \fIsession_id\fR
|
||||||
|
Specify the session ID (default: 42, must be between 0 and 1023)
|
||||||
|
.TP
|
||||||
.B \-4
|
.B \-4
|
||||||
Force IPv4 host lookup.
|
Force IPv4 host lookup.
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Name: pcapmirror
|
Name: pcapmirror
|
||||||
Version: 0.5
|
Version: 0.6
|
||||||
Release: %(perl -e 'print time()')%{?dist}
|
Release: %(perl -e 'print time()')%{?dist}
|
||||||
Summary: A simple packet capture mirror
|
Summary: A simple packet capture mirror
|
||||||
License: BSD 3-Clause License
|
License: BSD 3-Clause License
|
||||||
@@ -10,7 +10,7 @@ BuildRequires: make
|
|||||||
BuildRequires: libpcap-devel
|
BuildRequires: libpcap-devel
|
||||||
|
|
||||||
%description
|
%description
|
||||||
pcapmirror is a command-line tool for capturing and mirroring network traffic using TZSP encapsulation. It leverages the `libpcap` library for packet capture and supports BPF syntax for filtering traffic.
|
pcapmirror is a command-line tool for capturing and mirroring network traffic using TZSP or ERSPAN encapsulation. It leverages the `libpcap` library for packet capture and supports BPF syntax for filtering traffic.
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%make_build
|
%make_build
|
||||||
@@ -26,7 +26,11 @@ pcapmirror is a command-line tool for capturing and mirroring network traffic us
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Sat Mar 29 2025 Matthias Cramer <cramer@freesone.net> 0.5-1
|
* Sun Apr 20 2025 Matthias Cramer <cramer@freestone.net> 0.6-1
|
||||||
|
- Erspan Encapsulation support
|
||||||
|
- added option -e to set the encapsulation type
|
||||||
|
- added option -S to set ERSPAN session id
|
||||||
|
* Sat Mar 29 2025 Matthias Cramer <cramer@freestone.net> 0.5-1
|
||||||
- new option -c to count matching packets (overrides verbose mode)
|
- new option -c to count matching packets (overrides verbose mode)
|
||||||
- reworked packet decoder to also decode arp, vlan and qinq packets
|
- reworked packet decoder to also decode arp, vlan and qinq packets
|
||||||
- well known protocols numbers are now decoded
|
- well known protocols numbers are now decoded
|
||||||
|
|||||||
Reference in New Issue
Block a user