├── LICENSE ├── README.md └── conntrack-top /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Ragnar B. Johannsson 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Top utility for the nf_conntrack table 2 | 3 | A script that calculates the top 10 source and destination addresses in Netfilter's connection tracking table for UDP and TCP. 4 | 5 | 6 | ### Usage 7 | 8 | ``` 9 | $ conntrack_top 10 | 11 | Connection count: 3801 12 | Connections max: 296608 13 | 14 | Top TCP 15 | Source Num Destination Num 16 | 192.168.1.46 207 192.168.1.30 967 17 | 85.220.x.x 75 91.192.x.x 963 18 | 192.168.1.30 40 192.168.1.196 209 19 | 93.179.x.x 32 192.168.1.21 16 20 | 86.152.x.x 32 77.109.x.x 14 21 | 17.120.x.x 31 192.168.1.46 12 22 | 192.168.1.196 31 14.192.x.x 8 23 | 157.157.x.x 27 194.144.x.x 8 24 | 212.30.x.x 24 192.168.1.138 7 25 | 192.168.1.72 23 192.168.1.81 7 26 | 27 | Top UDP 28 | Source Num Destination Num 29 | 69.122.x.x 164 192.168.1.55 283 30 | 192.168.1.63 140 12.122.x.x 282 31 | 192.168.1.30 31 47.201.x.x 183 32 | 192.168.1.72 23 192.168.1.72 144 33 | 37.189.x.x 9 192.168.1.1 46 34 | 192.168.1.46 9 192.168.1.63 38 35 | 192.168.1.208 6 188.51.x.x 8 36 | 192.168.1.196 5 31.172.x.x 4 37 | 174.55.x.x 4 81.229.x.x 3 38 | 189.47.x.x 4 87.122.x.x 3 39 | 40 | $ 41 | ``` 42 | 43 | 44 | ### License 45 | 46 | Simplified BSD. See the LICENSE file for further information. 47 | -------------------------------------------------------------------------------- /conntrack-top: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # A script that summarizes the top source and destination addresses 4 | # in the netfilter conntrack table, for TCP and UDP. 5 | # 6 | # Note: awk should be the perfect candidate for a task such as this. 7 | # However, due to arrays not being first class citizens in awk and 8 | # the lack of an associative array sort function that doesn't destroy 9 | # all associations, the result is a bit cumbersome. But it works. 10 | # 11 | 12 | function initialize { 13 | if [ ! -e /proc/net/nf_conntrack ]; then 14 | echo "Unable to find /proc/net/nf_conntrack" 15 | exit 1 16 | fi 17 | 18 | parse_options "$@" 19 | test -z "$TOP" && TOP=10 20 | 21 | COUNT=$(/sbin/sysctl net.netfilter.nf_conntrack_count|awk '{print $3}') 22 | MAX=$(/sbin/sysctl net.netfilter.nf_conntrack_max|awk '{print $3}') 23 | 24 | if [ -n "$SAMPLE" ]; then 25 | let LINES=$COUNT/100*$SAMPLE 26 | elif [ "$COUNT" -gt 25000 ] && [ -z "$FULL" ] && [ -z "$SAMPLE" ]; then 27 | LINES=25000 28 | fi 29 | 30 | CONNTRACK_CMD="cat" 31 | test -n "$LINES" && CONNTRACK_CMD="head -$LINES" 32 | } 33 | 34 | function parse_options { 35 | while getopts ":t:s:fh" opt; do 36 | case $opt in 37 | t) 38 | if [ -z "$OPTARG" ] || [ "$OPTARG" -lt 1 ] || [ "$OPTARG" -gt 15 ]; then 39 | usage 1 "Value given with -t must be between 1 and 15" 40 | fi 41 | TOP=$OPTARG 42 | ;; 43 | s) 44 | if [ -z "$OPTARG" ] || [ "$OPTARG" -lt 1 ] || [ "$OPTARG" -gt 99 ]; then 45 | usage 1 "Value given with -s must be between 1 and 99" 46 | fi 47 | let SAMPLE=$OPTARG 48 | ;; 49 | f) 50 | FULL=1 51 | ;; 52 | h) 53 | usage 0 54 | ;; 55 | :) 56 | usage 1 "Option -$OPTARG requires an argument" 57 | ;; 58 | \?) 59 | usage 1 "Invalid option: -$OPTARG" 60 | ;; 61 | esac 62 | done 63 | 64 | if [ -n "$SAMPLE" ] && [ -n "$FULL" ]; then 65 | usage 1 "Options -s and -f are mutually exclusive" 66 | fi 67 | } 68 | 69 | function usage { 70 | test -n "$2" && printf "Error: %s\n" "$2" 71 | 72 | printf "\nUsage: %s [-t ] [-s ] [-f] [-h]\n\nOptions:\n" "$BASH_SOURCE" 73 | printf " %-10s %s\n" "-t" "Number of top entries, from 1-15." 74 | printf " %-10s %s\n" "-s" "Sample a percentage of connections, from 1-99." 75 | printf " %-10s %s\n" "-f" "Force full connection list scan. Default is to cap at 25.000 connections." 76 | printf " %-10s %s\n\n" "-h" "This message." 77 | 78 | exit $1 79 | } 80 | 81 | function calculate_top { 82 | $CONNTRACK_CMD /proc/net/nf_conntrack | awk -v top=$TOP -v count=$COUNT -v max=$MAX ' 83 | $3=="tcp" { 84 | split($7, a, "="); 85 | split($8, b, "="); 86 | tcp_src[a[2]] += 1; 87 | tcp_dst[b[2]] += 1; 88 | } 89 | 90 | $3=="udp" { 91 | split($6, a, "="); 92 | split($7, b, "="); 93 | udp_src[a[2]] += 1; 94 | udp_dst[b[2]] += 1; 95 | } 96 | 97 | function sort(arr, num) { 98 | for (i = 0; i < num; i++) { 99 | key = ""; 100 | high = 0; 101 | 102 | for (k in arr) { 103 | if ((arr[k]+0) > high && length(k) > 1) { 104 | high = arr[k]+0; 105 | key = k; 106 | } 107 | } 108 | 109 | arr[i] = key " " high; 110 | delete arr[key]; 111 | } 112 | } 113 | 114 | END { 115 | sort(tcp_src, top); 116 | sort(tcp_dst, top); 117 | sort(udp_src, top); 118 | sort(udp_dst, top); 119 | 120 | printf("\nCurrent connection count:\t%6s\nConnections max:\t\t%6s\n", count, max); 121 | printf("\nTop TCP\n%-17s%6s %-17s%6s\n", "Source", "Num", "Destination", "Num"); 122 | for (i = 0; i < top; i++) { 123 | split(tcp_src[i], src, " "); 124 | split(tcp_dst[i], dst, " "); 125 | printf("%-17s%6s %-17s%6s\n", src[1], src[2], dst[1], dst[2]); 126 | } 127 | 128 | printf("\nTop UDP\n%-17s%6s %-17s%6s\n", "Source", "Num", "Destination", "Num"); 129 | for (i = 0; i < top; i++) { 130 | split(udp_src[i], src, " "); 131 | split(udp_dst[i], dst, " "); 132 | printf("%-17s%6s %-17s%6s\n", src[1], src[2], dst[1], dst[2]); 133 | } 134 | 135 | printf("\n"); 136 | }' 137 | } 138 | 139 | # main 140 | initialize "$@" 141 | 142 | if [ -n "$LINES" ]; then 143 | echo "Showing top addresses for the first $LINES connections" 144 | fi 145 | 146 | calculate_top 147 | 148 | --------------------------------------------------------------------------------