udpconnect

@amitmund September 11, 2026

Linux udpconnect — Complete Learning Notes & Output Guide

udpconnect is an eBPF-powered tracing utility (commonly implemented via bpftrace or custom BCC/libbpf scripts) that intercepts the connect() system call invoked on datagram (UDP) sockets. It logs process identities, timestamps, and endpoint pairs whenever an application binds a UDP socket to a remote destination.


1. What is udpconnect?

Unlike TCP—which is connection-oriented and features a mandatory 3-way handshake (SYN, SYN-ACK, ACK) managed by a complex state machine—UDP is inherently connectionless.

However, Linux applications frequently call the standard connect() system call on UDP sockets (SOCK_DGRAM). Calling connect() on a UDP socket does not send any packets across the network; instead, it instructs the kernel network stack to cache a default destination IP address and port so the application can use standard send() and read() system calls instead of repeatedly specifying destination arguments with sendto().

udpconnect instruments this system call specifically for datagram sockets. It answers critical network diagnostic questions:

  • Which applications or system daemons are initiating UDP connections?
  • Where are DNS queries, NTP time syncs, syslog packets, or metrics payloads being directed?
  • Are applications dynamically shifting their UDP target endpoints, or are they locked to a single upstream server?

2. Implementation Context: BCC vs. bpftrace

While the BCC toolkit provides dedicated compiled tools like tcpconnect for TCP sockets, a dedicated compiled binary named udpconnect is often implemented as a lightweight bpftrace script or a customized libbpf program because UDP connection tracking requires filtering socket types (SOCK_DGRAM).

Standard bpftrace One-Liner Equivalent to udpconnect:

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_connect 
/args->uservaddr->sa_family == AF_INET/ 
{
    // Check if socket is UDP (SOCK_DGRAM)
    // and print PID, COMM, and destination IP/Port
    time("%H:%M:%S ");
    printf("%-6d %-16s %-15s -> \n", pid, comm,, daddr);
}
'


3. Basic Syntax & Output Structure

When running a standard UDP connection tracer (udpconnect or its equivalent bpftrace script):

sudo udpconnect

Raw Output Example

TIME     PID    COMM             LADDR:LPORT           RADDR:RPORT
07:35:01 1420   systemd-resolve  127.0.0.53:41202  ->  127.0.0.53:53
07:35:05 8912   chronyd          192.168.1.50:32410 ->  169.254.169.123:123
07:35:12 4515   python3          192.168.1.50:58102 ->  8.8.8.8:53
07:35:20 2104   rsyslogd         192.168.1.50:49210 ->  10.0.0.100:514


4. Breakdown of Every Output Heading & Field

+----------+-------+------------------+---------------------+---------------------+
| TIME     | PID   | COMM             | Local Endpoint      | Remote Endpoint     |
+----------+-------+------------------+---------------------+---------------------+
| 07:35:01 | 1420  | systemd-resolve  | 127.0.0.53:41202    | -> 127.0.0.53:53    |
+----------+-------+------------------+---------------------+---------------------+

4.1 TIME

  • Format: HH:MM:SS (wall-clock time).
  • Meaning: The exact moment the application invoked the connect() system call on a UDP socket.

4.2 PID

  • Format: Numeric integer (e.g., 1420, 8912).
  • Meaning: The Process ID of the task that initiated the UDP connection mapping.

4.3 COMM

  • Format: String (e.g., systemd-resolve, chronyd, python3, rsyslogd).
  • Meaning: The short executable command name of the process (first 16 characters of task_struct->comm).

4.4 Local Endpoint (LADDR:LPORT)

  • Format: <IP_Address>:<Port>
  • Meaning: The local host IP address and source/ephemeral port bound to the datagram socket.

4.5 Remote Endpoint (RADDR:RPORT)

  • Format: -> <Remote_IP>:<Port>
  • Meaning: The target destination IP address and port cached by the kernel for subsequent datagram transmissions.

5. How UDP Connection Tracing Works Internally

+-------------------------------------------------------------------------+
|                              KERNEL SPACE                               |
|                                                                         |
|   1. System Call Entry:                                                 |
|      - Hooks: sys_enter_connect (or inet_dgram_connect)                 |
|                                                                         |
|   2. Socket Type & Family Filtering:                                    |
|      - Validates sa_family == AF_INET / AF_INET6                        |
|      - Checks socket type to ensure SOCK_DGRAM (UDP), filtering         |
|        out SOCK_STREAM (TCP).                                           |
|                                                                         |
|   3. Data Extraction:                                                   |
|      - Reads user-space sockaddr struct passed to connect().            |
|      - Extracts destination IP and Port.                                |
|                                                                         |
|   4. Event Transmission:                                                |
|      - Emits event record through BPF Perf/Ring Buffer to user space.   |
+-------------------------------------------------------------------------+
                                    |
                                    v (Ring Buffer)
+-------------------------------------------------------------------------+
|                              USER SPACE                                 |
|   CLI Tool: Formats and prints PID, command name, and endpoints.        |
+-------------------------------------------------------------------------+


6. Real-World Troubleshooting Scenarios

Scenario A: Auditing Rogue DNS Resolvers or Hardcoded IPs

An internal microservice is leaking DNS queries to public resolvers instead of the local cluster nameserver.

Run udpconnect filtering for port 53 (DNS):

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_connect 
/args->uservaddr->sa_family == AF_INET/ 
{
    // Extract port from sockaddr_in
    $sa = (struct sockaddr_in *)args->uservaddr;
    if ($sa->sin_port == 13312) { // htons(53) = 13312 or check port directly
        time("%H:%M:%S ");
        printf("PID:%-6d COMM:%-16s Target IP\n", pid, comm);
    }
}
'

Diagnosis: Instantly exposes which application PIDs are bypassing local DNS configurations and connecting directly to external IPs.


Scenario B: Debugging Syslog or Metrics Forwarding Failures

A monitoring agent fails to report metrics to a remote collector.

Monitor UDP connection attempts:

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_connect 
{
    time("%H:%M:%S ");
    printf("PID:%-6d COMM:%-16s\n", pid, comm);
}
'

Diagnosis: Verifies whether the monitoring agent is actively executing connect() toward the target metrics collector port, ruling out local application failure before inspecting upstream network firewalls.


7. Important Interview Questions & Answers

Q: If UDP is connectionless, what does the connect() system call actually accomplish on a UDP socket?

Answer: Calling connect() on a UDP socket does not transmit any packets or perform a handshake across the network. Instead, it performs two local kernel operations:

  1. It registers the remote peer's IP address and port inside the socket structure (struct sock), allowing the application to use send() and recv() instead of sendto() and recvfrom().
  2. It enables asynchronous ICMP error reporting. Unconnected UDP sockets do not receive ICMP "Destination Unreachable" errors generated by intermediate routers; connecting the socket allows the kernel to receive and surface these errors to the application.

Q: Why is tracing UDP connections via connect() insufficient if an application uses sendto() exclusively?

Answer: Applications like high-frequency DNS clients, NTP daemons, or custom packet generators often avoid calling connect() entirely, opting instead to call sendto() directly for every outgoing packet by supplying destination addresses inline. Because sendto() does not invoke the connect() system call, tracing tools like udpconnect will not capture those datagram transmissions. To trace un-connected UDP traffic comprehensively, kernel network tracepoints like udp_sendmsg must be instrumented instead.


0 Likes
2 Views
0 Comments

Filters

No filters available for this view.

Reset All