Monitorare il traffico di rete con pmacct su Debian 10 “Buster”
Adattamento dell’articolo Monitorare il traffico di rete con pmacct su Ubuntu 18.04 per Debian 10 “Buster” procedendo all’installazione da sorgenti della versione 1.7.4 ed utlizzando la versione 9 della tabella.
Le seguenti operazioni vanno eseguite tramite account di root.
In questo esempio si utilizza un server MySQL esterno quindi se ne esclude la parte di installazione, occorre quindi installare solo la parte client:
1 |
apt install default-mysql-client |
Per avere le ultime versioni occorre installare da sorgenti, per avere però la comodità dei pacchetti .deb si può utilizzare il programma checkinstall per creare un installazione personalizzata (sono richiesti i repo backports):
1 |
apt install build-essential checkinstall |
Le dipendenze richieste per la compilazione:
1 |
apt install libpcap-dev default-libmysqlclient-dev |
Si scarica dal sito l’ultima versione e si estrae l’archivio, ad esempio:
1 2 3 |
wget http://www.pmacct.net/pmacct-1.7.4.tar.gz tar xzvf pmacct-1.7.4.tar.gz cd pmacct-1.7.4 |
Si procede alla preparazione dei sorgenti, ricordandosi di abilitare il plugin che ci interessa ( nel mio caso uso MySQL ) e infine richiamando checkinstall al posto di makeinstall verrà creato ed installato il pacchetto .deb:
1 2 3 |
./configure --enable-mysql make checkinstall |
L’installazione potrebbe fallire non riuscendo a creare le directory in /usr/local/lib/ (vedere gli errori a schermo se ci sono), basta crearle a mano e rilanciare l’installazione:
1 2 |
mkdir /usr/local/lib/pmacct mkdir /usr/local/lib/pmacct/examples |
Copiare a mano i file di esempio:
1 |
cp -R sql/ /usr/share/doc/pmacct/ |
E’ possibile ora cancellare i sorgenti in quanto se volessimo disinstallarlo essendo stato pacchettizzato .deb basta usare dpkg -r pmacct
Se sul server MySQL manca il database si deve creare con la tabella versione 9, che al momento in cui scrivo è l’ultima, se esiste già un database basta proseguire alla sezione ‘Configurare il programma‘:
1 |
mysql -h host -u root -p < /usr/share/doc/pmacct/sql/pmacct-create-db_v9.mysql |
Impostare i permessi di default ( utente pmacct@localhost ):
1 |
mysql -h host -u root -p < /usr/share/doc/pmacct/sql/pmacct-grant-db.mysql |
Cambiare la password:
1 |
mysql -h host -u root -p |
1 2 3 |
USE pmacct; UPDATE mysql.user SET Password=PASSWORD('nuova-password') WHERE User='pmacct'; FLUSH PRIVILEGES; |
Configurare il programma:
1 2 |
sudo mkdir /etc/pmacct sudo nano /etc/pmacct/pmacctd.conf |
Un esempio di configurazione:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
! pmacctd configuration ! ! ! daemonize: true pidfile: /var/run/pmacctd.pid syslog: daemon ! ! interested in in and outbound traffic aggregate: src_host,dst_host,src_port,dst_port ! on this network pcap_filter: net 192.168.1.0/24 ! on this interface interface: eth0 ! ! storage methods plugins: mysql sql_host: localhost sql_user: pmacct sql_passwd: nuova-password sql_db: pmacct sql_table: pmacct sql_table_version: 9 ! ! refresh the db every 5 minutes sql_refresh_time: 300 ! reduce the size of the insert/update clause sql_optimize_clauses: true ! accumulate values in each row for up to 5 minutes sql_history: 5m ! create new rows on the minute, hour, day boundaries !sql_history_roundoff: mhd sql_history_roundoff: m ! in case of emergency, log to this file !sql_recovery_logfile: /var/lib/pmacct/recovery_log ! try to use only INSERT sql_dont_try_update: true |
Avviare il demone e controllare sul nostro database i record che vengono inseriti:
1 |
sudo pmacctd -f /etc/pmacct/pmacctd.conf |
E’ anche possibile creare il file di avvio, si crea ad esempio uno script /etc/init.d/pmacctd:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
#! /bin/sh ### BEGIN INIT INFO # Provides: pmacct-daemons # Required-Start: $local_fs $remote_fs # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: pmacct daemons initscript # Description: pmacct daemons initscript ### END INIT INFO # Author: Pier Carlo Chiodi (aka Pierky) <pierky@pierky.com> # http://www.pierky.com # # This script is aimed to manage multiple instances of pmacct daemons # (http://www.pmacct.net/ by Paolo Lucente) # # For each daemon (pmacctd|nfacctd|sfacctd|uacctd), one or more # instances may be managed; instances are mapped one-to-one to # configuration files that are in the $CONFIG_DIR directory # (/etc/pmacct by default). Configuration files' names must # follow this schema: # # <daemon_name>[.<instance_id>].conf # # An instance's name is composed by the name of the daemon + "." + # an optional instance ID; if the instance ID is omitted the # "default" ID is used. # # Example: # # pmacctd.conf ---> daemon = pmacctd, instance = "pmacctd.default" # pmacctd.2.conf -> daemon = pmacctd, instance = "pmacctd.2" # nfacctd.1.conf -> daemon = nfacctd, instance = "nfacctd.1" # # The second argument of this script may be used to selectively # start/stop a single instance; if omitted, all the instances # are started/stopped: # # Example: # # /etc/init.d/pmacct start pmacctd.default # # service pmacct stop nfacctd.1 # # Daemons are started with -D option (Daemonize) and with # -F option (PID file) pointing to $PIDDIR/<instance_id> # (PIDDIR default to /var/run/pmacct). It's safe to avoid # using the "pidfile" and "daemonize" keys in the configuration # file. PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin DESC="pmacct daemons" SCRIPTNAME="pmacct" CONFIG_DIR=/etc/pmacct PIDDIR=/var/run/pmacct DAEMONDIR=/usr/local/sbin mkdir -p $PIDDIR >/dev/null 2>&1 || true # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.2-14) to ensure that this file is present # and status_of_proc is working. . /lib/lsb/init-functions CONFIGS=`cd $CONFIG_DIR; ls *.conf 2>/dev/null | egrep -e "^(pmacctd|nfacctd|sfacctd|uacctd)."` if [ -z "$CONFIGS" ]; then log_failure_msg "ERROR: no pmacct configuration instances found on $CONFIG_DIR. Please refer to comments in $0 for more details." exit 1 fi SELECTED_INSTANCE="$2" signal_to_childprocesses() { # $1 PID # $2 Signal for PID in `ps --ppid $1 -o pid h` do kill -$2 $PID done } # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS || return 2 } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred RETVAL="2" if [ -f $PIDFILE ]; then signal_to_childprocesses `cat $PIDFILE` INT for w in 2 5 10 do # wait for child processes to end sleep $w if [ -f $PIDFILE ]; then ps `cat $PIDFILE` | grep $DAEMON_NAME >/dev/null if [ $? -ne 0 ]; then RETVAL="0" break fi else RETVAL="0" break fi done if [ "$RETVAL" -ne "0" ]; then if [ -f $PIDFILE ]; then ps `cat $PIDFILE` | grep $DAEMON_NAME >/dev/null if [ $? -eq 0 ]; then start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $DAEMON_NAME RETVAL="$?" fi fi fi rm -f $PIDFILE return "$RETVAL" else return "2" fi } do_reload() { if [ -f $PIDFILE ]; then #signal_to_childprocesses `cat $PIDFILE` USR2 kill -USR2 `cat $PIDFILE` return 0 else return 1 fi } for CONFIG in $CONFIGS do INSTANCE=${CONFIG%%.conf} DAEMON_NAME=`echo ${CONFIG%%.} | cut -d"." -f1` if [ "$INSTANCE" = "$DAEMON_NAME" ]; then INSTANCE="$DAEMON_NAME.default" fi DAEMON=$DAEMONDIR/$DAEMON_NAME PIDFILE=$PIDDIR/$INSTANCE DAEMON_ARGS="-F $PIDFILE -D -f $CONFIG_DIR/$CONFIG" #echo "INSTANCE: $INSTANCE" #echo "DAEMON_NAME: $DAEMON_NAME" #echo "DAEMON: $DAEMON" #echo "PIDFILE: $PIDFILE" #echo "DAEMON_ARGS: $DAEMON_ARGS" #continue if [ -z "$SELECTED_INSTANCE" -o "$SELECTED_INSTANCE" = "$INSTANCE" ]; then case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DAEMON_NAME, instance $INSTANCE" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DAEMON_NAME, instance $INSTANCE" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) if [ -f $PIDFILE ]; then ps `cat $PIDFILE` | grep "$DAEMON_NAME" >/dev/null if [ $? -eq 0 ]; then log_success_msg "$DAEMON_NAME, instance $INSTANCE is running" else log_failure_msg "$DAEMON_NAME, instance $INSTANCE is not running" fi else log_failure_msg "$DAEMON_NAME, instance $INSTANCE is not running" fi ;; reload) log_daemon_msg "Reloading $DAEMON_NAME, instance $INSTANCE" do_reload log_end_msg $? ;; restart|force-reload) log_daemon_msg "Restarting $DAEMON_NAME, instance $INSTANCE" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload}" >&2 exit 3 ;; esac fi done : |
E lo si abilita:
1 |
update-rc.d pmacctd defaults |
Nota: ho notato che su reti diciamo discrete la mole di dati generata influisce notevolmente sulle prestazioni richieste dal server MySQL, ogni tanto è cosigliato spostare i dati storici su una copia della tabella meglio ancora su un altro database/host ed è comunque consigliato avere MySQL impostato con l’opzione di creare le tabelle su singoli files.
Nota 2: se il traffico è elevato e si usa il raggruppamento è possibile che venga richiesto un server MySQL con alte prestazioni di CPU e di I/O su disco in quanto le istruzioni di UPDATE sono molte, in tal caso ridurre il periodo di raggruppamento ( es. da 30m a 5m ) e usare l’istruzione “sql_dont_try_update: true” che usa la memoria per limitare al massimo le istruzioni di UPDATE, appoggiandosi a versioni InnoDB invece che MyISAM delle tabelle.
Nota 3: Nel caso servisse recuperare i dati dal file di recupero ( recovery_log ) utilizzare il comando pmmplay:
1 |
pmmplay -d -f /var/lib/pmacct/recovery_log -U <utentemysql> -P <passwordmysql> |
Se serve solo testare cosa c’è nel file senza fare modifiche al database aggiungere il parametro -t.
Sul wiki ufficiale però sconsigliano di utilizzare il file di recupero dicendo che sarà dismesso ma di utilizzare eventualmente un DB di backup:
While planning for a recovery method, consider that the logfile method is being discontinued and you are encouraged to use the backup DB option.
Nota 4: Nel caso si utilizzi un server MySQL esterno controllare che le due macchine abbiano lo stesso timezone tramite il comando date, in caso siano diversi occorre riconfigurarlo per impostarlo uguale, riavviare anche MySQL dopo:
1 2 |
sudo dpkg-reconfigure tzdata sudo service mysql restart |
Per tenere anche sincronizzati gli orari tramite un NTP server:
1 |
sudo ntpdate <host-ntp> |
Nota 5: Nel caso servisse controllare eventuali errori fare riferimento al syslog:
1 2 3 4 5 |
# Gli ultimi log sudo tail /var/log/syslog # Monitor realtime dei log (uscire con CTRL+C) sudo tail /var/log/syslog -f |
Nota 6: Se sul gateway ci sono configurate più interfacce di rete da monitorare ho notato che conviene far girare un processo distinto per ogni scheda, quindi creare una copia del file di configurazione:
1 |
sudo cp /etc/pmacct/pmacctd.conf /etc/pmacct/pmacctd.eth1.conf |
Modificare il nuovo file di configurazione che legga sulla seconda interfaccia e cambiare lo script di avvio in maniera che mandi in esecuzione due processi distinti, quindi aprire /etc/init.d/pmacctd e nella procedura start() modificare in:
1 2 3 4 5 6 |
... else $DAEMON -f $CONFDIR/pmacctd.conf $DAEMON_OPTS $DAEMON -f $CONFDIR/pmacctd.eth1.conf $DAEMON_OPTS fi ... |