• Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Search
  • Register
  • Login
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 231 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 Mar 1, 2024, 7:26 AM Mar 1, 2024, 7:17 AM

    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
    1 out of 1
    • First post
      1/1
      Last post
    Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.
      This community forum collects and processes your personal information.
      consent.not_received