Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    Remote tcpdump script

    Scheduled Pinned Locked Moved General pfSense Questions
    1 Posts 1 Posters 234 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A
      ameinild
      last edited by ameinild

      Hello

      I've created this script that allows you to make a remote tcpdump via SSH from any machine running Bash. The script saves the .pcap files in the default directory (/tmp), so they can be viewed from the WebUI, or viewed with Wireshark or similar software. To run the script you will (of course) need to have set up an SSH key on the pfSense system.

      The script takes up to 2 arguments: Host or port filter, and number of packets to capture. The other options are defined in a .conf file, which also sets the default values when nu arguments are used. Finally, it's possible to define up to 9 predefined host/port and number of packet combinations, which can be triggered when the argument is 1 to 9 (kind of a shortcut).

      Here's the script file:

      #!/bin/bash
      
      # Initial configuration variables
      scriptpath="/path/to/file"
      
      # Include configuration file
      source "${scriptpath}/rtcpdump.conf"
      
      # Local function definition
      exit_error() {
        echo "Error: $1"
        exit 1
      }
      
      # Example command to be run - for reference
      # ssh admin@10.10.1.1 "/usr/sbin/tcpdump -ni igc0 -c 4000 -s 128 -U -w /tmp/packetcapture-igc0-$(date '+%Y%m%d%H%M%S').pcap \"((host 10.10.2.22)) and ((not vlan))\""
      
      
      # Check that $1 is a valid IP address or port
      if [[ "$1" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ || "$1" =~ ^[0-9]{1,5}$ ]]
      then
        # Set filter with first parameter (exclude 1-9, that are reserved for predefined array)
        if [[ ! "$1" =~ ^[0-9]{1}$ ]]
        then
          filter_new="$1"
      
          # Set # of packets to $2 or default
          if [[ "$2" =~ ^[0-9]{1,5}$ ]]
          then
            nr_p_new="$2"
          else
            nr_p_new="${rtcp_p_nr}"
          fi
        fi
      
        # Check if $1 matches predefined filters
        for i in "${!rtcp_ar_filters[@]}"
        do
          # Matches the first argument against the list in rtcp_ar_filters, or shortcut 1-9
          if [[ "$1" == "${rtcp_ar_filters[i]}" || "$1" == $(( i+1 )) ]]
          then
            filter_new="${rtcp_ar_filters[i]}"
      
            # Set # of packets to $2 or default
            if [[ "$2" =~ ^[0-9]{1,5}$ ]]
            then
              nr_p_new="$2"
            else
              nr_p_new="${rtcp_ar_packets[i]}"
            fi
          fi
        done
        #echo "Filter is valid"
      fi
      
      # If no arguments are given, just set to defaults
      if [[ -z "$1" ]]
      then
        filter_new="${rtcp_filter}"
        nr_p_new="${rtcp_p_nr}"
      fi
      
      if [[ -n "${filter_new}" ]]
      then
        # Set filter type to host or port, depending on the format of $1
        if [[ "${filter_new}" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
        then
          rtcp_type="host"
        elif [[ "${filter_new}" =~ ^[0-9]{2,5}$ ]]
        then
          rtcp_type="port"
        fi
      
        echo "$rtcp_type: $filter_new"
        echo "packets: $nr_p_new"
      
        # Set output filename
        rtcp_filename="/tmp/packetcapture-${rtcp_nic_id}-$(date '+%Y%m%d%H%M%S').pcap"
      
        # Run TCP dump command
        echo "Remote TCP dump initiated - please run diagnostics"
        # shellcheck disable=SC2029
        ssh "${rtcp_user}@${rtcp_server}" "/usr/sbin/tcpdump -ni ${rtcp_nic_id} -c ${nr_p_new} -s ${rtcp_p_size} -U -w ${rtcp_filename} \"((${rtcp_type} ${filter_new})) and ((not vlan))\""
      else
        exit_error "No valid filter given"
      fi
      

      And here's the config:

      # IP of the Firewall performing the capture
      rtcp_server="10.10.1.1"
      # Admin user of the Firewall (requires SSH key)
      rtcp_user="admin"
      # ID of the network interface to capture
      rtcp_nic_id="igc0"
      # Default filter for capture (IP of the client)
      rtcp_filter="10.10.2.22"
      # Default number of packets to capture
      rtcp_p_nr="4000"
      # Size of packets written to disk
      rtcp_p_size="128"
      
      # Primary Array with predefined filters
      rtcp_ar_filters=("10.10.2.22" "8080")
      # Complimentary Array with # of packets
      rtcp_ar_packets=("4000" "10")
      

      So it can be used in one of the following ways:

      • With no arguments: rtcp_filter and rtcp_p_nr from the config is used.
      • With one argument, that can be one of the following:
        • A number 1 to 9, which selects the corresponding rtcp_ar_filters and rtcp_ar_packets from the arrays (up to 9 "shortcuts", which are likely not used as ports).
        • Any host (IP address) or port. If it matches the host or port in rtcp_ar_filters, the corresponding number of packets are used, else the default is used.
      • With two arguments that is any host/port and number of packets. In this case, these values override the default rtcp_filter and rtcp_p_nr from the config.

      The arguments for host will match any IPv4 address, and the port will match any port between 2 to 5 digits (and yes I know there are only 65535 possible ports). Number of packets will match any number between 1 and 99999 (actually from 0, but doesn't matter).

      The default settings are in the config, and it also filters no vlan by default. Hope it's of use to somebody, and of course change all you like.

      1 Reply Last reply Reply Quote 1
      • First post
        Last post
      Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.