.SH NAME
tcpconnect \- Trace TCP active connections (connect()). Uses Linux eBPF/bcc.
.SH SYNOPSIS
-.B tcpconnect [\-h] [\-t] [\-x] [\-p PID]
+.B tcpconnect [\-h] [\-t] [\-x] [\-p PID] [-P PORT]
.SH DESCRIPTION
This tool traces active TCP connections (eg, via a connect() syscall;
accept() are passive connections). This can be useful for general
.TP
\-p PID
Trace this process ID only (filtered in-kernel).
+.TP
+\-P PORT
+Comma-separated list of destination ports to trace (filtered in-kernel).
.SH EXAMPLES
.TP
Trace all active TCP connections:
Trace PID 181 only:
#
.B tcpconnect \-p 181
+.TP
+Trace ports 80 and 81 only:
+#
+.B tcpconnect \-P 80,81
.SH FIELDS
.TP
TIME(s)
# tcpconnect Trace TCP connect()s.
# For Linux, uses BCC, eBPF. Embedded C.
#
-# USAGE: tcpconnect [-h] [-t] [-p PID]
+# USAGE: tcpconnect [-h] [-t] [-p PID] [-P PORT [PORT ...]]
#
# All connection attempts are traced, even if they ultimately fail.
#
from __future__ import print_function
from bcc import BPF
import argparse
-from socket import inet_ntop, AF_INET, AF_INET6
+from socket import inet_ntop, ntohs, AF_INET, AF_INET6
from struct import pack
import ctypes as ct
./tcpconnect # trace all TCP connect()s
./tcpconnect -t # include timestamps
./tcpconnect -p 181 # only trace PID 181
+ ./tcpconnect -P 80 # only trace port 80
+ ./tcpconnect -P 80,81 # only trace port 80 and 81
"""
parser = argparse.ArgumentParser(
description="Trace TCP connects",
help="include timestamp on output")
parser.add_argument("-p", "--pid",
help="trace this PID only")
+parser.add_argument("-P", "--port",
+ help="comma-separated list of destination ports to trace.")
args = parser.parse_args()
debug = 0
int trace_connect_entry(struct pt_regs *ctx, struct sock *sk)
{
u32 pid = bpf_get_current_pid_tgid();
- FILTER
+ FILTER_PID
// stash the sock ptr for lookup on return
currsock.update(&pid, &sk);
u16 dport = 0;
bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);
+ FILTER_PORT
+
if (ipver == 4) {
struct ipv4_data_t data4 = {.pid = pid, .ip = ipver};
data4.ts_us = bpf_ktime_get_ns() / 1000;
# code substitutions
if args.pid:
- bpf_text = bpf_text.replace('FILTER',
+ bpf_text = bpf_text.replace('FILTER_PID',
'if (pid != %s) { return 0; }' % args.pid)
-else:
- bpf_text = bpf_text.replace('FILTER', '')
+if args.port:
+ dports = [int(dport) for dport in args.port.split(',')]
+ dports_if = ' && '.join(['dport != %d' % ntohs(dport) for dport in dports])
+ bpf_text = bpf_text.replace('FILTER_PORT',
+ 'if (%s) { currsock.delete(&pid); return 0; }' % dports_if)
+
+bpf_text = bpf_text.replace('FILTER_PID', '')
+bpf_text = bpf_text.replace('FILTER_PORT', '')
+
if debug:
print(bpf_text)
USAGE message:
# ./tcpconnect -h
-usage: tcpconnect [-h] [-t] [-p PID]
+usage: tcpconnect [-h] [-t] [-p PID] [-P PORT]
Trace TCP connects
-h, --help show this help message and exit
-t, --timestamp include timestamp on output
-p PID, --pid PID trace this PID only
+ -P PORT, --port PORT
+ comma-separated list of destination ports to trace.
examples:
./tcpconnect # trace all TCP connect()s
./tcpconnect -t # include timestamps
./tcpconnect -p 181 # only trace PID 181
+ ./tcpconnect -P 80 # only trace port 80
+ ./tcpconnect -P 80,81 # only trace port 80 and 81