Skip to content

Commit

Permalink
Fix cannot translate peer address in some UDP scenarios (#134)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrproliu authored Jul 30, 2024
1 parent a916a69 commit 89b8b62
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Release Notes.
* Fixed `ip_list_rcv` probe is not exist in older linux kernel.
* Fix concurrent map operation in the access log module.
* Fix the profiling cannot found process issue.
* Fix cannot translate peer address in some UDP scenarios.

#### Documentation

Expand Down
5 changes: 5 additions & 0 deletions bpf/accesslog/common/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ static __always_inline void submit_new_connection(void* ctx, bool success, __u32
event->success = success;

__u16 port;
event->local_port = 0;
event->remote_port = 0;
if (socket != NULL) {
// only get from accept function(server side)
struct sock* s;
Expand Down Expand Up @@ -247,11 +249,14 @@ static __always_inline void submit_new_connection(void* ctx, bool success, __u32
bpf_probe_read(&event->remote_addr_v4, sizeof(event->remote_addr_v4), &daddr->sin_addr.s_addr);
bpf_probe_read(&port, sizeof(port), &daddr->sin_port);
event->remote_port = bpf_ntohs(port);
// cleanup the local address
event->local_addr_v4 = 0;
} else if (event->socket_family == AF_INET6) {
struct sockaddr_in6 *daddr = (struct sockaddr_in6 *)addr;
bpf_probe_read(&event->remote_addr_v6, sizeof(event->remote_addr_v6), &daddr->sin6_addr.s6_addr);
bpf_probe_read(&port, sizeof(port), &daddr->sin6_port);
event->remote_port = bpf_ntohs(port);
__builtin_memset(&event->local_addr_v6, 0, sizeof(event->local_addr_v6));
}
} else {
event->socket_family = AF_UNKNOWN;
Expand Down
11 changes: 11 additions & 0 deletions bpf/accesslog/syscalls/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,15 @@ int sock_alloc_ret(struct pt_regs *ctx) {
return 0;
}

SEC("kprobe/ip4_datagram_connect")
int ip4_udp_datagram_connect(struct pt_regs *ctx) {
__u64 id = bpf_get_current_pid_tgid();
struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
if (connect_args) {
struct sock *sock = (struct sock*)PT_REGS_PARM1(ctx);
connect_args->sock = sock;
}
return 0;
}

#include "connect_conntrack.c"
5 changes: 5 additions & 0 deletions bpf/accesslog/syscalls/connect_conntrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,8 @@ SEC("kprobe/nf_confirm")
int nf_confirm(struct pt_regs* ctx) {
return nf_conn_aware(ctx, (struct nf_conn*)PT_REGS_PARM3(ctx));
}

SEC("kprobe/ctnetlink_fill_info")
int nf_ctnetlink_fill_info(struct pt_regs* ctx) {
return nf_conn_aware(ctx, (struct nf_conn*)PT_REGS_PARM5(ctx));
}
16 changes: 14 additions & 2 deletions pkg/accesslog/collector/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,18 @@ func (c *ConnectCollector) Start(_ *module.Manager, context *common.AccessLogCon
context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{
"sock_alloc": context.BPF.SockAllocRet,
})

context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{
"ip4_datagram_connect": context.BPF.Ip4UdpDatagramConnect,
})

_ = context.BPF.AddLinkOrError(link.Kprobe, map[string]*ebpf.Program{
"__nf_conntrack_hash_insert": context.BPF.NfConntrackHashInsert,
"nf_confirm": context.BPF.NfConfirm,
})
_ = context.BPF.AddLinkOrError(link.Kprobe, map[string]*ebpf.Program{
"nf_confirm": context.BPF.NfConfirm,
})
_ = context.BPF.AddLinkOrError(link.Kprobe, map[string]*ebpf.Program{
"ctnetlink_fill_info": context.BPF.NfCtnetlinkFillInfo,
})

context.BPF.ReadEventAsync(context.BPF.SocketConnectionEventQueue, func(data interface{}) {
Expand Down Expand Up @@ -127,11 +135,15 @@ func (c *ConnectCollector) buildSocketFromConnectEvent(event *events.SocketConne
}
socketPair := c.buildSocketPair(event)
if socketPair != nil && socketPair.IsValid() {
connectLogger.Debugf("found the connection from the connect event is valid, connection ID: %d, randomID: %d",
event.ConID, event.RandomID)
return socketPair
}
// if only the local port not success, maybe the upstream port is not open, so it could be continued
if c.isOnlyLocalPortEmpty(socketPair) {
event.ConnectSuccess = 0
connectLogger.Debugf("the connection from the connect event is only the local port is empty, connection ID: %d, randomID: %d",
event.ConID, event.RandomID)
return socketPair
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/tools/ip/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
)

func ParseIPV4(bpfVal uint32) string {
if bpfVal == 0 {
return ""
}
return net.IP((*(*[net.IPv4len]byte)(unsafe.Pointer(&bpfVal)))[:]).String()
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/tools/ip/conntrack.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ func (c *ConnTrack) UpdateRealPeerAddress(addr *SocketPair) bool {
}
if res := c.filterValidateReply(dump, tuple); res != nil {
addr.DestIP = res.Src.String()
log.Debugf("found the connection from the dump all conntrack, src: %s:%d, dst: %s:%d, proto number: %d",
tuple.Src, *tuple.Proto.SrcPort, tuple.Dst, *tuple.Proto.DstPort, *tuple.Proto.Number)
return true
}
return false
Expand Down

0 comments on commit 89b8b62

Please sign in to comment.