From 6b23f39fce620c74841772149af654b9bbf5b24e Mon Sep 17 00:00:00 2001 From: mozillazg Date: Sat, 26 Oct 2024 07:07:20 +0000 Subject: [PATCH 1/3] feat(docker): support running with docker --- .github/workflows/docker-latest-image.yml | 103 +++++++++++++++++++++ .github/workflows/release-docker-image.yml | 80 ++++++++++++++++ Dockerfile | 9 ++ Makefile | 7 +- README.md | 32 +++++-- README.zh-CN.md | 31 +++++-- testdata/run_with_docker.sh | 13 +++ testdata/test_run_with_docker.sh | 47 ++++++++++ 8 files changed, 301 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/docker-latest-image.yml create mode 100644 .github/workflows/release-docker-image.yml create mode 100644 Dockerfile create mode 100644 testdata/run_with_docker.sh create mode 100644 testdata/test_run_with_docker.sh diff --git a/.github/workflows/docker-latest-image.yml b/.github/workflows/docker-latest-image.yml new file mode 100644 index 00000000..6bde4676 --- /dev/null +++ b/.github/workflows/docker-latest-image.yml @@ -0,0 +1,103 @@ +name: docker-latest-image + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + workflow_dispatch: + push: + branches: + - 'master' + - 'docker-image' + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: quay.io + # github.repository as / + IMAGE_NAME: 'ptcpdump/ptcpdump' + + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + with: + fetch-depth: '100' + fetch-tags: 'true' + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 + with: + platforms: linux/amd64,linux/arm64 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.QUAY_USER }} + password: ${{ secrets.QUAY_PASSWD }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: generate tag name + run: | + echo "TAG_NAME=$(git describe --always)" >> $GITHUB_ENV + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image (no latest tag) + id: build-and-push + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + # platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG_NAME }}' + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: test image + run: | + set -xe + + IMAGE='${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG_NAME }}' + bash testdata/test_run_with_docker.sh ${IMAGE} + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image (latest tag) + id: build-and-push-latest + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + # platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest' + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/release-docker-image.yml b/.github/workflows/release-docker-image.yml new file mode 100644 index 00000000..d2dfe1cd --- /dev/null +++ b/.github/workflows/release-docker-image.yml @@ -0,0 +1,80 @@ +name: docker-latest-image + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + workflow_dispatch: + push: + tags: + - v* + + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: quay.io + # github.repository as / + IMAGE_NAME: 'ptcpdump/ptcpdump' + + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + with: + fetch-depth: '100' + fetch-tags: 'true' + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 + with: + platforms: linux/amd64,linux/arm64 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.QUAY_USER }} + password: ${{ secrets.QUAY_PASSWD }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: generate tag name + run: | + echo TAG_NAME=${{ github.ref }} | sed 's/=v/=/' >> $GITHUB_ENV + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + # platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG_NAME }}' + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..045d05de --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +# .github/build.Dockerfile +FROM quay.io/ptcpdump/develop:latest as build +WORKDIR /app +COPY . . +RUN make build + +FROM busybox:latest +WORKDIR /ptcpdump +COPY --from=build /app/ptcpdump /usr/local/bin/ diff --git a/Makefile b/Makefile index 61946fa3..8e678352 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,8 @@ CARCH ?= $(shell uname -m) LIBPCAP_ARCH = $(CARCH)-unknown-linux-gnu LIBPCAP_CC ?= gcc -IMAGE_BUILD ?= quay.io/ptcpdump/develop:latest +IMAGE_DEV ?= quay.io/ptcpdump/develop:latest +IMAGE_BIN ?= quay.io/ptcpdump/ptcpdump:latest .PHONY: libpcap libpcap: $(LIBPCAP_OBJ) @@ -76,12 +77,12 @@ build-bpf: .PHONY: build-bpf-via-docker build-bpf-via-docker: - docker run --rm -v `pwd`:/app quay.io/ptcpdump/develop:latest make build-bpf + docker run --rm -v `pwd`:/app $(IMAGE_DEV) make build-bpf .PHONY: build-via-docker build-via-docker: - docker run --rm -v `pwd`:/app quay.io/ptcpdump/develop:latest make build + docker run --rm -v `pwd`:/app $(IMAGE_DEV) make build .PHONY: lint diff --git a/README.md b/README.md index cde4fab6..3d035987 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,16 @@ Table of Contents * [Features](#features) * [Installation](#installation) - * [Requirements](#requirements) + * [Requirements](#requirements) * [Usage](#usage) - * [Example commands](#example-commands) - * [Example output](#example-output) - * [Flags](#flags) + * [Example commands](#example-commands) + * [Example output](#example-output) + * [Running with Docker](#running-with-docker) + * [Flags](#flags) * [Compare with tcpdump](#compare-with-tcpdump) * [Developing](#developing) - * [Dependencies](#dependencies) - * [Building](#building) + * [Dependencies](#dependencies) + * [Building](#building) ## Features @@ -60,9 +61,10 @@ Linux kernel version >= 5.2. ### Example commands Filter like tcpdump: + ``` sudo ptcpdump -i eth0 tcp -sudo ptcpdump -i eth0 -A -v tcp and port 80 and host 10.10.1.1 +sudo ptcpdump -i eth0 -A -s 0 -n -v tcp and port 80 and host 10.10.1.1 sudo ptcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' ``` @@ -145,7 +147,7 @@ Accept: */* With `-x`: ``` -14:44:34.457504 ens33 curl.205562 IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] +14:44:34.457504 ens33 curl.205562 Out IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] 0x0000: 4500 0072 de2c 4000 4006 6fbf 0a00 020f 0x0010: 8bb2 54d9 9c30 0050 a245 a0fc 352b 6707 0x0020: 5018 faf0 ecfe 0000 4745 5420 2f20 4854 @@ -159,7 +161,7 @@ With `-x`: With `-X`: ``` -14:44:34.457504 ens33 curl.205562 IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] +14:44:34.457504 ens33 curl.205562 Out IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] 0x0000: 4500 0072 de2c 4000 4006 6fbf 0a00 020f E..r.,@.@.o..... 0x0010: 8bb2 54d9 9c30 0050 a245 a0fc 352b 6707 ..T..0.P.E..5+g. 0x0020: 5018 faf0 ecfe 0000 4745 5420 2f20 4854 P.......GET / HT @@ -174,6 +176,18 @@ With `-X`:

๐Ÿ”

+### Running with Docker + +Docker images for `ptcpdump` are published at https://quay.io/repository/ptcpdump/ptcpdump. + +``` +docker run --privileged --rm -t --net=host --pid=host \ + quay.io/ptcpdump/ptcpdump:latest ptcpdump -i any -c 2 tcp +``` + +

๐Ÿ”

+ + ### Flags diff --git a/README.zh-CN.md b/README.zh-CN.md index 5df0fa98..7b4a3923 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -20,15 +20,16 @@ Table of Contents * [Features](#features) * [Installation](#installation) - * [Requirements](#requirements) + * [Requirements](#requirements) * [Usage](#usage) - * [Example commands](#example-commands) - * [Example output](#example-output) - * [Flags](#flags) + * [Example commands](#example-commands) + * [Example output](#example-output) + * [Running with Docker](#running-with-docker) + * [Flags](#flags) * [Compare with tcpdump](#compare-with-tcpdump) * [Developing](#developing) - * [Dependencies](#dependencies) - * [Building](#building) + * [Dependencies](#dependencies) + * [Building](#building) ## Features @@ -71,7 +72,7 @@ Table of Contents ``` sudo ptcpdump -i eth0 tcp -sudo ptcpdump -i eth0 -A -v tcp and port 80 and host 10.10.1.1 +sudo ptcpdump -i eth0 -A -s 0 -n -v tcp and port 80 and host 10.10.1.1 sudo ptcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' ``` @@ -154,7 +155,7 @@ Accept: */* ้€š่ฟ‡ `-x` ๅ‚ๆ•ฐไปฅ 16 ่ฟ›ๅˆถๆ ผๅผ่พ“ๅ‡บ: ``` -14:44:34.457504 ens33 curl.205562 IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] +14:44:34.457504 ens33 curl.205562 Out IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] 0x0000: 4500 0072 de2c 4000 4006 6fbf 0a00 020f 0x0010: 8bb2 54d9 9c30 0050 a245 a0fc 352b 6707 0x0020: 5018 faf0 ecfe 0000 4745 5420 2f20 4854 @@ -168,7 +169,7 @@ Accept: */* ้€š่ฟ‡ `-X` ๅ‚ๆ•ฐไปฅ 16 ่ฟ›ๅˆถๅ’Œ ASCII ๆ ผๅผ่พ“ๅ‡บ: ``` -14:44:34.457504 ens33 curl.205562 IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] +14:44:34.457504 ens33 curl.205562 Out IP 10.0.2.15.39984 > 139.178.84.217.80: Flags [P.], seq 2722472188:2722472262, ack 892036871, win 64240, length 74, ParentProc [bash.180205] 0x0000: 4500 0072 de2c 4000 4006 6fbf 0a00 020f E..r.,@.@.o..... 0x0010: 8bb2 54d9 9c30 0050 a245 a0fc 352b 6707 ..T..0.P.E..5+g. 0x0020: 5018 faf0 ecfe 0000 4745 5420 2f20 4854 P.......GET / HT @@ -183,6 +184,18 @@ Accept: */*

๐Ÿ”

+### Running with Docker + +Docker images for `ptcpdump` are published at https://quay.io/repository/ptcpdump/ptcpdump. + +``` +docker run --privileged --rm -t --net=host --pid=host \ + quay.io/ptcpdump/ptcpdump:latest ptcpdump -i any -c 2 tcp +``` + +

๐Ÿ”

+ + ### Flags diff --git a/testdata/run_with_docker.sh b/testdata/run_with_docker.sh new file mode 100644 index 00000000..89909eed --- /dev/null +++ b/testdata/run_with_docker.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -ex + +IMAGE="$1" +TMP=${TMP:-/tmp/} +shift + +docker run --privileged --rm -t --net=host --pid=host \ + -v /sys/kernel/debug/:/sys/kernel/debug/ \ + -v /run/netns/:/run/netns/ \ + -v ${TMP}:/tmp/ \ + -v `pwd`:/ptcpdump "${IMAGE}" ptcpdump $@ diff --git a/testdata/test_run_with_docker.sh b/testdata/test_run_with_docker.sh new file mode 100644 index 00000000..df1278e6 --- /dev/null +++ b/testdata/test_run_with_docker.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -ex + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" + +IMAGE="$1" +CMD="bash ${SCRIPT_DIR}/run_with_docker.sh ${IMAGE}" +FILE_PREFIX="/tmp/ptcpdump" +FNAME="${FILE_PREFIX}_run_with_docker_base.pcapng" +LNAME="${FILE_PREFIX}_run_with_docker_base.log" +RNAME="${FILE_PREFIX}_run_with_docker_base.read.txt" +export TMP="/tmp/" + + +function test_ptcpdump() { + timeout 30s ${CMD} -c 1 -v -i any --print -w "${FNAME}" \ + 'dst host 1.1.1.1 and tcp[tcpflags] = tcp-syn' | tee "${LNAME}" & + sleep 10 + curl -m 10 1.1.1.1 &>/dev/null || true + wait + + cat "${LNAME}" + cat "${LNAME}" | grep '/usr/bin/curl' + cat "${LNAME}" | grep -F ' > 1.1.1.1.80: Flags [S],' # SYN +} + +function test_tcpdump_read() { + which tcpdump || (apt update || true && apt install -y tcpdump) + tcpdump -nr "${FNAME}" + tcpdump -nr "${FNAME}" | grep -F ' > 1.1.1.1.80: Flags [S],' # SYN +} + +function test_ptcpdump_read() { + EXPECT_NAME="${LNAME}.read.expect" + cat "${LNAME}" |grep -v packets |grep -v WARN > "${EXPECT_NAME}" + timeout 30s ${CMD} -v -r "${FNAME}" |tee "${RNAME}" + diff "${EXPECT_NAME}" "${RNAME}" +} + +function main() { + test_ptcpdump + test_tcpdump_read + test_ptcpdump_read +} + +main From 2ec8274e7d6e1d9de757a2aa53ae03cbc07cc8de Mon Sep 17 00:00:00 2001 From: mozillazg Date: Sun, 27 Oct 2024 01:45:48 +0000 Subject: [PATCH 2/3] fix missing mount cgroup v2 root dir --- .github/workflows/test.yml | 6 ++++++ README.md | 1 + README.zh-CN.md | 1 + internal/utils/cgroup.go | 15 +++++++++++++-- testdata/run_with_docker.sh | 4 ++-- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 91194f42..7fb19dd9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,6 +34,12 @@ jobs: name: ptcpdump path: ptcpdump + run-with-docker: + runs-on: ubuntu-latest + steps: + - name: test running with docker + run: | + bash testdata/test_run_with_docker.sh "quay.io/ptcpdump/ptcpdump:latest" e2e-test: name: e2e-test diff --git a/README.md b/README.md index 3d035987..a679b2ee 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,7 @@ Docker images for `ptcpdump` are published at https://quay.io/repository/ptcpdum ``` docker run --privileged --rm -t --net=host --pid=host \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ quay.io/ptcpdump/ptcpdump:latest ptcpdump -i any -c 2 tcp ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 7b4a3923..51b84b65 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -190,6 +190,7 @@ Docker images for `ptcpdump` are published at https://quay.io/repository/ptcpdum ``` docker run --privileged --rm -t --net=host --pid=host \ + -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ quay.io/ptcpdump/ptcpdump:latest ptcpdump -i any -c 2 tcp ``` diff --git a/internal/utils/cgroup.go b/internal/utils/cgroup.go index fd516114..dcdbb941 100644 --- a/internal/utils/cgroup.go +++ b/internal/utils/cgroup.go @@ -7,11 +7,22 @@ import ( "regexp" ) -var PathProcMounts = "/proc/mounts" +const ( + pathProcMounts = "/proc/mounts" + defaultCgroupV2RootDir = "/sys/fs/cgroup" +) + var reCgroup2Mount = regexp.MustCompile(`(?m)^cgroup2\s(/\S+)\scgroup2\s`) func GetCgroupV2RootDir() (string, error) { - return getCgroupV2RootDir(PathProcMounts) + p, err := getCgroupV2RootDir(pathProcMounts) + if err != nil { + st, errv2 := os.Stat(defaultCgroupV2RootDir) + if errv2 == nil && st.IsDir() { + return defaultCgroupV2RootDir, nil + } + } + return p, err } func getCgroupV2RootDir(pathProcMounts string) (string, error) { diff --git a/testdata/run_with_docker.sh b/testdata/run_with_docker.sh index 89909eed..923e5a1e 100644 --- a/testdata/run_with_docker.sh +++ b/testdata/run_with_docker.sh @@ -7,7 +7,7 @@ TMP=${TMP:-/tmp/} shift docker run --privileged --rm -t --net=host --pid=host \ - -v /sys/kernel/debug/:/sys/kernel/debug/ \ - -v /run/netns/:/run/netns/ \ + -v /sys/fs/cgroup/:/sys/fs/cgroup/:ro \ + -v /run/netns/:/run/netns/:ro \ -v ${TMP}:/tmp/ \ -v `pwd`:/ptcpdump "${IMAGE}" ptcpdump $@ From 7d1c564fdef1623a175d176a233adef1d61f60f4 Mon Sep 17 00:00:00 2001 From: mozillazg Date: Sun, 27 Oct 2024 02:34:37 +0000 Subject: [PATCH 3/3] fix ci --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7fb19dd9..22a78f19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,6 +37,8 @@ jobs: run-with-docker: runs-on: ubuntu-latest steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + - name: test running with docker run: | bash testdata/test_run_with_docker.sh "quay.io/ptcpdump/ptcpdump:latest"