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

    PfCentinel V 1.0 Beta – Manager Update Platform/Packages for pfSense Multisite

    Scheduled Pinned Locked Moved Español
    18 Posts 4 Posters 2.1k 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.
    • J
      javcasta
      last edited by

      Hola.

      Gracias a ti por comunicar su funcionalidad. :)

      Salu2

      Javier Castañón
      Técnico de comunicaciones, soporte y sistemas.

      Mi web: https://javcasta.com/

      Soporte scripting/pfSense https://javcasta.com/soporte/

      1 Reply Last reply Reply Quote 0
      • J
        javcasta
        last edited by

        Hola

        Posteo el código (está en mi site, pero a modo de backup y poder leerlo sin hacer download es lo mejor)

        /scripts/pfCentinel-Setup.php

        
        /*
        	pfCentinel-Setup.php
        
        	Copyright (c) 2016 Javier Castañon
          javier@javcasta.com - https://javcasta.com/
        	All rights reserved.
        
        	Redistribution and use in source and binary forms, with or without
        	modification, are permitted provided that the following conditions are met:
        
        	1\. Redistributions of source code must retain the above copyright notice,
        	   this list of conditions and the following disclaimer.
        
        	2\. Redistributions in binary form must reproduce the above copyright
        	   notice, this list of conditions and the following disclaimer in the
        	   documentation and/or other materials provided with the distribution.
        
        	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
        	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
        	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
        	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
        	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        	POSSIBILITY OF SUCH DAMAGE.
        */
        
        set_time_limit(0);
        ini_set('max_execution_time', '0');
        //si no existe dir /scripts lo creamos
        if(!is_dir('/scripts')) {
          mkdir('/scripts');
        }
        
        $existemachines = false;
        if (file_exists('/scripts/machines.csv')) {
          $existemachines = true;    
        }
        
        echo "\033[34m################################################### \033[0m \n";
        echo "\033[31m#         Setup     pfCentinel       2016         # \033[0m \n";
        echo "\033[34m################################################### \033[0m \n";
        echo "\033[34m#by Javier Castan?on.javcasta https://javcasta.com# \033[0m \n";
        echo "\033[34m################################################### \033[0m \n";
        echo "\033[34m################################################### \033[0m \n";
        echo "\033[34m#   host pfCentinel-Setup.php  in /tmp  folder    # \033[0m \n";
        echo "\033[34m################################################### \033[0m \n";
        echo "\033[34m# run via shell: # php /tmp/pfCentinel-Setup.php  # \033[0m \n";
        echo "\033[34m################################################### \033[0m \n";
        // rutina introduccion datos > /scrips/machines.csv
        $goon = true;
        $i = 0;
        
        // condiciones necesarias:
        // cada host tenga habilitado sshd (Enable Secure Shell) en puerto tcp22
        // y no tengan restricciones a conectarse vía ssh al tcp22 desde otro host
        // por lo que es muy recomendable que las IPs de los hosts sean accesibles
        // vía tunel openVPN o IPSec , etc
        
        //Para 5 hosts de media tardará 1 minuto el script pfCenter-central.php
        //por cada host se toma de 10 a 30 sg, para 5 hosts: [ 50 .. 150 ] sg
        
        if ($existemachines) { 
          echo "\n Ya existe /scripts/machines.csv \n";
          $muestra = shell_exec("/bin/cat /scripts/machines.csv");
          echo $muestra . "\n";
          $adddata = readline("Introducimos mas hosts a /scripts/machines.csv ? (y/n): ");
          if ($adddata == "n") die("\nFin.\n");
        }
        
        while ( $goon ) {
          //&& $i <= 4
          $i++;
          echo "...\n";
          echo "\033[31m Introduccion de datos para Host $i \033[0m \n";
          $descripcion = readline("Introduce descripcion Host (p.e: pfMadrid): ");
          $elhost = readline("Introduce IP Host (p.e: 10.0.0.254): ");
          $eluser = readline("Introduce el usuario para el host $descripcion (p.e: root): ");
          echo "Introduce la clave para el usuario $eluser: ";
          `/bin/stty -echo`;
          $lapass = readline();
          `/bin/stty echo`;
          echo "\n";
          echo "Testeando conectividad, usurio:clave ...\n";
          @fdoit($elhost, 22, $eluser, $lapass);
          $escribir = readline("An?adimos $descripcion a /scripts/machines.csv ?(y/n):");
          if ($escribir == "y") fmachinesupdate($descripcion, $elhost, "xxx", "xxx", $eluser, fenydesencripta($lapass, true)); 
          $continuar = readline("Continuamos? (y/n): ");
          if ( $continuar == "n" ) $goon = false;
        
        }
        
        echo "END.\n";
        
        function fdoit($host, $port, $username, $password) {
          $paquetes = "";
          $comando = "pkg version > /tmp/pfcenter-status.tmp";
          fshh($host, $port, $username, $password, $comando);
          echo "Host: $host\n";
          echo "=====================\n";
          $comando = "cat /tmp/pfcenter-status.tmp | grep '^pfSense-pkg' | grep '<' | cut -f 1 -d ' '";
          $paquetes = @fshh($host, $port, $username, $password, $comando);
          if (strpos($paquetes, "ERROR_AUTENTICACION") !== false) { echo "ERROR DE AUTENTICACION\n"; return "ERROR DE AUTENTICACION"; }
          if (strpos($paquetes, "NO_CONEXION") !== false) { echo "NO CONEXION\n"; return "NO CONEXION"; }
          if (strlen($paquetes) < 5) { echo "NO HAY UPDATES PAQUETES\n"; echo " \n"; }
          else echo "HAY UPDATES PAQUETES: Paquetes a actualizar:\n" . $paquetes . "\n";
          $comando = "cat /tmp/pfcenter-status.tmp | grep '^pfSense-2' | cut -c 9- | cut -f 1 -d ' '";
          $vactual = fshh($host, $port, $username, $password, $comando);
          echo "Version pfSense actual: " . $vactual . "\n";
          $comando = "pkg rquery %v pfSense";
          $vdisponible = fshh($host, $port, $username, $password, $comando);
          echo "Version pfSense disponible: " . $vdisponible . "\n";
          if ($vactual !== $vdisponible) echo "HAY UPDATE PLATAFORMA\n";
          echo " \n";
        }
        
        function fpingssh($phost, $pport) {
          $waitTimeoutInSeconds = 2;
          try {
          if($fp = @fsockopen($phost,$pport,$errCode,$errStr,$waitTimeoutInSeconds)){   
           // It worked 
           return true;
          } else {
           // It didn't work
           return false; 
          } 
          fclose($fp);
          } catch(Exception $e) { return false; }
        }
        
        function fshh ( $vhost, $vport, $vuser, $vpass, $vcomando ){
          //if(!$connection) $connection = ssh2_connect($vhost, $vport)or die("The SSH2 connection could not be established.");
          if(fpingssh($vhost, $vport)) {
            set_time_limit(30);
            if(!$connection) {
              $connection = ssh2_connect($vhost, $vport);
              if (!$authentication) {
                $errorautenticacion = false;
                $authentication = @ssh2_auth_password($connection, $vuser, $vpass) or $errorautenticacion = true; //die("Could not authenticate '{$vuser}'");
                if ($errorautenticacion) return "ERROR_AUTENTICACION";
                $stream = ssh2_exec($connection, $vcomando) or die("Error comando...");
                stream_set_blocking( $stream, true );
                $cmd = stream_get_contents($stream);
                return $cmd;
                fclose($stream);
                sleep(1);
              } else return "NO_CONEXION";
            }
            } else {
              return "NO_CONEXION";
            }
          //flush();
        }  
        
        function fenydesencripta($vcadena, $modo) {
          //AES-256 / CBC / ZeroBytePadding - ref http://php.net/manual/es/function.mcrypt-encrypt.php
          $key = pack('H*', "dcb34c7d113acd07b53763052cef08cc66ace029fddbae4e1d427a1cfb2a10b2");
          $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
          $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
          if ($modo) {
            // $modo = true => encripta
            $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $vcadena, MCRYPT_MODE_CBC, $iv);
            $ciphertext = $iv . $ciphertext;
            $ciphertext_base64 = base64_encode($ciphertext);
            return $ciphertext_base64;
          } else {
            // $modo = false => desencripta
            $ciphertext_dec = base64_decode($vcadena);
            $iv_dec = substr($ciphertext_dec, 0, $iv_size);
            $ciphertext_dec = substr($ciphertext_dec, $iv_size);
            $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
            return $plaintext_dec;
          }
        }
        
        function fmachinesupdate($vdescr, $vhost, $vplatform, $vpackage, $vuser, $vpass) {
          $cabeza = '"descr";"host";"platform";"packages";"user";"password"'."\n";
          if (!file_exists('/scripts/machines.csv'))  
          file_put_contents('/scripts/machines.csv', $cabeza );
          $vlinea = '"'.$vdescr.'"'.';'.'"'.$vhost.'"'.';'.'"'.$vplatform.'"'.';'.'"'.$vpackage.'"'.';'.'"'.$vuser.'"'.';'.'"'.$vpass.'"'."\n";
          file_put_contents('/scripts/machines.csv', $vlinea, FILE_APPEND | LOCK_EX);
        }
        
        ?>[/code]
        
        Salu2
        

        Javier Castañón
        Técnico de comunicaciones, soporte y sistemas.

        Mi web: https://javcasta.com/

        Soporte scripting/pfSense https://javcasta.com/soporte/

        1 Reply Last reply Reply Quote 0
        • J
          javcasta
          last edited by

          Hola
          Y el código de /usr/local/www/pfCentinel-central.php

          
          Este script php, tarda entre 10sg a 30sg por host... paciencia :)"."[Feel Free to paypal me][0] [ --- By Javier Castan?on - @JavCasta - 2016][1]";
          
          $form = new Form;
          $section = new Form_Section('pfCentinel: CENTRAL (highly recommended to work with tunnels openVPN or IPsec)');
          
          $form->add($section);
          
          //si no existe dir /scripts lo creamos
          if(!is_dir('/scripts')) {
            mkdir('/scripts');
          }
          
          $existemachines = false;
          if (file_exists('/scripts/machines.csv')) {
            $existemachines = true;    
          }
          
          //csv file to array
          function csv_in_array($url, $delm=";", $encl="\"", $head=true) {
              $out = Array();
              //ref http://php.net/manual/es/function.file.php#105772
              
              $csvxrow = file($url);   // ---- csv rows to array ----
             
              $csvxrow[0] = chop($csvxrow[0]);
              $csvxrow[0] = str_replace($encl,'',$csvxrow[0]);
              $keydata = explode($delm,$csvxrow[0]);
              $keynumb = count($keydata);
             
              if ($head === true) {
              $anzdata = count($csvxrow);
              $z=0;
              for($x=1; $x
          

          Salu2

          Javier Castañón
          Técnico de comunicaciones, soporte y sistemas.

          Mi web: https://javcasta.com/

          Soporte scripting/pfSense https://javcasta.com/soporte/

          1 Reply Last reply Reply Quote 0
          • W
            whitenoise16
            last edited by

            Estimado. Si pongo nombre de máquina en algún caso en vez de la ip de tunel de la máquina no funciona, da no conexion.
            que puede ser?. Gracias por su ayuda.

            1 Reply Last reply Reply Quote 0
            • J
              javcasta
              last edited by

              Hola

              Si pones nombre de máquina o fqdn en el campo host, dependiendo de los registros de tu servicio dns, traducirá ese nombre de host tal vez a una ip pública o una privada (que no sea la del tunel), y puede que en esa interfaz de ese pfSense no tengas habilitado vía reglas del firewall el acceso a sshd (tcp22). Revisa los logs del firewall. Por eso es preferible poner la IP del tunel del host.

              Por cierto, no se recomienda dejar acceso a sshd vía ip pública wan en un firewall pfsense, ya que siempre hay scaneos e intentos de acceso vía ssh por fuerza bruta y si sale un zero day para ssh/freebsd, pues peor todavía :) .

              Salu2

              Javier Castañón
              Técnico de comunicaciones, soporte y sistemas.

              Mi web: https://javcasta.com/

              Soporte scripting/pfSense https://javcasta.com/soporte/

              1 Reply Last reply Reply Quote 0
              • W
                whitenoise16
                last edited by

                Gracias estimado.

                1 Reply Last reply Reply Quote 0
                • J
                  javcasta
                  last edited by

                  Hola

                  De nada.

                  En unos días (o semanas, depende). Pondré la versión 2 de este script.

                  En lugar de un fichero csv, usaré un fichero de bbdd sqlite3 y espero implementar bién lo que me falta de AJAX para que se vea en tiempo real el progreso de todos los registros de los hosts.

                  Salu2

                  Javier Castañón
                  Técnico de comunicaciones, soporte y sistemas.

                  Mi web: https://javcasta.com/

                  Soporte scripting/pfSense https://javcasta.com/soporte/

                  1 Reply Last reply Reply Quote 0
                  • J
                    javcasta
                    last edited by

                    Hola

                    Una duda que me ha llegado por correo (email).

                    Me preguntan si el propio pfSense (central) que ejecuta el script se puede incluir en la bbdd machines.csv.

                    La respuesta es sí (siempre que se defina para ese host en machines.csv la IP de una interfaz LAN o de Tunel y no haya restricciones al tcp/22)

                    Salu2

                    Javier Castañón
                    Técnico de comunicaciones, soporte y sistemas.

                    Mi web: https://javcasta.com/

                    Soporte scripting/pfSense https://javcasta.com/soporte/

                    1 Reply Last reply Reply Quote 0
                    • I
                      iplost
                      last edited by

                      Con poner como ip la de localhost 127.0.0.1 ya va bien para el central. lo he comprobado.

                      1 Reply Last reply Reply Quote 0
                      • J
                        javcasta
                        last edited by

                        Hola

                        Pues gracias por el dato, no lo había probado con 127.0.0.1 :)

                        Salu2

                        Javier Castañón
                        Técnico de comunicaciones, soporte y sistemas.

                        Mi web: https://javcasta.com/

                        Soporte scripting/pfSense https://javcasta.com/soporte/

                        1 Reply Last reply Reply Quote 0
                        • I
                          iplost
                          last edited by

                          jajaja, era de cajón. gracias por el tool.
                          ;D

                          1 Reply Last reply Reply Quote 0
                          • I
                            iplost
                            last edited by

                            Ya tenés  la v2 de la tool?

                            1 Reply Last reply Reply Quote 0
                            • J
                              javcasta
                              last edited by

                              Hola

                              Estoy en ello, tengo nivel medio en php (backend), pero poco nivel en AJAX y javascript (frontend), así que tardaré un poco más :)

                              Salu2

                              Javier Castañón
                              Técnico de comunicaciones, soporte y sistemas.

                              Mi web: https://javcasta.com/

                              Soporte scripting/pfSense https://javcasta.com/soporte/

                              1 Reply Last reply Reply Quote 0
                              • gersonofstoneG
                                gersonofstone
                                last edited by

                                +1

                                Papu!! :V

                                1 Reply Last reply Reply Quote 0
                                • I
                                  iplost
                                  last edited by

                                  Ok. Otra forma de desir que andás en vacaciones.  ;D  Esperamos

                                  1 Reply Last reply Reply Quote 0
                                  • J
                                    javcasta
                                    last edited by

                                    Hola

                                    Tras la actualización de pfSense a la v 2.3.2, el script, si se ejecuta desde un pfSense 2.3.2,  ya no soporta usar localhost (127.0.0.1) como uno de los registros de machines.csv.

                                    También he comprobado que si se ejecuta el script desde un pfSense con versión menor a 2.3.2, la conexión php ssh (ssh2_connect) contra un pfSense 2.3.2 da error, esto es debido a que pfSense 2.3.2 está usando como algoritmo de intercambio de key ssh2 a curve25519

                                    Por lo tanto, si alguien usa este script, conviene que sepa estas circunstancias y lo ejecute desde un pfSense actualizado a su última versión (desde un 2.3.2 la conexión php ssh a una versión menor 2.3 o 2.3.1 o 2.3.1_5 va bien, lo he testeado).

                                    El script no lo he testeado con versiones 2.2.6 y menores. En un firewall, dejar de actualizar durante mucho tiempo o dejar pasar varias versiones es una brecha de seguridad potencial :)

                                    Salu2

                                    Javier Castañón
                                    Técnico de comunicaciones, soporte y sistemas.

                                    Mi web: https://javcasta.com/

                                    Soporte scripting/pfSense https://javcasta.com/soporte/

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