Capítulo 4 - Seguridad y servicios

Capítulo 4

Seguridad y servicios

Una de las ventajas de los sistemas UNIX y por ende su clon Linux es la sencillez, usabilidad y seguridad. Es extremadamente sencillo monitorear y configurar el sistema de logs, automatizar tareas, configurar impresores, sincronizar por red automáticamente la fecha y hora del sistema. Lo sencillo no quita lo seguro, ya que a través del módulo SELinux se implementan políticas de seguridad a nivel kernel haciendo el sistema sumamente robusto y estable ante ataques externos.

Logs: Concepto de registros y auditoría

La auditoría en los sistemas GNU/Linux se centraliza a través de los demonios syslogd, klogd y auditd.
Por estandarización, todos los registros o logs se almacenan en el directorio /var/log/, por ejemplo el archivo /var/log/dmesg registra los mensajes del kernel al inicio o booteo del equipo, mientras que el archivo /var/log/messages registra los mensajes de error estándar en el sistema.
Estos dos archivos son a menudo los más consultados por los sysadmin (administradores de sistemas) y auditores del sistema. El comando dmesg es un equivalente a hacer un cat /var/log/dmesg. Existen otros archivos que también son de utilidad como el /var/log/maillog en el que se guardan los correos de mensajes y errores del sistema (y solo puede ser accedido por el root); el archivo /var/log/secure en el que se almacenan las alertas de seguridad, tcp_wrappers, autenticación y, en caso de estar habilitado, los mensajes del superdemonio xinetd (y solo puede ser accedido por el root); y por último el archivo /var/log/audit/audit.log en el que se auditan los mensajes exclusivos del kernel ya sean de funcionalidad o de seguridad a través de SELinux. Este último registro puede ser accedido a través de los comandos ausearch y aureport y es más completo y detallado que el que se obtiene al ejecutar dmesg). Cualquier aplicación que instalemos generará su propio directorio en el directorio de logs, por ejemplo si instalamos el paquete exim, se generarán un directorio /var/log/exim con los logs de dicho paquete; si instalamos apache será /var/log/httpd; lo mismo para el paquete squid que será /var/log/squid y así sucesivamente.

Configuración de los demonios syslogd y klogd

En los sistemas RHEL existe un mecanismo centralizado de registro de eventos que permite de obtener información detallada sobre errores y mensajes en el sistema. Esto se efectúa a través de un demonio denominado syslogd el cual es configurado a través del archivo /etc/syslog.conf. Los mensajes del sistema pueden ser almacenados en archivos locales dentro del mismo equipo o enviarse a varios usuarios del mismo e incluso enviarse remotamente a otros equipos a través de la red. Cada evento que se registra tiene asociado un grado de severidad. Algunas veces será necesario separar los mensajes de errores críticos o severos en un archivo distinto al de los errores normales o comunes, aunque la configuración por defecto bastará para la mayoría de los sistemas productivos que instalemos. No olvidemos también que aumentar el nivel de registro del sistema aumentará el espacio en disco requerido.
Los mensajes de emergencia o de nivel más alto (severos) son enviados a todos los usuarios, mientras que la mayoría de los mensajes, como pueden ser error del kernel al inicio o errores en aplicaciones del sistema como automount, servicios de logueo, etc, serán escritos en el archivo /var/log/messages. Cada entrada del registro del sistema contiene 4 campos, a saber:

  1. La fecha y la hora del mensaje.
  2. El nombre del equipo de donde proviene el mensaje (útil cuando los logs son enviados a través de la red a un servidor centralizado).
  3. El nombre de la aplicación o subsistema del cual viene el mensaje (por ejemplo: apache, kernel, squid, vsftpd, etc). Generalmente en este campo se agrega el identificador de dicho proceso (PID).
  4. El resto del detalle del mensaje.

Muchas veces encontraremos mensajes repetidos que serán marcado como tales.

Curiosidades: Escribir en el registro con el comando logger
Podemos escribir en el registro de eventos del sistema generado por el demonio syslogd con la aplicación logger. Este comando se ejecuta escribiendo simplemente el comando logger, a continuación el cursor titilará indicando que podemos escribir lo que queramos. Una vez cancelado o finalizado dicho programa podremos visualizar lo escrito en el archivo /var/log/messages. Esto es sumamente útil al programar aplicaciones sobre GNU/Linux.

Tareas administrativas programadas a través de cron

La aplicación cron consiste es un demonio denominado crond que ejecuta procesos o tareas a intervalos regulares (por ejemplo, cada minuto, día, semana o mes). Su archivo principal de configuración crontab, contiene él o los procesos que se ejecutarán junto con su fecha y hora de comienzo programado. Cada usuario tendrá su propio archivo crontab, incluso el root. En conjunto, estos archivos confirman las listas de trabajos y/o tareas para el demonio crond. En RHEL, cualquier usuario puede programar sus propias tareas, esto se debe a que por defecto, aparecen habilitados todos los usuarios para crear su propio archivo crontab. Esta habilitación la hacemos a través del archivo cron.allow y análogamente, bloqueamos usuarios a través del archivo cron.deny, ambos archivos ubicados en el directorio de configuraciones por defecto en los sistemas UNIX y derivados (/etc).
Metiéndonos en un archivo crontab, cada línea del mismo representa una tarea que se compone de una fecha programada seguido de la ruta completa del archivo o comando ejecutable que se desee correr. RHEL al igual que muchas distribuciones de GNU/Linux, implementa las especificación del nombre de usuario dentro del formato como un campo adicional (sexto), con el objetivo de determinar quién ejecutará la tarea especificada (siempre y cuando este usuario exista y tenga permisos autorizados). Aclaramos que esto solo es permitido en el archivo /etc/crontab y en los archivos agregados en el directorio /etc/cron.d/, dado a que allí cada usuario es asignado a una configuración de cron.

Curiosidades: Origen de cron
La denominación cron deriva del griego chronos que significa tiempo. Para los usuarios de los sistemas operativos de MS Windows podríamos defirnirlo como el equivalente a la función Tareas Programadas. Las primeras versiones de este programa datan del año 1979 y solo se podían ejecutar como root. En principio lo que hacía era simplemente una repetición constante de leer el archivo /etc/crontab, determinar si alguna tarea programada se estaba ejecutando tal como se planificó, esperar un minuto y repetir este ciclo indefinidamente (por eso corre como demonio).

Curiosidades: Cron y algunas consideraciones sobre el día
En el quinto campo del archivo crontab se define el día de la semana, siendo 0 el día Domingo, 1 el Lunes y así sucesivamente hasta el 6. Esto es así para la mayoría de las versiones de UNIX como AIX por ejemplo, aunque en los sistemas GNU/Linux se puede definir el número 7 como válido para especificar el día Domingo. No olvidemos que tanto si el tercer campo que define el día del mes como el que quinto que define el día de la semana son restringidos (es decir, en ambos no aparece la definición *), ambos coincidirían con el día actual.

Tareas diarias a través de cron

Ahora que sabemos que es posible programar tareas con cron, podremos utilizarlo para administrar nuestros sistemas. El comando crontab nos permitirá editar, instalar, y ver las tareas o trabajos programados. La sintaxis de este comando es:

crontab [-u usuario] archivo

Los parámetros más utilizados son -l para listar la cantidad de tareas, y -e para editar el archivo de configuración por defecto. El editor de textos utilizado para la configuración al ejecutar el comando mencionado será el definido en las variables de entorno VISUAL y EDITOR, por lo que recomendamos configurar por defecto el mejor editor de textos: vi, como se muestra a continuación:

export EDITOR=vi

Recomendamos agregar esta línea al archivo /etc/profile o .profile para que vi sea el editor por defecto del sistema.

Curiosidades: Que es vi?
Vi es un potente y eficiente editor de texto originalmente escrito por Bill Joy en 1976. Tiene como principal ventaja ser la aplicación de edición estándar en los sistemas de tipo UNIX y la mayoría de los GNU/Linux. Podríamos decir sin temor a equivocarnos que es imposible considerarnos un administrador de sistema sin saber utilizar este editor, ya que en ocasiones de emergencia será la única forma de realizar cambios en el sistema. Existe una versión mejorada denominada vim pero solo aparece por defecto en algunas distribuciones de GNU/Linux.

Dato útil: Funcionamiento básico de vi
El editor de texto vi funciona básicamente en modos diferentes: edición y comandos. En el primero lo que escribamos será agregado al texto, mientras que en el segundo las teclas presionadas representarán algún comando nativo del editor. Este último modo es el que aparece por defecto, por eso para comenzar a escribir en un archivo nuevo debemos presionar la tecla i y luego para salir es : seguido de q y presionamos la tecla ENTER. Al hacer esto último, nos preguntará si querés guardar los cambios, también podemos utilizar :q! seguido de ENTER para salir sin guardar.

Hay otros parámetros menos utilizados como el -r, que borrará todas las tareas programas para el usuario con el que se ejecute. Esto quiere decir que si ejecutamos el siguiente comando:

# crontab -r

Borraremos todas los trabajos planificados para el administrador y por lo tanto todas las tareas administrativas en el sistema. Generalmente, es conveniente utilizar el siguiente comando:

# crontab -e

Con esta instrucción podremos editar la configuración de cron, que consta principalmente de 6 campos: los primeros 5 con valores numéricos, a saber, minuto (puede ser del 0 al 59), hora (puede ser del 0 al 23), día del mes (puede ser del 1 al 31), mes (puede ser del 1 al 12, siendo 1 Enero), y día de la semana (puede ser del 0 al 6 siendo el 0 Domingo); y el último campo (sexto) campo alfanumérico que es el comando a ser ejecutado (junto con sus parámetros en caso de tenerlos).

Figura 1. Principales campos de configuración para crontab.

Esto nos permite programar tareas diarias. Supongamos que en nuestro equipo de escritorio en la oficina tenemos un script ejecutable denominado recreo y queremos que se ejecute cada 15 minutos en el horario laboral, es decir, de Lunes a Viernes de 9:00 a 18:00 hs, es decir, no se ejecutará los fines de semana ni a la noche. Esto se logra escribiendo simplemente la instrucción:

[matias@rhcsa ~]$ echo '*/15 8-17 * * 1-5 echo recreo' | crontab

Podemos comprobar que la tarea fue positivamente agregada al archivo crontab del usuario de ejemplo (matias en este caso):

[matias@rhcsa ~]$ crontab -l
*/15 9-18 * * 1-5 echo recreo

El */15 significa cada 15 minutos. Algunos optan por escribir los minutos de ejecución en lugar de esto, por ejemplo: 0,15,30,45 a efectos prácticos es lo mismo que escribir */15.
El segundo campo dice 9-18, el guión es importante porque indica desde y hasta inclusive. Si hubiésemos puesto 9,18 se ejecutaría solo a las 9:00 y a las 18:00 hs omitiendo las horas que están en el medio.
El tercer campo es un *, lo que significa que el script se ejecutará todos los días del mes, desde el primer día hasta el último.
El cuarto campo representado por un * significa que el script recreo se ejecutará todos los meses del año.
El quinto campo es importante en este caso porque cierra el campo de ejecución de días definido en el tercer campo, ya que dice que se ejecutará desde el día 1 (Lunes) hasta (-,guión) el 5 (Viernes).
El sexto campo es el invocación del script recreo que no tiene parámetros.

Para eliminar esta tarea y todas las que estén definidas en el archivo crontab, debemos escribir:

[matias@rhcsa ~]$ crontab -r

Y como se puede comprobar, no existirán mas tareas para el usuario que invocó dicho comando:

[matias@rhcsa ~]$ crontab -l
no crontab for matias

Aclaramos que en el ejemplo anterior se utilizó el comando echo redireccionado al comando crontab para agregar una tarea, pero esto bien se podría haber realizado escribiendo:

crontab -e

Luego, dentro del archivo crontab agregado la siguiente línea:

*/15 9-18 * * 1-5 echo recreo

Como mencionamos en el apartado anterior, el acceso de cada usuario al cron puede permitirse o prohibirse de acuerdo a los archivos /etc/cron.allow y /etc/cron.deny respectivamente. La aplicación cron depende de archivos de configuración crontab que puede ser el propio /etc/crontab para el sistema o bien puede alojarse en cualquiera de las siguientes carpetas:

- /etc/cron.hourly/
- /etc/cron.daily/
- /etc/cron.weekly/
- /etc/cron.monthly/

Esto significa que agregando un archivo al directorio /etc/cron.hourly/ se ejecutará cada hora, lo mismo sucede para el resto, siendo daily diario, weekly semanalmente, y monthly mensualmente. Ademas de esto, podrán agregarse definiciones en el directorio /etc/cron.d/. Para obtener más información acerca de este comando podemos escribir:

man 5 crontab

El sistema tmpwatch

La aplicación tmpwatch nos permitirá borrar los archivos que no son accedidos durante cierto período. Por ejemplo, en muchos sistemas se hace necesario eliminar diariamente los archivos temporales alojados en el directorio /tmp/. Esta aplicación se ejecuta diariamente a través de cron, que ejecuta el archivo /etc/cron.daily/tmpwatch, el cual puede ser modificado de acuerdo a nuestros requerimientos. La sintaxis de este comando es como la siguiente:

tmpwatch [-u|-m|-c] [-faqstv] [--verbose] [--force] [--all] [--test] \[--fuser ] [--atime|--mtime|--ctime] [--quiet] <hours> <dirs>

Las opciones de este script son:

Opción Descripción
-u, --atime Decide si se deben borrar los archivos en base al tiempo de acceso. Esta es la opción por defecto.
-m, --mtime Decide si se deben borrar los archivos en base al tiempo de modificación del archivo.
-c, --ctime Decide si se deben borrar los archivos en base al tiempo de modificación del inodo.
-a, --all Remueve todos los tipos de archivos, no sólo regulares y directorios.
-d, --nodirs No remover directorios.
-f, --force Remover aún sin permiso de escritura.
-t, --test No remover los archivos.
-s, --fuser Verifica con el comando fuser si los archivos están siendo utilizados.
-v, --verbose Muestra información detallada.

Para ver esto en la práctica, supongamos que nuestro archivo /etc/cron.daily/tmpwatch contiene la siguiente definición:

/usr/sbin/tmpwatch 240 /tmp /var/tmp

Esto significa que diariamente se verificarán todos los archivos y directorios en /tmp y /var/tmp que no fueron accedidos desde hace 10 días (240 horas) y se eliminarán.

En un sistema RHEL 6.4 está será la definición del archivo:

[matias@rhcsa ~]$ cat /etc/cron.daily/tmpwatch
#! /bin/sh
flags=-umc
/usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \
-x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \
-X '/tmp/hsperfdata_*' 10d /tmp
/usr/sbin/tmpwatch "$flags" 30d /var/tmp
for d in
    /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?};      do
    if [ -d "$d" ]; then
        /usr/sbin/tmpwatch "$flags" -f 30d "$d"
    fi
done

El sistema logrotate

En muchas oportunidades es útil rotar los logs del sistema para que no ocupen todo el espacio en disco del sistema. La aplicación logrotate permite en forma automática y planificada borrar y/o comprimir los registros del sistema liberando el tamaña utilizado en nuestro disco rígido. Se configura a través del archivo /etc/logrotate.conf, en el cual especificamos las directivas generales, y en el directorio /etc/logrotate.d/ agregamos un archivo con el procedimiento de rotación específico para cada servicio. Por defecto, esta aplicación se ejecuta a través del demonio crond en forma periódica, aunque es posible ejecutarlo manualmente escribiendo:

# logrotate /etc/logrotate.conf -f

En la práctica agregar una tareas al logrotate es algo sencillo. Por ejemplo, si deseáramos rotar los logs del servicio web Apache, tendríamos que crear dentro de /etc/logrotate.d/ un archivo de texto plano denominado apache y darle los permisos 644, como se muestra a continuación:

touch /etc/logrotate.d/apache ; chmod 644 /etc/logrotate.d/apache

Suponiendo que deseamos que los archivos por defecto de apache, a saber, access_log y error_log, diariamente roten y queden comprimidos durante 1 mes debemos asegurarnos que la definición sea como la siguiente:

/var/log/httpd/access_log {
daily
rotate 31
copytruncate
compress
notifempty
missingok
}

/var/log/httpd/error_log {
daily
rotate 31
copytruncate
compress
notifemptymissingok
}

La primera línea antes de cada símbolo { indica la ruta donde se guardan los logs y su nombre. A continuación se definen las políticas de rotación para dicha ruta como se muestra a continuación:

- daily : Realizar la rotación diariamente.
- rotate 31 : Mantiene las rotaciones de 1 mes (31 días).
- copytruncate : Copia el archivo original de log y vacía su contenido.
- compress : Comprime logs antiguos.
- notifempty : No rota archivos vacíos.
- missingok : Prosigue en caso de que desaparezca un archivo a rotar.

Si necesitamos que luego de rotar el servicio de apache se reinicie debemos escribir dentro de cada definición entre los símbolos { y } lo que se muestra a continuación:

/log/apache2/error_log {
daily
rotate 31
copytruncate
compress
notifempty
missingok
postrotate
/etc/init.d/httpd restart > /dev/null
endscript
}

Siempre que veamos en un script de logrotate las líneas postrotate y endscript, significará que luego de rotar los logs, se ejecutará lo que entre ellas esté. Por ejemplo, para la rotación del MTA (agente de transferencia de correo) exim debemos agregar las siguiente líneas:

postrotate
/usr/bin/killall -HUP exim
endscript

El sistema anacron

El programa anacron permite ejecutar trabajos ni bien inicia el equipo, su principal archivo de configuración es /etc/anacrontab en el que se especifican 4 campos, a saber: si la tareas no ha sido ejecutado en tantos días, número de minutos que debe esperar antes de ejecutarse, identificador único de tarea y la propia tarea a ejecutar (representada a través de un comando incluido sus parámetros de ejecución). Anacron es un programa útil que, al igual que Cron, ejecuta tareas programadas con la diferencia de que asume que el sistema no está encendido todo el día. El objetivo de esta utilidad es controlar la tareas vitales asegurando que se ejecuten y no se pasen pasen por alto en el caso de que estuviesen planificadas mediante el comando cron, ya que en ese caso, las mismas no se ejecutarían una vez que se haya (re)encendido el equipo ya que su tiempo de ejecución expiró. Suele considerarse al comando anacron como un complemento del cron para sistemas que no están encendidos las 24 horas del día, por eso es común utilizarlo en sistemas de escritorios, aunque también se utiliza en entornos corporativos para garantizar la ejecución de tareas críticas, incluso si el sistema tiene una interrupción temporal. Ejemplo de este tipo de tareas son la rotación de las bitácoras, de los logs (registros del sistema), la actualización de los repositorios del sistema, del sistema, etc, las cuales suelen ejecutarse durante la madrugada o en otro período de bajo uso de los recursos del equipo. Tomemos como caso la declaración por defecto de anacron en el archivo /etc/anacrontab en un servidor productivo con la última versión de RHEL:

#Tiempo en días Retardo Identificador Comando
7 60 cron.weekly run-parts /etc/cron.weekly

Esto indica que la próxima vez que se encienda el equipo, se verificará si han pasado 7 días desde la última ejecución, consultado la fecha en el archivo /var/spool/anacron/cron.weekly. De ser así se volverán a correr los scripts del directorio /etc/cron.weekly una vez que haya pasado 1 hora (60 minutos) después de la ejecución de anacron (el comando es run-parts /etc/cron.weekly). Al tener un identificador de tarea único anacron creará un archivo en el directorio /var/spool/anacron con el nombre del mismo. Para el caso citado caso se creará el archivo /var/spool/anacron/cron.weekly cuyo contenido será la fecha de su última ejecución. Por ejemplo, si se ejecutase a través del anacron el comando run-parts /etc/cron.weekly el día 20 de Octubre del corriente año el contenido sería:

# cat /var/spool/anacron/cron.weekly
20121020

Curiosidades: ¿Sustituye anacron a cron?
El comando anacron no sustituye a cron, más bien es un complemento. Mientras que con el primero se pueden programar tareas solo en intervalos menores a días, con el segundo se pueden planificar tareas a ser ejecutadas en horas o minutos, por lo tanto el comando cron es más específico. Además, cron corre como demonio lo que permite planificar tareas luego de encendido el equipo, algo que con anacron no puede lograrse.

Administración de impresoras con CUPS

Concepto de impresión y CUPS

En los sistemas UNIX se accede a la impresora a través de las colas de impresión que permiten almacenar los trabajos de impresión en forma transitoria mientras la impresora se libera. Una cola de impresión irá enviando los trabajos a la impresora seleccionada acorde a ésta se vaya desocupando y en un formato comprensible por la misma. A cada cola de impresión se la vinculará con una impresora y su controlador correspondiente. En cuanto a las impresoras debemos distinguir las locales de las remotas. Las primeras son las que están conectadas físicamente a nuestro servidor en un puerto que puede ser USB o Paralelo. Así, en los sistemas GNU/Linux veremos que /dev/lp0 identifica al primer puerto paralelo, mientras que /dev/lp1 al segundo; y que análogamente, /dev/usb/lp0 representa el primer puerto paralelo sobre USB, /dev/usb/lp1 al segundo y así sucesivamente. RHEL provee dos sistemas de impresión, a saber, LPRng y CUPS, ambos imposible de coexistir en un mismo sistema. Red Hat recomienda utilizar CUPS, ya que es el sistema de impresión por defecto en RHEL.
El concepto de impresoras en RHEL está ligado al modelo cliente-servidor, donde un equipo conectado a la impresora funciona como servidor de impresión y uno o más equipos acceden en calidad de cliente a dicho servidor. Así cada cliente puede cliente podrá enviar trabajos de impresión al servidor de impresión. El servidor de impresión no es más que un daemon o demonio, es decir, un proceso en segundo plano que brinda un servicio local, en este caso aceptando trabajos de impresión, que luego reenvía o procesa él mismo. También puede darse el caso de querer instalar una impresora local, es decir, hacer funcionar en nuestro sistema de escritorio la impresora recientemente adquirida. La configuración de la impresora, tanto local como remota en los sistemas RHEL se realiza por defecto a través del programa CUPS, una aplicación libre que se distribuye bajo licencia GNU General Public License y la versión 2 de la licencia GNU Lesser General Public License. Este programa cuyas siglas significan en ingles: Common Unix Printing System, es una aplicación desarrollada por la empresa Apple Inc. con el objetivo de hacer más sencilla la configuración de las impresoras en los sistemas UNIX y derivados como GNU/Linux. Precisamente la traducción al castellano de las siglas CUPS significan Sistema de impresión común de Unix. Esto significa que es un sistema de impresión modular que funciona con un equipo que funciona como servidor de impresión.

Funcionamiento de CUPS


CUPS tiene la ventaja de soportar los estilos de comandos BSD y System V, ahorrándole a los usuarios la tarea de aprender nuevos comandos para poder imprimir sus archivos. Entre sus principales componentes figuran una cola de impresión con su planificador, un sistema de filtros que convierte datos para imprimir hacia formatos que la impresora conozca, y un sistema de soporte que envía los datos al dispositivo de impresión. El servidor de impresión soporta muchos protocolos, principalmente el IPP cuyas siglas en ingles son Internet Printing Protocol, como base para el manejo de tareas de impresión y de colas de impresión. También soporta SMB, cuyas siglas en inglés significan Server Message Block; dispositivos USB local y incluso provee los comandos tradicionales de línea de comandos de impresión típicos de UNIX. Al instalar CUPS instalaremos un software que se ejecutará como servidor a través de un demonio denominado cupsd que corre en el puerto TCP número 631. Aunque existen varias GUI (interfaces gráficas de usuario) para configurar CUPS, la más recomendable es a través de la interfaz como aplicación Web. Si queremos acceder desde el mismo equipo como si este fuese un cliente (y probablemente lo sea en caso de ser una impresora local y no remota) debemos abrir nuestro browser (explorador) preferido y escribir: http://localhost:631/admin. Allí una vez abierto, podremos seleccionar add printer para agregar una nueva impresora,
completando con datos como el nombre para la cola de impresión, el puerto al cual está conectada la impresora, el modelo de la misma y su respectivo controlador. Cabe destacar que aunque esta tarea es preferible realizar desde la web gráfica en ocasiones será necesario hacerlo a través de la consola. El comando lpadmin configura las impresoras y clases de colas suministradas mientras que el comando lpinfo lista los dispositivos disponibles o los controladores conocidos por el servidor; ambos comandos son indispensable para administrar una impresora en modo texto. Los archivos de configuración de CUPS son principalmente: /etc/cups/cupsd.conf y /etc/cups/printers.conf. Como mencionamos utilizan archivos con extensión .ppd con la configuración de cada impresora y el principal protocolo que maneja es el IPP. Aunque es posible configurar manualmente editando manualmente los mencionados archivos, recomendamos la utilísima funcionalidad de control web remoto (basado en el protocolo HTTP/1.1) tanto para agregar impresoras como para administrar las colas de impresión. Por lo tanto, lo primero será instalar CUPS con la siguiente instrucción:

# yum install cups* -y

Luego, debemos editar el archivo de configuración y permitir el ingreso web solo de forma local como se muestra a continuación:

# vi /etc/cups/cupsd.conf
Order deny,allow
Deny from all
Allow from 127.0.0.1

Para deshabilitar la autenticación con contraseña debemos comentar en el archivo arriba mencionado las siguientes líneas:

AuthType Basic
AuthClass System

Luego, debemos reiniciar el demonios cupsd para que tome los cambios:

# service cups restart

Luego, ingresamos vía web y realizamos la configuración.

Agregar una impresora local


Supongamos, que por ejemplo tenemos un impresora local modelo Deskjet conectada al puerto paralelo de nuestro equipo, el comando para agregarla al sistema será el que se muestra a continuación:

# lpadminp impresora-01Ev parallel:/dev/lp0m deskjet.ppd

Esto significa que el parámetro -p especificará el nombre alfanumérico de la cola de impresión (en este caso impresora-01), mientras que el parámetro -E definirá la cola de impresión que estará activa y lista para recibir trabajos. El resto de los parámetros son intuitivos, el -v indicará de qué puerto se trata (parallel que significa paralelo en este caso, y está representado por el dispositivo /dev/lp0); y el -m asignará el controlador a utilizar de acuerdo al modelo de la impresora (en este caso: deskjet.ppd). Podemos ver una lista completa de los dispositivos soportados por el sistema mediante la ejecución del siguiente comando:

# lpinfov

También es posible agregar una impresora local o remota gráficamente a través del comando system-config-printer o desde el panel de GNOME clickeando en Applications>System Settings>Printing.

Agregar una impresora remota


Como mencionamos, al utilizar el protocolo IPP que es parte de la pila TCP/IP, CUPS permite de forma sencilla configurar una cola de impresión para imprimir sobre una impresora que está conectada remotamente a otro equipo en una red TCP/IP, cambiando solo el dispositivo sobre el cual trabaja la cola de impresión. Al utilizar la herramienta Web debemos ingresar los mismos datos que pondríamos para una impresora local, excepto el dispositivo que será protocolo IPP y la definición del URI (Uniform Resource Identifiers), que es el formato que lleva el nombre de dicho dispositivo. Esta definición generalmente sigue la siguiente sintaxis:

ipp://maquina-remota/printers/impresora-01

Siendo máquina-remota la dirección IP o hostname (nombre del equipo), impresora-01 la cola de impresión definida en el equipo remoto. En forma análoga se puede realizar esta operación de la línea de comandos a través del comando lpadmin, como se muestra a continuación:

lpadminp impresora-localEv ipp://maquina-remota/printers/impresora-01

Como vemos, los valores serán los mismos que en la configuración gráfica (sea vía web a través de system-config-printer o mediante la web local del servidor de impresión CUPS) con la salvedad de que impresora-local será el nombre de la cola de impresión local. Encontraremos más información sobre impresoras remota en la página oficial de CUPS http://www.cups.org/documentation.php/network.html.

Problemas típicos de CUPS


Algunos errores errores frecuentes en CUPS que son:

print_job: Unsupported format 'application/octet-stream'!
Hint: Do you have the raw file printing rules enabled?

Esto se soluciona comentando la siguiente línea en el archivo /etc/cups/mime.types:

application/octet-stream

También será necesario comentar la siguiente línea en el archivo /etc/cups/mime.convs:

application/octet-stream application/vnd.cups-raw

Si no podemos acceder vía web, es muy probable que tengamos nuestro firewall activo, por lo tanto debemos permitir la salida al puerto número 631 del protocolo TCP en la configuración de iptables. Una solución temporal, sobretodo para un equipo que no es servidor, puede ser deshabilitar el firewall, esto se efectúa escribir lo siguiente:

# system-config-securitylevel

Cuando aparezca el menú interactivo, debemos seleccionar Disabled (Deshabilitado si tenemos el sistema instalado en español) y el cortafuegos quedará sin efecto en nuestro sistema.

Configuración gráfica sencilla


Gráficamente es muy sencillo configurar una impresora local o remota en RHEL. Desde el panel superior de GNOME: Applications>System Settings> Printing nos aparecerá el menú de configuración de impresoras. Hacemos click en New (si el sistema está en español será Nuevo) y presionamos Forward (siguiente si está en español) para ingresar al asistente. Una vez allí debemos escribir el nombre que queremos darle a la impresora en el campo Name (Nombre) y una breve descripción en el campo Short Description. La definición para una impresora podría ser la siguiente:

- Name: hplj1020
- Short description: HP LaserJet 1020

Luego de hacer click en Forward (Siguiente), nos aparecerá el puerto y el modelo de la impresora detectada por nuestro sistema. Por defecto, nos permitirá agregar una impresora local, pero bien podremos elegir impresión remota a través de IPP. Si estamos de acuerdo pondremos Forward y Finish (Terminar) para agregar la impresora. En caso de que no aparezca podremos utilizar la opción Rescan devices para que el sistema verifique nuevamente si en alguno de los puertos del sistema, ya sean USB, paralelos o remoto.

Figura 2. Ejecución del comando system-config-printer, también accesible gráficamente desde el panel Sistema>Administración>Impresión.

Figura 3. Seleción de opción Impresora nueva a través del comando system-config-printer.

Figura 4. Configuración de una impresora de red Brother HL-5350DN en el puerto 9100.

Curiosidades: Historia de CUPS
La historia de CUPS de remota al año 1997, cuando Michael Sweet, dueño de Easy Software Products, comenzó a escribirlo. Luego de dos años aparecieron las primeras versiones públicas que utilizaban el protocolo LPD, cuyas siglas en inglés significan Line Printer Daemon. Luego, debido a limitaciones del mencionado protocolo, se cambió al protocolo IPP, cuyas siglas significan Internet Printing Protocol. Con el correr de los años fue estableciéndose como estandar en las distribuciones de GNU/Linux, por eso en marzo de 2002, la empresa Apple Inc. adoptó CUPS como el sistema de impresión en el sistema operativo Mac OS X 10.2 y luego, en febrero de 2007, lo compró.

Dato Útil: Ventajas de CUPS
Como ventaja principal de CUPS podemos mencionar que es un sistema de impresión estandarizado y modularizado, algo impensado anteriormente debido a la gran variedad de impresoras existentes en el mercado y teniendo en cuenta que cada una cada una utiliza su propio lenguaje de impresión y formatos. Por si esto fuera poco, también es capaz de procesar diferentes formatos de datos en el servidor de impresión. Esto hace de CUPS el servidor estandar en las instalaciones de los sistemas de tipo UNIX y las principales distribuciones de GNU/Linux como es el caso de RHEL.

Curiosidades: La vida antes de CUPS
Antes de CUPS, era casi imposible encontrar un sistema de impresión capaz de adaptarse a la gran variedad de impresoras disponible en el mercado, y encima utilizando cada una su propio lenguaje de impresión y formatos. Los sistemas de impresión de System V y de Berkeley, son un ejemplo claro de este tipo de incompatibilidad, ya que fueron durante mucho tiempo para funcionar requirieron de complejos scripts para lograr convertir el formato de datos desde el programa a un formato imprimible. Como no se lograba detectar el formato del archivo que se estaba enviado a la impresora, no se podía corregir y por lo tanto convertir automáticamente el flujo de datos. Encima la conversión de datos se realizaba en cada estación de trabajo y no centralizada en un servidor.

Sincronización horarios con NTP

Muchas aplicaciones como los servidores de base de datos o aplicaciones SAP requieren precisión en la hora del sistema. Muchos servidores tienen configurada correctamente la hora, pero luego de un tiempo sucede algún desfase. Surge entonces la necesidad de tener un servidor centralizado al que los servidores clientes entren y sincronicen su hora de acuerdo al mismo. Aquí entra en juego el concepto de servidor NTP que es la sigla en inglés de Network Time Protocol. Su origen se remonta desde antes de 1985, cuando fue diseñado originalmente en la Universidad de Delaware por David L. Mills junto con un equipo de voluntarios que lo mantienen hasta la fecha. Sencillamente es un protocolo de sincronización horaria a través de Internet mediante el ruteo de paquetes en redes con latencia variable, que permite que cualquier equipo en calidad de cliente actualice su hora. Este protocolo funciona a su vez en el puerto 123 bajo el protocolo UDP, que corresponde a la capa 4 del modelo OSI, es decir, la capa de transporte. Esto significa que no está orientado a conexión, es decir, UDP no hace un control de verifica de paquetes como hace el protocolo TCP, lo que hace ideal para resistir los efectos de la latencia intermitente, es decir, la suma de retrasos temporales. Por eso, es que los servidores NTP permiten logran alta precisión al sincronizar hasta los segundos, de hecho, en Internet puede lograrse una diferencia máxima o margen de 10 milisegundos (1/100 segundos) y en redes locales (LAN) puede llegar a acercarse incluso a una exactitud de 200 microsegundos (1/5000 segundos).

Figura 5. Principales campos de configuración para NTP al ejecutar system-config-date.

Configuración de un cliente NTP


En cada cliente se debe configurar un demonio NTP denominado ntpd que intentará obtener la hora del servidor de hora configurado. Los clientes NTP debe utilizar tres servidores de tiempo. En los sistemas RHEL la herramienta de configuración se ejecuta a través del siguiente comando:

# system-config-date

También es posible configurar NTP manualmente mediante la edición del archivo de configuración /etc/ntp.conf, que en una configuración básica para una red local (con 3 servidores NTP locales) debería ser similar a la siguiente:

server 192.168.0.1
server 192.168.0.2
server 192.168.0.3
driftfile /var/lib/ntp/drift

Hay muchas herramientas para comprobar si la sincronización está funcionando bien. Por ejemplo, el comando ntpq -p nos permite ver el estado de la hora actual del sistema.

# ntpq -p
remote refid st t when poll reach delay offset jitter
=========================================================
====================
*cudns.cit.corne ntp0.usno.navy. 2 u 732 1024 376 31.208 0.261 2.546
LOCAL(0) LOCAL(0) 10 l 13 64 376 0.000 0.000 0.006

El comando ntpdc -c loopinfo nos mostrará el desvío del reloj del sistema en segundos, conforme a la última vez que se contactó con el servidor de hora configurado.

# ntpdc -c loopinfo
offset: -0.003479 s
frequency: 123.625 ppm
poll adjust: 30
watchdog timer: 401 s

Por último, al ejecutar ntpdc -c kerninfo se mostrará la corrección actual acumulada, aunque actualmente se utiliza ntptime o incluso el comando ntpdate -d. Este último determinará la diferencia de tiempos pero al correr con el parámetro -d no modificará el reloj de su sistema.
La precisión de este protocolo radica en su robusto algoritmo de estimación de Keith Marzullo, que permite seleccionar fuentes de origen desordenadas, utilizando la escala UTC, para recabar las mejores muestra de datos. De esta forma, se consideran solo los datos correctos y se descartan los que parezcan tener datos erróneos.
Para activar el servicio de ntpd por defecto en el sistema y que en cada inicio del sistema aparezca en todos los niveles de ejecución (2, 3, 4 y 5), debemos ejecutar lo siguiente:

# chkconfig ntpd on

El comando chkconfig es la aplicación estándar de RHEL para activar o desactivar un servicio al inicio, en este caso, el servicio ntpd. Una vez iniciado el equipo, los servicios se paran, inician y reinician a través del comando service. Por lo tanto, si queremos iniciar el servicio ntpd por primera vez, necesitamos ejecutar:

# service ntpd start

Para reiniciarlo cambiaremos el último parámetro por restart, y para pararlo escribiremos stop en lugar de start.

Figura 6. A través del comando system-config-date podremos cambiar la zona horaria.

Permitir NTP en el firewall


Si nuestro sistema tiene firewall (cortafuegos) habilitado, debemos agregar la instrucción de iptables para permitir el puerto número 123 del protocolo UDP, ejecutando lo siguiente:

# iptables -A INPUT -m state --state NEW -m udp -p udp --dport 123 -j ACCEPT

Para guardar estos cambios de forma permanente, es decir, que al próximo reinicio del equipo esta regla aparezca, debemos escribir:

# service iptables save

También puede editarse manualmente el archivo de configuración del firewall de RHEL, a saber, /etc/sysconfig/iptables y agregarle la siguiente línea:

-A INPUT -m state --state NEW -m udp -p udp --dport 123 -j ACCEPT

Para sincronizar rápidamente la hora en un equipo recién configurado, debemos ejecutar:

# ntpdate -u 0.pool.ntp.org

Seguridad mediante SELinux

Concepto de MAC y control de acceso


La seguridad es un aspecto fundamental en los sistemas informáticos, en cada uno se debe decidir quién puede utilizar los recursos y sus aplicaciones. Aquí es donde entra en juego el concepto de Control de Acceso, es decir, definir un conjunto de criterios para dar derechos y/o permisos a los usuarios y/o aplicaciones. Existen tres modelos principales de control de acceso, a saber, Control de Acceso Obligatorio (en inglés Mandatory Access Control con sus siglas MAC), Control de Acceso Discrecional (en inglés Discretionary Access Control con sus siglas DAC), y Controles de Acceso Basado en Roles (en inglés Rule Based Access Control con sus siglas RBAC).
El DAC es el menos restrictivo de modelos, ya que el usuario final tiene libertad plena para asignar los derechos a los objetos a su conformidad. Esto puede suponer una brecha de seguridad si un atacante o programa malintencionado compromete un cuenta en particular , ya que obtendrá un control completo de los archivos pertenecientes a dicho usuario del sistema. La definición Discrecional es correcta, ya que un usuario puede transmitir sus permisos a otro. Es por eso que es utilizado en los sistemas GNU/Linux como estándar, debido a que los permisos están por grupos y usuarios, y cada usuario puede si lo desea cambiar los permisos de sus archivos, es decir, los archivos que le pertenecen con el comando chmod (aplicación que permite cambiar el owner o propietario de un archivo).
El RBAC es más seguro ya que asigna funciones y/o privilegios a los usuarios. Debido que, tanto a los archivos como a los recursos se les asignan permisos de acuerdo a las funciones que se necesiten, es muy utilizado en empresas y organizaciones. En la práctica significa que, por ejemplo un administrador del sistema podrá crear una función de acceso solamente para los directores, otra para los gerentes y otra para el resto de los empleados, cada una con acceso a distintos recursos.
El MAC es el más seguro de todos ya que las funciones de los usuarios están exclusivamente asignadas por administrador del sistema. Como el usuario final no puede establecer controles de acceso en los archivos, este método de control es el más restrictivo. Debido a su robustez, es utilizado en entidades gubernamentales o empresas privadas que extreman los cuidados de la información.
Una de las máximas de MAC es que cualquier acción no especificada es por defecto negada. Cada archivo binario tendrá definidas políticas definidas, a saber, contexto de seguridad (conocido como credenciales) y reglas para permitir acciones específicas que pueden ser habilitadas o deshabilitadas de acuerdo a una expresión booleana (es decir, 0 o 1). Además, permitirá satisfacer los requerimientos de auditoría ya que dejará grabado en los logs del sistema cada evento.

SELinux en RHEL


Vimos que de los 3 mecanismos de seguridad hay 2 que son más utilizados, a saber, MAC y DAC. La diferencia es que mientras en DAC el acceso esta descentralizado (el propietario de cada objeto es el encargado de asignar los permisos de los diversos usuarios o grupos que accederán al mismo), en MAC en cambio, los objetos y grupos solo tienen atributos y son las políticas las que autorizarán o no una acción.
Es importante entender lo anterior para comprender que es SELinux, ya que el mismo es una implementación del control de acceso MAC a nivel de kernel (núcleo). Esto significa que es transparente y que cada programa no necesitará ser modificado para utilizarlo. SELinux es la alternativa como método de acceso elegida por Red Hat para sus sistemas RHEL desde el mes de Agosto del año 2003. La ventaja principal de utilizar SELinux es limitar el acceso que tienen una aplicación a otra e incluso a los archivos del sistema, impidiendo que un proceso modifique un archivo del usuario propietario, es decir, el que ejecutó el proceso. En la práctica esto significa que un programa cualquiera, llamase Firefox por ejemplo, jamás podrás cambiar el contenido de un archivo del sistema o incluso del propio usuario, como ser el almacén de hosts conocidos de ssh (.ssh/known_hosts). Al utilizar MAC, es el sistema el que se encarga la decisión de habilitar un acceso, contrario a lo que sucedería con un sistema de control de acceso DAC, en donde si un atacante tomará el control del navegador podría modificar los archivos del usuario y comprometer la seguridad.

¿Cómo funciona SELinux?


SELinux se basa en atributos extendidos del sistema de archivos que indican tres cosas: el tipo de usuario (que no necesariamente tiene que coincidir con un usuario del sistema), el rol, y el tipo del objeto.
En la práctica, pueden comprobarse los atributos de un directorio al ejecutar la instrucción ls -lZ. Por ejemplo si estamos ubicados en el directorio de configuración del servidor web Apache (/etc/httpd) esta será la salida del comando mencionado:

[root@rhcsa httpd]# ls -lZ
drwxr-xr-x. root root system_u:object_r:httpd_config_t:s0 conf
drwxr-xr-x. root root system_u:object_r:httpd_config_t:s0 conf.d
lrwxrwxrwx. root root system_u:object_r:httpd_log_t:s0 logs -> ../../var/log/httpd
lrwxrwxrwx. root root system_u:object_r:httpd_modules_t:s0 modules -> ../../usr/lib64/httpd/modules
lrwxrwxrwx. root root system_u:object_r:httpd_config_t:s0 run -> ../../var/run/httpd

En este caso, la configuración por defecto indica que el usuario y rol coinciden, pero el atributo tipo cambia. Estos atributos están definidos en todo el sistema, y su incremento va en forma proporcional a la seguridad que deseamos. En muchas distribuciones con SELinux vienen configurados por defecto varios tipos de atributos en determinadas aplicaciones, pero es perfectamente factible que podamos definir aún más. Para ver todos los tipos disponibles debemos ejecutar el comando que se muestra a continuación:

# getsebool -a

Cada atributo tiene dos políticas, a saber, targeted y strict. Este último (strict) significa modo estricto, y como su nombre indica todo estará denegado por defecto, siguiendo el principio de mínimo privilegio. Este es el modo recomendado, aunque sea tedioso para al administrador del sistema tener que estar habilitando cada una de las funciones manualmente. El primero (targeted) es el modo dirigido o vigilado en el cual sólo los servicios de uso productivo estarán bajo la supervisión de SELinux, como es el caso de las aplicaciones httpd, named, mysqld, postgresql, etc; mientras que el resto estarán libres de restricciones.
Para ver el tipo de política configurada en nuestro sistema, que por defecto es targeted, debemos leer el archivo /etc/sysconfig/selinux, como se muestra a continuación:

[root@rhcsa ~]# cat /etc/sysconfig/selinux
SELINUXTYPE=targeted

Las políticas definen las interacciones entre objetos y pueden utilizar distintos controles de acceso de acuerdo a los atributos extra que utilicen. En la política targeted o vigilada utilizaremos Type Enforcement en el cual se usa únicamente el atributo tipo.

Dato útil: Type Enforcement como método de acceso estándar
Aunque existen otros métodos de control de acceso como el Role-Based Access Control que utiliza los atributos de usuario y rol; generalmente, el modo de acceso mas común es el Type Enforcement, en el cual se usa únicamente el atributo tipo. Esta elección se debe a que la política definida por defecto en los sistemas RHEL es targeted.

En el modo Type Enforcement, el atributo determinante será el atributo tipo de un objecto; así que si un servicio esta en el modo targeted (vigilado) solo podrá acceder a objetos con un tipo similar. Viendo con un caso real, si verificáramos los permisos con los que se está ejecutando un servicio web corriendo con el demonio de Apache, a saber, httpd veremos los objetos con el mismo podrá interactuar:

[root@rhcsa etc]# ps auxZ | grep httpd
user_u:system_r:httpd_t root 3438 0.2 0.4 11845 2924 ? Ss 02:21 0:00
/usr/sbin/httpd

Esto muestra que las políticas definen los tipos similares y las excepciones habilitadas. En el ejemplo citado arriba, el demonio httpd solo podrá interactuar con objetos de un tipo similar, como es el caso de los archivos almacenados dentro del directorio /etc/httpd. Esto representa una gran protección al sistema, ya que aunque exista en el disco un archivo con permisos de lectura y escritura a todos, este no podrá acceder al servicio web de Apache, como se se muestra a continuación:

[root@rhcsa matias]# ls -lZ /home/matias
drwxr-xrwx matias grprhcsa user_u:object_r:user_home_t archivodesprotegido

Esto significa que un usuario malintencionado que acceda y modifique el archivo archivodesprotegido no podrá comprometer el demonio httpd debido a que este último está definido dentro del tipo httpd bajo el dominio de SELinux. El archivo archivodesprotegido pertenece al tipo user_home y no puede acceder a un archivo que pertenece al tipo httpd. Esto se debe a que SELinux, cuyo principal desarrollado es Dan Walsh, es una implementación de un modelo robusto de seguridad basado en políticas y atributos. Como mencionamos, la política por defecto es targeted (vigilado), que protege el sistema de un servicio en peligro, no de los usuarios locales. La mayoría de los procesos locales tiene el atributo tipo definido como unconfined_t.
Para resumir todo lo mencionado, diremos que existen tres modos de ejecución para SELinux, a saber: Enforcing, Permissive y Disabled. Estos modos pueden definirse de forma permanente en el archivo /etc/sysconfig/selinux o a través del comando getenforce (system-config-securitylevel no existe a partir de la versión 6 de RHEL). Para habilitar o deshabilitar SELinux en caliente (sin reiniciar el equipo) debemos ejecutar el comando setenforce con el parámetro 0 o 1 respectivamente. También podremos especificarlo antes de cada inicio modificando los argumentos del kernel, ingresado selinux=0 o enforcing=0 para deshabilitarlo y selinux=1 o enforcing=1 para habilitarlo. Los mensajes de protección se registran en dos archivos, a saber: /var/log/messages y /var/log/audit/audit.log. Para obtener más información podremos escribir el siguiente comando:

man -k selinux


Resumen
Está es una unidad conceptual de como un sistema Linux guarda los eventos que se generan. Estos son lo que se conoce como logs (registros del sistema) se almacenan dentro del directorio /var/log/. Destacando la sencillez de UNIX/Linux en cuanto a su usabilidad: una tarea pueda se programada tan solo con el comando crontab -e, una impresora puede agregarse escribiendo system-config-printer y el sincronización de la hora del sistema a través del protocolo NTP puede configurarse mediante el comando system-config-date. Si bien Linux resalta la eficacia, no por eso deja de lado la seguridad, la cual es implementada a través de SELinux. Esta aplicación identifica y limita los procesos que se ejecutarán en el sistema de acuerdo a su tipo. Se configura con la herramienta system-config-securitylevel.

Actividades

Preguntas teóricas

1- ¿Qué es SELinux?
2- ¿Cuál es la ventajas del protocolo NTP?
3- ¿Cómo configurar una impresora remota a través del comando system-config-printer?
4- ¿Cómo agregar una imprerosa local?
5- ¿Cual es la finalidad de utilizar logrotate?

Ejercicios prácticos

1- Deshabilitar SELinux en un sistema RHEL.
2- Permitir la sincronización horaria a través del firewall.
3- Instalar CUPS y configurar una impresora remota a través del protocolo IPP.
4- Planificar una tarea para que todos los días a la medianoche se reinicie el servidor web Apache (httpd)
5- Configurar tpmwatch para que elimine los temporales todos los días a las 06:00 am.

Plaquetas adicionales

Curiosidades: Ataque DoS local en tmpwatch
El día 12 Septiembre de 2000 el hacker Zenith Parsec descubrió un bug en el tmpwatch (aplicación para eliminar automáticamente los archivos no accedidos durante un periodo determinable) de RedHat 6.1 de que permitía a cualquier usuario con acceso de escritura a /tmp o /var/tmp colgar literalmente el servidor. Esto se debe a que esta programa en realidad es un script que se ejecuta como root, y si bien existían protecciones para no eliminar archivos que no se deben, no existía una protección para el agotamiento de los recursos. RedHat prontamente publicó una errata para resolver el problema.

Dato útil: Agregar texto en vi
Para pasar a modo edición y agregar texto podemos utilizar varias teclas:
i/a, que inserta texto antes/después del carácter sobre el que está el cursor respectivamente.
I/A, que inserta texto al comienzo/final de la línea en la que está el cursor respectivamente.
o/O, que abre espacio para una nueva línea después/antes de la línea en la que está el cursor respectivamente y permite insertar texto en la nueva línea.


Dato útil: Comandos útiles de vi
Ademas de los comandos básicos, en vi existen otros útiles como ser:
ESC, que permite abandonar el modo de edición de texto.
Cntl-F/Cntl-B, que permite avanzar una página hacia adelante/atrás respectivamente.
Cntl-L, para refrescar la pantalla.
G/1G, que sitúa el cursor al final/principio del archivo respectivamente.
$, que sitúa el cursor al final de la línea
0 (cero), que sitúa el cursor al principio de la línea
dd, que elimina toda una línea.