Skip to content

Commit

Permalink
feat(capture): Automatically capture traffic from/to new interfaces w…
Browse files Browse the repository at this point in the history
…hen using `-i any`, `--netns any` or `--netns newly`

* feat(capture): Automatically capture traffic from/to new interfaces when using `-i any` or `--netns any`

closes #154

* fix legacy kernel raise "not found: no such file or directory"

* fix ci

* add more tests

* fix test

* filter interface and netns when handle interface and netns events
  • Loading branch information
mozillazg authored Oct 13, 2024
1 parent cdd4253 commit c3a5bca
Show file tree
Hide file tree
Showing 42 changed files with 2,615 additions and 791 deletions.
6 changes: 6 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ jobs:
command: |
sudo bash testdata/test_netns.sh ./ptcpdump
- run:
name: e2e (test netns newly)
command: |
sudo bash testdata/test_netns_newly_normal.sh ./ptcpdump
sudo bash testdata/test_netns_newly_exec.sh ./ptcpdump
- run:
name: e2e (test nat)
command: |
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,16 @@ jobs:
set -ex
bash /host/testdata/test_netns.sh /host/ptcpdump/ptcpdump
- name: Test netns newly
# if: ${{ (!startsWith(matrix.kernel, '5.4')) && (!startsWith(matrix.kernel, '4.')) }}
uses: cilium/little-vm-helper@97c89f004bd0ab4caeacfe92ebc956e13e362e6b # v0.0.19
with:
provision: 'false'
cmd: |
set -ex
bash /host/testdata/test_netns_newly_normal.sh /host/ptcpdump/ptcpdump
bash /host/testdata/test_netns_newly_exec.sh /host/ptcpdump/ptcpdump
- name: Test run sub program
uses: cilium/little-vm-helper@97c89f004bd0ab4caeacfe92ebc956e13e362e6b # v0.0.19
with:
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ lint: deps fmt
fmt:
go fmt ./...
clang-format -i bpf/ptcpdump.c
clang-format -i bpf/headers/custom.h
clang-format -i bpf/headers/gotls.h
clang-format -i bpf/*.h
clang-format -i bpf/headers/*.h

.PHONY: vet
vet:
Expand Down
94 changes: 91 additions & 3 deletions bpf/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
)

// $TARGET is set by the Makefile
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -no-strip -target $TARGET -type gconfig_t -type packet_event_t -type exec_event_t -type exit_event_t -type flow_pid_key_t -type process_meta_t -type packet_event_meta_t -type go_keylog_event_t Bpf ./ptcpdump.c -- -I./headers -I./headers/$TARGET -I. -Wall
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -no-strip -target $TARGET -type gconfig_t -type packet_event_t -type exec_event_t -type exit_event_t -type flow_pid_key_t -type process_meta_t -type packet_event_meta_t -type go_keylog_event_t -type new_netdevice_event_t -type netdevice_change_event_t -type mount_event_t Bpf ./ptcpdump.c -- -I./headers -I./headers/$TARGET -I. -Wall

const tcFilterName = "ptcpdump"
const logSzie = ebpf.DefaultVerifierLogSize * 64
Expand Down Expand Up @@ -47,6 +47,8 @@ type Options struct {
pidnsIds []uint32
netnsIds []uint32
maxPayloadSize uint32
hookMount bool
hookNetDev bool
kernelTypes *btf.Spec
}

Expand Down Expand Up @@ -276,6 +278,69 @@ func (b *BPF) AttachKprobes() error {
b.links = append(b.links, lk)
}

if b.opts.hookNetDev {
lk, err = link.Kprobe("register_netdevice",
b.objs.KprobeRegisterNetdevice, &link.KprobeOptions{})
if err != nil {
return fmt.Errorf("attach kprobe/register_netdevice: %w", err)
}
b.links = append(b.links, lk)
lk, err = link.Kretprobe("register_netdevice",
b.objs.KretprobeRegisterNetdevice, &link.KprobeOptions{})
if err != nil {
return fmt.Errorf("attach kretprobe/register_netdevice: %w", err)
}
b.links = append(b.links, lk)
lk, err = link.Kretprobe("__dev_get_by_index",
b.objs.KretprobeDevGetByIndex, &link.KprobeOptions{})
if err != nil {
log.Infof("%+v", err)
// TODO: use errors.Is(xxx) or ==
if strings.Contains(err.Error(), "no such file or directory") {
lk, err = link.Kretprobe("dev_get_by_index",
b.objs.KretprobeDevGetByIndexLegacy, &link.KprobeOptions{})
if err != nil {
return fmt.Errorf("attach kretprobe/dev_get_by_index: %w", err)
}
} else {
return fmt.Errorf("attach kretprobe/__dev_get_by_index: %w", err)
}
}
b.links = append(b.links, lk)
lk, err = link.Kprobe("__dev_change_net_namespace",
b.objs.KprobeDevChangeNetNamespace, &link.KprobeOptions{})
if err != nil {
log.Infof("%+v", err)
// TODO: use errors.Is(xxx) or ==
if strings.Contains(err.Error(), "no such file or directory") {
lk, err = link.Kprobe("dev_change_net_namespace",
b.objs.KprobeDevChangeNetNamespaceLegacy, &link.KprobeOptions{})
if err != nil {
return fmt.Errorf("attach kprobe/dev_change_net_namespace: %w", err)
}
} else {
return fmt.Errorf("attach kprobe/__dev_change_net_namespace: %w", err)
}
}
b.links = append(b.links, lk)
lk, err = link.Kretprobe("__dev_change_net_namespace",
b.objs.KretprobeDevChangeNetNamespace, &link.KprobeOptions{})
if err != nil {
log.Infof("%+v", err)
// TODO: use errors.Is(xxx) or ==
if strings.Contains(err.Error(), "no such file or directory") {
lk, err = link.Kretprobe("dev_change_net_namespace",
b.objs.KretprobeDevChangeNetNamespaceLegacy, &link.KprobeOptions{})
if err != nil {
return fmt.Errorf("attach kretprobe/dev_change_net_namespace: %w", err)
}
} else {
return fmt.Errorf("attach kretprobe/__dev_change_net_namespace: %w", err)
}
}
b.links = append(b.links, lk)
}

return nil
}

Expand Down Expand Up @@ -309,6 +374,19 @@ func (b *BPF) AttachTracepoints() error {
b.links = append(b.links, lk)
}

if b.opts.hookMount {
lk, err = link.Tracepoint("syscalls", "sys_enter_mount", b.objs.TracepointSyscallsSysEnterMount, &link.TracepointOptions{})
if err != nil {
return fmt.Errorf("attach tracepoint/syscalls/sys_enter_mount: %w", err)
}
b.links = append(b.links, lk)
lk, err = link.Tracepoint("syscalls", "sys_exit_mount", b.objs.TracepointSyscallsSysExitMount, &link.TracepointOptions{})
if err != nil {
return fmt.Errorf("attach tracepoint/syscalls/sys_exit_mount: %w", err)
}
b.links = append(b.links, lk)
}

return nil
}

Expand Down Expand Up @@ -386,9 +464,9 @@ func attachTcHook(ifindex int, prog *ebpf.Program, ingress bool) (func(), error)
},
},
}
log.Infof("try to add tc filter with handle %d", hid)
log.Infof("try to add tc filter with handle %d to %d", hid, ifindex)
if err = tcnl.Filter().Add(filter); err != nil {
log.Infof("add tc filter: %s", err)
log.Infof("add tc filter: %+v", err)
if !errors.Is(err, unix.EEXIST) {
return closeFunc, fmt.Errorf("add tc filter: %w", err)
} else {
Expand Down Expand Up @@ -580,6 +658,16 @@ func (opts *Options) WithMaxPayloadSize(n uint32) *Options {
return opts
}

func (opts *Options) WithHookMount(v bool) *Options {
opts.hookMount = v
return opts
}

func (opts *Options) WithHookNetDev(v bool) *Options {
opts.hookNetDev = v
return opts
}

func (opts *Options) WithKernelTypes(spec *btf.Spec) *Options {
opts.kernelTypes = spec
return opts
Expand Down
Loading

0 comments on commit c3a5bca

Please sign in to comment.