{"id":2185,"date":"2020-02-03T16:16:53","date_gmt":"2020-02-03T14:16:53","guid":{"rendered":"http:\/\/blog.sfsoft.it\/?p=2185"},"modified":"2020-02-03T16:19:07","modified_gmt":"2020-02-03T14:19:07","slug":"monitorare-il-traffico-di-rete-con-pmacct-su-debian-10-buster","status":"publish","type":"post","link":"http:\/\/www.sfsoft.it\/blog\/2020\/02\/03\/monitorare-il-traffico-di-rete-con-pmacct-su-debian-10-buster\/","title":{"rendered":"Monitorare il traffico di rete con pmacct su Debian 10 \u201cBuster\u201d"},"content":{"rendered":"<p>Adattamento dell&#8217;articolo <a href=\"http:\/\/blog.sfsoft.it\/2018\/06\/05\/monitorare-il-traffico-di-rete-con-pmacct-su-ubuntu-18-04\/\" target=\"_blank\" rel=\"noopener noreferrer\">Monitorare il traffico di rete con pmacct su Ubuntu 18.04<\/a> per Debian 10 \u201cBuster\u201d procedendo all&#8217;installazione da sorgenti della versione 1.7.4 ed utlizzando la versione 9 della tabella.<\/p>\n<hr \/>\n<p>Le seguenti operazioni vanno eseguite tramite account di root.<\/p>\n<p>In questo esempio si utilizza un server MySQL esterno quindi se ne esclude la parte di installazione, occorre quindi installare solo la parte client:<\/p>\n<pre class=\"lang:default decode:true\">apt install default-mysql-client<\/pre>\n<p>Per avere le ultime versioni occorre installare da sorgenti, per avere per\u00f2 la comodit\u00e0 dei pacchetti <em>.deb<\/em> si pu\u00f2 utilizzare il programma <em>checkinstall<\/em> per creare un installazione personalizzata (sono richiesti i repo backports):<\/p>\n<pre class=\"lang:default decode:true\">apt install build-essential checkinstall<\/pre>\n<p>Le dipendenze richieste per la compilazione:<\/p>\n<pre class=\"lang:default decode:true\">apt install libpcap-dev default-libmysqlclient-dev<\/pre>\n<p>Si scarica <a href=\"http:\/\/www.pmacct.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">dal sito<\/a> l&#8217;ultima versione e si estrae l&#8217;archivio, ad esempio:<\/p>\n<pre class=\"lang:default decode:true\">wget http:\/\/www.pmacct.net\/pmacct-1.7.4.tar.gz\r\ntar xzvf pmacct-1.7.4.tar.gz\r\ncd pmacct-1.7.4<\/pre>\n<p>Si procede alla preparazione dei sorgenti, ricordandosi di abilitare il plugin che ci interessa ( nel mio caso uso <em>MySQL<\/em> ) e infine richiamando <em>checkinstall<\/em> al posto di <em>makeinstall<\/em> verr\u00e0 creato ed installato il pacchetto <em>.deb<\/em>:<\/p>\n<pre class=\"lang:default decode:true\">.\/configure --enable-mysql\r\nmake\r\ncheckinstall<\/pre>\n<p>L&#8217;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&#8217;installazione:<\/p>\n<pre class=\"lang:default decode:true \">mkdir \/usr\/local\/lib\/pmacct\r\nmkdir \/usr\/local\/lib\/pmacct\/examples<\/pre>\n<p>Copiare a mano i file di esempio:<\/p>\n<pre class=\"lang:default decode:true\">cp -R sql\/ \/usr\/share\/doc\/pmacct\/<\/pre>\n<p>E&#8217; possibile ora cancellare i sorgenti in quanto se volessimo disinstallarlo essendo stato pacchettizzato <em>.deb<\/em> basta usare <em>dpkg -r pmacct<br \/>\n<\/em><\/p>\n<p>Se sul server MySQL manca il database si deve creare con la tabella versione 9, che al momento in cui scrivo \u00e8 l&#8217;ultima, se esiste gi\u00e0 un database basta proseguire alla sezione &#8216;<em>Configurare il programma<\/em>&#8216;:<\/p>\n<pre class=\"lang:default decode:true\">mysql -h host -u root -p &lt; \/usr\/share\/doc\/pmacct\/sql\/pmacct-create-db_v9.mysql<\/pre>\n<p>Impostare i permessi di default ( utente <em>pmacct@localhost <\/em> ):<\/p>\n<pre class=\"lang:default decode:true\">mysql -h host -u root -p &lt; \/usr\/share\/doc\/pmacct\/sql\/pmacct-grant-db.mysql<\/pre>\n<p>Cambiare la password:<\/p>\n<pre class=\"lang:default decode:true\">mysql -h host -u root -p<\/pre>\n<pre class=\"lang:default decode:true\">USE pmacct;\r\nUPDATE mysql.user SET Password=PASSWORD('nuova-password') WHERE User='pmacct';\r\nFLUSH PRIVILEGES;<\/pre>\n<p>Configurare il programma:<\/p>\n<pre class=\"lang:default decode:true\">sudo mkdir \/etc\/pmacct\r\nsudo nano \/etc\/pmacct\/pmacctd.conf<\/pre>\n<p>Un esempio di configurazione:<\/p>\n<pre class=\"lang:default decode:true\">! pmacctd configuration\r\n!\r\n!\r\n!\r\ndaemonize: true\r\npidfile: \/var\/run\/pmacctd.pid\r\nsyslog: daemon\r\n!\r\n! interested in in and outbound traffic\r\naggregate: src_host,dst_host,src_port,dst_port\r\n! on this network\r\npcap_filter: net 192.168.1.0\/24\r\n! on this interface\r\ninterface: eth0\r\n!\r\n! storage methods\r\nplugins: mysql\r\nsql_host: localhost\r\nsql_user: pmacct\r\nsql_passwd: nuova-password\r\nsql_db: pmacct\r\nsql_table: pmacct\r\nsql_table_version: 9\r\n!\r\n! refresh the db every 5 minutes\r\nsql_refresh_time: 300\r\n! reduce the size of the insert\/update clause\r\nsql_optimize_clauses: true\r\n! accumulate values in each row for up to 5 minutes\r\nsql_history: 5m\r\n! create new rows on the minute, hour, day boundaries\r\n!sql_history_roundoff: mhd\r\nsql_history_roundoff: m\r\n! in case of emergency, log to this file\r\n!sql_recovery_logfile: \/var\/lib\/pmacct\/recovery_log\r\n! try to use only INSERT\r\nsql_dont_try_update: true<\/pre>\n<p>Avviare il demone e controllare sul nostro database i record che vengono inseriti:<\/p>\n<pre class=\"lang:default decode:true\">sudo pmacctd -f \/etc\/pmacct\/pmacctd.conf<\/pre>\n<p>E&#8217; anche possibile creare il file di avvio, si crea ad esempio uno script <em>\/etc\/init.d\/pmacctd<\/em>:<\/p>\n<pre class=\"lang:default decode:true\">#! \/bin\/sh\r\n### BEGIN INIT INFO\r\n# Provides:          pmacct-daemons\r\n# Required-Start:    $local_fs $remote_fs\r\n# Required-Stop:\r\n# Default-Start:     2 3 4 5\r\n# Default-Stop:      0 1 6\r\n# Short-Description: pmacct daemons initscript\r\n# Description:       pmacct daemons initscript\r\n### END INIT INFO\r\n\r\n# Author: Pier Carlo Chiodi (aka Pierky) &lt;pierky@pierky.com&gt;\r\n#         http:\/\/www.pierky.com\r\n#\r\n# This script is aimed to manage multiple instances of pmacct daemons\r\n# (http:\/\/www.pmacct.net\/ by Paolo Lucente)\r\n#\r\n# For each daemon (pmacctd|nfacctd|sfacctd|uacctd), one or more\r\n# instances may be managed; instances are mapped one-to-one to\r\n# configuration files that are in the $CONFIG_DIR directory\r\n# (\/etc\/pmacct by default). Configuration files' names must\r\n# follow this schema:\r\n#\r\n#  &lt;daemon_name&gt;[.&lt;instance_id&gt;].conf\r\n#\r\n# An instance's name is composed by the name of the daemon + \".\" +\r\n# an optional instance ID; if the instance ID is omitted the\r\n# \"default\" ID is used.\r\n#\r\n# Example:\r\n#\r\n#  pmacctd.conf ---&gt; daemon = pmacctd, instance = \"pmacctd.default\"\r\n#  pmacctd.2.conf -&gt; daemon = pmacctd, instance = \"pmacctd.2\"\r\n#  nfacctd.1.conf -&gt; daemon = nfacctd, instance = \"nfacctd.1\"\r\n#\r\n# The second argument of this script may be used to selectively\r\n# start\/stop a single instance; if omitted, all the instances\r\n# are started\/stopped:\r\n#\r\n# Example:\r\n#\r\n#  \/etc\/init.d\/pmacct start pmacctd.default\r\n#\r\n#  service pmacct stop nfacctd.1\r\n#\r\n# Daemons are started with -D option (Daemonize) and with\r\n# -F option (PID file) pointing to $PIDDIR\/&lt;instance_id&gt;\r\n# (PIDDIR default to \/var\/run\/pmacct). It's safe to avoid\r\n# using the \"pidfile\" and \"daemonize\" keys in the configuration\r\n# file.\r\n\r\nPATH=\/sbin:\/usr\/sbin:\/bin:\/usr\/bin:\/usr\/local\/sbin\r\nDESC=\"pmacct daemons\"\r\nSCRIPTNAME=\"pmacct\"\r\n\r\nCONFIG_DIR=\/etc\/pmacct\r\nPIDDIR=\/var\/run\/pmacct\r\nDAEMONDIR=\/usr\/local\/sbin\r\n\r\nmkdir -p $PIDDIR &gt;\/dev\/null 2&gt;&amp;1 || true\r\n\r\n# Load the VERBOSE setting and other rcS variables\r\n. \/lib\/init\/vars.sh\r\n\r\n# Define LSB log_* functions.\r\n# Depend on lsb-base (&gt;= 3.2-14) to ensure that this file is present\r\n# and status_of_proc is working.\r\n. \/lib\/lsb\/init-functions\r\n\r\nCONFIGS=`cd $CONFIG_DIR; ls *.conf 2&gt;\/dev\/null | egrep -e \"^(pmacctd|nfacctd|sfacctd|uacctd).\"`\r\n\r\nif [ -z \"$CONFIGS\" ]; then\r\n        log_failure_msg \"ERROR: no pmacct configuration instances found on $CONFIG_DIR. Please refer to comments in $0 for more details.\"\r\n        exit 1\r\nfi\r\n\r\nSELECTED_INSTANCE=\"$2\"\r\n\r\nsignal_to_childprocesses()\r\n{\r\n        # $1 PID\r\n        # $2 Signal\r\n\r\n        for PID in `ps --ppid $1 -o pid h`\r\n        do\r\n                kill -$2 $PID\r\n        done\r\n}\r\n\r\n# Function that starts the daemon\/service\r\n#\r\ndo_start()\r\n{\r\n        # Return\r\n        #   0 if daemon has been started\r\n        #   1 if daemon was already running\r\n        #   2 if daemon could not be started\r\n\r\n        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test &gt; \/dev\/null \r\n                || return 1\r\n        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \r\n                $DAEMON_ARGS \r\n                || return 2\r\n}\r\n\r\n#\r\n# Function that stops the daemon\/service\r\n#\r\ndo_stop()\r\n{\r\n        # Return\r\n        #   0 if daemon has been stopped\r\n        #   1 if daemon was already stopped\r\n        #   2 if daemon could not be stopped\r\n        #   other if a failure occurred\r\n\r\n        RETVAL=\"2\"\r\n\r\n        if [ -f $PIDFILE ]; then\r\n                signal_to_childprocesses `cat $PIDFILE` INT\r\n\r\n                for w in 2 5 10\r\n                do\r\n                        # wait for child processes to end\r\n\r\n                        sleep $w\r\n\r\n                        if [ -f $PIDFILE ]; then\r\n                                ps `cat $PIDFILE` | grep $DAEMON_NAME &gt;\/dev\/null\r\n\r\n                                if [ $? -ne 0 ]; then\r\n                                        RETVAL=\"0\"\r\n                                        break\r\n                                fi\r\n                        else\r\n                                RETVAL=\"0\"\r\n                                break\r\n                        fi\r\n                done\r\n\r\n                if [ \"$RETVAL\" -ne \"0\" ]; then\r\n                        if [ -f $PIDFILE ]; then\r\n                                ps `cat $PIDFILE` | grep $DAEMON_NAME &gt;\/dev\/null\r\n\r\n                                if [ $? -eq 0 ]; then\r\n                                        start-stop-daemon --stop --quiet --retry=TERM\/30\/KILL\/5 --pidfile $PIDFILE --name $DAEMON_NAME\r\n                                        RETVAL=\"$?\"\r\n                                fi\r\n                        fi\r\n                fi\r\n\r\n                rm -f $PIDFILE\r\n                return \"$RETVAL\"\r\n        else\r\n                return \"2\"\r\n        fi\r\n}\r\n\r\ndo_reload() {\r\n        if [ -f $PIDFILE ]; then\r\n                #signal_to_childprocesses `cat $PIDFILE` USR2\r\n                kill -USR2 `cat $PIDFILE`\r\n                return 0\r\n        else\r\n                return 1\r\n        fi\r\n}\r\n\r\nfor CONFIG in $CONFIGS\r\ndo\r\n        INSTANCE=${CONFIG%%.conf}\r\n        DAEMON_NAME=`echo ${CONFIG%%.} | cut -d\".\" -f1`\r\n        if [ \"$INSTANCE\" = \"$DAEMON_NAME\" ]; then\r\n                INSTANCE=\"$DAEMON_NAME.default\"\r\n        fi\r\n        DAEMON=$DAEMONDIR\/$DAEMON_NAME\r\n        PIDFILE=$PIDDIR\/$INSTANCE\r\n        DAEMON_ARGS=\"-F $PIDFILE -D -f $CONFIG_DIR\/$CONFIG\"\r\n\r\n        #echo \"INSTANCE: $INSTANCE\"\r\n        #echo \"DAEMON_NAME: $DAEMON_NAME\"\r\n        #echo \"DAEMON: $DAEMON\"\r\n        #echo \"PIDFILE: $PIDFILE\"\r\n        #echo \"DAEMON_ARGS: $DAEMON_ARGS\"\r\n        #continue\r\n\r\n        if [ -z \"$SELECTED_INSTANCE\" -o \"$SELECTED_INSTANCE\" = \"$INSTANCE\" ]; then\r\n                case \"$1\" in\r\n                  start)\r\n                        [ \"$VERBOSE\" != no ] &amp;&amp; log_daemon_msg \"Starting $DAEMON_NAME, instance $INSTANCE\"\r\n                        do_start\r\n                        case \"$?\" in\r\n                                0|1) [ \"$VERBOSE\" != no ] &amp;&amp; log_end_msg 0 ;;\r\n                                2) [ \"$VERBOSE\" != no ] &amp;&amp; log_end_msg 1 ;;\r\n                        esac\r\n                        ;;\r\n                  stop)\r\n                        [ \"$VERBOSE\" != no ] &amp;&amp; log_daemon_msg \"Stopping $DAEMON_NAME, instance $INSTANCE\"\r\n                        do_stop\r\n                        case \"$?\" in\r\n                                0|1) [ \"$VERBOSE\" != no ] &amp;&amp; log_end_msg 0 ;;\r\n                                2) [ \"$VERBOSE\" != no ] &amp;&amp; log_end_msg 1 ;;\r\n                        esac\r\n                        ;;\r\n                  status)\r\n                        if [ -f $PIDFILE ]; then\r\n                                ps `cat $PIDFILE` | grep \"$DAEMON_NAME\" &gt;\/dev\/null\r\n\r\n                                if [ $? -eq 0 ]; then\r\n                                        log_success_msg \"$DAEMON_NAME, instance $INSTANCE is running\"\r\n                                else\r\n                                        log_failure_msg \"$DAEMON_NAME, instance $INSTANCE is not running\"\r\n                                fi\r\n                        else\r\n                                log_failure_msg \"$DAEMON_NAME, instance $INSTANCE is not running\"\r\n                        fi\r\n                        ;;\r\n                  reload)\r\n                        log_daemon_msg \"Reloading $DAEMON_NAME, instance $INSTANCE\"\r\n                        do_reload\r\n                        log_end_msg $?\r\n                        ;;\r\n                  restart|force-reload)\r\n                        log_daemon_msg \"Restarting $DAEMON_NAME, instance $INSTANCE\"\r\n                        do_stop\r\n                        case \"$?\" in\r\n                          0|1)\r\n                                do_start\r\n                                case \"$?\" in\r\n                                        0) log_end_msg 0 ;;\r\n                                        1) log_end_msg 1 ;; # Old process is still running\r\n                                        *) log_end_msg 1 ;; # Failed to start\r\n                                esac\r\n                                ;;\r\n                          *)\r\n                                # Failed to stop\r\n                                log_end_msg 1\r\n                                ;;\r\n                        esac\r\n                        ;;\r\n                  *)\r\n                        echo \"Usage: $SCRIPTNAME {start|stop|status|restart|reload}\" &gt;&amp;2\r\n                        exit 3\r\n                        ;;\r\n                esac\r\n        fi\r\ndone\r\n:<\/pre>\n<p>E lo si abilita:<\/p>\n<pre class=\"lang:default decode:true \">update-rc.d pmacctd defaults<\/pre>\n<p><strong>Nota<\/strong>: ho notato che su reti diciamo discrete la mole di dati generata influisce notevolmente sulle prestazioni richieste dal server <em>MySQL<\/em>, ogni tanto \u00e8 cosigliato spostare i dati storici su una copia della tabella meglio ancora su un altro <em>database<\/em>\/<em>host<\/em> ed \u00e8 comunque consigliato avere MySQL impostato con l&#8217;opzione di creare le tabelle su singoli files.<\/p>\n<p><strong>Nota 2<\/strong>: se il traffico \u00e8 elevato e si usa il raggruppamento \u00e8 possibile che venga richiesto un server <em>MySQL<\/em> con alte prestazioni di <em>CPU<\/em> e di <em>I\/O<\/em> su disco in quanto le istruzioni di <em>UPDATE<\/em> sono molte, in tal caso ridurre il periodo di raggruppamento ( es. da 30m a 5m ) e usare l&#8217;istruzione &#8220;<em>sql_dont_try_update: true<\/em>&#8221; che usa la memoria per limitare al massimo le istruzioni di <em>UPDATE<\/em>, appoggiandosi a versioni <em>InnoDB<\/em> invece che <em>MyISAM<\/em> delle tabelle.<\/p>\n<p><strong>Nota 3<\/strong>: Nel caso servisse recuperare i dati dal file di recupero ( <em>recovery_log<\/em> ) utilizzare il comando <em>pmmplay<\/em>:<\/p>\n<pre class=\"lang:default decode:true\">pmmplay -d -f \/var\/lib\/pmacct\/recovery_log -U &lt;utentemysql&gt; -P &lt;passwordmysql&gt;<\/pre>\n<p>Se serve solo testare cosa c&#8217;\u00e8 nel file senza fare modifiche al database aggiungere il parametro <em>-t<\/em>.<\/p>\n<p>Sul <a href=\"http:\/\/wiki.pmacct.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">wiki ufficiale<\/a> per\u00f2 sconsigliano di utilizzare il file di recupero dicendo che sar\u00e0 dismesso ma di utilizzare eventualmente un DB di backup:<\/p>\n<blockquote><p><em>While planning for a recovery method, consider that the logfile method is being discontinued and you are encouraged to use the backup DB option.<\/em><\/p><\/blockquote>\n<p><strong>Nota 4<\/strong>: Nel caso si utilizzi un server <em>MySQL<\/em> esterno controllare che le due macchine abbiano lo stesso <em>timezone<\/em> tramite il comando <em>date<\/em>, in caso siano diversi occorre riconfigurarlo per impostarlo uguale, riavviare anche <em>MySQL<\/em> dopo:<\/p>\n<pre class=\"lang:default decode:true\">sudo dpkg-reconfigure tzdata\r\nsudo service mysql restart<\/pre>\n<p>Per tenere anche sincronizzati gli orari tramite un NTP server:<\/p>\n<pre class=\"lang:default decode:true \">sudo ntpdate &lt;host-ntp&gt;<\/pre>\n<p><strong>Nota 5<\/strong>: Nel caso servisse controllare eventuali errori fare riferimento al <em>syslog<\/em>:<\/p>\n<pre class=\"lang:default decode:true \"># Gli ultimi log\r\nsudo tail \/var\/log\/syslog\r\n\r\n# Monitor realtime dei log (uscire con CTRL+C)\r\nsudo tail \/var\/log\/syslog -f<\/pre>\n<p><strong>Nota 6<\/strong>: Se sul gateway ci sono configurate pi\u00f9 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:<\/p>\n<pre class=\"lang:default decode:true\">sudo cp \/etc\/pmacct\/pmacctd.conf \/etc\/pmacct\/pmacctd.eth1.conf<\/pre>\n<p>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 <em>\/etc\/init.d\/pmacctd<\/em> e nella procedura <em>start()<\/em> modificare in:<\/p>\n<pre class=\"lang:default decode:true \">...\r\n    else\r\n        $DAEMON -f $CONFDIR\/pmacctd.conf $DAEMON_OPTS\r\n        $DAEMON -f $CONFDIR\/pmacctd.eth1.conf $DAEMON_OPTS\r\n    fi\r\n...<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Adattamento dell&#8217;articolo Monitorare il traffico di rete con pmacct su Ubuntu 18.04 per Debian 10 \u201cBuster\u201d procedendo all&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[166,15,3],"tags":[282,167,16,8,205,20],"_links":{"self":[{"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/posts\/2185"}],"collection":[{"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/comments?post=2185"}],"version-history":[{"count":2,"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/posts\/2185\/revisions"}],"predecessor-version":[{"id":2187,"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/posts\/2185\/revisions\/2187"}],"wp:attachment":[{"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/media?parent=2185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/categories?post=2185"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.sfsoft.it\/blog\/wp-json\/wp\/v2\/tags?post=2185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}