Commit 870b1cd1 authored by Brendan Gregg's avatar Brendan Gregg

tcpv4connect

parent a8fbb90f
......@@ -72,6 +72,7 @@ Tools:
- tools/[opensnoop](tools/opensnoop): Trace open() syscalls. [Examples](tools/opensnoop_example.txt).
- tools/[pidpersec](tools/pidpersec): Count new processes (via fork). [Examples](tools/pidpersec_example.txt).
- tools/[syncsnoop](tools/syncsnoop): Trace sync() syscall. [Examples](tools/syncsnoop_example.txt).
- tools/[tcpv4connect](tools/tcpv4connect): Trace TCP IPv4 active connections. [Examples](tools/tcpv4connect_example.txt).
- tools/[vfscount](tools/vfscount) tools/[vfscount.c](tools/vfscount.c): Count VFS calls. [Examples](tools/vfscount_example.txt).
- tools/[vfsstat](tools/vfsstat) tools/[vfsstat.c](tools/vfsstat.c): Count some VFS calls, with column output. [Examples](tools/vfsstat_example.txt).
......
.TH tcpv4connect 8 "2015-08-25" "USER COMMANDS"
.SH NAME
tcpv4connect \- Trace TCP IPv4 active connections. Uses Linux eBPF/bcc.
.SH SYNOPSIS
.B tcpv4connect [\-h] [\-t] [\-x] [\-p PID]
.SH DESCRIPTION
This tool traces active TCP IPv4 connections (eg, via a connect() syscall;
accept() are passive connections). This can be useful for general
troubleshooting to see what connections are initiated by the local server.
This works by tracing the kernel tcp_v4_connect() function using dynamic
tracing, and will need updating to match any changes to this function.
Since this uses BPF, only the root user can use this tool.
.SH REQUIREMENTS
CONFIG_BPF and bcc.
.SH OPTIONS
.TP
\-h
Print usage message.
.TP
\-t
Include a timestamp column.
.TP
\-p PID
Trace this process ID only (filtered in-kernel).
.SH EXAMPLES
.TP
Trace all active TCP IPv4 connections:
#
.B tcpv4connect
.TP
Trace all TCP IPv4 connects, and include timestamps:
#
.B tcpv4connect \-t
.TP
Trace PID 181 only:
#
.B tcpv4connect \-p 181
.SH FIELDS
.TP
TIME(s)
Time of the call, in seconds.
.TP
PID
Process ID
.TP
COMM
Process name
.TP
SADDR
IPv4 source address, as a dotted quad
.TP
DADDR
IPv4 destination address, as a dotted quad
.TP
DPORT
Destination port
.SH OVERHEAD
This traces the kernel tcp_v4_connect function and prints output for each event.
As the rate of this is generally expected to be low (< 1000/s), the overhead is
also expected to be negligible. If you have an application that is calling a high
rate of connects()s, such as a proxy server, then test and understand this
overhead before use.
.SH SOURCE
This is from bcc.
.IP
https://github.com/iovisor/bcc
.PP
Also look in the bcc distribution for a companion _examples.txt file containing
example usage, output, and commentary for this tool.
.SH OS
Linux
.SH STABILITY
Unstable - in development.
.SH AUTHOR
Brendan Gregg
.SH SEE ALSO
funccount(8), tcpdump(8)
#!/usr/bin/python
#
# tcpv4connect Trace TCP IPv4 connect()s.
# For Linux, uses BCC, eBPF. Embedded C.
#
# USAGE: tcpv4connect [-h] [-t] [-p PID]
#
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 25-Sep-2015 Brendan Gregg Created this.
from __future__ import print_function
from bcc import BPF
import argparse
# arguments
examples = """examples:
./tcpv4connect # trace all open() syscalls
./tcpv4connect -t # include timestamps
./tcpv4connect -p 181 # only trace PID 181
"""
parser = argparse.ArgumentParser(
description="Trace TCP IPv4 connects",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
parser.add_argument("-t", "--timestamp", action="store_true",
help="include timestamp on output")
parser.add_argument("-p", "--pid",
help="trace this PID only")
args = parser.parse_args()
debug = 0
# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>
BPF_HASH(currsock, u32, struct sock *);
int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
{
u32 pid = bpf_get_current_pid_tgid();
FILTER
// stash the sock ptr for lookup on return
currsock.update(&pid, &sk);
return 0;
};
int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
{
int ret = ctx->ax;
u32 pid = bpf_get_current_pid_tgid();
struct sock **skpp;
skpp = currsock.lookup(&pid);
if (skpp == 0) {
return 0; // missed entry
}
// pull in details
struct sock *skp = *skpp;
u32 saddr = 0, daddr = 0;
u16 dport = 0;
bpf_probe_read(&saddr, sizeof(saddr), &skp->__sk_common.skc_rcv_saddr);
bpf_probe_read(&daddr, sizeof(daddr), &skp->__sk_common.skc_daddr);
bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);
// output
bpf_trace_printk("%x %x %d\\n", saddr, daddr, ntohs(dport));
currsock.delete(&pid);
return 0;
}
"""
# code substitutions
if args.pid:
bpf_text = bpf_text.replace('FILTER',
'if (pid != %s) { return 0; }' % args.pid)
else:
bpf_text = bpf_text.replace('FILTER', '')
if debug:
print(bpf_text)
# initialize BPF
b = BPF(text=bpf_text)
# header
if args.timestamp:
print("%-9s" % ("TIME(s)"), end="")
print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
"DPORT"))
start_ts = 0
def inet_ntoa(addr):
dq = ''
for i in range(0, 4):
dq = dq + str(addr & 0xff)
if (i != 3):
dq = dq + '.'
addr = addr >> 8
return dq
# format output
while 1:
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
(saddr_hs, daddr_hs, dport_s) = msg.split(" ")
if args.timestamp:
if start_ts == 0:
start_ts = ts
print("%-9.3f" % (ts - start_ts), end="")
print("%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
inet_ntoa(int(saddr_hs, 16)),
inet_ntoa(int(daddr_hs, 16)),
dport_s))
Demonstrations of tcpv4connect, the Linux eBPF/bcc version.
This tool traces the kernel function performing active TCP IPv4 connections
(eg, via a connect() syscall; accept() are passive connections). Some example
output (IP addresses changed to protect the innocent):
# ./tcpv4connect
PID COMM SADDR DADDR DPORT
1479 telnet 127.0.0.1 127.0.0.1 23
1469 curl 10.201.219.236 54.245.105.25 80
1469 curl 10.201.219.236 54.67.101.145 80
This output shows three connections, one from a "telnet" process and two from
"curl". The output details shows the source address, destination address,
and destination port. This traces attempted connections: these may have failed.
The overhead of this tool should be negligible, since it is only tracing the
kernel function performing a connect. It is not tracing every packet and then
filtering.
The -t option prints a timestamp column:
# ./tcpv4connect -t
TIME(s) PID COMM SADDR DADDR DPORT
31.871 2482 local_agent 10.103.219.236 10.251.148.38 7001
31.874 2482 local_agent 10.103.219.236 10.101.3.132 7001
31.878 2482 local_agent 10.103.219.236 10.171.133.98 7101
90.917 2482 local_agent 10.103.219.236 10.251.148.38 7001
90.928 2482 local_agent 10.103.219.236 10.102.64.230 7001
90.938 2482 local_agent 10.103.219.236 10.115.167.169 7101
The output shows some periodic connections (or attempts) from a "local_agent"
process to various other addresses. A few connections occur every minute.
USAGE message:
# ./tcpv4connect -h
usage: tcpv4connect [-h] [-t] [-p PID]
Trace TCP IPv4 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
examples:
./tcpv4connect # trace all open() syscalls
./tcpv4connect -t # include timestamps
./tcpv4connect -p 181 # only trace PID 181
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment