diff --git a/man/man8/tcpconnect.8 b/man/man8/tcpconnect.8 index e298dec4e626..55105709e41b 100644 --- a/man/man8/tcpconnect.8 +++ b/man/man8/tcpconnect.8 @@ -2,7 +2,7 @@ .SH NAME tcpconnect \- Trace TCP active connections (connect()). Uses Linux eBPF/bcc. .SH SYNOPSIS -.B tcpconnect [\-h] [\-c] [\-t] [\-p PID] [-P PORT] [-u UID] [-U] [\-\-cgroupmap MAPPATH] [\-\-mntnsmap MAPPATH] [\-d] +.B tcpconnect [\-h] [\-c] [\-t] [\-p PID] [-P PORT] [\-L] [-u UID] [-U] [\-\-cgroupmap MAPPATH] [\-\-mntnsmap MAPPATH] [\-d] .SH DESCRIPTION This tool traces active TCP connections (eg, via a connect() syscall; accept() are passive connections). This can be useful for general @@ -43,6 +43,9 @@ Trace this process ID only (filtered in-kernel). \-P PORT Comma-separated list of destination ports to trace (filtered in-kernel). .TP +\-L +Include a LPORT column. +.TP \-U Include a UID column. .TP @@ -96,6 +99,10 @@ Trace ports 80 and 81 only: # .B tcpconnect \-P 80,81 .TP +Trace all TCP connects, and include LPORT: +# +.B tcpconnect \-L +.TP Trace all TCP connects, and include UID: # .B tcpconnect \-U @@ -135,6 +142,9 @@ IP address family (4 or 6) SADDR Source IP address. .TP +LPORT +Source port +.TP DADDR Destination IP address. .TP diff --git a/tools/tcpconnect.py b/tools/tcpconnect.py index acdf176723dc..0d204ea5c69f 100755 --- a/tools/tcpconnect.py +++ b/tools/tcpconnect.py @@ -19,6 +19,7 @@ # 09-Jan-2019 Takuma Kume Support filtering by UID # 30-Jul-2019 Xiaozhou Liu Count connects. # 07-Oct-2020 Nabil Schear Correlate connects with DNS responses +# 08-Mar-2021 Suresh Kumar Added LPORT option from __future__ import print_function from bcc import BPF @@ -41,6 +42,7 @@ ./tcpconnect -U # include UID ./tcpconnect -u 1000 # only trace UID 1000 ./tcpconnect -c # count connects per src ip and dest ip/port + ./tcpconnect -L # include LPORT while printing outputs ./tcpconnect --cgroupmap mappath # only trace cgroups in this BPF map ./tcpconnect --mntnsmap mappath # only trace mount namespaces in the map """ @@ -54,6 +56,8 @@ help="trace this PID only") parser.add_argument("-P", "--port", help="comma-separated list of destination ports to trace.") +parser.add_argument("-L", "--lport", action="store_true", + help="include LPORT on output") parser.add_argument("-U", "--print-uid", action="store_true", help="include UID on output") parser.add_argument("-u", "--uid", @@ -87,6 +91,7 @@ u32 saddr; u32 daddr; u64 ip; + u16 lport; u16 dport; char task[TASK_COMM_LEN]; }; @@ -99,6 +104,7 @@ unsigned __int128 saddr; unsigned __int128 daddr; u64 ip; + u16 lport; u16 dport; char task[TASK_COMM_LEN]; }; @@ -161,6 +167,7 @@ // pull in details struct sock *skp = *skpp; + u16 lport = skp->__sk_common.skc_num; u16 dport = skp->__sk_common.skc_dport; FILTER_PORT @@ -202,6 +209,7 @@ data4.ts_us = bpf_ktime_get_ns() / 1000; data4.saddr = skp->__sk_common.skc_rcv_saddr; data4.daddr = skp->__sk_common.skc_daddr; + data4.lport = lport; data4.dport = ntohs(dport); bpf_get_current_comm(&data4.task, sizeof(data4.task)); ipv4_events.perf_submit(ctx, &data4, sizeof(data4));""" @@ -225,6 +233,7 @@ skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr), skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32); + data6.lport = lport; data6.dport = ntohs(dport); bpf_get_current_comm(&data6.task, sizeof(data6.task)); ipv6_events.perf_submit(ctx, &data6, sizeof(data6));""" @@ -354,10 +363,16 @@ def print_ipv4_event(cpu, data, size): if args.print_uid: printb(b"%-6d" % event.uid, nl="") dest_ip = inet_ntop(AF_INET, pack("I", event.daddr)).encode() - printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid, - event.task, event.ip, - inet_ntop(AF_INET, pack("I", event.saddr)).encode(), - dest_ip, event.dport, print_dns(dest_ip))) + if args.lport: + printb(b"%-6d %-12.12s %-2d %-16s %-6d %-16s %-6d %s" % (event.pid, + event.task, event.ip, + inet_ntop(AF_INET, pack("I", event.saddr)).encode(), event.lport, + dest_ip, event.dport, print_dns(dest_ip))) + else: + printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid, + event.task, event.ip, + inet_ntop(AF_INET, pack("I", event.saddr)).encode(), + dest_ip, event.dport, print_dns(dest_ip))) def print_ipv6_event(cpu, data, size): event = b["ipv6_events"].event(data) @@ -369,10 +384,16 @@ def print_ipv6_event(cpu, data, size): if args.print_uid: printb(b"%-6d" % event.uid, nl="") dest_ip = inet_ntop(AF_INET6, event.daddr).encode() - printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid, - event.task, event.ip, - inet_ntop(AF_INET6, event.saddr).encode(), dest_ip, - event.dport, print_dns(dest_ip))) + if args.lport: + printb(b"%-6d %-12.12s %-2d %-16s %-6d %-16s %-6d %s" % (event.pid, + event.task, event.ip, + inet_ntop(AF_INET6, event.saddr).encode(), event.lport, + dest_ip, event.dport, print_dns(dest_ip))) + else: + printb(b"%-6d %-12.12s %-2d %-16s %-16s %-6d %s" % (event.pid, + event.task, event.ip, + inet_ntop(AF_INET6, event.saddr).encode(), + dest_ip, event.dport, print_dns(dest_ip))) def depict_cnt(counts_tab, l3prot='ipv4'): for k, v in sorted(counts_tab.items(), @@ -490,8 +511,12 @@ def save_dns(cpu, data, size): print("%-9s" % ("TIME(s)"), end="") if args.print_uid: print("%-6s" % ("UID"), end="") - print("%-6s %-12s %-2s %-16s %-16s %-6s" % ("PID", "COMM", "IP", "SADDR", - "DADDR", "DPORT"), end="") + if args.lport: + print("%-6s %-12s %-2s %-16s %-6s %-16s %-6s" % ("PID", "COMM", "IP", "SADDR", + "LPORT", "DADDR", "DPORT"), end="") + else: + print("%-6s %-12s %-2s %-16s %-16s %-6s" % ("PID", "COMM", "IP", "SADDR", + "DADDR", "DPORT"), end="") if args.dns: print(" QUERY") else: diff --git a/tools/tcpconnect_example.txt b/tools/tcpconnect_example.txt index b8ad22d1326d..f2e6d72f3e50 100644 --- a/tools/tcpconnect_example.txt +++ b/tools/tcpconnect_example.txt @@ -55,6 +55,15 @@ PID COMM IP SADDR DADDR DPORT QUERY 2015 ssh 6 fe80::2000:bff:fe82:3ac fe80::2000:bff:fe82:3ac 22 anotherhost.org +The -L option prints a LPORT column: + +# ./tcpconnect -L +PID COMM IP SADDR LPORT DADDR DPORT +3706 nc 4 192.168.122.205 57266 192.168.122.150 5000 +3722 ssh 4 192.168.122.205 50966 192.168.122.150 22 +3779 ssh 6 fe80::1 52328 fe80::2 22 + + The -U option prints a UID column: # ./tcpconnect -U @@ -97,7 +106,7 @@ USAGE message: # ./tcpconnect -h -usage: tcpconnect.py [-h] [-t] [-p PID] [-P PORT] [-U] [-u UID] [-c] +usage: tcpconnect.py [-h] [-t] [-p PID] [-P PORT] [-L] [-U] [-u UID] [-c] [--cgroupmap CGROUPMAP] [--mntnsmap MNTNSMAP] [-d] Trace TCP connects @@ -107,6 +116,7 @@ optional arguments: -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. + -L, --lport include LPORT on output -U, --print-uid include UID on output -u UID, --uid UID trace this UID only -c, --count count connects per src ip and dest ip/port @@ -118,11 +128,13 @@ optional arguments: examples: ./tcpconnect # trace all TCP connect()s ./tcpconnect -t # include timestamps + ./tcpconnect -d # include DNS queries associated with connects ./tcpconnect -p 181 # only trace PID 181 ./tcpconnect -P 80 # only trace port 80 ./tcpconnect -P 80,81 # only trace port 80 and 81 ./tcpconnect -U # include UID ./tcpconnect -u 1000 # only trace UID 1000 ./tcpconnect -c # count connects per src ip and dest ip/port + ./tcpconnect -L # include LPORT while printing outputs ./tcpconnect --cgroupmap mappath # only trace cgroups in this BPF map - ./tcpconnect --mntnsmap mappath # only trace mount namespaces in the map \ No newline at end of file + ./tcpconnect --mntnsmap mappath # only trace mount namespaces in the map