Skip to content

Commit

Permalink
[tcpconnect] filter traced connection based on destination ports
Browse files Browse the repository at this point in the history
Test:
While running:
while [ 1 ]; do nc -w 1 100.127.0.1 80; nc -w 1 100.127.0.1 81; done

root@vagrant:/mnt/bcc# ./tools/tcpconnect.py
PID    COMM         IP SADDR            DADDR            DPORT
19978  nc           4  10.0.2.15        100.127.0.1      80
19979  nc           4  10.0.2.15        100.127.0.1      81
19980  nc           4  10.0.2.15        100.127.0.1      80
19981  nc           4  10.0.2.15        100.127.0.1      81
root@vagrant:/mnt/bcc# ./tools/tcpconnect.py  -P 80
PID    COMM         IP SADDR            DADDR            DPORT
19987  nc           4  10.0.2.15        100.127.0.1      80
19989  nc           4  10.0.2.15        100.127.0.1      80
19991  nc           4  10.0.2.15        100.127.0.1      80
19993  nc           4  10.0.2.15        100.127.0.1      80
19995  nc           4  10.0.2.15        100.127.0.1      80
root@vagrant:/mnt/bcc# ./tools/tcpconnect.py  -P 80,81
PID    COMM         IP SADDR            DADDR            DPORT
8725   nc           4  10.0.2.15        100.127.0.1      80
8726   nc           4  10.0.2.15        100.127.0.1      81
8727   nc           4  10.0.2.15        100.127.0.1      80
8728   nc           4  10.0.2.15        100.127.0.1      81
8729   nc           4  10.0.2.15        100.127.0.1      80

Fixes iovisor#681
  • Loading branch information
chantra committed Sep 16, 2016
1 parent 1298998 commit 5293805
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
9 changes: 8 additions & 1 deletion man/man8/tcpconnect.8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.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
Expand All @@ -27,6 +27,9 @@ Include a timestamp column.
.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:
Expand All @@ -40,6 +43,10 @@ Trace all TCP connects, and include timestamps:
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)
Expand Down
25 changes: 19 additions & 6 deletions tools/tcpconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# 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.
#
Expand All @@ -20,7 +20,7 @@
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

Expand All @@ -29,6 +29,8 @@
./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",
Expand All @@ -38,6 +40,8 @@
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

Expand Down Expand Up @@ -76,7 +80,7 @@
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);
Expand Down Expand Up @@ -107,6 +111,8 @@
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;
Expand Down Expand Up @@ -148,10 +154,17 @@

# 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)

Expand Down
6 changes: 5 additions & 1 deletion tools/tcpconnect_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,20 @@ process to various other addresses. A few connections occur every minute.
USAGE message:

# ./tcpconnect -h
usage: tcpconnect [-h] [-t] [-p PID]
usage: tcpconnect [-h] [-t] [-p PID] [-P PORT]

Trace TCP connects

optional arguments:
-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

0 comments on commit 5293805

Please sign in to comment.