PfCentinel V 1.0 Beta – Manager Update Platform/Packages for pfSense Multisite
-
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
-
Hola
Y el código de /usr/local/www/pfCentinel-central.phpEste 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
-
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. -
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
-
Gracias estimado.
-
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
-
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
-
Con poner como ip la de localhost 127.0.0.1 ya va bien para el central. lo he comprobado.
-
Hola
Pues gracias por el dato, no lo había probado con 127.0.0.1 :)
Salu2
-
jajaja, era de cajón. gracias por el tool.
;D -
Ya tenés la v2 de la tool?
-
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
-
+1
-
Ok. Otra forma de desir que andás en vacaciones. ;D Esperamos
-
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