Cómo iniciar una sesión gráfica remota con ssh

A veces, es necesario conectarse a una sesión gráfica a un servidor (equipo remoto) e interactuar con las aplicaciones como si se estuviera al frente de la pantalla.
Básicamente hay varias maneras de hacerlo, yo he usado las tres siguientes:
a) TeamViewer (se instala en ambos equipos)
b) VNC como demonio en el servidor
c) Con X11 forwarding en una conexión por terminal ssh
Pero en este caso, y la razón del porqué escribo esta publicación es porque el firewall de la universidad donde trabajo bloquea los puertos poco usuales y eso me impide usar VNC (puerto 5901) o el TeamViewer (puertos 5938 y 5939) para conectarme a mi servidor.
En mi caso, afortunadamente, el puerto 22 (ssh) si es accesible desde afuera de la red universitaria.
Así pues, no me quedó más alternativa que usar X11 Forwarding a través de ssh
Antes que otra cosa, se debe configurar en el servidor remoto el servicio de SSH para habilitar el modo gráfico a través de una terminal de manera remota; también cabe destacar que para configurar y/o reiniciar el servicio de SSHD se requieren permisos de root en el servidor remoto. Lo bueno de ser root es que puedes hacer eso y más…
1) Empezamos por habilitar el parámetro de X11 forwarding en el archivo de configuración del servicio SSH en el servidor:

sudo vi /etc/ssh/sshd_config
Luego hay que agregar o editar las siguientes líneas al archivo de configuración:
X11Forwarding yes

X11UseLocalhost yes

X11DisplayOffset 10

AllowTcpForwarding yes

XAuthLocation /usr/bin/xauth

TCPKeepAlive yes
2) Guardar los cambios del archivo y reiniciar el servicio de ssh:

sudo /etc/init.d/ssh restart
3) En el equipo local se requiere instalar un cliente para X11. Las dos opciones siguientes son free y open-source
Para macOS X, se requiere de XQuartz:
Para Windows se puede usar Xming:
4) Después de instalar el cliente X11, abrimos una terminal en el equipo local y se agrega el dominio o número IP del host remoto
 anteponiendo un signo + en el nombre o el ip:
xhost +dominio.remoto.com
5) Conectarse por SSH al equipo remoto habilitando la opción de X11 forwarding: -X y la compresión de transmisión de datos -C para hacer más fluida la conexión

ssh -XC javiercamacho@dominio.remoto.com
6) Una vez que se ha iniciado la sesión por ssh en el equipo remoto, se debe lanzar el gestor gráfico (por ejemplo: Xfce):
/usr/bin/xfce4-session &
O la aplicación gráfica deseada, por ejemplo G-edit:
gedit /etc/resolv.conf
7) Enjoy it! ;-)
Espero que esto le sea útil a alguien más.
Anuncios

Script en bash para respaldar MySQL

En el ámbito personal, muchas veces pasamos por alto la importancia de contar con un respaldo de nuestra información y continuamos sin preocuparnos hasta que llega en día en que por alguna desafortunada situación te preguntas con tristeza: “¿Porqué no hice un respaldo?”

En el ámbito laboral, ni siquiera debes pensar como una alternativa el contar con respaldos, ahí debes tenerlos obligadamente, “por si acaso” llegan a ser necesarios.

En ese tenor, y como administrador de sistemas en Linux, quiero compartir un script muy pequeñito que hice en mi trabajo para respaldar bases de datos de MySQL del servidor, lo que me gustó como resultado final, es que en cada carpeta se crea un archivo comprimido e independiente por cada base de datos; creo que resulta más práctico administrar la restauración de una base de datos de esta manera en lugar de tener un enooorme archivo con tooodas las bases de datos; también le agregué un par de líneas para realizar la rotación de respaldos, eliminando los más antiguos y conservando siempre los más recientes.

Archivo:  backup_mysqldb_cron.sh

Código:

#!/bin/bash

# MySQL credentials for connection
 user="root"
 password="secretPassword"
 host="localhost"

# WARNING: Never user the root "/" as backup_path
# This folder must be exist:
 backup_path="/backups/srv/www/mysqlbackup"

# The maximum of backups to keep
# (the oldest backups will be erased)
 maximum_backup_folders=3

# Create a folder using actual date to storage the backup
 date=$(date +"%Y-%m-%d_-_%H-%M-%S")
 mkdir $backup_path/$date

# Get a list of all databases in MySQL
 databases=$(mysql --user=$user --password=$password -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema)")

# Create a file dumps for each database
 for db in $databases
  do
   mysqldump --user=$user --password=$password --host=$host $db | gzip -9 > $backup_path/$date/$db.sql.gz
 done

# Remove the oldest backups
 total_backup_folders=$(ls -tr $backup_path | wc -l)
 if [ $total_backup_folders -gt $maximum_backup_folders ];then
  to_delete=$(( $total_backup_folders - $maximum_backup_folders ));
  for delete_folder in $(ls -tr $backup_path | head -$to_delete);
   do
    rm -rf $backup_path/$delete_folder;
  done
 fi;

 

Para usar el script, sólo bastará con tener los permisos suficientes en el sistema para hacerlo ejecutable, en una terminal ejecuta la siguiente orden:

chmod +x backup_mysqldb_cron.sh

El script se puede ejecutar directamente desde la consola o bien, agregarlo en una entrada en cron para que se ejecute cada determinado tiempo de forma automática; esto se logra con la siguiente orden desde una consola:

crontab -e

Una vez dentro del editor de cron, se añaden las siguientes líneas:

# backup the mysql databases on separated files at midnight every day
@midnight /root/backup_mysqldb_cron.sh >/dev/null 2>&1

 

Después de guardar los cambios en crontab, habrá que reiniciarlo; en mi entorno se realiza con la instrucción:

/etc/init.d/cron restart

Al final y como siempre, espero que esta pequeña aportación, le sea útil a alguien más.

Denyhosts e IPtables

Tengo bastante tiempo usando Denyhosts para proteger el servidor de mi trabajo contra intentos de intrusión por fuerza bruta, especialmente por el puerto 22 (servicio de ssh).

Denyhosts funciona perfecto y hace lo que promete; cada que un “hacker” [mejor escrito: script kiddie]  intenta acceder por SSH con un nombre de usuario o una contraseña incorrecta más de 3 veces, Denyhost bloquea su IP agregando una entrada al archivo /etc/hosts.deny
De esa manera, el IP ofensivo ya no puede establecer conexión al servidor por el puerto 22

Editando la configuración del script intenté que Denyhost bloqueara todos los puertos para el atacante y que así no tuviera acceso al servidor; ¡pero no lo conseguí!

Después de muchas horas, al final, hice un pequeño script en bash que lee la lista de IPs en /etc/hosts.deny (agregadas previamente por DenyHost) para agregarlas  a iptables; logrando así, bloquear totalmente al ofensor.

Para ejecutar el script, solo hay que darle permisos de ejecución y opcionalmente, agregarlo al crontab
Espero que a alguien más le sirva este script para bloquear con iptables los IPs registrados por Denyhosts.

#!/bin/bash

# I will be kind to the computers in my network segment
MY_NETWORK_SEGMENT=148.228.204.

# File to store IP address
MY_HOSTS_DENY=/root/.hosts_deny

# Die if /etc/hosts.deny file not found
[ ! -f "/etc/hosts.deny" ] && { echo "File /etc/hosts.deny not found."; exit 1; }

# Filter the /etc/hosts.deny to generate MY_HOSTS_DENY file
grep -vE "^#|^S" /etc/hosts.deny | awk {'print $2'} | grep -v $MY_NETWORK_SEGMENT | sort -n > $MY_HOSTS_DENY

while read -r IP
do
 # check if the IP isn't blank
 if [ -n "$IP" ]
  then
   CURRENT_IP=$(iptables-save | grep $IP)
   # if the current IP does not exists in iptables rules then...
   if [ -z "$CURRENT_IP" ]
    then
     # Die IP, Die!
     iptables -A INPUT -p all -s $IP -j DROP
     echo "IP: $IP banned in ALL ports"
   fi
 fi
done <"${MY_HOSTS_DENY}"

# Clean the mess
rm $MY_HOSTS_DENY

Listas en cascada con jQuery, Kendo UI, XML y PHP

El problema es de lo más básico, sobre todo si se considera desde el punto de vista del usuario.

Desde el punto de vista del programador se trata de enlazar dos listas de selección, llenar las listas con los nodos de un archivo XML creado al vuelo a través de una consulta a una base de datos y filtrar la información dependiendo de la selección en la primera lista.
En forma visual se trata de lo siguiente.

Se tienen dos listas, la segunda lista está deshabilitada y se activa hasta que se haga una selección en la primera lista:

Con un XML (que se puede construir fácilmente con PHP) se llena la primera lista:

Cuando se elije una opción; se activa la segunda lista:

En la segunda lista, se filtran los datos del archivo XML para colocar únicamente los nodos que tengan correspondencia con la primera selección:

Ahora bien, para lograr esto, no se necesita reinventar la rueda pero si hay que poner algunas líneas de programación y comprender el proceso como se muestra a continuación:

Sigue leyendo

Cómo hacer el respaldo de moodle y todos los cursos

Empezaré por escribir que no soy un experto en moodle ni tampoco doy asesorías sobre su uso; lo cierto es que, como muchos; he tenido que ir aprendiendo paso a paso algunas cosas sobre la marcha, mientras se va utilizando esta magnífica plataforma educativa. Lo último con lo que me he tenido que enfrentar es con la realización de respaldos periódicos.

En este mini-micro tutorial, probablemente no logre escribir la octava maravilla, pero al menos espero que el compartir la forma en que yo he resuelto el asunto de los respaldos de moodle, le sirva a alguien más y lo ponga en práctica, o bien; que mejore la idea y la comparta con todos los lectores.

Considero que hay dos maneras de realizar respaldos, veamos la primera:

1.- Dentro de Moodle, en su interfaz gráfica se incluyen las herramientas para hacer respaldos de cada curso, de los alumnos inscritos, calificaciones, tareas, etc:

En el bloque administracion (dentro de tu curso) existe un botón llamado copia de seguridad que te permite crear un respaldo del curso con las opciones que tú elijas.

Este respaldo es un paquete zip que deberás restaurar cuando sea necesario, mediante la opción restaurar  en el bloque de administración del sitio.

El mayor dilema de este método es que se tiene que hacer, curso por curso y eso no es muy grato cuando tienes tantos cursos en la plataforma educativa o cuando quieres que cada determinado tiempo se hagan los respaldos de forma automática.

2.- La otra forma, es a través de un script que ejecuta algunas instrucciones directamente en el servidor; además este script se puede agregar al programador de tareas cron, para que se ejecute periodicamente.

Escencialmente lo que se tiene que respaldar es:

  • La base de datos de Moodle
  • La instalación de Moodle
  • Los archivos y recursos de todos los cursos, usuarios, etc.

He creado este script para hacer esas tres tareas consecutivamente; si te interesa usarlo, unicamente tienes que adaptarlo a tus variables de entorno:

#!/bin/bash
#Comprobamos que el usuario es root (super usuario) quien ejecuta este escript.
if [ $UID != 0 ]; then
 echo "No tienes los privilegios necesarios para ejecutar este script."
 echo "Debes ingresar como root, escribe \"su root\" sin las comillas."
 exit 1
fi

#Fecha actual
FECHA=$(date +%F);

#Hora actual
HORA=$(date +%H-%M-%S);

#Nombre del host en donde se ejecuta mysql (si hay dudas, ver moodle/config.php)
DBHOST=localhost

#Nombre de la base de datos  
DBNAME=moodledatabase

#Nombre del usuario que accede a la base de datos en mysql
DBUSER=moodleuser

#Clave de acceso a la base de datos en mysql
#Por defecto, se solicita cada vez que se ejecuta el script
#Pero se puede definir aqui
DBPASSWORD=""

#Directorio con la instalacion de moodle
MOODLE_DIR=/server/www/htdocs/moodle

#Directorio en donde se guardan los archivos de los cursos, las tareas, etc.
MOODLEDATA_DIR=/server/www/moodledata

#Directorio donde se guardaran los respaldos
BACKUP_DIR=/backups/moodle

#Respaldar la base de datos
if [ "$DBPASSWORD" = "" ]; then
 echo -n "Clave de acceso a la base de datos '$DBNAME' en mysql?: "
 read DBPASSWORD
fi
mysqldump -u $DBUSER -p$DBPASSWORD $DBNAME > $BACKUP_DIR/$DBNAME-$FECHA--$HORA.sql

#Comprimir el archivo de respaldo de la base de datos
echo "Desea comprimir el archivo de respaldo de la base de datos [Y/n]?"
echo -n " Valor por defecto [Y]: "
read COMPRESSDBFILE
if [ "$COMPRESSDBFILE" = "n" ]; then
 sleep 0
else
 bzip2 $BACKUP_DIR/$DBNAME-$FECHA--$HORA.sql
fi

#Hacer el archivo.tar.gz con el respaldo de moodle
tar czPf $BACKUP_DIR/moodle-$FECHA--$HORA.tar.gz $MOODLE_DIR

#Hacer el archivo.tar.gz con los archivos de los cursos, tareas, usuarios, etc
tar czPf $BACKUP_DIR/moodledata-$FECHA--$HORA.tar.gz $MOODLEDATA_DIR

##################################### FIN DEL SCRIPT ##################################

Puedes copiar y pegar el código de arriba y guardarlo en un archivo con extensión .sh o bien, bajar el script de este enlace; después sólo tienes que subirlo a tu servidor, editar las variables como son, el nombre de la base de datos, el nombre del usuario, la ubicacion a los directorios de moodle y el directorio donde se guarda el respaldo; para ejecutar el script tienes que cambiarle los permisos de ejecución; desde tu terminal escribe:

chmod +x backupMoodle.sh

y para ejecutarlo:

./backupMoodle.sh

Finalmente, espero que esa publicación sea de ayuda para más personas.

Script para la gestión de usuarios en bash

#!/bin/bash
#Comprobamos que el usuario es root.
if [ $UID != 0 ]; then
 echo "No tienes los privilegios necesarios para ejecutar este script."
 echo "Debes ingresar como root, escribe \"su root\" sin las comillas."
 exit 1
fi

echo
echo "Administración básica de usuarios y grupos en linux"
echo

while [ "$option" != "0" ]
 do
 clear
  echo
  echo "Opciones:"
  echo "---------"
  echo " 1. Agregar un usuario al sistema."
  echo " 2. Cambiar la clave de acceso de un usuario."
  echo " 3. Editar la información personal de un usuario."
  echo " 4. Borrar a un usuario del sistema."
  echo " 5. Crear grupo."
  echo " 6. Agregar un usuario a un grupo."
  echo " 7. Borrar un grupo."
  echo " 0. Salir."
  echo
  echo -n " Ejecutar: "
   read option
   case $option in
    1 )
     echo
     echo -n "Nombre del usuario a crear?: "
     read username
     echo "Con acceso a la línea de comandos bash [Y/n]?"
     echo -n " Valor por defecto [n]: "
     read shell_access
     if [ "$shell_access" = "Y" ]; then
       TERMINAL='/bin/bash'
     else
      TERMINAL='/bin/false'
     fi
     echo "Crear el directorio de trabajo para el nuevo usuario [Y/n]?"
     echo -n " Valor por defecto [Y]: "
     read home_directory
     if [ "$home_directory" = "n" ]; then
      useradd $username -s $TERMINAL
     else
      useradd $username -m -s $TERMINAL
     fi
     echo
    ;;
    2 )
     echo
     echo -n "Nombre del usuario del que se desea cambiar la clave?: "
     read username
     echo
     passwd $username
     echo
    ;;
    3 )
     echo
     echo -n "Nombre del usuario al cual cambiar la información personal?: "
     read username
     echo
     chfn $username
     echo
    ;;
    4 )
     echo
     echo -n "Nombre del usuario a borrar?: "
     read username
     if [ "$username" = "root" ]; then
      echo "Estúpido script, no puedes eliminar al Dios root"
      exit 0
     else
      echo
      echo "Desea borrar el directorio de trabajo y todo su contenido [Y/n]? "
      echo -n " Valor por defecto [n]: "
      read delete_home
     fi
     if [ "$delete_home" = "Y" ]; then
      userdel -r $username
     else
      userdel $username
     fi
     echo
    ;;
    5 )
     echo
     echo -n "Nombre del grupo a crear?: "
     read group
     echo
     groupadd $group
     echo    
    ;;
    6 )
     echo
     echo -n "Nombre del usuario para agregar al grupo?: "
     read username
     echo -n "Nombre del del grupo para agregar el usuario?: "
     read group
     echo
     groupadd $username $group
     echo
    ;;
    7 )
     echo -n "Nombre del grupo a borrar?: "
     read group
     echo
     groupdel $group
     echo
    ;;
    *) 
    ;;
   esac
  done
echo
exit 0

Evitar la sobre escritura de archivos cargados con php

Pues aquí dejo un segmento de código que me parece algo sencillo pero puede ser útil a otros (además de que no compromete la confidencialidad de mis proyectos laborales) y sirve únicamente para renombrar un archivo que se sube por formulario web para evitar la sobrescritura; eso se hace agregando una serie numérica entre el nombre del archivo y su extensión:

<?php
/**
* @author Javier B. Camacho Martínez
* @copyright DGB - Agosto 2009
*/

$fileSize = $_FILES['fileUploaded']['size'];
$fileName= $_FILES['fileUploaded']['name'];
$fileType = $_FILES['fileUploaded']['type'];
$fileTmp
= $_FILES['fileUploaded']['tmp_name'];

// Reemplazar espacios y signos de puntación del nombre de archivo por guiones bajos
$fileName
= preg_replace('/[^a-z0-9-_\-\.]/i','_',$fileName);

// Obtener la extensión del archivo (a veces resulta útil saberlo)
$extFile
= substr($fileName,-4,4); // mantiene desde -4 a 4 caracteres: .txt

// Obtener el puro nombre del archivo (sin la extensión)
$fileName
= substr($fileName,0,-4); // mantiene desde 0 hasta -4 caracteres: carta_a_los_reyes_magos
$uploadsFolder
= './uploads/';

// Si no existe el directorio para almacenar los archivos, crearlo con permisos 777
!
is_dir($uploadsFolder) ? mkdir($uploadsFolder,0777) : null;

// Antes de mover el archivo al directorio, prevenir la sobre escritura
if(
file_exists($uploadsFolder.$fileName.$extFile)){
$counter = 1;
while(@
file_exists($uploadsFolder.$fileName.'_'.$counter.$extFile)) { $counter++;  }
// Si existe se renombra a con un infijo numérico: carta_a_los_reyes_magos_2.txt
$fileName = $fileName.'_'.$counter.$extFile;
}
// Si no existe, no se renombra y queda tal cual: carta_a_los_reyes_magos.txt

else{

$fileName
= $fileName.$extFile;
}

// Mover el archivo a su nuevo hogar:
$statusMovedFile
= move_uploaded_file($fileTmp,$uploadsFolder.$fileName);

// Verificación final
echo
'el status es: '.$statusMovedFile;
?>