{"id":674,"date":"2008-12-28T21:43:17","date_gmt":"2008-12-28T19:43:17","guid":{"rendered":"http:\/\/www.marblestation.com\/blog\/?p=674"},"modified":"2012-04-26T16:18:58","modified_gmt":"2012-04-26T14:18:58","slug":"securizacion-de-una-ubuntu-server-gnulinux","status":"publish","type":"post","link":"https:\/\/www.marblestation.com\/?p=674","title":{"rendered":"Securizaci\u00f3n de un sistema Ubuntu (GNU\/Linux)"},"content":{"rendered":"<p>\u00daltimamente he escrito varios posts sobre est\u00e1ndares y aspectos m\u00e1s estrat\u00e9gicos de negocio e IT, como por ejemplo:<\/p>\n<ul>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=650\">BS 25999-1: Gesti\u00f3n de la Continuidad del Negocio<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=645\">Cobit, est\u00e1ndar para el buen gobierno de los Sistemas de Informaci\u00f3n<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=646\">ITIL y ISO 20000, marcos de trabajo para servicios IT<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=644\">Metodolog\u00edas de desarrollo<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=635\">Estructurar las organizaciones en procesos<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=660\">PMBOK, Project Management \/ Gesti\u00f3n de proyectos<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=657\">PRINCE2 como complemento a PMBOK para la gesti\u00f3n de proyectos (project management)<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=661\">Metodolog\u00edas \u00e1giles de gesti\u00f3n de proyectos (Scrum, DSDM, Extreme Programming &#8211; XP\u2026)<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=663\">Scrum, gesti\u00f3n \u00e1gil de proyectos \/ agile project management<\/a><\/li>\n<li><a href=\"http:\/\/www.marblestation.com\/blog\/?p=666\">Getting Things Done (GTD), organ\u00edzate con eficacia de David Allen<\/a><\/li>\n<\/ul>\n<p>Es habitual escuchar cr\u00edticas a este tipo de enfoque m\u00e1s estrat\u00e9gico, aludiendo al hecho de que se habla y teoriza mucho pero no se concreta nada. En este nuevo art\u00edculo, en el que ha colaborado Ra\u00fal G\u00f3mez (experto en seguridad t\u00e9cnica), se plasman de forma t\u00e9cnica muchas de las ideas de buena gesti\u00f3n estrat\u00e9gica IT o de negocio.<\/p>\n<p>Vamos a ver c\u00f3mo podemos montar un servidor con Ubuntu Linux que cumpla m\u00ednimamente con las buenas pr\u00e1cticas de seguridad:<\/p>\n<ul>\n<li>Efectuar una configuraci\u00f3n segura<\/li>\n<li>Establecer una pol\u00edtica de contrase\u00f1as<\/li>\n<li>Utilizar herramientas para la gesti\u00f3n de usuarios<\/li>\n<li>Proteger los servicios de red<\/li>\n<li>Garantizar la trazabilidad<\/li>\n<li>Proporcionar herramientas de monitorizaci\u00f3n en tiempo real e hist\u00f3rica para facilitar proyecciones de futuras necesidades<\/li>\n<li>Establecer pol\u00edtica de copias de seguridad<\/li>\n<li>Efectuar tests de stress del sistema<\/li>\n<\/ul>\n<p>Y es que en definitiva el software libre, por m\u00e1s libre y abierto que sea, no tiene porque ser seguro a no ser que se establezca una configuraci\u00f3n adecuada y alineada con las pol\u00edticas\/normativas\/procedimientos de la organizaci\u00f3n.<br \/>\n<!--more--><\/p>\n<h3>Contenido<\/h3>\n<p><a href=\"#1\">1. Configuraci\u00f3n m\u00ednima<\/a><br \/>\n<a href=\"#2\">2. Securizaci\u00f3n del sistema base<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Kernel: par\u00e1metros de seguridad<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Limitando los recursos del sistema<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Memoria, n\u00famero de procesos y sesiones concurrentes<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Espacio en disco<br \/>\n<a href=\"#3\">3. Interacci\u00f3n b\u00e1sica con el sistema<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Shells<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Shell Bash<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Locales: configuraci\u00f3n del idioma<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Mensajes legales e informativos: Issue &#038; motd<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Usuarios privilegiados: sudo<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Sistema de archivos<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Esquema de los permisos de ficheros\/directorios<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Permisos por defecto: UMASK<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Permisos especiales: SUID y SGID<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Directorios con permisos de escritura global<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Archivos sin propietarios<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Detecci\u00f3n de modificaciones de ficheros: Tripwire<br \/>\n<a href=\"#4\">4. Pol\u00edtica de contrase\u00f1as<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Pol\u00edtica global<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Contrase\u00f1as de un solo uso: OTP (One time password)<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Gesti\u00f3n del acceso<br \/>\n<a href=\"#5\">5. Gesti\u00f3n de usuarios<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Creaci\u00f3n de usuarios<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Gestion de cuentas<br \/>\n<a href=\"#6\">6. Servicios b\u00e1sicos del sistema<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Activaci\u00f3n en arranque<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Servicio de correo: Postfix<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Servicio web: Apache<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PHP<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Apache b\u00e1sico<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;M\u00f3dulos de Apache<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Servir por localhost las aplicaciones m\u00e1s criticas<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Base de datos MySQL<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Acceso remoto: SSH<br \/>\n<a href=\"#7\">7. Trazabilidad<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Fecha y hora del sistema<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Logs de usuario con Bash<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Rotaci\u00f3n y conservaci\u00f3n de logs<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;An\u00e1lisis de logs de Apache mediante Awstats<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Envio por correo de los eventos m\u00e1s significativos con logcheck<br \/>\n<a href=\"#8\">8. Monitorizaci\u00f3n del sistema<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Actualizaci\u00f3n autom\u00e1tica de la lista de paquetes del sistema<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Monitorizar desde la consola<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Espacio en disco<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPU<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ancho de banda \/ Bandwidth<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ancho de banda \/ Bandwidth<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Memoria RAM \/ Swap<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Monitorizaci\u00f3n en tiempo real: Nagios<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Ancho de banda consumido con Bandwidthd<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;SNMP<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Soporte \u2018Devices I\/O\u2019 en net-snmp<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Monitorizaci\u00f3n historica: Cacti<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Script Device I\/O para cacti<br \/>\n<a href=\"#9\">9. Seguridad<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Cortafuegos \/ Firewall<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Monitorizaci\u00f3n de firewall con fwlogwatch<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Detecci\u00f3n de intrusos \/ IDS: Snort<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Rootkits<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Control del ancho de banda<br \/>\n<a href=\"#10\">10. Copias de seguridad<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Utilidades rsnapshot<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Informaci\u00f3n de estado<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dpkg y mysql<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tars semanales<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reportes<br \/>\n<a href=\"#11\">11. Tests de stress<\/a><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Sistema<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Conexiones HTTP con httperf<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Conexiones HTTP con Apache Benchmarking tool<br \/>\n<a href=\"#12\">12. Issue tracking<\/a><\/p>\n<h3><a name=\"1\">1. Configuraci\u00f3n m\u00ednima<\/a><\/h3>\n<p>Recomiendo echar un vistazo a la <a href=\"http:\/\/www.marblestation.com\/blog\/?p=595\">Gu\u00eda de referencia r\u00e1pida para la personalizaci\u00f3n de Ubuntu Edgy (6.10) GNU\/Linux<\/a>, aunque la versi\u00f3n de Ubuntu es bastante antigua, la mayor\u00eda de secciones a\u00fan son v\u00e1lidas. En el caso de los servidores, resultan especialmente interesante las siguientes secciones:<\/p>\n<ul>\n<li>Editor de textos de consola Vim<\/li>\n<li>(Des)Compresores<\/li>\n<li>Compartir directorios\/ficheros<\/li>\n<li>Antivirus<\/li>\n<li>Hacking<\/li>\n<li>Conexi\u00f3n SSH sin password<\/li>\n<li>Otros<\/li>\n<li>Otro art\u00edculo: <a href=\"http:\/\/www.marblestation.com\/blog\/?p=246\">Mutt como cliente de correo de consola<\/a><\/li>\n<\/ul>\n<h3><a name=\"2\">2. Securizaci\u00f3n del sistema base<\/a><\/h3>\n<h4>Kernel: par\u00e1metros de seguridad<\/h4>\n<p>El kernel de Linux dispone de diversos par\u00e1metros que nos permiten configurar su actuaci\u00f3n frente al tr\u00e1fico de red. Al iniciar el sistema se establecen los valores de los par\u00e1metros indicados en &#8216;\/etc\/sysctl.conf&#8217;. No obstante, tambi\u00e9n es posible modificarlos mediante el comando &#8216;sysctl&#8217;.<\/p>\n<p>Los par\u00e1metros m\u00e1s importantes a tener en cuenta son:<\/p>\n<p>&#8211; Activar la protecci\u00f3n contra IP spoofing:<\/p>\n<pre>\r\nsysctl -w net.ipv4.conf.default.rp_filter=1\r\nsysctl -w net.ipv4.conf.all.rp_filter=1\r\n<\/pre>\n<p>&#8211; Activar TCP SYN Cookie Protection para minimizar la posibilidad de ataques de denegaci\u00f3n de servicio por ataques de paquetes SYN. No obstante, actualmente ya no se recomienda esta opci\u00f3n dado que las capacidades de los sistemas han aumentado considerablemente y activarlo nos hace perder otras caracter\u00edsticas de TCP (ver <a href=\"http:\/\/lwn.net\/Articles\/277216\/\">recomendaci\u00f3n de Andi Kleen, autor de las SynCookies<\/a>):<\/p>\n<pre>\r\nsysctl -w net.ipv4.tcp_syncookies=1\r\n<\/pre>\n<p>&#8211; Desactivar el reenv\u00edo de paquetes IP (solo es necesario cuando queremos que la m\u00e1quina actue como una pasarela mediante NAT):<\/p>\n<pre>\r\nsysctl -w net.ipv4.ip_forward=0\r\nsysctl -w net.ipv6.ip_forward=0\r\n<\/pre>\n<p>&#8211; Ignorar Broadcasts Request:<\/p>\n<pre>\r\nsysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1\r\n<\/pre>\n<p>&#8211; Activar la protecci\u00f3n contra mensajes de error mal construidos:<\/p>\n<pre>\r\nsysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1\r\n<\/pre>\n<p>&#8211; Desactivar ICMP Redirect Acceptance, mediante los cuales un atacante podr\u00eda indicar al sistema una ruta mejor para llegar a otras redes (habitualmente utilizado por routers). \u00danicamente los permitiremos si proceden de nuestro gateway:<\/p>\n<pre>\r\nsysctl -w net\/ipv4\/conf\/all\/accept_redirects=0\r\nsysctl -w net\/ipv4\/conf\/all\/send_redirects=0\r\nsysctl -w net\/ipv4\/conf\/all\/secure_redirects=1\r\n<\/pre>\n<p>&#8211; Desactivar IP Sourcing routing mediante el cual un atacante podr\u00eda especificar la ruta a seguir para ir desde una IP origen a una destino:<\/p>\n<pre>\r\nsysctl -w net.ipv4.conf.all.accept_source_route=0\r\n<\/pre>\n<p>&#8211; Logear paquetes: Spoofed Packets, Source Routed Packets, Redirect Packets<\/p>\n<pre>\r\nsysctl -w net.ipv4.conf.all.log_martians=1\r\n<\/pre>\n<p>&#8211; Ignorar ICMP Requests PINGs, personalmente prefiero dejarlo a 0 y controlar desde donde y hacia donde permito los pings mediante iptables (firewall). En cualquier caso, si queremos desactivar completamente que el sistema responda a pings:<\/p>\n<pre>\r\nsysctl -w net.ipv4.icmp_echo_ignore_all=1\r\n<\/pre>\n<p>Para consultar los valores actuales:<\/p>\n<pre>\r\nsysctl net.ipv4.conf.default.rp_filter\r\nsysctl net.ipv4.conf.all.rp_filter\r\nsysctl net.ipv4.tcp_syncookies\r\nsysctl net.ipv4.ip_forward\r\nsysctl net.ipv6.ip_forward\r\nsysctl net.ipv4.icmp_echo_ignore_broadcasts\r\nsysctl net.ipv4.icmp_ignore_bogus_error_responses\r\nsysctl net.ipv4.conf.all.accept_redirects\r\nsysctl net.ipv4.conf.all.send_redirects\r\nsysctl net.ipv4.conf.all.accept_source_route\r\nsysctl net.ipv4.conf.all.log_martians\r\n<\/pre>\n<p>Para establecer los nuevos valores de forma permanente para sucesivos reinicios es necesario modificar \/etc\/sysctl.conf.<\/p>\n<h4>Limitando los recursos del sistema<\/h4>\n<p>Se considera una buena pr\u00e1ctica limitar los recursos del sistema utilizados por los usuarios, de forma que minimicemos las probabilidades de que se efect\u00faen ataques de denegaci\u00f3n de servicio contra todo el sistema.<\/p>\n<h5>Memoria, n\u00famero de procesos y sesiones concurrentes<\/h5>\n<p>Para limitar la memoria, el n\u00famero de procesos y las sesiones concurrentes que puede tener cada usuario debemos editar &#8216;\/etc\/security\/limits.conf&#8217;. A modo de ejemplo:<\/p>\n<pre>\r\n# Prevents anyone from dumping core files.\r\n*               hard    core   0\r\n\r\n# This will prevent anyone (except root) from having more than 150 processes, and a warning will be given at 100 processes.\r\n*          soft    nproc  100\r\n*          hard    nproc  150\r\n\r\n# This will prevent anyone in the 'users' group from having more than 150 processes, and a warning will be given at 100 processes.\r\n@users          soft    nproc  100\r\n@users          hard    nproc  150\r\n@users          -       maxlogins 4\r\n\r\n# Address space limit: 2GB\r\n*           hard    as  2097152\r\n# Maximum data size: 128MB\r\n*           hard    data 131072\r\n# Maximum locked-in-memory address space: 128MB\r\n*           hard    memlock 131072\r\n# Maximum resident set size: 1GB\r\n*           hard    rss 1013352\r\n<\/pre>\n<p>En este caso estamos limitando cada usuario (excepto root) a un m\u00e1ximo de:<\/p>\n<ul>\n<li>150 procesos para todos los usuarios<\/li>\n<li>100 procesos para los usuarios del grupo &#8216;users&#8217;<\/li>\n<li>2GB de RAM<\/li>\n<li>4 logins concurrentes<\/li>\n<\/ul>\n<p>Una vez configurado, podemos realizar una sencilla prueba para verificar que el sistema no nos permite crear m\u00e1s de 100 procesos:<\/p>\n<pre>\r\n$ for i in `seq 500`; do sleep 5 & done\r\n<\/pre>\n<h5>Espacio en disco<\/h5>\n<p>Para habilitar las limitaciones de espacio debemos tener montada las particiones afectadas con los par\u00e1metros &#8216;usrjquota&#8217; y &#8216;grpjquota&#8217; en &#8216;\/etc\/fstab&#8217; (journalling quotas). Por ejemplo:<\/p>\n<pre>\r\n\/dev\/sda4 \/ ext4 defaults,errors=remount-ro,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0 1 1\r\n<\/pre>\n<p>Por otra parte, el servicio de quotas (\/etc\/init.d\/quota) debe estar activo. Podemos comprobarlo mediante la aplicaci\u00f3n &#8216;sysv-rc-conf&#8217; (consultar secci\u00f3n de Servicios de esta gu\u00eda).<\/p>\n<p>Podemos activar inmediatamente las quotas mediante:<\/p>\n<pre>\r\ntouch \/aquota.user \/aquota.group\r\nchmod 600 \/aquota.*\r\nmount -o remount \/\r\n\r\nquotacheck -avugm\r\nquotaon -avug\r\n<\/pre>\n<p>Si encontramos algun tipo de problema con quotacheck (p.ej. puede ser que entre en conflicto con gvfs), podemos probar a reiniciar el sistema. <\/p>\n<p>A continuaci\u00f3n, para modificar las quotas de un grupo de usuario determinado:<\/p>\n<pre>\r\nEDITOR=\"vi\" edquota -g users\r\n<\/pre>\n<p>Tendremos que cambiar los n\u00fameros correspondientes, por ejemplo:<\/p>\n<pre>\r\nDisk quotas for group users (gid 100):\r\n  Filesystem                 blocks        soft          hard              inodes     soft     hard\r\n  \/dev\/sda6                  23808        1048576    1572864         37           0        0\r\n  \/dev\/sda7                  10312844   47185920   52428800       8780        0        0\r\n<\/pre>\n<p>En este caso, el sistema realizar\u00e1 un aviso por mail local a los 45GB (45*1024*1024), mientras que el l\u00edmite real se encuentra en los 50GB (50*1024*1024) para el grupo &#8216;users&#8217; y el dispositivo sda7 (p.ej. \/home\/). En el caso de sda6 (p.ej. ra\u00edz \/), el limite blando es 1GB (1*1024*1024) y el duro 1.5 GB (1.5*1024*1024).<\/p>\n<p>Los ficheros que contabilizan dentro de la quota de grupo son aquellos que tienen como propietario el mismo grupo. Es decir, un usuario que pertenece al grupo A y B puede crear archivos asign\u00e1ndolos a uno u a otro hasta agotar ambas quotas. Por este motivo, establecer los l\u00edmites por usuario permite un mayor control:<\/p>\n<pre>\r\nEDITOR=\"vi\" edquota -u usuario\r\n<\/pre>\n<p>Es tambi\u00e9n interesante limitar todos aquellos grupos que corren servicios como apache2.<\/p>\n<p>Podemos ver un resumen de todas las quotas aplicadas:<\/p>\n<pre>\r\n# repquota -s -a\r\n*** Informe para user quotas en dispositivo \/dev\/mapper\/isw_beahgicji_Volume07\r\nPer\u00edodo de gracia de bloque: 7d\u00edas; per\u00edodo de gracia de Inode: 7d\u00edas\r\n                        L\u00edmites de bloque l\u00edmites de archivo\r\nUsuario         usado   blando  duro  gracia   usado bland duro  gracia\r\n----------------------------------------------------------------------\r\nroot      --   63404       0       0          18960     0     0       \r\nusuario1    --    457G       0       0           303k     0     0       \r\nusuario2    +-  10072M   5120M   5120M 6d\u00edas    8780     0     0       \r\nftp       --       4       0       0              1     0     0       \r\nfreevo    --      44       0       0             18     0     0       \r\nmythtv    --      48       0       0             15     0     0       \r\ncouchdb   --     132       0       0             33     0     0       \r\n<\/pre>\n<p>Un usuario puede consultar el estado de su cuota:<\/p>\n<pre>\r\n$ quota -s\r\nDisk quotas for user usuario (uid 1000): \r\n     Filesystem  blocks   quota   limit   grace   files   quota   limit   grace\r\n      \/dev\/vzfs      24      26      28               6       0       0        \r\n<\/pre>\n<p>Cabe destacar que el periodo de gracia (grace limit) es el tiempo que transcurre antes de que el usuario es obligado a cumplir el &#8220;soft limit&#8221;. Para modificarlo:<\/p>\n<pre>\r\n# edquota -t\r\n\r\nPer\u00edodo de gracia antes de imponer l\u00edmites blandos para users:\r\nLa unidad de tiempo puede ser: d\u00edas, horas, minutos, o segundos\r\n  Sistema de archivos Per\u00edodo de gracia de bloque Per\u00edodo de gracia de inode\r\n  \/dev\/mapper\/isw_beahgicji_Volume06                 7d\u00edas                 7d\u00edas\r\n  \/dev\/mapper\/isw_beahgicji_Volume07                 7d\u00edas                 7d\u00edas\r\n<\/pre>\n<p>Finalmente, en caso de agotar la cuota, el usuario recibir\u00e1 el siguiente mensaje:<\/p>\n<pre>\r\n$ cp \/usr\/bin\/dpkg .\r\ncp: writing `.\/dpkg': Disk quota exceeded\r\n<\/pre>\n<h3><a name=\"3\">3. Interacci\u00f3n b\u00e1sica con el sistema<\/a><\/h3>\n<h4>Shells<\/h4>\n<p>La shell es la aplicaci\u00f3n mediante la cual los usuarios pueden interactuar con el sistema. Es recomendable habilitar \u00fanicamente las shells que nos interesen editando &#8216;\/etc\/shells&#8217;:<\/p>\n<pre>\r\n# \/etc\/shells: valid login shells\r\n#\/bin\/csh\r\n\/bin\/sh\r\n#\/usr\/bin\/es\r\n#\/usr\/bin\/ksh\r\n#\/bin\/ksh\r\n#\/usr\/bin\/rc\r\n#\/usr\/bin\/tcsh\r\n#\/bin\/tcsh\r\n#\/usr\/bin\/esh\r\n#\/usr\/bin\/screen\r\n#\/bin\/dash\r\n\/bin\/bash\r\n#\/bin\/rbash\r\n<\/pre>\n<p>\u00danicamente las shells no comentadas seran permitidas, siempre y cuando a\u00f1adamos al principio de &#8216;\/etc\/pam.d\/common-auth&#8217;:<\/p>\n<pre>\r\n# This will not allow a user to change their shell unless\r\n# their current one is listed in \/etc\/shells. This keeps\r\n# accounts with special shells from changing them.\r\nauth       required   pam_shells.so\r\n<\/pre>\n<h4>Shell Bash<\/h4>\n<p>Es interesante configurar la shell Bash para permitir el auto-completado inteligente de comandos (presionando [tab]) editando &#8216;\/etc\/bash.bashrc&#8217; y descomentado:<\/p>\n<pre>\r\n# enable bash completion in interactive shells\r\nif [ -f \/etc\/bash_completion ]; then\r\n    . \/etc\/bash_completion\r\nfi\r\n<\/pre>\n<p>En ese mismo fichero, es recomendable a\u00f1adir los siguiente alias:<\/p>\n<pre>\r\nalias mv='mv -i'\r\nalias cp='cp -i'\r\nalias rm='rm -i'\r\nalias ln='ln -i'\r\nexport EDITOR='vim' \r\nexport TMOUT=3600\r\n<\/pre>\n<p>Esto evitar\u00e1 borrados involuntarios de ficheros dado que cada vez que modifiquemos un fichero mediante mv, cp, rm o ln se pedir\u00e1 confirmaci\u00f3n.<\/p>\n<p>Por otra parte, la variable TMOUT provocar\u00e1 autom\u00e1ticamente un logout de la terminal si no se ejecuta nada durante los segundos especificados (si se est\u00e1 visualizando un programa interactivo como top, no se produce timeout). De esta forma reduciremos las probabilidades de que un usuario se deje su sesi\u00f3n abierta y accesible por otra persona que tenga acceso f\u00edsico a su ordenador.<\/p>\n<p>Cabe destacar que si se ejecuta screen despu\u00e9s de establecer la variable TMOUT, se hereda y se produce logout primero de las ventanas de screen y despues de la sesi\u00f3n que ejecut\u00f3 screen.<\/p>\n<h4>Locales: configuraci\u00f3n del idioma<\/h4>\n<p>Para que el sistema muestre los mensajes en un idioma determinado (p.ej. Castellano):<\/p>\n<pre>\r\napt-get install language-pack-es language-pack-en\r\n<\/pre>\n<p>Y a continuaci\u00f3n editamos &#8216;\/etc\/environment&#8217; y &#8216;\/etc\/default\/locale&#8217;:<\/p>\n<pre>\r\n#LANG=\"en_GB.utf8\"\r\nLANG=\"es_ES.UTF-8\"\r\n\r\nLANGUAGE=\"es_ES:en_EN\"\r\n#LANGUAGE=\"en_GB:en:es_ES:es\"\r\n<\/pre>\n<h4>Mensajes legales e informativos: Issue &#038; motd<\/h4>\n<p>Se recomienda establecer un mensaje legal que notifique a los usuarios que el acceso al sistema es exclusivo para aqu\u00e9llos que han sido autorizados. Para ello se debe editar los ficheros &#8216;\/etc\/issue&#8217; y &#8216;\/etc\/issue.net&#8217;, por ejemplo:<\/p>\n<pre>\r\n***************************************************************************\r\n                           NOTICE TO USERS\r\n\r\nThis computer system is for authorized use only. Use of this system \r\nconstitutes consent to security monitoring and testing. All activity is \r\nlogged with your host name and IP address.\r\n\r\nAny or all uses of this system and all files on this system may be\r\nintercepted, monitored, recorded, copied, audited, inspected, and disclosed \r\nto law enforcement personnel, as well as authorized officials of other \r\nagencies, both domestic and foreign.\r\n\r\nUnauthorized or improper use of this system may result in administrative\r\ndisciplinary action and civil and criminal penalties. By continuing to use\r\nthis system you indicate your awareness of and consent to these terms and\r\nconditions of use. LOG OFF IMMEDIATELY if you do not agree to the conditions\r\nstated in this warning.\r\n\r\n*****************************************************************************\r\n<\/pre>\n<p>Cabe destacar que si queremos que el banner se muestre a los usuarios que se conecten mediante SSH (ver secci\u00f3n de Servicios de esta gu\u00eda), debemos editar &#8216;\/etc\/ssh\/sshd_config&#8217; y descomentar:<\/p>\n<pre>\r\nBanner \/etc\/issue.net\r\n<\/pre>\n<p>Por otra parte, una configuraci\u00f3n segura implica proporcionar la m\u00ednima informaci\u00f3n sobre el sistema al usuario en cuanto a las caracter\u00edsticas del mismo (p.ej. distribuci\u00f3n, kernel, etc). Para minimizar ese aspecto podemos poner en blanco el mensaje de bienvenida (o incluir el mensaje gen\u00e9rico que nos interese):<\/p>\n<pre>\r\necho > \/etc\/motd\r\necho > \/etc\/motd.tail\r\n<\/pre>\n<p>Si lo dejamos en blanco, debemos asegurarnos que el script de inicio &#8216;\/etc\/init.d\/bootmisc.sh&#8217; no lo reconstruye. Para ello lo editamos y comentamos las siguientes lineas:<\/p>\n<pre>\r\n    # Update motd\r\n    #uname -snrvm > \/var\/run\/motd\r\n    [ -f \/etc\/motd.tail ] && cat \/etc\/motd.tail >> \/var\/run\/motd\r\n<\/pre>\n<p>Y por otra parte, editamos &#8216;\/etc\/cron.d\/update-motd&#8217; y comentamos:<\/p>\n<pre>\r\n#*\/10 * * * *    root    [ -x \/usr\/sbin\/update-motd ] && \/usr\/sbin\/update-motd 2>\/dev\/null\r\n<\/pre>\n<h4>Usuarios privilegiados: sudo<\/h4>\n<p>Con el objetivo de garantizar la m\u00e1xima trazabilidad, se requiere que el usuario root no sea utilizado directamente. Para ello podemos configurar el sistema para que el grupo de usuarios que nos interese puedan adquirir privilegios de root editando &#8216;\/etc\/group&#8217; y a\u00f1adiendo:<\/p>\n<pre>\r\nadmin:x:114:miusuario\r\n<\/pre>\n<pre>\r\n\r\nAdemas debemos tener en '\/etc\/sudoers' la siguiente l\u00ednea:\r\n\r\n<\/pre>\n<pre>\r\n# Members of the admin group may gain root privileges\r\n%admin ALL=(ALL) ALL\r\n<\/pre>\n<p>Para editar sudoers siempre debemos utilizar el comando &#8216;visudo&#8217;. Con esta configuraci\u00f3n, el usuario o usuarios del grupo seleccionado (&#8216;admin&#8217; en este caso) podr\u00e1n acceder al sistema normalmente y una vez dentro ejecutar &#8216;sudo comando&#8217; o &#8216;sudo -s&#8217; para adquirir privilegios de root.<\/p>\n<p>Cabe destacar que Ubuntu suele venir configurada as\u00ed por defecto.<\/p>\n<h4>Sistema de archivos<\/h4>\n<h5>Esquema de los permisos de ficheros\/directorios<\/h5>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/observatorio.cnice.mec.es\/images\/upload\/ccam0040\/seguridadlinux\/seguridad1.png\"\/><br \/>\n<\/center><\/p>\n<h5>Permisos por defecto: UMASK<\/h5>\n<p>Es posible establecer los permisos con los que se crean los nuevos ficheros\/directorios, para ello tendremos que editar varios ficheros. El primero es &#8216;\/etc\/login.defs&#8217;:<\/p>\n<pre>\r\nUMASK      022\r\n<\/pre>\n<p>El segundo &#8216;\/etc\/profile&#8217;:<\/p>\n<pre>\r\numask 022\r\n<\/pre>\n<p>Y finalmente, editamos &#8216;\/etc\/pam.d\/common-session&#8217; y a\u00f1adimos al final:<\/p>\n<pre>\r\nsession optional pam_umask.so umask=0022\r\n<\/pre>\n<p>Son necesarios tantos cambios porque en funci\u00f3n de como nos conectemos a la m\u00e1quina (f\u00edsicamente, remotamente por ssh, X Window, etc.) se utilizaran unos scripts u otros.<\/p>\n<p>En cuanto a la mascara, nos podr\u00eda interesar establecer umask como 027 para que todos los ficheros\/directorios creados no tengan permisos de acceso para otros usuarios que no sean los del grupo del propietario.<\/p>\n<p>Ejemplo de funcionamiento de umask:<\/p>\n<pre>\r\n$ umask 000\r\n$ touch file1\r\n$ ls -l file1\r\n-rw-rw-rw-  1 oracle oinstall 0 Dec 26 19:24 file1\r\n$ umask 002\r\n$ touch file2\r\n$ ls -l file2\r\n-rw-rw-r--  1 oracle oinstall 0 Dec 26 19:24 file2\r\n$ umask 022\r\n$ touch file3\r\n$ ls -l file3\r\n-rw-r--r--  1 oracle oinstall 0 Dec 26 19:25 file3\r\n<\/pre>\n<h5>Permisos especiales: SUID y SGID<\/h5>\n<p>Cuando el bit SUID (set user ID) o SGID (set group ID) est\u00e1 activo en un ejecutable, esto implica que ese archivo se ejecutar\u00e1 con los permisos del propietario o grupo propietario respectivamente. Por ejemplo:<\/p>\n<pre>\r\n# ls -la \/bin\/ping\r\n-rwsr-xr-x 1 root root 30856 2007-12-10 18:33 \/bin\/ping\r\n<\/pre>\n<p>Ping tiene activado el bit SUID y su propietario es root, por tanto cuando sea ejecutado por un usuario, el programa adquirir\u00e1 los privilegios de root. En ocasiones se requiere este comportamiento, pero en otras puede ser innecesario y \u00fanicamente contribuye a debilitar la seguridad del sistema (p.ej. se descubre una vulnerabilidad\/overflow en ping que permite al usuario obtener una shell, esta shell seria con permisos de root).<\/p>\n<p>Para identificar todos los ficheros SUID o GUID podemos utilizar:<\/p>\n<pre>\r\nfind \/ -path \/proc -prune -o -type f -perm +6000 -ls\r\n<\/pre>\n<p>Solo SUID:<\/p>\n<pre>\r\nfind \/ -path \/proc -prune -o -type f -perm +2000 -ls\r\n<\/pre>\n<p>Solo GUID:<\/p>\n<pre>\r\nfind \/ -path \/proc -prune -o -type f -perm +4000 -ls\r\n<\/pre>\n<p>Una vez identificados, podemos proceder a seleccionar cuales queremos dejar con el bit SUID o SGID activado.<\/p>\n<p>Para activar\/desactivar SUID:<\/p>\n<pre>\r\nchmod u+s fichero\r\nchmod u-s fichero\r\n<\/pre>\n<p>Y para activar\/desactivar SGID:<\/p>\n<pre>\r\nchmod g+s fichero\r\nchmod g-s fichero\r\n<\/pre>\n<h5>Directorios con permisos de escritura global<\/h5>\n<p>Para identificar directorios con permisos de escritura global ejecutaremos:<\/p>\n<pre>\r\nfind \/ -path \/proc -prune -o -perm -2 ! -type l -ls\r\n<\/pre>\n<p>En ocasiones estos son necesarios, como por ejemplo &#8216;\/tmp&#8217;. Pero en otras puede suponer un peligro para el sistema. Est\u00e1 en nuestras manos decidir cuales dejar con dichos permisos.<\/p>\n<p>A modo de ejemplo, con el usuario user01 creamos un directorio con permisos de escritura universales:<\/p>\n<pre>\r\n$ mkdir test\r\n$ chmod 777 test\r\n$ sudo chown -R root:root test\r\n$ cd test\r\n$ touch hola\r\n$ ls -la\r\ntotal 8\r\ndrwxrwxrwx   2 root   root   4096 2008-08-22 13:56 .\r\ndrwxr-x--- 126 root   root   4096 2008-08-22 13:55 ..\r\n-rw-r--r--   1 user01 group1    0 2008-08-22 13:56 hola\r\n<\/pre>\n<p>En el ejemplo anterior, como el directorio tiene permisos de escritura para todo el mundo, el usuario user02 podr\u00eda borrar\/modificar el archivo &#8216;hola&#8217; a pesar de que este pertenece a user01 y sus permisos sean -rw-r&#8211;r&#8211;. Por ejemplo, con el usuario user02 ejecutamos el borrado:<\/p>\n<pre>\r\n$ rm hola\r\nrm: \u00bfborrar el archivo regular vac\u00edo \u00abhola\u00bb  protegido contra escritura? (s\/n) y\r\n<\/pre>\n<p>Por otra parte, los directorios con permisos de escritura global que tienen el Sticky bit activado como &#8216;\/tmp&#8217;:<\/p>\n<pre>\r\n$ ls -lad \/tmp\/\r\ndrwxrwxrwt 13 root root 49152 2008-08-22 13:54 \/tmp\/\r\n<\/pre>\n<p>Este comportamiento no tiene lugar, los ficheros creados \u00fanicamente pueden ser modificados por sus propietarios o por el propietario del directorio. Por ejemplo, con el usuario user02:<\/p>\n<pre>\r\n$ rm hola\r\nrm: \u00bfborrar el archivo regular vac\u00edo \u00abhola\u00bb  protegido contra escritura? (s\/n) y\r\nrm: no se puede borrar \u00abhola\u00bb: Operaci\u00f3n no permitida\r\n<\/pre>\n<p>Consecuentemente, del listado de directorios con permisos globales de escritura, los que tienen el bit Sticky activado son casos especiales que debemos tener en cuenta.<\/p>\n<p>Para activar\/desactivar el bit sticky en un directorio:<\/p>\n<pre>\r\nchmod +t directorio\/\r\nchmod -t directorio\/\r\n<\/pre>\n<h5>Archivos sin propietarios<\/h5>\n<p>Para identificar archivos sin propietarios:<\/p>\n<pre>\r\n\r\nfind \/ -path \/proc -prune -o -nouser -o -nogroup\r\n<\/pre>\n<p>Si en el futuro se crease un usuario con el mismo ID, este adquirir\u00eda permisos autom\u00e1ticamente sobre estos ficheros y podr\u00eda suponer un problema de seguridad.<\/p>\n<h5>Detecci\u00f3n de modificaciones de ficheros: Tripwire<\/h5>\n<p>Podr\u00edamos utilizar tripwire para detectar modificaciones en ficheros del sistema. Tripwire construye una BBDD con los MD5 de los ficheros:<\/p>\n<pre>\r\napt-get install tripwire\r\n<\/pre>\n<h3><a name=\"4\">4. Pol\u00edtica de contrase\u00f1as<\/a><\/h3>\n<h4>Pol\u00edtica global<\/h4>\n<p>Todas las contrase\u00f1as deben ser cifradas y por tanto, contenidas en \/etc\/shadow. Para validar que passwd no contiene passwords:<\/p>\n<pre>\r\n$ grep -v ':x:' \/etc\/passwd\r\n<\/pre>\n<p>En &#8216;\/etc\/passwd&#8217; todos los usuarios deben tener el campo password una x.<\/p>\n<p>Se recomienda forzar a los usuarios a cambiar sus contrase\u00f1as de forma peri\u00f3dica (p.ej. 60 d\u00edas) y que no puedan ser cambiadas m\u00e1s de una vez en un d\u00eda (p.ej. en caso de que tengamos configurado el sistema para mantener un hist\u00f3rico de contrase\u00f1as irrepetibles, el usuario no podr\u00e1 cambiar su contrase\u00f1a N veces en el mismo d\u00eda hasta volver a tener la misma). Para ello editamos &#8216;\/etc\/login.defs&#8217; y establecemos:<\/p>\n<pre>\r\n# Maximum number of days a password is valid. \r\nPASS_MAX_DAYS   60\r\n# Minimum number of days before a user can change the password since the last change.\r\nPASS_MIN_DAYS   1\r\n#Number of days when the password change reminder starts.\r\nPASS_WARN_AGE   15\r\n<\/pre>\n<p>Adicionalmente, si un usuario no cambia su contrase\u00f1a 2 semanas despu\u00e9s de haberse caducado, se recomienda bloquear la cuenta. De esta forma el sistema desactivar\u00e1 las cuentas de usuario que no est\u00e9n siendo utilizadas y minimizaremos el riesgo de accesos indebidos. Debemos editar &#8216;\/etc\/default\/useradd&#8217;:<\/p>\n<pre>\r\n# Number of days after password expiration that account is disabled. \r\nINACTIVE=14 \r\n<\/pre>\n<p>Por otra parte, es recomendable que el sistema lleve un control de contrase\u00f1as hist\u00f3ricas para evitar que el usuario reutilice los \u00faltimos N passwords. Adem\u00e1s, es interesante que el sistema tambi\u00e9n valide la robustez de las nuevas contrase\u00f1as. Con este objetivo, debemos instalar <a href=\"http:\/\/www.deer-run.com\/~hal\/sysadmin\/pam_cracklib.html\">cracklib<\/a>:<\/p>\n<pre>\r\napt-get install libpam-cracklib\r\nupdate-cracklib\r\n<\/pre>\n<p>A continuaci\u00f3n editamos &#8216;\/etc\/pam.d\/common-password&#8217; y lo dejamos as\u00ed:<\/p>\n<pre>\r\npassword required pam_cracklib.so retry=3 minlen=8 difok=1 lcredit=0 ucredit=1 dcredit=1 ocredit=2\r\npassword requisite pam_unix.so use_authtok obscure md5 remember=12\r\n<\/pre>\n<p>En este ejemplo hemos hecho que:<\/p>\n<ul>\n<li>El usuario tiene que repetir 3 veces la nueva contrase\u00f1a para realizar el cambio.<\/li>\n<li>Longitud m\u00ednima de 8 caracteres, no obstante puede ser inferior si se utilizan caracteres que valen m\u00e1s: May\u00fasculas, min\u00fasculas, d\u00edgitos, etc&#8230;<\/li>\n<li>Al menos 1 caracteres deben ser diferentes al password anterior.<\/li>\n<li>Seg\u00fan el manual, el par\u00e1metro &#8216;obscure&#8217; provoca que se realicen las siguientes validaciones:\n<ul>\n<li>Palindrome: Verifies that the new password is not a palindrome of (i.e., the reverse of) the previous one.<\/li>\n<li>Case Change Only: Verifies that the new password isn\u00b4t the same as the old one with a change of case.<\/li>\n<li>Similar: Verifies that the new password isn\u00b4t too much like the previous one<\/li>\n<li>Simple:  Is the new password too simple? This is based on the length of the password and the number of different types of characters (alpha, numeric, etc.) used.<\/li>\n<li>Rotated:    Is the new password a rotated version of the old password? (E.g., &#8220;billy&#8221; and &#8220;illyb&#8221;)<\/li>\n<\/ul>\n<\/li>\n<li>Por su parte, cracklib realiza estas otras comprobaciones:\n<ul>\n<li>Que los cambios de passwords no se simplemente invertir la palabra o cambiar may\u00fasculas por min\u00fasculas.<\/li>\n<li>Comprobaciones contra un diccionario interno, construido a partir de datos que hay en los ficheros del sistema (update-cracklib)<\/li>\n<\/ul>\n<\/li>\n<li>Finalmente &#8216;remember=12&#8217; hace que el sistema recuerde las \u00faltimas 12 contrase\u00f1as y no deja que el usuario las repita. Para que funcione correctamente vamos a necesitar ejecutar tambi\u00e9n:\n<pre>\r\ntouch \/etc\/security\/opasswd\r\nchown root:root \/etc\/security\/opasswd\r\nchmod 600 \/etc\/security\/opasswd\r\n<\/pre>\n<\/li>\n<\/ul>\n<p>Existen alternativas a cracklib como por ejemplo <a href=\"http:\/\/www.openwall.com\/passwdqc\/README.shtml\">libpam-passwdqc<\/a>, el cual es m\u00e1s configurable aunque hoy por hoy menos popular.<\/p>\n<p>Finalmente, validamos el estado actual de alg\u00fan usuario del sistema:<\/p>\n<pre>\r\n# chage -l miusuario\r\nLast password change                                    : Aug 05, 2008\r\nPassword expires                                        : Oct 04, 2008\r\nPassword inactive                                       : never\r\nAccount expires                                         : never\r\nMinimum number of days between password change          : 1\r\nMaximum number of days between password change          : 60\r\nNumber of days of warning before password expires       : 15\r\n<\/pre>\n<p>Cabe destacar que para usuarios ya creados podemos modificar sus opciones mediante chage (ver man).<\/p>\n<h4>Contrase\u00f1as de un solo uso: OTP (One time password)<\/h4>\n<p>Podemos configurar el sistema para que en el momento del acceso, si introducimos incorrectamente o en blanco nuestro password, el sistema nos ofrezca la alternativa de logearnos con un password de un solo uso. Esto puede ser de gran utilidad si nos conectamos a la m\u00e1quina desde un ordenador que no podemos confiar (p.ej. un cibercaf\u00e9).<\/p>\n<p>Para esto necesitamos instalar opie:<\/p>\n<pre>\r\napt-get install opie-server\r\n<\/pre>\n<p>A continuaci\u00f3n, como usuario establecemos una contrase\u00f1a y el programa nos proporciona un challenge:<\/p>\n<pre>\r\nopiepasswd -c -f\r\n\r\n  ID marble OTP key is 499 vp5957\r\n  CAB TILE YOU NINA BRED ELLA\r\n<\/pre>\n<p>Podemos obtener un listado de los 10 futuros password de un solo uso que vamos a poder usar mediante el comando siguiente:<\/p>\n<pre>\r\n$ opiekey -n 10 499 vp5957\r\n490: WARD PIE ROSE SKY SKI SHAY\r\n491: I MITE VET AN IQ DENY\r\n492: BED BIEN TWIN WACK GELD SENT\r\n493: NECK MASH FLIT RICE GALE BY\r\n494: FLUB GET NOB MOOD TUM CITE\r\n495: WOO SNOB THEY SARA JILT GUSH\r\n496: VALE HOWE GAIT EEL HUED ODE\r\n497: I WON FOOL TOAD FEE HOFF\r\n498: FULL SOWN EGAN RICH WEAN HUGE\r\n499: CAB TILE YOU NINA BRED ELLA\r\n<\/pre>\n<p>No obstante, resulta interesante utilizar alg\u00fan programa escrito en J2ME para m\u00f3viles como <a href=\"http:\/\/fatsquirrel.org\/software\/vejotp\/\">vejotp<\/a>, con el cual podremos generar el password de un solo uso que necesitemos indicando el challenge correspondiente que nos indique el servidor al conectarnos.<\/p>\n<p>Por \u00faltimo, falta configurar el sistema para que acepte estas contrase\u00f1as. Editamos &#8216;\/etc\/pam.d\/common-auth&#8217;:<\/p>\n<pre>\r\nauth sufficient pam_unix.so nullok_secure\r\nauth sufficient pam_opie.so\r\nauth required pam_deny.so\r\n#auth   requisite   pam_unix.so nullok_secure\r\n#auth   optional    pam_smbpass.so migrate missingok\r\n<\/pre>\n<p>Y en el caso de que usemos SSH, editamos &#8216;\/etc\/ssh\/sshd_config&#8217;:<\/p>\n<pre>\r\nChallengeResponseAuthentication yes\r\n<\/pre>\n<p>Existen alternativas a OPIE como por ejemplo <a href=\"http:\/\/www.cl.cam.ac.uk\/~mgk25\/otpw.html\">libpam-otpw<\/a>, el cual utiliza la t\u00edpica tarjeta de coordenadas en lugar de passwords de un solo uso.<\/p>\n<h4>Gesti\u00f3n del acceso<\/h4>\n<p>Despu\u00e9s de 3 intentos fallidos de un usuario, es recomendable bloquear su cuenta para los siguientes 30 segundos por ejemplo (durante los cuales ser\u00e1 denegado su acceso aunque ponga correctamente sus credenciales). A partir de ese punto, cada nuevo intento fallido representar\u00e1 otros 30 segundos de bloqueo. Si el usuario indica su contrase\u00f1a correcta pasado ese tiempo, el contador de intentos fallidos se resetea a 0.<\/p>\n<p>Para ello utilizaremos &#8216;pam_tally&#8217; editando &#8216;\/etc\/pam.d\/common-auth&#8217;:<\/p>\n<pre>\r\n# 3 auth attempts, after that user will be locked for 30 seconds for each new failed attempt\r\nauth required pam_tally.so onerr=succeed deny=3 unlock_time=30 per_user\r\nauth sufficient pam_unix.so\r\nauth sufficient pam_opie.so\r\nauth required pam_deny.so\r\n\r\n# Reset user lock if auth suceeds\r\naccount required pam_tally.so onerr=succeed\r\n<\/pre>\n<p>El par\u00e1metro &#8216;per_user&#8217; har\u00e1 que tally valide si se ha establecido alg\u00fan valor individual (diferente de 0) al usuario mediante faillog. Por ejemplo, para limita el n\u00famero de reintentos fallidos y establecer el tiempo de bloqueo para un usuario concreto:<\/p>\n<pre>\r\nfaillog --maximum 5 --lock-time 120 -u miusuario\r\n<\/pre>\n<p>Otro ejemplo, no permitir que un usuario se bloquee aunque sobrepase los valores por defecto de intentos fallidos de autenticaci\u00f3n:<\/p>\n<pre>\r\nfaillog --maximum -1 -u miusuario\r\n<\/pre>\n<p>Para ver el estado de los usuarios podemos utilizar:<\/p>\n<pre>\r\npam_tally\r\npam_tally --user misusuario\r\nfaillog -a\r\nfaillog -u miusuario\r\n<\/pre>\n<p>Para desbloquear:<\/p>\n<pre>\r\npam_tally --user miusuario --reset\r\nfaillog -u miusuario -r\r\n<\/pre>\n<p>Es importante eliminar todos los par\u00e1metros &#8216;nullok&#8217; o &#8216;nullok_secure&#8217; del modulo pam_unix.o dado que permiten passwords en blanco (tanto en common-password como en common-auth).<\/p>\n<p>Ver m\u00e1s en opciones (bloqueos permanentes, etc.) <a href=\"http:\/\/www.kernel.org\/pub\/linux\/libs\/pam\/Linux-PAM-html\/sag-pam_tally.html\">en el siguiente manual<\/a>.<\/p>\n<h3><a name=\"5\">5. Gesti\u00f3n de usuarios<\/a><\/h3>\n<h4>Creaci\u00f3n de usuarios<\/h4>\n<p>Para crear un usuario y asignarle un password:<\/p>\n<pre>\r\nuseradd -d \/home\/miusuario -m -G admin,users -K PASS_MAX_DAYS=60,PASS_MIN_DAYS=1,PASS_WARN_AGE=15,UMASK=0022 -s \/bin\/bash miusuario\r\npasswd miusuario\r\n<\/pre>\n<p>Estos comando crean su directorio de usuario con el skeleton b\u00e1sico (-m), crea un grupo con el mismo nombre que el usuario y ser\u00e1 su grupo primario (-n) y adem\u00e1s pertenecer\u00e1 al grupo admin. Por otra parte, tambi\u00e9n se especifica la pol\u00edtica de contrase\u00f1as espec\u00edfica.<\/p>\n<p>Para establecer contrase\u00f1as aleatorios podemos ayudarnos del siguiente programa:<\/p>\n<pre>\r\napt-get install makepasswd\r\nmakepasswd --chars=8\r\n<\/pre>\n<h4>Gesti\u00f3n de cuentas<\/h4>\n<p>Tomando como ejemplo un usuario que dispone de la siguiente entrada en &#8216;\/etc\/shadow&#8217;:<\/p>\n<pre>\r\nusuario:$1$ZyihUAz0$RqBWU1OINGOsUILv3g2Kh\/:14111:0:99999:7:::\r\n<\/pre>\n<p>Veamos diversas acciones de utilidad&#8230;.<\/p>\n<ul>\n<li>Expira la contrase\u00f1a de un usuario para obligarle a cambiarla:\n<pre>\r\n\tpasswd -e usuario\r\n\t<\/pre>\n<p>\tEstablece el 3er campo de \/etc\/shadow a 0:<\/p>\n<pre>\r\n\tusuario:$1$ZyihUAz0$RqBWU1OINGOsUILv3g2Kh\/:0:0:99999:7:::\r\n\t<\/pre>\n<\/li>\n<li>Bloquea o desbloquea (recuperando password anterior) un usuario:\n<pre>\r\n\tpasswd -l usuario\r\n\t<\/pre>\n<p>\tA\u00f1ade una exclamaci\u00f3n delante del hash de la contrase\u00f1a en \/etc\/shadow y en el octavo campo a\u00f1ade un 1 (cuenta caducada el 2 de Enero de 1970):<\/p>\n<pre>\r\n\tusuario:!$1$ZyihUAz0$RqBWU1OINGOsUILv3g2Kh\/:14111:0:99999:7::1:\r\n\t<\/pre>\n<p>\tPara deshacer los cambios:<\/p>\n<pre>\r\n\tpasswd -u usuario\r\n\t<\/pre>\n<\/li>\n<li>Desactiva un usuario (sin posibilidad de recuperar el password):\n<pre>\r\n\tpasswd -d usuario\r\n\t<\/pre>\n<p>\tSe asigna un hash en blanco y en el octavo campo a\u00f1ade un 1 (cuenta caducada el 2 de Enero de 1970):<\/p>\n<pre>\r\n\tusuario::14111:0:99999:7::1:\r\n\t<\/pre>\n<\/li>\n<li>Activar un usuario que ha sido desactivado: eliminar la expiraci\u00f3n y asignar una nueva contrase\u00f1a\n<pre>\r\n\tchage -E -1 aurora\r\n\r\n\tpasswd aurora\r\n\t<\/pre>\n<\/li>\n<li>Estado:\n<pre>\r\n\tpasswd -S usuario\r\n\tchage -l usuario\r\n\t<\/pre>\n<\/li>\n<li>Si no queremos que root pueda logearse directamente al sistema y que el acceso a la cuenta de administraci\u00f3n se realice mediante sudo. Aparte de configurar correctamente sudo, debemos bloquear y desactivar el usuario root:\n<pre>\r\n\tpasswd -l -d root\r\n\t<\/pre>\n<p>\tQuedando algo parecido a:<\/p>\n<pre>\r\n\troot:!:13449:0:99999:7::1:\r\n\t<\/pre>\n<\/li>\n<\/ul>\n<p>En resumen, campos del \/etc\/shadow:<\/p>\n<pre>\r\n[username]:[password]:[date]:PASS_MIN_DAYS:PASS_MAX_DAYS:PASS_WARN_AGE:INACTIVE:EXPIRE:\r\n<\/pre>\n<p>Seg\u00fan el manual:<\/p>\n<pre>\r\n  \u00b7   login name\r\n  \u00b7   encrypted password\r\n  \u00b7   days since Jan 1, 1970 that password was last changed\r\n  \u00b7   days before password may be changed\r\n  \u00b7   days after which password must be changed\r\n  \u00b7   days before password is to expire that user is warned\r\n  \u00b7   days after password expires that account is disabled\r\n  \u00b7   days since Jan 1, 1970 that account is disabled\r\n<\/pre>\n<p>Otras funcionalidades \u00fatiles:<\/p>\n<ul>\n<li>Listar usuarios no bloqueados:\n<pre>\r\n\tegrep -v '.*:*|:!' \/etc\/shadow | awk -F: '{print $1}'\r\n\t<\/pre>\n<\/li>\n<li>Listar archivos de un usuario concreto (nos puede servir para identificar usuarios que no disponen de informaci\u00f3n en el sistema):\n<pre>\r\n\tfind \/ -path \/proc -prune -o -user usuario -ls\r\n\t<\/pre>\n<\/li>\n<li>Comprobamos que el fichero de grupos es correcto:\n<pre>\r\n\t# grpck -r\r\n\t'www-data' is a member of the 'adm' group in \/etc\/group but not in \/etc\/gshadow\r\n\t'miusuario' is a member of the 'users' group in \/etc\/group but not in \/etc\/gshadow\r\n\tno matching group file entry in \/etc\/gshadow\r\n\tadd group 'admin' in \/etc\/gshadow ?No\r\n\tgroup marble: no user 0\r\n\tdelete member '0'? No\r\n\tno matching group file entry in \/etc\/gshadow\r\n\tadd group 'marble' in \/etc\/gshadow ?No\r\n\t'miusuario' is a member of the 'adm' group in \/etc\/gshadow but not in \/etc\/group\r\n\tgrpck: no changes\r\n\t<\/pre>\n<\/li>\n<\/ul>\n<h3><a name=\"6\">6. Servicios b\u00e1sicos del sistema<\/a><\/h3>\n<h4>Activaci\u00f3n en arranque<\/h4>\n<p>Para la activaci\u00f3n\/desactivaci\u00f3n de los servicios que queremos en arranque podemos utilizar la herramienta de consola &#8216;sysv-rc-conf&#8217;:<\/p>\n<pre>\r\napt-get install sysv-rc-conf\r\n<\/pre>\n<p>Ejecutando &#8216;sysv-rc-conf&#8217; podremos marcar los servicios\/scripts\/demonios que queremos arrancar al iniciar el sistema. La aplicaci\u00f3n aplica los cambios de forma instantanea al situarnos sobre alguna de las X y pulsar &#8216;espacio&#8217;. Para salir pulsamos la &#8216;q&#8217;.<\/p>\n<p>Si queremos saber en que runlevel arranca el sistema por defecto:<\/p>\n<pre>\r\n$ grep ':initdefault' \/etc\/inittab\r\nid:2:initdefault:\r\n<\/pre>\n<p>En caso de que no exista el fichero, es porque probablemente tengamos el sistema de arranque <a href=\"http:\/\/upstart.ubuntu.com\/\">Upstart<\/a>, el runlevel por defecto suele ser el 2 (es posible verificarlo en &#8216;\/etc\/event.d\/rc-default&#8217;).<\/p>\n<p>Suele ser recomendable desactivar la posibilidad de reiniciar el ordenador mediante CTRL+ALT+SUPR para evitar reinicios involuntarios (p.ej. la se\u00f1ora de la limpieza). <\/p>\n<p>En caso de que utilicemos el tradicional sistema de arranque de Unix\/Linux (System V init), bastar\u00e1 con comentar (\/etc\/inittab):<\/p>\n<pre>\r\n# What to do when CTRL-ALT-DEL is pressed.\r\n#ca:12345:ctrlaltdel:\/sbin\/shutdown -t1 -a -r now\r\n<\/pre>\n<p>Y aplicar los cambios:<\/p>\n<pre>\r\n# init q\r\n<\/pre>\n<p>O si como mecanismo de arranque usamos <a href=\"http:\/\/upstart.ubuntu.com\/\">Upstart<\/a> (como es el caso de Ubuntu), editamos &#8216;\/etc\/event.d\/control-alt-delete&#8217; y comentamos:<\/p>\n<pre>\r\n#exec \/sbin\/shutdown -r now \"Control-Alt-Delete pressed\"\r\n<\/pre>\n<h4>Servicio de correo: Postfix<\/h4>\n<p>El sistema requerir\u00e1 un servicio de correo aunque \u00fanicamente sea para uso local, dado que varias tareas autom\u00e1ticas reportaran su estado mediante correo.<\/p>\n<p>En caso de que nuestro sistema venga configurado con sendmail, es recomendable desinstalarlo e instalar alg\u00fan otro sistema m\u00e1s robusto como postfix (historicamente sendmail ha tenido muchos fallos de seguridad):<\/p>\n<pre>\r\napt-get purge sendmail sendmail-base sendmail-bin sendmail-cf sendmail-doc\r\napt-get install procmail\r\napt-get install postfix\r\n<\/pre>\n<p>Para una configuraci\u00f3n b\u00e1sica y segura, primero definiremos que usuario del sistema recibir\u00e1 los correos destinados a root (p.ej. muchas tareas autom\u00e1ticas del sistema env\u00edan correo a root). Editamos &#8216;\/etc\/aliases&#8217; y a\u00f1adimos:<\/p>\n<pre>\r\nroot: miusuario\r\n<\/pre>\n<p>Y ejecutamos:<\/p>\n<pre>\r\nnewaliases\r\n<\/pre>\n<p>A continuaci\u00f3n, securizaremos la instalaci\u00f3n de postfix de forma que muestre la informaci\u00f3n m\u00ednima necesaria. Editamos &#8216;\/etc\/postfix\/main.cf&#8217;:<\/p>\n<pre>\r\n#smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)\r\nsmtpd_banner = Welcome\r\nbiff = no\r\n\r\n# Rewrite \"user\" to \"user@$myorigin\" with locally submitted mail\r\n\r\n# Or \"user\" to \"user@$remote_header_rewrite_domain\" with remote connection\r\n# only if $remote_header_rewrite_domain is not empty (by default it is empty)\r\n#\r\n# By default: myorigin = $mydomain = \/etc\/mailname\r\nappend_at_myorigin = yes\r\n<\/pre>\n<p>Asi ocultamos la versi\u00f3n y obligamos a que todo mail enviado por los procesos autom\u00e1ticos del sistema tengan como dominio el especificado en &#8216;\/etc\/mailname&#8217; (si se envian a usuario@localhost se reescribira como usuario@dominio).<\/p>\n<p>Editamos &#8216;\/etc\/mailname&#8217; para establecer el dominio que queremos, por ejemplo:<\/p>\n<pre>\r\nun.ejemplo.com\r\n<\/pre>\n<p>Si no vamos a utilizar Postfix como un servicio de correo remoto y \u00fanicamente lo queremos usar de forma local, editamos &#8216;\/etc\/postfix\/master.cf&#8217; para asegurarnos que \u00fanicamente se aceptan conexiones localhost:<\/p>\n<pre>\r\n127.0.0.1:smtp      inet  n       -       -       -       -       smtpd\r\n<\/pre>\n<p>Con esto ya tenemos postfix preparado:<\/p>\n<pre>\r\n\/etc\/init.d\/postfix restart\r\n<\/pre>\n<p>Finalmente, si nos interesa que el correo local que reciba un usuario sea reenviado a otra direcci\u00f3n, en el directorio personal del usuario creamos &#8216;.procmailrc&#8217;:<\/p>\n<pre>\r\n:0 c\r\n\/var\/mail\/miusuario\r\n\r\n# Copia del correo personal a gmail\r\n:0\r\n!miotrousuario@gmail.com\r\n<\/pre>\n<p>Para realizar <a href=\"http:\/\/www.marblestation.com\/blog\/?p=549\">configuraciones m\u00e1s complejas de Postfix<\/a> podemos consultar esta otra gu\u00eda.<\/p>\n<h4>Servicio web: Apache<\/h4>\n<p>Una vez instalado apache (habitualmente con soporte PHP), podemos proceder a realizar una securizaci\u00f3n de su configuraci\u00f3n.<\/p>\n<h5>PHP<\/h5>\n<p>En primer lugar, nos aseguramos que PHP no informe de su presencia editando &#8216;\/etc\/php5\/apache2\/php.ini&#8217; y modificando:<\/p>\n<pre>\r\n; Misc\r\n;\r\n; Decides whether PHP may expose the fact that it is installed on the server\r\n; (e.g. by adding its signature to the Web server header).  It is no security\r\n; threat in any way, but it makes it possible to determine whether you use PHP\r\n; on your server or not.\r\nexpose_php = On\r\n<\/pre>\n<p>por:<\/p>\n<pre>\r\nexpose_php = Off \r\n<\/pre>\n<p>Por otra parte, tambi\u00e9n se recomienda establecer l\u00edmites a los recursos que puede utilizar una web PHP:<\/p>\n<pre>\r\n;;;;;;;;;;;;;;;;;;;\r\n; Resource Limits ;\r\n;;;;;;;;;;;;;;;;;;;\r\n\r\nmax_execution_time = 30     ; Maximum execution time of each script, in seconds\r\nmax_input_time = 60 ; Maximum amount of time each script may spend parsing request data\r\n;max_input_nesting_level = 64 ; Maximum input variable nesting level\r\nmemory_limit = 16M      ; Maximum amount of memory a script may consume (16MB)\r\n<\/pre>\n<h5>Apache b\u00e1sico<\/h5>\n<p>Veamos como mejorar la configuraci\u00f3n de apache. Por un lado editamos &#8216;\/etc\/apache2\/apache2.conf&#8217; y cambiamos los siguientes par\u00e1metros para que Apache no muestre informaci\u00f3n innecesaria:<\/p>\n<pre>\r\n#ServerTokens Full\r\nServerTokens Prod\r\n\r\n#ServerSignature On\r\nServerSignature Off\r\n<\/pre>\n<p>Tambi\u00e9n debemos aseguramos que no se cambian estos par\u00e1metros en los sites activos (&#8216;\/etc\/apache2\/sites-enabled\/*).<\/p>\n<p>En general los comando HTTP TRACE y TRACK no son utilizados para servir p\u00e1ginas y por tanto, podemos desactivarlos para evitar que un usuario malintencionado los utilice para intentar atacar. Para cada uno de los sites-enabled, lo editamos y a\u00f1adimos dentro del VirtualHost:<\/p>\n<pre>\r\n    RewriteEngine on\r\n    RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)\r\n    RewriteRule .* - [F]\r\n<\/pre>\n<p>Activamos el modulo &#8216;rewrite&#8217; y reiniciamos el servicio:<\/p>\n<pre>\r\na2enmod rewrite\r\n\/etc\/init.d\/apache2 restart\r\n<\/pre>\n<p>A continuaci\u00f3n podemos validar que realmente ha surgido efecto el bloqueo de los comandos TRACE y TRACK:<\/p>\n<pre>\r\n$ telnet 127.0.0.1 80\r\nTrying 127.0.0.1...\r\nConnected to 127.0.0.1.\r\nEscape character is '^]'.\r\n\r\n\r\nTRACE \/ HTTP\/1.0\r\nA: b\r\nC: d\r\nHost: foo\r\n\r\nHTTP\/1.1 403 Forbidden\r\nDate: Tue, 05 Aug 2008 17:09:34 GMT\r\nServer: Apache\r\nContent-Length: 255\r\nConnection: close\r\nContent-Type: text\/html; charset=iso-8859-1\r\n\r\n&#60;!DOCTYPE HTML PUBLIC \"-\/\/IETF\/\/DTD HTML 2.0\/\/EN\">\r\n&#60;html>&#60;head>\r\n&#60;title>403 Forbidden&#60;\/title>\r\n&#60;\/head>&#60;body>\r\n&#60;h1>Forbidden&#60;\/h1>\r\n&#60;p>You don't have permission to access \/\r\non this server.&#60;\/p>\r\n&#60;hr>\r\n&#60;address>Apache Server at foo Port 80&#60;\/address>\r\n&#60;\/body>&#60;\/html>\r\nConnection closed by foreign host.\r\n<\/pre>\n<p>Otra medida de seguridad consiste en desactivar el uso de FollowSymLinks para no permitir que un usuario pueda crear enlaces simb\u00f3licos hacia directorios que no deseamos que est\u00e9n expuestos. Para ello, en las opciones de los sites-enabled debemos indicar:<\/p>\n<pre>\r\n  Options None\r\n<\/pre>\n<p>Finalmente, es conveniente que le indiquemos a Apache exactamente en que IPs queremos que escuche. De esta forma podemos limitarlo por ejemplo \u00fanicamente para uso local. Para ello editamos &#8216;\/etc\/apache2\/ports.conf&#8217; y cambiamos Listen 80 por Listen ip_maquina:80.<\/p>\n<p>Otro aspecto importante es proteger el servicio de ataques de denegaci\u00f3n de servicio (DoS). En el fichero &#8216;\/etc\/apache2\/apache2.conf&#8217; podemos realizar algunos cambios:<\/p>\n<ul>\n<li>Si establecemos un timeout bajo, minimizamos el impacto de los ataques pero puede que algunos CGIs que requieran m\u00e1s tiempo dejen de funcionar (p.ej. 300 segundos):\n<pre>\r\n  Timeout 300\r\n<\/pre>\n<\/li>\n<li>Si tenemos activado el HTTP KeepAlive, definir un timeout bajo minimiza el impacto de ataques (p.ej. 15 segundos):\n<pre>\r\n  KeepAliveTimeout 15\r\n  MaxKeepAliveRequests 100\r\n<\/pre>\n<\/li>\n<li>Habitualmente, aunque apache2-mpm-worker, se utiliza apache2-mpm-prefork como versi\u00f3n de apache por defecto dado que esta es compatible con PHP. Prefork puede ser customizado, pero estos son los valores recomendados por defecto:\n<pre>\r\n&#60;IfModule mpm_prefork_module>\r\n    # Number of child server processes created on startup\r\n    StartServers          5\r\n    # Sets the desired minimum number of idle child server processes\r\n    MinSpareServers       5\r\n    # Sets the desired maximum number of idle child server processes\r\n    MaxSpareServers      10\r\n    # Sets the limit on the number of simultaneous requests that can be supported;\r\n    MaxClients          150\r\n    # Sets the limit on the number of requests that an individual child server process will handle\r\n    MaxRequestsPerChild   0\r\n&#60;\/IfModule>\r\n<\/pre>\n<p>De todos ellos, los \u00fanicos par\u00e1metros con los que se suele jugar son MaxClient y MaxRquestPerChild. Con este \u00faltimo, indicar un valor diferente de cero nos permitir\u00eda limitar la memoria utilizada por procesos que tienen memory leakages.\n<\/li>\n<li>Limitar el tama\u00f1o del BODY de las peticiones puede ser muy \u00fatil por ejemplo para evitar que los usuarios suban ficheros excesivamente grandes (p.ej. 500 KB = 1024*500 bytes):\n<pre>\r\n  LimitRequestBody 512000\r\n<\/pre>\n<\/li>\n<li>Limitamos el n\u00famero de campos que puede tener una petici\u00f3n en el HEADER (de media suelen tener 20) y su tama\u00f1o (7KB = 8190 bytes)\n<pre>\r\n  LimitRequestFields 50\r\n  LimitRequestFieldSize 8190\r\n  LimitRequestLine 8190\r\n<\/pre>\n<\/li>\n<\/ul>\n<h5>M\u00f3dulos de Apache<\/h5>\n<p>Apache se encuentra programado con funciones residentes en m\u00f3dulos independientes al core de la aplicaci\u00f3n, eso nos permite activar \u00fanicamente aquellas caracter\u00edsticas que vamos a utilizar para minimizar riesgos. Desactivaci\u00f3n de m\u00f3dulos:<\/p>\n<pre>\r\na2dismod alias\r\na2dismod auth_basic\r\na2dismod authn_file\r\na2dismod authz_default\r\na2dismod authz_groupfile\r\na2dismod authz_host\r\na2dismod authz_user\r\na2dismod autoindex\r\na2dismod cgi\r\na2dismod dir\r\na2dismod env\r\na2dismod mime\r\na2dismod negotiation\r\na2dismod php5\r\na2dismod rewrite\r\na2dismod setenvif\r\na2dismod ssl\r\na2dismod status\r\n<\/pre>\n<p>Activaci\u00f3n de modulos m\u00ednimos:<\/p>\n<pre>\r\n# Default page (e.g. index.html)\r\na2enmod dir\r\na2enmod mime\r\n# Language preference\r\na2enmod negotiation\r\na2enmod php5\r\na2enmod rewrite\r\n# Workarounds for certain browser bugs\r\na2enmod setenvif\r\n# Allows access rules based on hosts (allow from...)\r\na2enmod authz_host\r\n<\/pre>\n<h5>Servir por localhost las aplicaciones m\u00e1s criticas<\/h5>\n<p>Finalmente, si vamos a utilizar Apache como servidor web remoto pero queremos tambi\u00e9n instalar aplicaciones de gesti\u00f3n como phpmyadmin, cacti, nagios, etc&#8230; Es recomendable que estas se encuentren en una instancia del servidor que solo sea accesible desde local para los usuarios de la m\u00e1quina, pero no para el resto del mundo. Es decir, vamos a evitar que cualquier persona pueda acceder libremente por ejemplo a &#8216;http:\/\/www.midominio.com\/phpmyadmin&#8217;, pero si vamos a permitir que un usuario con cuenta en el sistema pueda acceder mediante SSH realizando Port Forwarding:<\/p>\n<pre>\r\nssh -L 8080:localhost:80 miusuario@IP_DEL_SERVIDOR\r\n<\/pre>\n<p>Con el anterior comando, ssh abrir\u00e1 el puerto 8080 en la m\u00e1quina del cliente y redireccionar\u00e1 todo lo que le llegue al puerto 80 de la interfaz localhost del servidor. Por tanto, el cliente (una vez se ha autenticado con su usuario por SSH) podr\u00e1 acceder a phpmyadmin mediante &#8216;http:\/\/localhost:8080\/phpmyadmin&#8217;. Adicionalmente, todo el tr\u00e1fico viajar\u00e1 cifrado sin necesidad de configurar el SSL de Apache.<\/p>\n<p>Con este objetivo, vamos a crear &#8216;\/etc\/apache2\/sites-available\/localhost&#8217;:<\/p>\n<pre>\r\nNameVirtualHost 127.0.0.1:80\r\n&#60;VirtualHost 127.0.0.1:80>\r\n    ServerAdmin admin@admin.com\r\n    ServerName localhost\r\n    ServerAlias localhost.localdomain\r\n\r\n    DocumentRoot \/var\/www\/localhost\r\n    &#60;Directory \/var\/www\/localhost>\r\n        AllowOverride All\r\n        Options FollowSymLinks\r\n        Order allow,deny\r\n        allow from all\r\n    &#60;\/Directory>\r\n\r\n    # Possible values include: debug, info, notice, warn, error, crit,\r\n    # alert, emerg.\r\n    LogLevel warn\r\n\r\n\r\n    ErrorLog \/var\/log\/apache2\/localhost\/error.log\r\n    CustomLog \/var\/log\/apache2\/localhost\/access.log combined\r\n    ServerSignature Off\r\n\r\n\r\n\r\n    Include \/etc\/apache2\/conf.d\/\r\n\r\n&#60;\/VirtualHost>\r\n<\/pre>\n<p>Activamos el site:<\/p>\n<pre>\r\nmkdir \/var\/www\/localhost\r\nmkdir \/var\/log\/apache2\/localhost\r\na2ensite localhost\r\n\/etc\/init.d\/apache2 restart\r\n<\/pre>\n<p>Cuando instalamos phpmyadmin (u otras aplicaciones web similares) mediante el sistema de paquetes de Ubuntu, se generan ficheros de configuraci\u00f3n en &#8216;\/etc\/apache2\/conf.d\/&#8217; para que apache pueda encontrar la aplicaci\u00f3n web (p.ej. mediante alias). Esto nos resta control y por defecto hace que la web sea accesible remotamente. Para minimizar riesgos, comentamos la l\u00ednea de &#8216;\/etc\/apache2\/apache2.conf&#8217; que carga estas configuraciones est\u00e1ndar:<\/p>\n<pre>\r\n# Include generic snippets of statements\r\n#Include \/etc\/apache2\/conf.d\/\r\n<\/pre>\n<p>Y en contrapartida, tendremos que copiar\/enlazar todo aquello que queramos que sea accesible \u00fanicamente por localhost en el directorio &#8216;\/var\/www\/localhost&#8217;.<\/p>\n<h4>Base de datos MySQL<\/h4>\n<p>Securizamos la instalaci\u00f3n b\u00e1sica ejecutando &#8216;mysql_secure_installation&#8217;. Seg\u00fan el manual, este comando permite:<\/p>\n<ul>\n<li>You can set a password for root accounts.<\/li>\n<li>You can remove root accounts that are accessible from outside the local host.<\/li>\n<li>You can remove anonymous-user accounts.<\/li>\n<li>You can remove the test database, which by default can be accessed by anonymous users.<\/li>\n<\/ul>\n<p>Se recomienda aplicar las 4 acciones. Por otra parte, en la configuraci\u00f3n de &#8216;\/etc\/mysql\/my.cnf&#8217;:<\/p>\n<pre>\r\n# Both location gets rotated by the cronjob.\r\n# Be aware that this log type is a performance killer.\r\n# log     = \/var\/log\/mysql\/mysql.log\r\n#\r\n# Error logging goes to syslog. This is a Debian improvement :)\r\n#\r\n# Here you can see queries with especially long duration\r\nlog_slow_queries    = \/var\/log\/mysql\/mysql-slow.log\r\nlong_query_time = 2\r\n<\/pre>\n<p>Logeamos las queries que tardan m\u00e1s de 2 segundos en ejecutarse.<\/p>\n<pre>\r\n\/etc\/init.d\/mysql restart\r\n<\/pre>\n<p>Finalmente, para crear un usuario con su propia base de datos:<\/p>\n<pre>\r\nCREATE USER 'miusuario'@'localhost' IDENTIFIED BY 'YB9gYu6I';\r\n\r\nGRANT USAGE ON *.* TO 'miusuario'@'localhost' IDENTIFIED BY 'YB9gYu6I' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;\r\n\r\nCREATE DATABASE IF NOT EXISTS miusuario;\r\n\r\nGRANT ALL PRIVILEGES ON miusuario.* TO 'miusuario'@'localhost';\r\n\r\nFLUSH PRIVILEGES;\r\n<\/pre>\n<h4>Acceso remoto: SSH<\/h4>\n<p>Para la securizaci\u00f3n de SSH, vamos a hacer que \u00fanicamente un grupo de usuario pueda conectarse. Creamos el grupo &#8216;sshlogin&#8217; y a\u00f1adimos usuarios al mismo:<\/p>\n<pre>\r\nsudo groupadd sshlogin\r\nsudo adduser miusuario sshlogin\r\n<\/pre>\n<p><b>Importante:<\/b> Si utilizamos <a href=\"http:\/\/freenx.berlios.de\/\">FreeNX<\/a> o <a href=\"http:\/\/www.nomachine.com\/\">NX<\/a> (<a href=\"http:\/\/www.marblestation.com\/blog\/?p=249\">art\u00edculo sobre FreeNX<\/a>) para el acceso remoto al escritorio, tambi\u00e9n tendremos que a\u00f1adir al grupo &#8216;sshlogin&#8217; el usuario &#8216;nx&#8217;.<\/p>\n<p>Editamos &#8216;\/etc\/ssh\/sshd_config&#8217; para impedir que root pueda acceder directamente y no se forwardeen las X:<\/p>\n<pre>\r\nPermitRootLogin no\r\nX11Forwarding no\r\n\r\nAllowGroups sshlogin\r\n<\/pre>\n<p>Reiniciamos el servicio:<\/p>\n<pre>\r\nsudo \/etc\/init.d\/ssh restart\r\n<\/pre>\n<p>En caso de que desde nuestra m\u00e1quina tengamos que acceder a diversos servicios SSH y no queremos tener que recordar las diferentes contrase\u00f1as, podemos generar una pareja de claves RSA (p\u00fablica y privada) en la m\u00e1quina cliente (se recomienda que asignar password para proteger la clave privada):<\/p>\n<pre>\r\n$ ssh-keygen \r\nGenerating public\/private rsa key pair.\r\nEnter file in which to save the key (\/home\/user\/.ssh\/id_rsa): \r\nEnter passphrase (empty for no passphrase): \r\nEnter same passphrase again: \r\nYour identification has been saved in \/home\/user\/.ssh\/id_rsa.\r\nYour public key has been saved in \/home\/user\/.ssh\/id_rsa.pub.\r\nThe key fingerprint is:\r\n18:0f:fe:29:b2:17:c2:a0:8d:6e:11:80:de:01:21:be user@localhost\r\n<\/pre>\n<p>Con ssh-keygen hemos creado una clave privada &#8216;~\/.ssh\/id_rsa&#8217; que no debemos compartir con nadie y una clave p\u00fablica &#8216;~\/.ssh\/id_rsa.pub&#8217; que hay que copiar en el directorio &#8216;~\/.ssh\/authorized_keys&#8217; de los servidores a los que queramos conectar con SSH:<\/p>\n<pre>\r\nscp ~\/.ssh\/id_rsa.pub usuario@servidor:\/home\/user\/\r\n<\/pre>\n<p>Y desde cada servidor:<\/p>\n<pre>\r\n$ cat id_rsa.pub >> .ssh\/authorized_keys\r\n$ rm id_rsa.pub\r\n<\/pre>\n<p>Podemos poner determinadas condiciones bajo las cuales se utilizaran estas claves, por ejemplo:<\/p>\n<pre>\r\nfrom=\"81.11.105.10\",command=\"\/bin\/ls\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAABdZjH4WE5y5EH\/O9nHoplj8sZz0iIb1XPU5e5ZTxd7tWhMf9p391yAfM6ybjabmFXZZuFm9q\/AjD53qjX+q7YhQUXC0I5JhFU0CAHxKuvuguogWio39x36Ag\/zgJ5IJXcrCNsuoDw== root@servidor.com\r\n<\/pre>\n<p>Al inicio de la clave hemos especificado:<\/p>\n<ul>\n<li>from=&#8221;81.11.105.10&#8243;: \u00fanicamente puede ser utilizada desde un cliente con esa IP.<\/li>\n<li>command=&#8221;\/bin\/ls&#8221;: \u00fanicamente se permitir\u00e1 la ejecuci\u00f3n de ese fichero.<\/li>\n<li>no-port-forwarding: no permite redirigir puertos.<\/li>\n<li>no-X11-forwarding: no permite la redirecci\u00f3n gr\u00e1fica de programas (X Window)<\/li>\n<li>no-agent-forwarding: no permite redirigir peticiones entre servidores a agentes ssh de autenticaci\u00f3n.<\/li>\n<li>no-pty: el cliente no obtendr\u00e1 una terminal con shell, solo podra ejecutar comando (p.ej. &#8216;ssh usuario@servidor \/bin\/ls&#8217;)<\/li>\n<\/ul>\n<p>A partir de este momento, cada vez que queramos conectarnos a uno de estos servidores SSH, ssh nos preguntar\u00e1 por la contrase\u00f1a que le hemos puesto a nuestra clave privada y por tanto, solo hace falta recordar 1 contrase\u00f1a. No obstante, aun podemos simplificar m\u00e1s la gesti\u00f3n:<\/p>\n<ul>\n<li>En la generaci\u00f3n de las claves RSA no asignamos contrase\u00f1a y por tanto esta no ser\u00e1 requerida para conectarnos a los servidores por SSH (en caso de que ya la hayamos asignado, podemos cambiarla mediante &#8216;ssh-keygen -p&#8217;). Este punto tiene el inconveniente de que en caso de que alguien se haga con el fichero que contiene la clave privada, tendr\u00e1 acceso completo a los servidores configurados.<\/li>\n<li>Uso de keychain (ssh-agent) para que \u00fanicamente tengamos que teclear la contrase\u00f1a que protege la clave privada una vez.<\/li>\n<\/ul>\n<p>Veamos como configurar el segundo punto:<\/p>\n<pre>\r\n$ sudo apt-get install keychain\r\n<\/pre>\n<p>Editamos el fichero &#8216;~\/.bashrc&#8217; y a\u00f1adimos al final:<\/p>\n<pre>\r\n## SSH Agent\r\n# Do not execute if I am root (sudo -s)\r\nif [ \"$(id -u)\" != \"0\" ]; then\r\n    keychain id_rsa --nocolor --quiet\r\n    . ~\/.keychain\/`uname -n`-sh\r\nfi\r\n<\/pre>\n<p>Salimos del sistema y volvemos a entrar para que sean efectivos los cambios de bashrc. La primera vez que se ejecute &#8216;keychain&#8217; nos preguntar\u00e1 la contrase\u00f1a que protege a la clave privada:<\/p>\n<pre>\r\nEnter passphrase for \/home\/user\/.ssh\/id_rsa: \r\nIdentity added: \/home\/user\/.ssh\/id_rsa (\/home\/user\/.ssh\/id_rsa)\r\n<\/pre>\n<p>Mientras permanezca la m\u00e1quina en marcha podremos acceder a los servidores mediante SSH sin que nos solicite de nuevo la contrase\u00f1a.<\/p>\n<p>En el siguiente enlace pod\u00e9is encontrar una descripci\u00f3n detallada de <a href=\"http:\/\/www.unixwiz.net\/techtips\/ssh-agent-forwarding.html\">c\u00f3mo funciona SSH<\/a>.<\/p>\n<h3><a name=\"7\">7. Trazabilidad<\/a><\/h3>\n<h4>Fecha y hora del sistema<\/h4>\n<p>Para que los logs resulten de utilidad y tengamos una buena trazabilidad de todo lo que ocurre en el sistema, es necesario que la m\u00e1quina disponga de la fecha\/hora correcta. Para ello podemos configurar la sincronizaci\u00f3n autom\u00e1tica con otros servidores de Internet via NTP:<\/p>\n<pre>\r\napt-get install ntpdate\r\n<\/pre>\n<p>Creamos &#8216;\/etc\/cron.daily\/ntpdate&#8217;:<\/p>\n<pre>\r\n#! \/bin\/bash\r\n\/usr\/sbin\/ntpdate -u ntp.ubuntu.com\r\n<\/pre>\n<p>Y damos permisos de ejecuci\u00f3n:<\/p>\n<pre>\r\nchmod 755 \/etc\/cron.daily\/ntpdate\r\n<\/pre>\n<p>Por defecto el sistema utilizar\u00e1 los servidores de Ubuntu (ntp.ubuntu.com) para la sincronizaci\u00f3n.<\/p>\n<p>En caso de que fuese necesario, tambi\u00e9n conviene asegurarnos que el sistema tiene configurada la zona horaria que nos interese (p.ej. Europa\/Madrid):<\/p>\n<pre>\r\n# date\r\nWed Aug  6 07:14:36 EDT 2008\r\n# cd \/etc\r\n# mv timezone timezone.old\r\n# echo \"Europe\/Madrid\" > timezone\r\n# mv localtime localtime.old\r\n# ln -s \/usr\/share\/zoneinfo\/Europe\/Madrid localtime\r\n# date\r\nWed Aug  6 13:16:08 CEST 2008\r\n<\/pre>\n<h4>Logs de usuario con Bash<\/h4>\n<p>En &#8216;\/etc\/profile&#8217; podemos a\u00f1adir las siguientes variables de entorno (personalmente \u00fanicamente a\u00f1ado la que permite tener hist\u00f3rico con timestamp, visualizable con el comando history de cada usuario):<\/p>\n<pre>\r\n########\r\n## declare -r: Variables de entorno que no pueden ser modificadas\r\n## readonly -p: Lista variables que no pueden ser modificadas\r\n\r\n# Nombre del archivo de historial (default '~\/.bash_history')\r\nexport HISTFILE='~\/.bash_history'\r\n#declare -r HISTFILE='~\/.bash_history'\r\n\r\n# n\u00ba m\u00e1ximo de comandos que puede contener el archivo (default 500).\r\nexport HISTFILESIZE='500'\r\n\r\n# n\u00ba de comandos por los que podr\u00e1 navegar el usuario con las teclas de cursor (default 500)\r\nexport HISTSIZE='500'\r\n\r\n# Ignorar comandos duplicados y espacios en blanco delante (default blank)\r\nexport HISTCONTROL=ignorespace:ignoredups\r\n\r\n# Save history with timestamp (default blank)\r\nexport HISTTIMEFORMAT=\"%Y-%m-%d %H:%M:%S \"\r\n\r\n# No guardar en el historial los siguientes comandos (por defecto en blanco)\r\nexport HISTIGNORE=\u201d:ls:cd ..:cd \/:\u201d\r\n<\/pre>\n<p>Esto mismo tambi\u00e9n lo podemos establecer en &#8216;\/etc\/bash.bashrc&#8217; si queremos que no solo afecte a las login shells.<\/p>\n<h4>Rotaci\u00f3n y conservaci\u00f3n de logs<\/h4>\n<p>En el sistema debemos tener instalado anacron o cron, si tenemos ambos simultaneamente (aunque uno de los dos demonios est\u00e9 parado) no se ejecutaran las tareas de \/etc\/cron.daily, weekly, etc.. (debido a como viene por defecto \/etc\/crontab). En nuestro caso, al ser un servidor y estar siempre en marcha usaremos cron:<\/p>\n<pre>\r\napt-get purge anacron\r\napt-get install cron\r\n<\/pre>\n<p>La pol\u00edtica de gesti\u00f3n de logs ser\u00e1:<\/p>\n<ul>\n<li>Rotaci\u00f3n mensual<\/li>\n<li>Mantenimiento de las \u00faltimas 24 copias (2 a\u00f1os de log)<\/li>\n<li>Incorporar la fecha de creaci\u00f3n al nombre del fichero<\/li>\n<\/ul>\n<p>Preparamos las tareas de rotacion de log a ejecutar por cron de forma mensual:<\/p>\n<pre>\r\nchmod 644 \/etc\/cron.daily\/sysklogd\r\nchmod 644 \/etc\/cron.weekly\/sysklogd\r\ncp \/etc\/cron.weekly\/sysklogd \/etc\/cron.monthly\/\r\nchmod 755 \/etc\/cron.monthly\/sysklogd\r\n<\/pre>\n<p>Editamos &#8216;\/etc\/cron.monthly\/sysklogd&#8217; y modificamos la linea que llama a save_log para incluir en la rotaci\u00f3n todos los ficheros log gestionados por syslogd:<\/p>\n<pre>\r\nlogs=$(syslogd-listfiles --weekly)\r\n<\/pre>\n<p>por:<\/p>\n<pre>\r\nlogs=$(syslogd-listfiles --all)\r\n<\/pre>\n<p>Tambi\u00e9n modificaremos:<\/p>\n<pre>\r\n savelog -g adm -m 640 -u ${USER} -c 4 $LOG >\/dev\/null\r\n<\/pre>\n<p>por:<\/p>\n<pre>\r\n      # Rotate monthly (script placed at \/etc\/cron.monthly\/)\r\n      # Keep 24 copies: -c 24\r\n      # Clean older copies than 24: -C\r\n      # Add date instead of .0 .1: -d\r\n      # Create a new file owned by adm and syslog with permission 640\r\n      savelog -g adm -m 640 -u ${USER} -c 24 -d -C $LOG >\/dev\/null\r\n<\/pre>\n<p>De esta forma, syslogd cumplir\u00e1 con la pol\u00edtica de gesti\u00f3n de logs que hemos definido.<\/p>\n<p>Mediante &#8216;syslogd-listfiles &#8211;all&#8217; podemos ver todos los ficheros que ser\u00e1n rotados, por ejemplo:<\/p>\n<pre>\r\n\/var\/log\/mail.warn\r\n\/var\/log\/uucp.log\r\n\/var\/log\/user.log\r\n\/var\/log\/daemon.log\r\n\/var\/log\/messages\r\n\/var\/log\/debug\r\n\/var\/log\/auth.log\r\n\/var\/log\/mail.err\r\n\/var\/log\/syslog\r\n\/var\/log\/mail.log\r\n\/var\/log\/mail.info\r\n\/var\/log\/kern.log\r\n\/var\/log\/lpr.log\r\n<\/pre>\n<p>El resto de logs que no son generados por syslogd, los gestionaremos a trav\u00e9s de logrotate.<\/p>\n<p>Editamos \/etc\/logrotate.conf y establecemos la pol\u00edtica general de logs:<\/p>\n<pre>\r\n# rotate log monthly\r\nmonthly\r\n# keep 24 months of backlog\r\nrotate 24\r\n\r\n# uncomment this if you want your log files compressed\r\ncompress\r\n\r\n# Postpone compression of the previous log file to the next rotation cycle\r\ndelaycompress\r\n\r\n\r\n\r\n\r\n\r\n\r\n# create new (empty) log files after rotating old ones\r\ncreate\r\n\r\n# uncomment this if you want your log files compressed\r\ncompress\r\n\r\n# Postpone compression of the previous log file to the next rotation cycle\r\ndelaycompress\r\n\r\n# Archive old versions of log files adding a daily extension like YYYYMMDD instead of simply adding a number.\r\ndateext\r\n\r\n# Rotate the log file even if it is empty\r\nifempty\r\n\r\n# packages drop log rotation information into this directory\r\ninclude \/etc\/logrotate.d\r\n\r\n# no packages own wtmp, or btmp -- we'll rotate them here\r\n\/var\/log\/wtmp {\r\n    missingok\r\n#    monthly\r\n    create 0664 root utmp\r\n#    rotate 1\r\n}\r\n\r\n\/var\/log\/btmp {\r\n    missingok\r\n#    monthly\r\n    create 0664 root utmp\r\n#    rotate 1\r\n}\r\n<\/pre>\n<p>En &#8216;\/etc\/logrotate.d&#8217; tenemos ficheros con los logs a rotar y en algunos casos, con pol\u00edticas concretas diferentes a la global. Para nos aseguramos que no haya pol\u00edticas diferentes a la global para logs espec\u00edficos podemos ejecutar:<\/p>\n<pre>\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/daily\/#daily\/g' {} ;\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/weekly\/#weekly\/g' {} ;\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/monthly\/#monthly\/g' {} ;\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/rotate\/#rotate\/g' {} ;\r\n\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/post#rotate\/postrotate\/g' {} ;\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/pre#rotate\/prerotate\/g' {} ;\r\n\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/notifempty\/#notifempty\/g' {} ;\r\nfind \/etc\/logrotate.d\/ -type f -exec sed -i 's\/size\/#size\/g' {} ;\r\n<\/pre>\n<p>Cabe destacar que es necesario revisar la configuraci\u00f3n existente en &#8216;\/etc\/logrotate.d&#8217; por si faltase realizar alguna modificaci\u00f3n extra (p.ej. logs extra de apache como &#8216;\/var\/log\/apache2\/localhost\/*.log&#8217;).<\/p>\n<p>Del resto de logs del sistema que queramos rotar y no est\u00e9n ya incluidos, tendremos que crear un fichero nuevo en &#8216;\/etc\/logrotate.d&#8217; indic\u00e1ndolo (en general, todo paquete de Ubuntu ya viene preparado para que sus logs sean gestionados autom\u00e1ticamente por syslogd o logrotate). Es importante tener en cuenta que no debemos rotar:<\/p>\n<ul>\n<li>Binarios como \/var\/log\/faillog o \/var\/log\/lastlog<\/li>\n<li>Logs de nagios dado que romper\u00edamos el historial interno. Mejor que lo gestione la propia aplicaci\u00f3n directamente.<\/li>\n<li>Logs generados directamente por syslogd (como hemos visto antes). Visualizar con syslogd-listfiles &#8211;all<\/li>\n<\/ul>\n<h5>An\u00e1lisis de logs de Apache mediante Awstats<\/h5>\n<p>Con awstats podremos ver las visitas, tr\u00e1fico y otros aspectos relacionados con cada uno de los dominios virtuales que tengamos configurados en Apache. Para su instalaci\u00f3n presuponemos que ya tenemos configurado Apache y que awstats va ser accesible \u00fanicamente de forma local:<\/p>\n<pre>\r\napt-get install awstats\r\nmkdir \/var\/lib\/awstats\/localhost\r\nchown www-data:www-data \/var\/lib\/awstats\/localhost\r\n<\/pre>\n<p>Creamos &#8216;\/etc\/awstats\/awstats.localhost.conf&#8217; apuntando al log que queramos analizar:<\/p>\n<pre>\r\nLogFile=\"\/var\/log\/apache2\/localhost\/access.log\"\r\nLogFormat=1\r\nDNSLookup=1\r\nDirData=\"\/var\/lib\/awstats\/localhost\"\r\nDirCgi=\"\/cgi-bin\"\r\nDirIcons=\"\/icon\"\r\nSiteDomain=\"localhost\"\r\nAllowToUpdateStatsFromBrowser=1\r\nAllowFullYearView=3\r\n<\/pre>\n<p>Copiamos iconos b\u00e1sicos:<\/p>\n<pre>\r\ncp -r \/usr\/share\/awstats\/icon \/var\/www\/localhost\/\r\n<\/pre>\n<p>Actualizamos output HTML:<\/p>\n<pre>\r\n\/usr\/lib\/cgi-bin\/awstats.pl -config=localhost -update\r\n<\/pre>\n<p>Creamos el fichero &#8216;\/etc\/apache2\/conf.d\/awstats.conf&#8217; con el siguiente contenido:<\/p>\n<pre>\r\nScriptAlias \/cgi-bin\/awstats.pl \/usr\/lib\/cgi-bin\/awstats.pl\r\n<\/pre>\n<p>Reiniciamos apache:<\/p>\n<pre>\r\n\/etc\/init.d\/apache2 restart\r\n<\/pre>\n<p>Y accedemos a la web mediante &#8216;http:\/\/localhost:8080\/cgi-bin\/awstats.pl?config=localhost&#8217;.<\/p>\n<p>Para que se actualice peri\u00f3dicamente el an\u00e1lisis de Awstats, editamos \/etc\/cron.d\/awstats (cada noche):<\/p>\n<pre>\r\n0 1 * * * www-data \/usr\/lib\/cgi-bin\/awstats.pl -config=localhost -update >\/dev\/null\r\n<\/pre>\n<h5>Env\u00edo por correo de los eventos m\u00e1s significativos con logcheck<\/h5>\n<p>Con logcheck podremos resumir los eventos del sistema registrados en los logs y enviarlos a nuestro correo de forma diaria:<\/p>\n<pre>\r\napt-get install logcheck logcheck-database\r\n<\/pre>\n<p>Editamos &#8216;\/etc\/logcheck\/logcheck.logfiles&#8217;:<\/p>\n<pre>\r\n# Estos 2 ficheros incluyen todos los mensajes enviados a syslog  ()\/etc\/syslog.conf)\r\n\/var\/log\/syslog\r\n\/var\/log\/auth.log\r\n# Apache\r\n\/var\/log\/apache2\/error.log\r\n\/var\/log\/apache2\/localhost\/error.log\r\n# MySQL\r\n#\/var\/log\/mysql\/mysql.log # En debian, si descomentas la linea de log de \/etc\/mysql\/my.cnf, el log va por syslog\r\n#\/var\/log\/mysql\/mysql-slow.log\r\n<\/pre>\n<p>La tarea cron que se encarga de la ejecuci\u00f3n diaria es &#8216;\/etc\/cron.d\/logcheck&#8217;.<\/p>\n<p>Por otra parte, la configuraci\u00f3n de logcheck se encuentra en &#8216;\/etc\/logcheck\/logcheck.conf&#8217;:<\/p>\n<pre>\r\n# Controls the address mail goes to:\r\n# *NOTE* the script does not set a default value for this variable!\r\n# Should be set to an offsite \"emailaddress@some.domain.tld\"\r\n\r\nSENDMAILTO=\"miusuario\"\r\n\r\n# Send the results as attachment or not.\r\n# 0=not as attachment; 1=as attachment\r\n# Default ist 0\r\nMAILASATTACH=1\r\n<\/pre>\n<p>Una vez configurado, podemos probar su funcionamiento ejecutando:<\/p>\n<pre>\r\nsudo -u logcheck logcheck\r\n<\/pre>\n<p>Logcheck incorpora por defecto toda una serie de reglas para la selecci\u00f3n o el descarte de las lineas del log a enviar en el resumen. Es posible que nos interese refinar estas reglas, haciendo que sean descartadas cadenas que no nos aporten nada. Por ejemplo, veamos como ignorar las lineas generadas por el firewall o nagios (ver secciones correspondientes), dado que esa informaci\u00f3n ya la analizamos con otras herramientas.<\/p>\n<p>Creamos &#8216;\/etc\/logcheck\/ignore.d.server\/000-custom&#8217; y a\u00f1adimos:<\/p>\n<pre>\r\n^w{3} [ :0-9]{11} [._[:alnum:]-]+ kernel: [FW:[ ._[:alnum:]-]+]\r\n^w{3} [ :0-9]{11} [._[:alnum:]-]+ nagios2: CURRENT SERVICE STATE:\r\n^w{3} [ :0-9]{11} [._[:alnum:]-]+ nagios2: CURRENT HOST STATE:\r\n^w{3} [ :0-9]{11} [._[:alnum:]-]+ nagios2: Warning: A system time change of [0-9]+ seconds (backwards in time) has been detected.  Compensating...\r\n<\/pre>\n<p>Si queremos incluir m\u00e1s reglas, podemos validarlas contra el log que nos interese:<\/p>\n<pre>\r\nsed -e 's\/[[:space:]]*$\/\/' \/var\/log\/ulog\/syslogemu.log | egrep '^w{3} [ :0-9]{11} [._[:alnum:]-]+ kernel: [FW:[ ._[:alnum:]-]+]'\r\nsed -e 's\/[[:space:]]*$\/\/' \/var\/log\/syslog | egrep '^w{3} [ :0-9]{11} [._[:alnum:]-]+ nagios2: CURRENT SERVICE STATE:'\r\nsed -e 's\/[[:space:]]*$\/\/' \/var\/log\/syslog | egrep '^w{3} [ :0-9]{11} [._[:alnum:]-]+ nagios2: CURRENT HOST STATE:'\r\nsed -e 's\/[[:space:]]*$\/\/' \/var\/log\/syslog | egrep '^w{3} [ :0-9]{11} [._[:alnum:]-]+ nagios2: Warning: A system time change of [0-9]+ seconds (backwards in time) has been detected.  Compensating...'\r\n<\/pre>\n<p>Si la regla funciona, aparecer\u00e1n los mensajes que queremos eliminar.<\/p>\n<h3><a name=\"8\">8. Monitorizaci\u00f3n del sistema<\/a><\/h3>\n<h4>Actualizaci\u00f3n autom\u00e1tica de la lista de paquetes del sistema<\/h4>\n<p>Para comprobar que nuestro sistema se encuentra actualizado, primero necesitamos que se actualice la lista de paquetes autom\u00e1ticamente. Creamos &#8216;\/etc\/apt\/apt.conf.d\/10periodic&#8217;:<\/p>\n<pre>\r\nAPT::Periodic::Update-Package-Lists \"1\";\r\nAPT::Periodic::Download-Upgradeable-Packages \"0\";\r\nAPT::Periodic::AutocleanInterval \"0\";\r\n<\/pre>\n<p>De esta forma se actualizar\u00e1 el listado de paquetes (apt-get update) cada d\u00eda mediante el fichero &#8216;\/etc\/cron.daily\/apt&#8217;.<\/p>\n<p>Si hemos instalado nagios (ver Secci\u00f3n correspondiente), este nos informar\u00e1 de cuando hay paquetes pendientes de ser actualizados.<\/p>\n<h4>Aviso de actualizaciones pendientes<\/h4>\n<p>Con apticron podremos hacer que el sistema nos env\u00ede un correo cada vez que se disponga de paquetes pendientes de ser actualizados (p.ej. parches de seguridad):<\/p>\n<pre>\r\napt-get install apticron \r\n<\/pre>\n<p>Para su uso necesitamos tener configurado un servidor de correo (SMTP), podemos configurar un postfix (ver secci\u00f3n anterior de servicios) o utilizar ssmtp para conectar contra un servidor de correo ya configurado.<\/p>\n<p>En el segundo caso, instalamos mediante &#8216;apt-get install ssmtp&#8217; y editamos &#8216;\/etc\/ssmtp\/ssmtp.conf&#8217;:<\/p>\n<pre>\r\n# Config file for sSMTP sendmail\r\n#\r\n# The person who gets all mail for userids < 1000\r\n# Make this empty to disable rewriting.\r\nroot=miusuario\r\n\r\n# The place where the mail goes. The actual machine name is required no\r\n# MX records are consulted. Commonly mailhosts are named mail.domain.com\r\nmailhub=servidor.correo.com:25\r\n\r\n# Where will the mail seem to come from?\r\n#rewriteDomain=nonsense.non\r\n\r\n# The full hostname\r\nhostname=el.dominio.de.esta.maquina.com\r\n\r\n# Are users allowed to set their own From: address?\r\n# YES - Allow the user to specify their own From: address\r\n# NO - Use the system generated From: address\r\nFromLineOverride=NO\r\n<\/pre>\n<p>En el fichero anterior indicamos a quien redirigimos los correos de root, el servidor de correo que utilizaremos y el dominio con el que saldr\u00e1n los correos de la m\u00e1quina actual. <\/p>\n<p>Tanto si ya tenemos un servidor postfix configurado como si hemos optado por SSMTP, debemos probar que el comando 'mail' nos permite enviar correos:<\/p>\n<pre>\r\necho \"Prueba\" | mail -s \"Prueba\" miusuario@otrolugar.com\r\n<\/pre>\n<p>Una vez validado, podemos continuar con la configuraci\u00f3n de apticron editando &#8216;\/etc\/apticron\/apticron.conf&#8217; y estableciendo el correo al que queremos recibir las alertas:<\/p>\n<pre>\r\nEMAIL=\"miusuario@otrolugar.com\"\r\n<\/pre>\n<p>Esto es todo. Cron ejecutar\u00e1 diariamente el script &#8216;\/etc\/cron.daily\/apticron&#8217;, el cual comprobar\u00e1 las actualizaciones pendientes y enviar\u00e1 un correo en caso de que sea necesario.<\/p>\n<p>Cabe destacar que para que funcione, el sistema debe estar configurado para que actualice autom\u00e1ticamente el listado de paquetes (ver secci\u00f3n anterior).<\/p>\n<h4>Monitorizar desde la consola<\/h4>\n<h5>Espacio en disco<\/h5>\n<p>Para la monitorizaci\u00f3n del espacio en disco podemo usar los comandos:<\/p>\n<pre>\r\ndf -h\r\ndu -ms\r\n<\/pre>\n<p>El primero muestra el estado de todas las particiones, el segundo presenta los megas que ocupa el directorio actual.<\/p>\n<p>Puede que nos interese ordenar los directorios en funci\u00f3n de su tama\u00f1o, para ello podemos descargar un script espec\u00edfico:<\/p>\n<pre>\r\ncd \/usr\/local\/bin\r\nwget http:\/\/www.pixelbeat.org\/scripts\/dutop\r\nchmod 755 \/usr\/local\/bin\/dutop\r\n<\/pre>\n<p>Que al ejecutar facilita la siguiente informaci\u00f3n:<\/p>\n<pre>\r\n# dutop\r\n27%    183.8M    .\/Fotos\r\n26%    180.5M    .\/Fotos.zip \r\n19%    135.0M    .\/Documentos\r\n 5%     37.4M    .\/Trabajo\r\n 5%     35.6M    .\/Musica \r\n<\/pre>\n<h5>CPU<\/h5>\n<p>La monitorizaci\u00f3n de la CPU (m\u00e1s otros par\u00e1metros) podemos llevarla a cabo mediante &#8216;top&#8217; o &#8216;htop&#8217;:<\/p>\n<pre>\r\napt-get install htop\r\n<\/pre>\n<h5>Ancho de banda \/ Bandwidth<\/h5>\n<p>Aplicaciones recomendadas:<\/p>\n<pre>\r\napt-get install bwm-ng\r\n<\/pre>\n<p>Y tambi\u00e9n:<\/p>\n<pre>\r\napt-get install jnettop\r\n<\/pre>\n<p>Para este \u00faltimo debemos crear el fichero &#8216;~\/.jnettop&#8217;:<\/p>\n<pre>\r\n#interface \"eth0\"\r\n# Show IP and Ports per separate\r\nlocal_aggregation     none\r\n# I don't care about remote port\r\nremote_aggregation    port\r\n# Do not generate more traffic resolving every IP\r\nresolve               off\r\n<\/pre>\n<p>Al ejecutar jnettop podemos interactuar con la aplicaci\u00f3n para cambiar los par\u00e1metros establecidos. Por ejemplo:<\/p>\n<ul>\n<li>&#8216;l&#8217;: cambia la agregaci\u00f3n local<\/li>\n<li>&#8216;r&#8217;: cambia la agregaci\u00f3n remota<\/li>\n<\/ul>\n<h5>Conexiones de red<\/h5>\n<p>Conexiones de la m\u00e1quina:<\/p>\n<pre>\r\n# netstat -atunp\r\n<\/pre>\n<p>Si la m\u00e1quina se encuentra haciendo NAT en una red, podemos ver tambi\u00e9n las conexiones &#8220;NATeadas&#8221;:<\/p>\n<pre>\r\n# apt-get install netstat-nat\r\n# netstat-nat -N\r\n<\/pre>\n<p>Si hemos configurado el firewall con iptables (ver secci\u00f3n correspondiente), podremos ver las conexiones controladas por el m\u00f3dulo CONNTRACK:<\/p>\n<pre>\r\n# apt-get install iptstate\r\n# iptstate\r\n<\/pre>\n<h5>Memoria RAM \/ Swap<\/h5>\n<p>Para obtener un listado de los procesos del sistema ordenados por la memoria consumida:<\/p>\n<pre>\r\n\r\nps -A --sort=-rsz -o pid,vsz,rssize,pmem,comm\r\n<\/pre>\n<p>Cada par\u00e1metro indica:<\/p>\n<ul>\n<li>pid: Process ID<\/li>\n<li>vsz: Virtual Memory Size (includes RAM &#038; Swap)<\/li>\n<li>rssize: Resident Memory Size (only RAM)<\/li>\n<li>pmem: Ratio of the process\u2019s resident set size  to the physical memory on the machine<\/li>\n<\/ul>\n<p>Para ver la memoria total utilizada tenemos dos opciones:<\/p>\n<pre>\r\n# vmstat -S M \r\nprocs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\r\n r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa\r\n 0  0     34      6     12    134    0    0   348    60  556  521 10  1 75 14\r\n<\/pre>\n<pre>\r\n# free -m\r\n             total       used       free     shared    buffers     cached\r\nMem:           502        494          8          0         12        132\r\n-\/+ buffers\/cache:        349        153\r\nSwap:          972         34        938\r\n<\/pre>\n<p>Cada columna significa:<\/p>\n<ul>\n<li>Cache: Bloques de informaci\u00f3n le\u00eddos del disco duro<\/li>\n<li>Buffer: Memoria temporal utilizada por el kernel (p.ej. comunicaciones con dispositivos, envio\/recepci\u00f3n de informaci\u00f3n por red, etc.)<\/li>\n<li>Swap: Cuando la memoria RAM escasea, el kernel transfiere partes de la memoria RAM a la memoria SWAP, la cual realmente se encuentra en el disco duro y por tanto es mucho m\u00e1s lenta (pero nos permite cargar m\u00e1s aplicaciones de las que podriamos con nuestra RAM actual).<\/li>\n<\/ul>\n<p>Cuando se requiere m\u00e1s memoria, el kernel debe decidir si reducir la cache\/buffers o enviar bloques de memoria a la Swap. Esta decisi\u00f3n se encuentra parametrizada mediante el valor swappines:<\/p>\n<pre>\r\ncat \/proc\/sys\/vm\/swappiness\r\n<\/pre>\n<p>Habitualmente su valor es de 60, pero puede situarse entre 0 (poco probable que se realice swap) y 100 (m\u00e1xima prioridad a realizar swap). Seg\u00fan las aplicaciones de nuestro sistema quiz\u00e1s nos interese cambiarlo, p.ej. en un desktop, cuando se ejecutan procesos cron que consumen mucho disco duro (por ejemplo slocate), la cache crecer\u00e1 y puede que se env\u00eden aplicaciones a la swap (swap-in) y el usuario notar\u00e1 una ralentizaci\u00f3n notable del sistema en el momento que quiera acceder a ellas (swap-out). Para cambiar el par\u00e1metro:<\/p>\n<pre>\r\n# echo \"10\" > \/proc\/sys\/vm\/swappiness\r\n# cat \/proc\/sys\/vm\/swappiness\r\n<\/pre>\n<p>Este cambio se perder\u00e1 en el siguiente reinicio, para que sea permanente editamos \/etc\/sysctl.conf y a\u00f1adimos la linea:<\/p>\n<pre>\r\nvm.swappiness=10\r\n<\/pre>\n<p>&#8216;ps_mem&#8217; es un script (python) que imprime el total de memoria RAM sumarizada por proceso padre (p.ej. si apache realiza varios forks, al mostrar la informaci\u00f3n los unificar\u00e1):<\/p>\n<pre>\r\ncd \/usr\/local\/bin\r\nwget http:\/\/www.pixelbeat.org\/scripts\/ps_mem.py\r\nchmod 755 \/usr\/local\/bin\/ps_mem.py\r\n<\/pre>\n<p>Resultado de ejemplo:<\/p>\n<pre>\r\n# ps_mem.py |less\r\nWarning: Shared memory is slightly over-estimated by this system\r\nfor each program, so totals are not reported.\r\n Private  +   Shared  =  RAM used       Program \r\n\r\n 68.0 KiB + 320.0 KiB = 388.0 KiB       klogd\r\n116.0 KiB + 288.0 KiB = 404.0 KiB       atd\r\n 80.0 KiB + 416.0 KiB = 496.0 KiB       mysqld_safe\r\n 88.0 KiB + 416.0 KiB = 504.0 KiB       dd\r\n 68.0 KiB + 436.0 KiB = 504.0 KiB       logger\r\n152.0 KiB + 520.0 KiB = 672.0 KiB       syslogd\r\n 96.0 KiB + 584.0 KiB = 680.0 KiB       init\r\n152.0 KiB + 720.0 KiB = 872.0 KiB       less\r\n208.0 KiB + 740.0 KiB = 948.0 KiB       cron\r\n308.0 KiB +   1.3 MiB =   1.6 MiB       pickup\r\n332.0 KiB +   1.3 MiB =   1.7 MiB       master\r\n352.0 KiB +   1.4 MiB =   1.7 MiB       qmgr\r\n  1.2 MiB + 856.0 KiB =   2.0 MiB       screen (2)\r\n780.0 KiB +   2.3 MiB =   3.0 MiB       sshd (3)\r\n  1.2 MiB +   1.9 MiB =   3.1 MiB       mutt\r\n  1.8 MiB +   2.3 MiB =   4.1 MiB       snmpd\r\n840.0 KiB +   7.0 MiB =   7.8 MiB       apache2 (6)\r\n  9.0 MiB +   1.4 MiB =  10.4 MiB       bash (6)\r\n 15.4 MiB +   5.1 MiB =  20.6 MiB       mysqld\r\n<\/pre>\n<h4>Monitorizaci\u00f3n en tiempo real: Nagios<\/h4>\n<p>Con Nagios podemos monitorizar diversos sistemas en tiempo real, generando alertas cuando se incumpla alguno de los par\u00e1metros especificados. Tambi\u00e9n vale la pena considerar la opci\u00f3n de utilizar <a href=\"http:\/\/www.tildeslash.com\/monit\/\">Monit<\/a> en su lugar.<\/p>\n<pre>\r\n# apt-get install nagios2 nagios-images nagios-plugins\r\n<\/pre>\n<p>Configuramos un usuario para nagios:<\/p>\n<pre>\r\n# sudo htpasswd -c \/etc\/nagios2\/htpasswd.users nagiosadmin\r\nNew password: \r\nRe-type new password: \r\nAdding password for user nagiosadmin\r\n<\/pre>\n<p>Preparamos el sistema:<\/p>\n<pre>\r\n# chown nagios:nagios \/var\/log\/nagios2\/\r\n# chown -R nagios:www-data \/var\/cache\/nagios2\/\r\n\r\n# cd \/bin\/\r\n# ln -s \/usr\/bin\/mail mail\r\n<\/pre>\n<p>Creamos nuestra configuraci\u00f3n espec\u00edfica:<\/p>\n<pre>\r\nmkdir \/etc\/nagios2\/mysite\r\ncd \/etc\/nagios2\/mysite\r\ncp \r\ncp ..\/conf.d\/contacts_nagios2.cfg  contacts.cfg\r\ncp ..\/conf.d\/timeperiods_nagios2.cfg timeperiods.cfg\r\ncp ..\/conf.d\/localhost_nagios2.cfg localhost.cfg\r\ncp ..\/conf.d\/generic-service_nagios2.cfg generic-service.cfg\r\ncp ..\/conf.d\/generic-host_nagios2.cfg generic-host.cfg\r\n<\/pre>\n<p>En estos ficheros de configuraci\u00f3n especificaremos los servidores y servicios que queremos monitorizar. Para una gu\u00eda m\u00e1s detallada consultar <a href=\"https:\/\/help.ubuntu.com\/community\/Nagios2\">el wiki de Ubuntu sobre Nagios<\/a> para as\u00ed configurar Nagios seg\u00fan nuestras necesidades..<\/p>\n<p>Hay que tener en cuenta que si alguno de los servicios a comprobar es una mysql, debemos asegurarnos que nagios tiene su propio usuario con acceso:<\/p>\n<pre>\r\nmysql -u root -p\r\n\r\nCREATE USER 'nagios'@'localhost';\r\nFLUSH PRIVILEGES;\r\n<\/pre>\n<p>Nagios depende de apache, dado que su interfaz principal es via web. Para ello apache va a requerir algunos m\u00f3dulos extra:<\/p>\n<pre>\r\na2enmod auth_basic\r\na2enmod authn_file\r\na2enmod authz_default\r\na2enmod authz_groupfile\r\na2enmod authz_host\r\na2enmod authz_user\r\na2enmod cgi\r\na2enmod alias\r\n\r\n\/etc\/init.d\/apache2 restart\r\n<\/pre>\n<p>Una vez configurado, la puesta en marcha:<\/p>\n<pre>\r\n# \/etc\/init.d\/nagios2 stop\r\n# \/etc\/init.d\/nagios2 start\r\n<\/pre>\n<p>Cabe destacar que los plugins de nagios se encuentran en &#8216;\/usr\/lib\/nagios\/plugins&#8217;, y puede que nos interese tener soporte SNMP (ver secci\u00f3n SNMP):<\/p>\n<pre>\r\napt-get install nagios-snmp-plugins\r\n<\/pre>\n<h5>Ancho de banda consumido con Bandwidthd<\/h5>\n<p>Bandwidthd dibuja gr\u00e1ficas y tablas HTML con el tr\u00e1fico generado, as\u00ed podemos controlar lo que sucede en el servidor:<\/p>\n<pre>\r\napt-get install bandwidthd\r\ncd \/var\/www\r\nln -s \/var\/lib\/bandwidthd\/htdocs\/ bandwidthd\r\n<\/pre>\n<p>Configuraci\u00f3n en \/etc\/bandwidthd\/bandwidthd.conf:<\/p>\n<pre>\r\nsubnet 0.0.0.0\/0\r\n<\/pre>\n<p>Cabe destacar que bandwithd consume bastante memoria RAM (200 MB aprox. de media) y quiz\u00e1s con otras herramientas como Cacti ya tenemos informaci\u00f3n suficiente sobre el ancho de banda.<\/p>\n<h4>SNMP<\/h4>\n<p>SNMP es un protocolo que permite monitorizar servidores y dispositivos de red de forma remota. Nos puede resultar \u00fatil activarlo en nuestra m\u00e1quina de forma local para que sea utilizado en conjunto con Nagios y\/o Cacti. <\/p>\n<pre>\r\n# apt-get install snmpd snmp\r\n<\/pre>\n<p>Nos aseguramos que solo sea accesible por localhost \/etc\/default\/snmpd y desactivamos los m\u00f3dulos smux, ipv6 :<\/p>\n<pre>\r\n\r\n# snmpd options (use syslog, close stdin\/out\/err).\r\n# Log by Syslog only: warning messages, errors, alerts and critical.\r\n#   ingore: notice info and debug\r\nSNMPDOPTS='-Ls 01234 -Lf \/dev\/null -A -u snmp -I -smux,ipv6 -p \/var\/run\/snmpd.pid 127.0.0.1'\r\n<\/pre>\n<p>En la configuraci\u00f3n &#8216;\/etc\/snmp\/snmpd.conf&#8217; indicamos::<\/p>\n<pre>\r\n##       sec.name     source           community\r\n##       ========     ======           =========\r\n#com2sec  local       localhost        public\r\n#com2sec  network_1   172.16.1.0\/24    public\r\n#com2sec  network_2   192.168.2.0\/24   public\r\n\r\n##       Access.group.name   sec.model        sec.name\r\n##       =================  =========         ========\r\n#group    MyROGroup_1        v1                local\r\n#group    MyROGroup_1        v1                network_1\r\n#group    MyROGroup_2        v2c               network_2\r\n\r\n##   MIB.view.name     incl\/excl  MIB.subtree  mask\r\n##   ==============   =========  ===========  ====\r\n#view all-mibs         included   .1           80\r\n\r\n##      MIB                \r\n##      group.name   context sec.model sec.level prefix read     write  notif\r\n##      ==========   ======= ========= ========= ====== ====     =====  =====\r\n\r\n#access  MyROGroup_1  \"\"       v1       noauth    exact  all-mibs none   none\r\n#access  MyROGroup_2  \"\"       v2c      noauth    exact  all-mibs none   none\r\n#\r\n\r\nrocommunity public\r\n\r\nsyslocation NewYork\r\nsyscontact admin@localhost\r\n\r\n\r\n#ignoredisk \/dev\/rdsk\/c0t2d0\r\ndisk \/\r\n#disk \/usr\r\n#disk \/var\r\n\r\nproc apache2\r\nproc mysqld\r\n<\/pre>\n<p>La configuraci\u00f3n anterior hace que SNMP sea accesible en modo lectura para cualquier usuario, adem\u00e1s monitorizar\u00e1 el disco principal &#8220;\/&#8221; y los procesos apache2 y mysqld.<\/p>\n<p>Reiniciamos el servicio:<\/p>\n<pre>\r\n\/etc\/init.d\/snmpd restart\r\n<\/pre>\n<p>Si queremos lanzar consultas SNMP desde la terminal:<\/p>\n<pre>\r\nsnmpwalk -v 1 -c public localhost interface|less\r\nsnmpwalk -v 1 -c public localhost system|less\r\nsnmpget -v 1 -c const1payted localhost ifPhysAddress.2\r\n<\/pre>\n<p>Para una explicaci\u00f3n m\u00e1s detallada vale la pena leer el siguiente tutorial: <a href=\"http:\/\/www.linuxhomenetworking.com\/wiki\/index.php\/Quick_HOWTO_:_Ch22_:_Monitoring_Server_Performance\">Monitoring Server Performance<\/a>.<\/p>\n<h5>Soporte &#8216;Devices I\/O&#8217; en net-snmp<\/h5>\n<p>En Ubuntu, net-snmp no viene compilado con soporte para proporcionar informaci\u00f3n de I\/O de los dispositivos del sistema (disco duro). Tenemos la opci\u00f3n de recompilar activando la funcionalidad, o delegar esta tarea a un script que consultar\u00e1 \/proc\/diskstats. Optamos por la segunda por su sencillez:<\/p>\n<p>Editamos\/etc\/snmp\/snmpd.conf y a\u00f1adimos al final:<\/p>\n<pre>\r\npass .1.3.6.1.4.1.2021.13.15 \/usr\/local\/bin\/snmp-diskio-collector\r\n<\/pre>\n<p>Creamos el script <a href=\"\"# http:\/\/spacepants.org\/blog\/net-snmp-linux-diskio-collector-2>\/usr\/local\/bin\/snmp-diskio-collector<\/a>:<\/p>\n<pre>\r\n#!\/bin\/sh\r\n\r\n# by Jamie Wilkinson jamie @anchor.net.au\r\n# this code is in the public domain\r\n# based on passtest from the net-snmp distribution examples\r\n# WARNING there is shitloads of IO required to get this information :)\r\n\r\ndebug_flag=0\r\n\r\ndebug () {\r\n    if [ $debug_flag -eq 1 ]; then\r\n        echo $* >> \/tmp\/snmp-diskio-collector-debug.log\r\n    fi\r\n}\r\n\r\nPLACE=\".1.3.6.1.4.1.2021.13.15\"\r\nREQ=\"$2\"\r\n\r\ndebug\r\ndebug \"new run\" \r\ndebug \"args $*\" \r\nif [ \"$1\" = \"-s\" ]; then\r\n  exit 0\r\nfi\r\n\r\n# the 'tail' of the oid, everything after $PLACE\r\noidtail=`echo $REQ | sed \"s\/^$PLACE\/\/\"`\r\ndebug \"oidtail=$oidtail\" \r\n\r\n# number of devices we can export\r\ndevcount=`wc -l \/proc\/diskstats | cut -f1 -d' '`\r\ndebug \"devcount=$devcount\" \r\n\r\nitem=`echo $oidtail | cut -f4 -d.`\r\nindex=`echo $oidtail | cut -f5 -d.`\r\ndebug \"oidtail=$oidtail, item=$item, index=$index\" \r\n\r\nif [ \"$1\" = \"-n\" ]; then\r\n    if [ -z \"$item\" ]; then\r\n        item=1\r\n        index=1\r\n    elif [ -z \"$index\" ]; then\r\n        index=1\r\n    else\r\n        index=`expr $index + 1`\r\n        if [ \"$index\" -gt \"$devcount\" ]; then\r\n            index=1\r\n            item=`expr $item + 1`\r\n            if [ \"$item\" -gt 6 ]; then\r\n                # break out of the loop\r\n                exit 0;\r\n            fi\r\n        fi\r\n    fi\r\n    RET=$PLACE.1.1.$item.$index\r\nelse\r\n    case \"$REQ\" in\r\n        $PLACE) exit 0;;\r\n        *) RET=$REQ ;;\r\n    esac\r\nfi\r\n\r\ndebug \"after -n, item=$item, index=$index\" \r\ndebug \"RET is now $RET\" \r\n\r\necho \"$RET\"\r\n\r\ndebug \"oidtail=$oidtail, item=$item, index=$index\" \r\n\r\n# awk uses this variable in the environment below\r\nexport index\r\n# see linux kernel Documentation\/iostats.txt for format\r\nif [ -n \"$index\" ]; then\r\n    case \"$item\" in\r\n        1)\r\n            # diskIOIndex\r\n            debug \"result: diskIOIndex $index\" \r\n            echo \"integer\"\r\n            echo $index\r\n            exit 0\r\n            ;;\r\n        2)\r\n            # diskIODevice\r\n            debug \"result: diskIODevice $index\" \r\n            echo \"string\"\r\n            awk 'FNR == ENVIRON[\"index\"] { print $3 }' \/proc\/diskstats\r\n            exit 0\r\n            ;;\r\n        3)\r\n            # diskIONRead\r\n            debug \"result: diskIONRead $index\" \r\n            echo \"counter\"\r\n            awk 'FNR == ENVIRON[\"index\"] { print $6 }' \/proc\/diskstats\r\n            exit 0\r\n            ;;\r\n        4)\r\n            # diskIONWritten\r\n            debug \"result: diskIONWritten $index\" \r\n            echo \"counter\"\r\n            awk 'FNR == ENVIRON[\"index\"] { print $10 }' \/proc\/diskstats\r\n            exit 0\r\n            ;;\r\n        5)\r\n\r\n            # diskIOReads\r\n            debug \"result: diskIOReads $index\" \r\n            echo \"counter\"\r\n            awk 'FNR == ENVIRON[\"index\"] { print $4 }' \/proc\/diskstats\r\n            exit 0\r\n            ;;\r\n        6)\r\n            # diskIOWrites\r\n            debug \"result: diskIOWrites $index\" \r\n            echo \"counter\"\r\n            awk 'FNR == ENVIRON[\"index\"] { print $8 }' \/proc\/diskstats\r\n            exit 0\r\n            ;;\r\n        *) exit 0; #echo \"string\"; echo \"debug... $RET $REQ\"; exit 0 ;;\r\n    esac\r\nelse\r\n    exit 0\r\nfi\r\n<\/pre>\n<p>Damos permisos de ejecuci\u00f3n y reiniciamos SNMP:<\/p>\n<pre>\r\nchmod 755 \/usr\/local\/bin\/snmp-diskio-collector\r\n\/etc\/init.d\/snmpd restart\r\n<\/pre>\n<p>Para probar que funciona correctamente:<\/p>\n<pre>\r\nsnmpwalk -m ALL -v1 -c public localhost diskIOTable\r\n<\/pre>\n<h4>Monitorizaci\u00f3n historica: Cacti<\/h4>\n<p>Cacti es una herramienta que almacena un hist\u00f3rico del estado de diferentes aspecto del sistema local (p.ej. CPU, Memoria, ancho de banda, etc.) o remoto via SNMP. Vale la pena considerar tambi\u00e9n <a href=\"http:\/\/munin.projects.linpro.no\/\">muni<\/a> como alternativa.<\/p>\n<p>Cacti requerir\u00e1 Apache y SNMP para funcionar (ver secciones correspondientes).<\/p>\n<pre>\r\napt-get install cacti\r\nln -s \/usr\/bin\/php5 \/usr\/bin\/php\r\n<\/pre>\n<p>Una vez instalado, podemos acceder v\u00eda web por defecto en &#8216;http:\/\/localhost\/cacti&#8217; (aunque puede variar depende de como configuremos apache).<\/p>\n<p>A trav\u00e9s de la web, crearemos un &#8220;dispositivo SNMP&#8221; que realmente ser\u00e1 nuestro sistema y a\u00f1adiremos unas gr\u00e1ficas est\u00e1ndar:<\/p>\n<ul>\n<li>Crear dispositivo &#8220;ucd\/net SNMP Host&#8221; apuntando a localhost.<\/li>\n<li>A\u00f1adir graph templates:<br \/>\n1) ucd\/net &#8211; CPU Usage<br \/>\n2) ucd\/net &#8211; Load Average<br \/>\n3) ucd\/net &#8211; Memory Usage<br \/>\n4) Unix &#8211; Logged in Users<br \/>\n5) Unix &#8211; Ping Latency<br \/>\n6) Unix &#8211; Processes\n<\/li>\n<li>A\u00f1adir data queries:<br \/>\n1) SNMP &#8211; Get Mounted Partitions<br \/>\n2) SNMP &#8211; Get Processor Information<br \/>\n3) SNMP &#8211; Interface Statistics<br \/>\n4) ucd\/net &#8211; Get Monitored Partitions\n<\/li>\n<li>A\u00f1adir gr\u00e1ficas desde &#8220;New graphs&#8221;<\/li>\n<li>Desde &#8220;Graph Management&#8221;, seleccionar las nuevas gr\u00e1ficas y a\u00f1adirlas al al \u00e1rbol (Place on a Tree)<\/li>\n<\/ul>\n<p>M\u00e1s informaci\u00f3n en la <a href=\"http:\/\/docs.cacti.net\/\">web de cacti<\/a>.<\/p>\n<h5>Script Device I\/O para cacti<\/h5>\n<p>Si hemos activado el soporte I\/O para dispositivos (disco duro) en el servicio SNMP, podemos hacer que cacti monitorice tambi\u00e9n esa informaci\u00f3n.<\/p>\n<p>Lo mejor es seguir las instrucciones del <a href=\"http:\/\/forums.cacti.net\/about8777.html\">foro de cacti<\/a>, pero a grandes rasgos los pasos a seguir son los siguientes:<\/p>\n<pre>\r\n# cd \/usr\/share\/cacti\/resource\/snmp_queries\/\r\n# wget http:\/\/forums.cacti.net\/download.php?id=2635\r\n# mv download.php?id=2635 Cacti_Net-SNMP_DevIO_v2.zip\r\n# unzip Cacti_Net-SNMP_DevIO_v2.zip\r\n# rm -f *TMPL.xml Cacti_Net-SNMP_DevIO_v2.zip\r\n<\/pre>\n<p>Desde un PC cliente, descargamos el mismo fichero e importamos via web los ficheros:<\/p>\n<ul>\n<li>&#8216;net-snmp_devIO-BytesRW_graphTMPL.xml&#8217;:\n<pre>\r\nCacti has imported the following items:\r\n\r\nGPRINT Preset\r\n[success] Normal [update]\r\n\r\nData Input Method\r\n[success] Get SNMP Data (Indexed) [update]\r\n\r\nData Template\r\n[success] ucd\/net - Device I\/O [new]\r\n\r\nGraph Template\r\n[success] ucd\/net - Device I\/O - Bytes Read\/Written [new]\r\n<\/pre>\n<\/li>\n<li>&#8216;net-snmp_devIO-ReadsWrites_graphTMPL.xml&#8217;\n<pre>\r\nCacti has imported the following items:\r\n\r\nGPRINT Preset\r\n[success] Exact Numbers [update]\r\n\r\nData Input Method\r\n[success] Get SNMP Data (Indexed) [update]\r\n\r\nData Template\r\n[success] ucd\/net - Device I\/O [update]\r\n\r\nGraph Template\r\n[success] ucd\/net - Device I\/O - Reads\/Writes [new]\r\n<\/pre>\n<\/li>\n<li>&#8216;net-snmp_devIO-LoadAVG_graphTMPL&#8217;: solo es compatible con sistemas BSD. No lo cargamos en Linux.<\/li>\n<\/ul>\n<p>Creamos el Data Query mediante &#8220;Data Queries &#8211; Add&#8221;:<\/p>\n<pre>\r\nName: ucd\/net - Get Device I\/O\r\nDescription:\r\nXML Path: &#60;path_cacti>\/resource\/snmp_queries\/net-snmp_devio.xml\r\nData Input Method: Get SNMP Data (indexed)\r\n<\/pre>\n<p>Pulsamos &#8220;Create&#8221;. <\/p>\n<p>Ahora es el momento de a\u00f1adir las gr\u00e1ficas asociadas. En el recuadro associate graph, pulsamos sobre Add y rellenamos el formulario:<\/p>\n<pre>\r\nName: Device I\/O - Bytes Read\/Written\r\nGraph template: ucd\/net Device I\/O - Bytes Read\/Written\r\n<\/pre>\n<p>Pulsamos Create.<\/p>\n<p>A continuaci\u00f3n, asociamos las siguientes fuentes seleccionando del desplegable la fuente que concuerde seg\u00fan la descripci\u00f3n y marcando el checkout de la derecha:<\/p>\n<pre>\r\nData Source: Bytes_Read\r\nData Source: Bytes_Written \r\n<\/pre>\n<p>Volvemos a a\u00f1adir una nueva gr\u00e1fica al Data Query:<\/p>\n<pre>\r\nName: Device I\/O - Reads\/Writes\r\nGraph template: ucd\/net Device I\/O - Reads\/Writes\r\n<\/pre>\n<p>Asociamos las siguientes fuentes:<\/p>\n<pre>\r\nData Source: Device_Reads\r\nData Source: Device_Writes\r\n<\/pre>\n<p>Finalmente al Host template &#8220;ucd\/net SNMP Host&#8221; asociamos la Data Query &#8220;ucd\/net &#8211; Get Device I\/O &#8220;. A partir de aqu\u00ed, todos los nuevos hosts que se asignen la plantilla &#8220;ucd\/net SNMP Host&#8221;, podran crear gr\u00e1ficas de lectura\/escritura al disco duro.<\/p>\n<h3><a name=\"9\">9. Seguridad<\/a><\/h3>\n<h4>Cortafuegos \/ Firewall<\/h4>\n<p>Antes de configurar el cortafuegos, vamos a preparar el sistema ULOG que nos permitir\u00e1 registrar eventos procedentes de iptables:<\/p>\n<pre>\r\napt-get install ulogd ulogd-mysql\r\n<\/pre>\n<p>Por defecto ULOG viene configurado para que el fichero de log sea &#8216;\/var\/log\/ulog\/syslogemu.log&#8217;. No obstante, ULOG tambi\u00e9n nos permite almacenar la informaci\u00f3n en una MySQL. Para activarlo descomentamos de &#8216;\/etc\/ulogd.conf&#8217;:<\/p>\n<pre>\r\nplugin=\"\/usr\/lib\/ulogd\/ulogd_MYSQL.so\"\r\n<\/pre>\n<p>Y, en el mismo fichero, configuramos el acceso a la MySQL:<\/p>\n<pre>\r\n[MYSQL]\r\ntable=\"ulog\"\r\npass=\"secret\"\r\nuser=\"ulog\"\r\ndb=\"ulog\"\r\nhost=\"localhost\"\r\n<\/pre>\n<p>Finalmente, en la MySQL creamos el usuario y la BBDD con su correspondiente estructura:<\/p>\n<pre>\r\nCREATE USER 'ulog'@'localhost' IDENTIFIED BY 'secret';\r\n\r\nGRANT USAGE ON * . * TO 'ulog'@'localhost' IDENTIFIED BY 'secret' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;\r\n\r\nCREATE DATABASE IF NOT EXISTS `ulog` ;\r\n\r\nGRANT ALL PRIVILEGES ON `ulog` . * TO 'ulog'@'localhost';\r\n\r\nFLUSH PRIVILEGES;\r\n\r\nUSE ulog;\r\n\r\nsource \/usr\/share\/doc\/ulogd-mysql\/mysql.table;\r\n<\/pre>\n<p>Para conocer las bases de &#8220;iptables&#8221; podemos ver este otro art\u00edculo con <a href=\"http:\/\/www.marblestation.com\/blog\/?p=546\">m\u00e1s explicaciones sobre iptables<\/a>, veamos un ejemplo m\u00e1s avanzado que en general establece las siguientes reglas:<\/p>\n<ul>\n<li>Por defecto denegamos todo el tr\u00e1fico.<\/li>\n<li>Limitamos los rangos de IP reservados para redes privadas (excepto si estamos en una de ellas)<\/li>\n<li>Bloqueamos ataques de SYN\/RST flood.<\/li>\n<li>Bloqueamos paquetes malformados.<\/li>\n<li>Mantenemos una lista negra temporal de IPs que han intentado realizar un ataque de fuerza bruta: han intentado realizar m\u00e1s de 2 conexiones en 20 segundos al puerto de SSH. Las IPs se mantienen en la lista negra durante 10 minutos.<\/li>\n<li>Dejamos el puerto SSH de entrada abierto.<\/li>\n<li>De salida permitimos:\n<ul>\n<li>DNS<\/li>\n<li>SMTP + IMAP SSL<\/li>\n<li>SSH<\/li>\n<li>HTTP\/HTTPS<\/li>\n<li>NTP de Ubuntu<\/li>\n<\/ul>\n<\/li>\n<li>Respecto al protocolo ICMP, permitimos:\n<ul>\n<li>Echo request hacia Internet<\/li>\n<li>Echo reply desde Internet<\/li>\n<li>Destination Unrecheable desde Internet<\/li>\n<li>Time exceed desde Internet<\/li>\n<\/ul>\n<\/li>\n<li>Registramos el tr\u00e1fico que no ha sido aceptado por las reglas anteriores (no obstante limitamos el n\u00famero de registros por segundo para no desbordar el sistema):\n<ul>\n<li>Entrada<\/li>\n<li>Salida<\/li>\n<li>Redirecciones: en nuestro ejemplo no aplica.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Podemos guardar el script en &#8216;\/usr\/local\/bin\/firewall&#8217;:<\/p>\n<pre>\r\n#!\/bin\/bash\r\n#\r\n# Copyright (C) 2008 http:\/\/www.marblestation.com\r\n#\r\n# This program is free software; you can redistribute it and\/or modify\r\n# it under the terms of the GNU General Public License as published by\r\n# the Free Software Foundation; either version 2 of the License, or\r\n# (at your option) any later version.\r\n#\r\n# This program is distributed in the hope that it will be useful,\r\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n# GNU General Public License for more details.\r\n#\r\n# You should have received a copy of the GNU General Public License\r\n# along with this program; if not, write to the Free Software\r\n# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r\n#\r\n\r\n######### CONFIGURABLE #########\r\nIPTABLES=\"\/sbin\/iptables\";\r\nECHO=\"\/bin\/echo\";\r\n\r\n#LAN_INTERFACE_GETIP=\"eth0:0\"\r\n\r\nLAN_INTERFACE=\"eth0\"\r\nLOOPBACK_INTERFACE=\"lo\"\r\n\r\n#LAN_IP1=\"71.11.10.19\"\r\nLAN_IP1=`ifconfig $LAN_INTERFACE|grep inet|grep -v inet6|cut -d \" \" -f 12|cut -d \":\" -f 2`\r\nLAN_IP2=\"\"\r\nLAN_IP3=\"\"\r\nDNS_IP=\"213.186.33.99\" # NS1 NS2 of ISP\r\n\r\n#BROADCAST_IP1=71.11.10.255\"\r\nBROADCAST_IP1=`ifconfig $LAN_INTERFACE|grep inet|grep -v inet6|cut -d \" \" -f 14|cut -d \":\" -f 2`\r\n\r\n#LAN_NET=$LAN_IP\/`ifconfig $LAN_INTERFACE|grep inet|grep -v inet6|cut -d \" \" -f 16|cut -d \":\" -f 2`\r\n\r\nBANNED_IPs=\"\"\r\n\r\nNTP_UBUNTU=\"91.189.94.4\"\r\n####### FIN CONFIGURABLE #######\r\n\r\n##\r\n# Required kernel modules: nf_conntrack, nf_nat, nf_nat_ftp, nf_conntrack_ftp\r\n#\r\n#  * Non-standard ports:\r\n#      modprobe ip_conntrack_ftp ports=21,2121\r\n#      modprobe ip_nat_ftp ports=21,2121\r\n#\r\n# Current tracked connections:\r\n#  cat \/proc\/net\/ip_conntrack | wc -l\r\n# \r\n# Max allowed tracked connections:\r\n#  sysctl -a net.ipv4.netfilter.ip_conntrack_max\r\n#\r\n# Possible modifications to \/etc\/sysctl.conf:\r\n#\r\n## Time limit to consider a connection active: 432000 seconds (432000 \/ (60*60*24) = 8 days)\r\n#  net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 28800\r\n#\r\n## Max tracked connections (65536 connections * 350 bytes per connection) \/ (1024 * 1024) = 21,87 MBytes\r\n#  net.ipv4.netfilter.ip_conntrack_max = 65536\r\n#\r\n## Time limit to close a connection (60 seconds)\r\n#  net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60\r\n#\r\n# Reload sysctl: sysctl -p\r\n##\r\n\r\n\r\n\r\n# Reset tablas de filtrado\r\n$IPTABLES -t filter -Z\r\n$IPTABLES -t filter -F\r\n$IPTABLES -t filter -X\r\n\r\n# Reset tablas de nuevas conexiones\r\n$IPTABLES -t nat -Z\r\n$IPTABLES -t nat -F\r\n$IPTABLES -t nat -X\r\n\r\n# Reset tablas de modificaci\u00f3n de paquetes\r\n$IPTABLES -t mangle -Z\r\n$IPTABLES -t mangle -F\r\n$IPTABLES -t mangle -X\r\n\r\n\r\necho \"[start] Default policy\"\r\n# Politica general de tr\u00e1fico entrante\/saliente y redirigido\r\n$IPTABLES -t filter -P INPUT DROP\r\n$IPTABLES -t filter -P OUTPUT DROP\r\n$IPTABLES -t filter -P FORWARD DROP\r\n\r\n# Politica de las cadenas extendidas (donde se pueden realizar alteraciones de paquetes)\r\n$IPTABLES -t mangle -P INPUT ACCEPT\r\n$IPTABLES -t mangle -P OUTPUT ACCEPT\r\n$IPTABLES -t mangle -P PREROUTING ACCEPT\r\n$IPTABLES -t mangle -P POSTROUTING ACCEPT\r\n\r\n# Paquetes que crean nuevas conexiones y deben ser alterados por NAT\r\n$IPTABLES -t nat -P OUTPUT ACCEPT\r\n$IPTABLES -t nat -P PREROUTING ACCEPT\r\n$IPTABLES -t nat -P POSTROUTING ACCEPT\r\necho \"[end] Default policy\"\r\n\r\n\r\n\r\necho \"[start] Local users control\"\r\n#--uid-owner {USERNAME} : Matches if the packet was created by a process with the given effective USERNAME. \r\n#--gid-owner {groupid}: Matches if the packet was created by a process with the given effective group id. \r\n#--pid-owner {processed}: Matches if the packet was created by a process with the given process id. \r\n\r\n# Allow any TCP connection originated by myuser\r\n#$IPTABLES -A OUTPUT -o $LAN_INTERFACE -p tcp --sport 1024:65535 --dport 1:65535 -m state --state NEW,ESTABLISHED -m owner --uid-owner myuser -j ACCEPT\r\n#$IPTABLES -A INPUT -i $LAN_INTERFACE -p tcp --sport 1:65535 --dport 1024:65535 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\necho \"[end] Local users control\"\r\n\r\necho \"[start] Loopback\"\r\n# Permitir trafico a la interfaz loopback\r\n$IPTABLES -A INPUT  -i $LOOPBACK_INTERFACE -s 127.0.0.1 -j ACCEPT\r\n$IPTABLES -A OUTPUT -o $LOOPBACK_INTERFACE -d 127.0.0.1 -j ACCEPT\r\n\r\n# Permitir trafico a la interfaz loopback con IPs internas\r\nSPACE=\" \"\r\nINTERNAL_IPs=$LAN_IP1$SPACE$LAN_IP2$SPACE$LAN_IP3\r\nfor internal_ip in $INTERNAL_IPs\r\ndo\r\n\t$IPTABLES -A INPUT  -i $LOOPBACK_INTERFACE -s $internal_ip -j ACCEPT\r\n\t$IPTABLES -A OUTPUT -o $LOOPBACK_INTERFACE -d $internal_ip -j ACCEPT\r\ndone\r\necho \"[end] Loopback\"\r\n\r\n\r\necho \"[start] Banned IPs\"\r\n##################### IPs Baneadas\r\nfor banned_ip in $BANNED_IPs\r\ndo\r\n\t$IPTABLES -A INPUT -s $banned_ip -j DROP\r\n\t$IPTABLES -A OUTPUT -s $banned_ip -j DROP\r\n\t$IPTABLES -A FORWARD -s $banned_ip -j DROP\r\ndone\r\n##################### Fin IPs Baneadas\r\necho \"[end] Banned IPs\"\r\n\r\n\r\necho \"[start] Reserved IPs blocks\"\r\n##################### Prevent spoofing\r\n# New chain\r\n$IPTABLES -N reserved_blocks\r\n$IPTABLES -F reserved_blocks\r\n\r\n# Redirect all traffic to new chain\r\n$IPTABLES -A INPUT -j reserved_blocks\r\n$IPTABLES -A OUTPUT -j reserved_blocks\r\n\r\n### [start] private networks\r\n# 10.0.0.0\/8 Private network RFC 1918 \r\n$IPTABLES -A reserved_blocks -s 10.0.0.0\/8 -j DROP\r\n$IPTABLES -A reserved_blocks -d 10.0.0.0\/8 -j DROP\r\n\r\n# 172.16.0.0\/12 Private network RFC 1918 \r\n$IPTABLES -A reserved_blocks -s 172.16.0.0\/12 -j DROP\r\n$IPTABLES -A reserved_blocks -d 172.16.0.0\/12 -j DROP\r\n\r\n# 169.254.0.0\/16 Link-Local RFC 3927 \r\n$IPTABLES -A reserved_blocks -s 169.254.0.0\/16 -j DROP\r\n$IPTABLES -A reserved_blocks -d 169.254.0.0\/16 -j DROP\r\n\r\n# 192.168.0.0\/16 Private network RFC 1918 \r\n# !! Limited to LAN_INTERFACE, because in other interface we have 192.168.0.0 networks\r\n#$IPTABLES -A reserved_blocks -i $LAN_INTERFACE -s 192.168.0.0\/16 -j DROP\r\n#$IPTABLES -A reserved_blocks -o $LAN_INTERFACE -d 192.168.0.0\/16 -j DROP\r\n### [end] private networks\r\n\r\n\r\n### [start] Other reserved blocks\r\n# 0.0.0.0\/8 Current network (only valid as source address) RFC 1700 \r\n$IPTABLES -A reserved_blocks -s 0.0.0.0\/8 -j DROP\r\n$IPTABLES -A reserved_blocks -d 0.0.0.0\/8 -j DROP\r\n\r\n# 14.0.0.0\/8 Public data networks (per 2008-02-10, available for use[1]) RFC 1700 \r\n# Addresses within this block are assigned to users and should be treated as such\r\n# Do not drop\r\n\r\n# 127.0.0.0\/8 Loopback RFC 3330 \r\n$IPTABLES -A reserved_blocks -s 127.0.0.0\/8 -j DROP\r\n$IPTABLES -A reserved_blocks -d 127.0.0.0\/8 -j DROP\r\n\r\n# 128.0.0.0\/16 Reserved (IANA) RFC 3330 \r\n# Addresses in this block are subject to future allocation to a Regional Internet\r\n# Registry for assignment in the normal manner.\r\n## Do not drop\r\n\r\n# 191.255.0.0\/16 Reserved (IANA) RFC 3330 \r\n# Addresses in this block are subject to future allocation to a Regional Internet\r\n# Registry for assignment in the normal manner.\r\n## Do not drop\r\n\r\n# 192.0.2.0\/24 Documentation and example code RFC 3330 (Test-Net [RFC3330])\r\n$IPTABLES -A reserved_blocks -s 192.0.2.0\/24      -j DROP\r\n$IPTABLES -A reserved_blocks -d 192.0.2.0\/24      -j DROP\r\n\r\n# 192.88.99.0\/24 IPv6 to IPv4 relay RFC 3068 \r\n$IPTABLES -A reserved_blocks -s 192.88.99.0\/24      -j DROP\r\n$IPTABLES -A reserved_blocks -d 192.88.99.0\/24      -j DROP\r\n\r\n# 198.18.0.0\/15 Network benchmark tests RFC 2544 \r\n$IPTABLES -A reserved_blocks -s 198.18.0.0\/15      -j DROP\r\n$IPTABLES -A reserved_blocks -d 198.18.0.0\/15      -j DROP\r\n\r\n# 223.255.255.0\/24 Reserved (IANA) RFC 3330 \r\n$IPTABLES -A reserved_blocks -s 223.255.255.0\/24      -j DROP\r\n$IPTABLES -A reserved_blocks -d 223.255.255.0\/24      -j DROP\r\n\r\n# 224.0.0.0\/3 includes:\r\n#   - Reserved for Multicast (former Class D network) RFC 3171 (224.0.0.0\/4): From 224\/8 to 239\/8\r\n#   - Reserved for Future use (former Class E network) RFC 1700 (240.0.0.0\/4): From 240\/8 to 255\/8\r\n#   - Broadcast: 255.255.255.255\r\n$IPTABLES -A reserved_blocks -s 224.0.0.0\/3 -j DROP\r\n$IPTABLES -A reserved_blocks -d 224.0.0.0\/3 -j DROP\r\n### [end] Other reserved blocks\r\n\r\n##################### Fin Direcciones privadas\r\necho \"[end] Reserved IPs blocks\"\r\n\r\necho \"[start] Attack protection\"\r\n##################### Ataques\r\n\r\necho \"* SYN\/RST flood\"\r\n# Stop  flood\r\n\r\n# New chain\r\n$IPTABLES -N flood\r\n$IPTABLES -F flood\r\n\r\n# Redirect all eth0 traffic to new chain\r\n$IPTABLES -A INPUT -i $LAN_INTERFACE -p tcp --syn -j flood\r\n$IPTABLES -A OUTPUT -o $LAN_INTERFACE -p tcp --syn -j flood\r\n$IPTABLES -A FORWARD -i $LAN_INTERFACE -p tcp --syn -j flood\r\n\r\n# Chain rules\r\n# Drop excessive RST packets to avoid TCP reset attacks, by given the\r\n# next real data packet in the sequence a better chance to arrive first.\r\n$IPTABLES -A flood -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2\/second --limit-burst 2 -j ACCEPT\r\n\t\r\n# Protect against SYN floods by rate limiting the number of new\r\n# connections from any host to 5 per second.\r\n$IPTABLES -A flood -m state --state NEW -p tcp -m tcp --syn -m recent --name synflood --set\r\n$IPTABLES -A flood -m state --state NEW -p tcp -m tcp --syn -m recent --name synflood --update --seconds 1 --hitcount 5 -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:SYN Packets flood] \"\r\n$IPTABLES -A flood -m state --state NEW -p tcp -m tcp --syn -m recent --name synflood --update --seconds 1 --hitcount 5 -j DROP\r\n\r\necho \"* Malformed packets\"\r\n# Create new chain\r\n$IPTABLES -N malformed_packets\r\n$IPTABLES -F malformed_packets\r\n\r\n# Redirect all traffic to new chain\r\n$IPTABLES -A INPUT -j malformed_packets\r\n$IPTABLES -A OUTPUT -j malformed_packets\r\n$IPTABLES -A FORWARD -j malformed_packets\r\n\r\n# Log & Drop all incoming fragments\r\n$IPTABLES -A malformed_packets -f -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:Fragments Packets] \"\r\n$IPTABLES -A malformed_packets -f -j DROP\r\n\r\n# Log & Drop new connections with SYN flag not set\r\n#$IPTABLES -A malformed_packets -p tcp ! --syn -m state --state NEW -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:New without SYN] \"\r\n$IPTABLES -A malformed_packets -p tcp ! --syn -m state --state NEW -j DROP \r\n\r\n# Log & Drop all incoming malformed NULL packets (Block null scans)\r\n$IPTABLES  -A malformed_packets -p tcp --tcp-flags ALL NONE -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:NULL Packets] \"\r\n$IPTABLES  -A malformed_packets -p tcp --tcp-flags ALL NONE -j DROP # NULL packets \r\n\r\n# Drop all incoming malformed XMAS packets (Block xmas scans)\r\n$IPTABLES  -A malformed_packets -p tcp --tcp-flags ALL ALL -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:XMAS Packets] \"\r\n$IPTABLES  -A malformed_packets -p tcp --tcp-flags ALL ALL -j DROP #XMAS\r\n\r\n# Drop all incoming malformed FIN packets (Block FIN scans)\r\n$IPTABLES  -A malformed_packets -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:Fin Packets Scan] \"\r\n$IPTABLES  -A malformed_packets -p tcp --tcp-flags FIN,ACK FIN -j DROP # FIN packet scans\r\n\r\n# Drop bogus TCP packets\r\n$IPTABLES -A malformed_packets -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:Bogus Packets] \"\r\n$IPTABLES -A malformed_packets -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP\r\n$IPTABLES -A malformed_packets -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:Bogus Packets] \"\r\n$IPTABLES -A malformed_packets -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP\r\n\r\n# Log & Drop all incoming invalid packets\r\n#$IPTABLES -A malformed_packets -m state --state INVALID -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:Invalid Packets] \"\r\n$IPTABLES -A malformed_packets -m state --state INVALID -j DROP\r\n\r\necho \"  - Bruce force attack prevention\"\r\n##### [start] Prevent Brute force attack\r\n$IPTABLES -N brute_force\r\n$IPTABLES -N brute_force_blacklist\r\n\r\n$IPTABLES -A brute_force_blacklist -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:Bruteforce] \"\r\n$IPTABLES -A brute_force_blacklist -m recent --name brute_force_blacklist --set\r\n$IPTABLES -A brute_force_blacklist -j DROP\r\n\r\n# Incoming connections from blacklisted hosts are dropped for 10 minutes (every droped connection, restarts the 10 minutes period).\r\n$IPTABLES -A brute_force -m recent --update --name brute_force_blacklist --seconds   600 --hitcount   1 -j DROP\r\n\r\n# These rules are just for counting of incoming connections. \r\n$IPTABLES -A brute_force -m recent --set    --name counting1\r\n$IPTABLES -A brute_force -m recent --set    --name counting2\r\n$IPTABLES -A brute_force -m recent --set    --name counting3\r\n$IPTABLES -A brute_force -m recent --set    --name counting4\r\n\r\n# A host is blacklisted if it exceeds:\r\n#   - 2 connection attempts in 20 seconds\r\n#   - 14 in 200 seconds\r\n#   - 79 in 2000 seconds\r\n#   - 399 attempts in 20000 seconds. \r\n$IPTABLES -A brute_force -m recent --update --name counting1 --seconds    20 --hitcount   3 -j brute_force_blacklist\r\n$IPTABLES -A brute_force -m recent --update --name counting2 --seconds   200 --hitcount  15 -j brute_force_blacklist\r\n$IPTABLES -A brute_force -m recent --update --name counting3 --seconds  2000 --hitcount  80 -j brute_force_blacklist\r\n$IPTABLES -A brute_force -m recent --update --name counting4 --seconds 20000 --hitcount 400 -j brute_force_blacklist\r\n\r\n$IPTABLES -A brute_force -j ACCEPT\r\n\r\n# Control SSH service: only new conections\r\nBRUTEFORCE_EXCEPTION_IP=\"132.106.3.12\"\r\n#$IPTABLES -A INPUT -p TCP -s ! $BRUTEFORCE_EXCEPTION_IP --dport 22 -m state --state NEW -j brute_force\r\n$IPTABLES -A INPUT -p TCP --dport 22 -m state --state NEW -j brute_force\r\n##### [end] Prevent Brute force attack\r\n\r\n\r\n##################### Fin Ataques\r\necho \"[end] Attack protection\"\r\n\r\n\r\necho \"[start] Internet < -> Host\"\r\necho \"* Incoming traffic\"\r\n##################### Puertos de entrada abiertos\r\necho \"  - SSH\"\r\n# Aceptamos SSH\r\n$IPTABLES -A INPUT -i $LAN_INTERFACE -p tcp -s 0\/0 --sport 1024:65535 -d $LAN_IP1 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A OUTPUT -o $LAN_INTERFACE -p tcp -s $LAN_IP1 --sport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\n##################### Fin Puertos de entrada abiertos\r\n\r\necho \"* Outgoing traffic\"\r\n##################### Puertos de salida abiertos\r\necho \"  - DNS\"\r\n# Outgoing DNS\r\n# udp first\r\nfor dns_server_ip in $DNS_IP\r\ndo\r\n  $IPTABLES -A OUTPUT -p udp -s $LAN_IP1 --sport 1024:65535 -d $dns_server_ip --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n  $IPTABLES -A INPUT -p udp -s $dns_server_ip --sport 53 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n  # tcp next\r\n  $IPTABLES -A OUTPUT -p tcp -s $LAN_IP1 --sport 1024:65535 -d $dns_server_ip --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n  $IPTABLES -A INPUT -p tcp -s $dns_server_ip --sport 53 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\ndone\r\n\r\necho \"  - SMTP\"\r\n#outgoing SMTP\r\n$IPTABLES -A OUTPUT -p tcp -s $LAN_IP1 --sport 1024:65535 -d 0\/0 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A INPUT -p tcp -s 0\/0 --sport 25 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\necho \"  - IMAP SSL\"\r\n#outgoing IMAP SSL\r\n$IPTABLES -A OUTPUT -p tcp -s $LAN_IP1 --sport 1024:65535 -d 0\/0 --dport 993 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A INPUT -p tcp -s 0\/0 --sport 993 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\necho \"  - SSH\"\r\n#outgoing SSH\r\n$IPTABLES -A OUTPUT -p tcp -s $LAN_IP1  --sport 1024:65535 -d 0\/0 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A INPUT -p tcp -s 0\/0 --sport 22 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\necho \"  - HTTP & HTTPS\"\r\n#outgoing http and https\r\n# for apt-get and other stuff\r\n$IPTABLES -A OUTPUT -p tcp -s $LAN_IP1  --sport 1024:65535 -d 0\/0 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A INPUT -p tcp -s 0\/0 --sport 80 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A OUTPUT -p tcp -s $LAN_IP1  --sport 1024:65535 -d 0\/0 --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A INPUT -p tcp -s 0\/0 --sport 443 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\necho \" - NTP\"\r\n#outgoing NTP to ubuntu servers\r\n$IPTABLES -A OUTPUT -p udp -s $LAN_IP1  --sport 1024:65535 -d $NTP_UBUNTU --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT\r\n$IPTABLES -A INPUT -p udp -s $NTP_UBUNTU --sport 123 -d $LAN_IP1 -m state --state RELATED,ESTABLISHED -j ACCEPT\r\n\r\n##################### Fin Puertos de salida abiertos\r\n\r\n\r\necho \"* ICMP\"\r\n##################### ICMP\r\n### Drop icmp, but only after letting certain types through.\r\n# Echo Reply\r\n#$IPTABLES -A INPUT -p icmp --icmp-type 0 -j ACCEPT\r\n# Destination Unreachable\r\n#$IPTABLES -A INPUT -p icmp --icmp-type 3 -j ACCEPT\r\n# Tiempo Excedido\r\n#$IPTABLES -A INPUT -p icmp --icmp-type 11 -j ACCEPT\r\n# Echo Request\r\n#$IPTABLES -A INPUT -p icmp --icmp-type 8 -m limit --limit 30\/second -j ACCEPT\r\n\r\n## Allow outgoing ping\r\n# Echo Request to Internet\r\n$IPTABLES -A OUTPUT -o $LAN_INTERFACE -p icmp --icmp-type 8 -d 0\/0 -s $LAN_IP1 -m limit --limit 30\/second -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT\r\n# Echo Reply from Internet\r\n$IPTABLES -A INPUT -i $LAN_INTERFACE -p icmp --icmp-type 0 -d $LAN_IP1 -s 0\/0 -m state --state ESTABLISHED,RELATED -j ACCEPT\r\n# Destination Unreachable from Internet\r\n$IPTABLES -A INPUT -i $LAN_INTERFACE -p icmp --icmp-type 3 -d $LAN_IP1 -s 0\/0 -m state --state ESTABLISHED,RELATED -j ACCEPT\r\n# Time Exceeded from Internet\r\n$IPTABLES -A INPUT -i $LAN_INTERFACE -p icmp --icmp-type 11 -d $LAN_IP1 -s 0\/0 -m state --state ESTABLISHED,RELATED -j ACCEPT\r\n\r\n# Allow ping between internal IPs\r\nSPACE=\" \"\r\nINTERNAL_IPs=$LAN_IP1$SPACE$LAN_IP2$SPACE$LAN_IP3\r\nfor internal_ip1 in $INTERNAL_IPs\r\ndo\r\n    for internal_ip2 in $INTERNAL_IPs\r\n    do\r\n        # Receive Echo Reply\r\n        $IPTABLES -A INPUT  -p icmp --icmp-type 0 -d $internal_ip1 -s $internal_ip2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT\r\n\r\n        # Receive Echo Request\r\n        $IPTABLES -A INPUT  -p icmp --icmp-type 8 -d $internal_ip1 -s $internal_ip2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT\r\n\r\n        # Send Echo Request\r\n        $IPTABLES -A OUTPUT -p icmp --icmp-type 8 -d $internal_ip1 -s $internal_ip2 -m limit --limit 30\/second -m state --state ESTABLISHED,RELATED -j ACCEPT\r\n\r\n        # Receive Echo Reply\r\n        $IPTABLES -A OUTPUT -p icmp --icmp-type 0 -d $internal_ip1 -s $internal_ip2 -m limit --limit 30\/second -m state --state ESTABLISHED,RELATED -j ACCEPT\r\n    done\r\ndone\r\n\r\n\r\n##################### Fin ICMP\r\n\r\n\r\n# Use \"-m state\" (ip_conntrack module) in order to allow legitim traffic:\r\n#\r\n#  - NEW: A packet which creates a new connection.\r\n#  - ESTABLISHED: A packet which belongs to an existing connection (i.e., a reply packet, or outgoing packet on a\r\n#    connection which has seen replies).\r\n#  - RELATED: A packet which is related to, but not part of, an existing connection, such as an ICMP error, or (with\r\n#    the FTP module inserted), a packet establishing an ftp data connection.\r\n#  - INVALID: A packet which could not be identified for some reason: this includes running out of memory and ICMP\r\n#    errors which don't correspond to any known connection. Generally these packets should be dropped.\r\n\r\n\r\n### Log\r\n\r\necho \"[start] Logging\"\r\n\r\necho \"* Logging exceptions\"\r\n## [start] Do not log\r\n# netbios UDP\r\n$IPTABLES -A INPUT -p udp -d $BROADCAST_IP1 --dport 137:138 -j DROP\r\n## [end] Do not log\r\n\r\necho \"* Logging rules\"\r\n# Limit: The first 3 packets that match this rule will be logged. After this, it will be 30 seconds until one of the\r\n# burst will be regained; if no packets hit the rule for 90 seconds, the burst will be fully recharged.\r\n$IPTABLES -A INPUT -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:INPUT Drop] \"\r\n$IPTABLES -A OUTPUT -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:OUTPUT Drop] \"\r\n$IPTABLES -A FORWARD -m limit --limit 30\/s --limit-burst 3 -j ULOG --ulog-nlgroup 1 --ulog-prefix \"[FW:FORWARD Drop] \"\r\n\r\necho \"[end] Logging\"\r\n\r\n# Disable firewall in 30 seconds...\r\n# ...so we can test it\r\n#SAFETY=`sleep 30;\/usr\/local\/bin\/firewall-off` &\r\n<\/pre>\n<p>Creamos el script &#8216;\/usr\/local\/bin\/firewall-off&#8217;:<\/p>\n<pre>\r\n#!\/bin\/bash\r\n\r\n######### CONFIGURABLE #########\r\nIPTABLES=\"\/sbin\/iptables\";\r\n####### FIN CONFIGURABLE #######\r\n\r\n# Reset\r\n$IPTABLES -Z\r\n$IPTABLES -F\r\n$IPTABLES -t nat -F\r\n$IPTABLES -t nat -X\r\n$IPTABLES -t mangle -F\r\n$IPTABLES -t mangle -X\r\n\r\n# Politica general\r\n$IPTABLES -P INPUT ACCEPT\r\n$IPTABLES -P OUTPUT ACCEPT\r\n$IPTABLES -P FORWARD ACCEPT\r\n<\/pre>\n<p>Es importante que establezcamos unos permisos seguros a los scripts:<\/p>\n<pre>\r\n# chmod 750 \/usr\/local\/firewall\r\n# chmod 750 \/usr\/local\/firewall-off\r\n# chown root:root \/usr\/local\/firewall\r\n# chown root:root \/usr\/local\/firewall-off\r\n<\/pre>\n<p>A partir de estos ejemplos, probablemente ser\u00e1 necesario adaptarlos a nuestras necesidades. Cuando cubra nuestros requerimientos, podemos hacer que se ejecute autom\u00e1ticamente al iniciar el sistema si lo a\u00f1adimos al fichero &#8216;\/etc\/rc.local&#8217; (antes del exit 0).<\/p>\n<h5>Monitorizaci\u00f3n de firewall con fwlogwatch<\/h5>\n<p>fwlogwatch permite enviar resumenes diarios por correo o generar output en HTML sobre el estado del firewall:<\/p>\n<pre>\r\n# apt-get install fwlogwatch \r\n# dpkg-reconfigure fwlogwatch \r\n<\/pre>\n<p>Depues del reconfigure, \/etc\/default\/fwlogwatch quedara parecido a lo siguiente:<\/p>\n<pre>\r\nSTART_DAEMON='true'\r\nPARAMS='-A '\r\nMODE=''\r\nEMAIL='root@localhost'\r\nCRON_EMAIL='root@localhost'\r\nCRON_PARAMS='-l 1h -t -p -d -n -N -O Sapata'\r\n# 1 day: -l 1d \r\n# show time: -t\r\n# show protocol: -p\r\n# differenciate destination port: -d\r\n# reverse dns: -n\r\n# service (not only port): -N\r\n# sort by destination IP (ascending), protocol (asc) and time (asc): -O Sapata\r\n<\/pre>\n<p>Editamos \/etc\/fwlogwatch\/fwlogwatch.config para indicarle el log:<\/p>\n<pre>\r\ninput = \/var\/log\/ulog\/syslogemu.log\r\n\r\n# Use 'alert_threshold' to define how many connections must happen (within\r\n# the 'forget' time range) to activate an alert\/response.\r\n# Command line option: -a [count]\r\n#\r\nalert_threshold = 10\r\n<\/pre>\n<p>Editamos \/etc\/group:<\/p>\n<pre>\r\nadm:x:4:logcheck,www-data\r\n<\/pre>\n<p>Para el reporte HTML, presuponemos que tenemos configurado Apache. Copiamos el CGI correspondiente:<\/p>\n<pre>\r\ncp \/usr\/share\/doc\/fwlogwatch\/examples\/fwlogsummary.cgi \/usr\/lib\/cgi-bin\/\r\n<\/pre>\n<p>Editamos \/usr\/lib\/cgi-bin\/fwlogsummary.cgi:<\/p>\n<pre>\r\n# 1 day info\r\nRECENT=\"-l 1d\"\r\nWEBDIR=\"\/var\/www\/localhost\/fwlogwatch\"\r\n...\r\nMESSAGES=\"\/var\/log\/ulog\/syslogemu.log\"\r\n...\r\n#if [ -z $1 ]\r\n#then\r\n  MESSAGES=\"\/var\/log\/ulog\/syslogemu.log\"\r\n#else\r\n#  MESSAGES=\"$1\"\r\n#fi\r\n<\/pre>\n<p>Esta \u00faltima parte la comento pq no me parece seguro permitir abrir un fichero del sistema indicado por par\u00e1metro.<\/p>\n<p>Suponiendo que en \/var\/www\/localhost tenemos un host virtual:<\/p>\n<pre>\r\nmkdir \/var\/www\/localhost\/fwlogwatch\r\nchown -R www-data:www-data \/var\/www\/localhost\/fwlogwatch\/\r\n<\/pre>\n<p>Creamos el fichero \/etc\/apache2\/conf.d\/fwlogwatch.conf con el siguiente contenido:<\/p>\n<pre>\r\nScriptAlias \/cgi-bin\/fwlogsummary.cgi \/usr\/lib\/cgi-bin\/fwlogsummary.cgi\r\n<\/pre>\n<p>Reiniciamos apache:<\/p>\n<pre>\r\n\/etc\/init.d\/apache2 restart\r\n<\/pre>\n<p>Y accedemos a la versi\u00f3n web via http:\/\/localhost\/cgi-bin\/fwlogsummary.cgi.<\/p>\n<p>En caso de que queramos recibir alertas por correo en tiempo real, activaremos el demonio en el fichero \/etc\/default\/fwlogwatch mediante START_DAEMON=&#8217;true&#8217; y iniciaremos el servicio:<\/p>\n<pre>\r\n\/etc\/init.d\/fwlogwatch restart\r\n<\/pre>\n<h4>Detecci\u00f3n de intrusos \/ IDS: Snort<\/h4>\n<p>Podr\u00edamos instalar Snort como sistema de detecci\u00f3n de intrusos (IDS) de nuestra red:<\/p>\n<pre>\r\napt-get install snort\r\n<\/pre>\n<p>Tambi\u00e9n disponemos de Acidbase que utiliza snort para facilitar el an\u00e1lisis y detecci\u00f3n de intrusiones mediante una interfaz web:<\/p>\n<pre>\r\napt-get install snort-mysql acidbase\r\n<\/pre>\n<h4>Rootkits<\/h4>\n<p>Validamos que el sistema no dispone de ning\u00fan rootkit instalado:<\/p>\n<pre>\r\napt-get install chkrootkit rkhunter\r\nsudo rkhunter --update\r\nsudo rkhunter --check\r\nsudo chkrootkit\r\n<\/pre>\n<p>Las desinstalo pq no me interesa que se ejecuten periodicamente:<\/p>\n<pre>\r\napt-get purge chkrootkit rkhunter\r\n<\/pre>\n<h4>Control del ancho de banda<\/h4>\n<p>Es recomendable establecer pol\u00edticas para controlar el tr\u00e1fico que recibimos y enviamos, o incluso dar m\u00e1s prioridad a determinados paquetes (p.ej. conexiones SSH). Para ello tenemos m\u00e1s informaci\u00f3n en otros tutoriales como <a href=\"http:\/\/www.gulic.org\/comos\/LARTC\/html\/x2193.html#AEN2242\">Enrutamiento avanzado y control de tr\u00e1fico en Linux<\/a>.<\/p>\n<p>A\u00f1ado varios scripts de ejemplo que pueden ser de utilidad que establecen los siguientes par\u00e1metros utilizando Hierarchy Token Bucket (HTB):<\/p>\n<ul>\n<li>Limita la velocidad de bajada a 95 megabits<\/li>\n<li>Se crea una clase raiz &#8220;1:1&#8221; que limita la subida a 95 Megabits (para evitar la saturaci\u00f3n del enlace) y de la cual cuelgan 3 colas de diferentes prioridades:\n<ul>\n<li>&#8220;1:10&#8221; Cola de prioridad alta (ideal para tr\u00e1fico interactivo como SSH).<\/li>\n<li>&#8220;1:20&#8221; Cola de prioridad media (por defecto)<\/li>\n<li>&#8220;1:30&#8221; Cola de prioridad baja que limita la velocidad de subida al 70% de los 95 Megabits (perfecto para hosts o servicios que no queremos que nos saturen la conexi\u00f3n)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Entre las 3 colas el sistema coger\u00e1 m\u00e1s paquetes de aquellas que tienen mayor prioridad, y dentro de las colas se utiliza un reparto uniforme entre las diferentes conexiones para que una no se haga con todo el caudal (Stochastic Fairness Queueing &#8211; SFQ).<\/p>\n<p>Una vez establecidas las colas, por defecto todo el tr\u00e1fico va a la cola &#8220;1:20&#8221; y podemos marcar mediante iptables aquellas que queremos que vayan a una cola diferente. Por ejemplo:<\/p>\n<pre>\r\n$IPTABLES -t mangle -I OUTPUT -p tcp --sport 22 -s $LAN_IP1 -m mark --mark 0 -j MARK --set-mark 10\r\n<\/pre>\n<p>En el ejemplo anterior, todo el tr\u00e1fico que surjan del puerto 22 (servicio SSH) es etiquetado con la marca &#8220;10&#8221; que har\u00e1 que el paquete vaya a la cola &#8220;1:10&#8221; (la m\u00e1s prioritaria).<\/p>\n<p>Veamos el script completo &#8216;\/usr\/local\/bin\/traffic-control&#8217;:<\/p>\n<pre>\r\n#!\/bin\/bash\r\n\r\n## http:\/\/www.docum.org\/docum.org\/monitor\/\r\n## http:\/\/crysol.inf-cr.uclm.es\/node\/692\r\n\r\n# In megabits\r\nDOWNLINK=95\r\nUPLINK=95\r\nDEV=eth0\r\nLAN_IP1=\"71.11.5.10\"\r\nIPTABLES=\"\/sbin\/iptables\";\r\n#LIMIT_IP1=\"192.168.22.3\"\r\n\r\n\r\n# Clean existing down\/up-link qdiscs\r\ntc qdisc del dev $DEV root    2> \/dev\/null > \/dev\/null\r\ntc qdisc del dev $DEV ingress 2> \/dev\/null > \/dev\/null\r\n\r\n###### uplink\r\n\r\n#### QDISC\r\n# Hierarchy Token Bucket which (HBT) pointing by default to class 1:20 (HBT is the most easy one)\r\ntc qdisc add dev $DEV root handle 1: htb default 20\r\n\r\n#### Classes\r\n# Root class that shape everything at $UPLINK speed preventing huge queues which destroy latency\r\ntc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}mbit burst 6k\r\n\r\n# High priority class (1:10)\r\ntc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK}mbit burst 6k prio 1\r\n\r\n# Medium priority class (1:20)\r\ntc class add dev $DEV parent 1:1 classid 1:20 htb rate ${UPLINK}mbit burst 6k prio 2\r\n\r\n# Low priority class (1:20) with speed reduced to 70%\r\ntc class add dev $DEV parent 1:1 classid 1:30 htb rate $[7*$UPLINK\/10]mbit burst 6k prio 3\r\n\r\n#### Queueing\r\n# Stochastic Fairness Queueing: avoid that one connection consumes all the bandwidth\r\ntc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10\r\ntc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10\r\ntc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10\r\n\r\n\r\n#### Marking\r\n### Mark traffic with 10 (highest), 20 or 30 (lowest)\r\n$IPTABLES -F -t mangle\r\n# Prioritize local SSH\r\n$IPTABLES -t mangle -I OUTPUT -p tcp --sport 22 -s $LAN_IP1 -m mark --mark 0 -j MARK --set-mark 10\r\n# Limit host\r\n#$IPTABLES -t mangle -I FORWARD -s $LIMIT_IP1 -m mark --mark 0 -j MARK --set-mark 30\r\n\r\n#### Classify\r\n# Traffic with MARK 10 to the highest prioritized class (1:10)\r\ntc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10\r\ntc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20\r\ntc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 30 fw flowid 1:30\r\n# By default, the rest ends up in 1:20\r\n\r\n\r\n########## downlink\r\n# Slow downloads down to somewhat less than the real speed to prevent queuing the ISP.\r\n#\r\n# Attach ingress policer:\r\ntc qdisc add dev $DEV handle ffff: ingress\r\n\r\n# Filter *everything* to it (0.0.0.0\/0), drop everything that's coming in too fast:\r\ntc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \r\n   0.0.0.0\/0 police rate ${DOWNLINK}mbit burst 10k drop flowid :1\r\n<\/pre>\n<p>Por otra parte, podemos tener un script para listar las colas &#8216;\/usr\/local\/bin\/traffic-control-list&#8217;:<\/p>\n<pre>\r\n#!\/bin\/bash\r\ntc -s qdisc ls dev eth0\r\n<\/pre>\n<p>Y finalmente, para desactivar las colas &#8216;\/usr\/local\/bin\/traffic-control-list-off&#8217;:<\/p>\n<pre>\r\n#!\/bin\/bash\r\nDEV=eth0\r\nTC=\/sbin\/tc\r\n\r\n# clean existing down- and uplink qdiscs, hide errors\r\n$TC qdisc del dev $DEV root    2> \/dev\/null > \/dev\/null\r\n$TC qdisc del dev $DEV ingress 2> \/dev\/null > \/dev\/null\r\n<\/pre>\n<p>Para ver en tiempo real el efecto de las colas establecidas, es recomendable utilizar el script &#8216;<a href=\"http:\/\/www.docum.org\/docum.org\/monitor\/download\/monitor_tc_top.pl\">monitor_tc_top.pl<\/a>&#8216; de la siguiente <a href=\"http:\/\/www.docum.org\/docum.org\/monitor\/\">web<\/a>:<\/p>\n<pre>\r\n# cd \/usr\/local\/bin\/\r\n# wget -c http:\/\/www.docum.org\/docum.org\/monitor\/download\/monitor_tc_top.pl\r\n# chmod 755 monitor_tc_top.pl\r\n# monitor_tc_top.pl\r\n<\/pre>\n<p>Ejemplo:<\/p>\n<pre>\r\n 20:37:11 up 18 days,  7:30,  2 users,  load average: 0.18, 0.05, 0.01\r\n                                          Interval    Cumulated Total\r\nDev  Classid   Tokens   Ctokens Rate      Speed       Send      Send\r\n-------------------------------------------------------------------------\r\neth0 1:1       485      4033    2.42KB    624.32KB\/s  6.91MB    8.47MB\r\neth0 1:10      485      4033    6.67KB    1.37KB\/s    18.52KB   23.42KB\r\neth0 1:20      500      4048    18.41KB   558B\/s      2.39KB    87.90KB\r\neth0 1:30      4        3388    2.39KB    622.40KB\/s  6.89MB    8.36MB\r\n<\/pre>\n<h3><a name=\"10\">10. Copias de seguridad<\/a><\/h3>\n<p>Con rsnapshot podremos hacer copias de seguridad autom\u00e1ticas y peri\u00f3dicas, optimizando al m\u00e1ximo el espacio ocupado mediante el uso de enlaces simb\u00f3licos:<\/p>\n<pre>\r\napt-get install rsnapshot\r\n<\/pre>\n<p>Para configurar las copias editamos \/etc\/rsnapshot.conf para indicar donde se guardaran los scripts:<\/p>\n<pre>\r\nsnapshot_root   \/var\/cache\/rsnapshot\/\r\n<\/pre>\n<p>Adem\u00e1s, en este mismo fichero vamos a establecer nuestra pol\u00edtica de backups: Se almacenaran las \u00faltimas 6 horas, los \u00faltimos 7 d\u00edas, las \u00faltimas 4 semanas y los \u00faltimos 6 meses. Por otra parte, tambi\u00e9n indicaremos que directorios queremos copiar y que scripts ejecutar:<\/p>\n<pre>\r\n...\r\n#rsync_short_args   -a\r\nrsync_long_args --delete --numeric-ids --relative --delete-excluded --stats --timeout=10\r\n...\r\n\r\n#########################################\r\n#           BACKUP INTERVALS            #\r\n# Must be unique and in ascending order #\r\n# i.e. hourly, daily, weekly, etc.      #\r\n#########################################\r\n\r\n## Tendremos backup de las \u00faltimas 6 horas, los \u00faltimos 7 d\u00edas, las \u00faltimas 4 semanas y los \u00faltimos 6 meses:\r\ninterval    hourly  6\r\ninterval    daily   7\r\ninterval    weekly  4\r\ninterval    monthly 6\r\n\r\n...\r\n# Excluimos algunos ficheros para hacer m\u00e1s peque\u00f1os los backups\r\nexclude access.log\r\nexclude access.log.*\r\nexclude access_log\r\nexclude error.log\r\nexclude error.log.*\r\nexclude .bash_history\r\n...\r\n\r\n###############################\r\n### BACKUP POINTS \/ SCRIPTS ###\r\n###############################\r\n\r\n# LOCALHOST\r\nbackup  \/etc\/       localhost\/\r\nbackup\t\/home\/\tlocalhost\r\nbackup\t\/var\/www\/\tlocalhost\r\nbackup\t\/usr\/local\/\tlocalhost\r\nbackup\t\/var\/lib\/awstats\/\tlocalhost\r\nbackup\t\/var\/lib\/bandwidthd\/\tlocalhost\r\nbackup\t\/var\/lib\/cacti\/\tlocalhost\r\nbackup\t\/var\/cache\/nagios2\/\tlocalhost\r\nbackup\t\/var\/lib\/nagios2\/\tlocalho\r\nbackup_script\t\/usr\/local\/bin\/backup_dpkg.sh\tlocalhost\/dpkg\/\r\nbackup_script\t\/usr\/local\/bin\/backup_mysql.sh\tlocalhost\/mysql\/\r\nbackup_script\t\/usr\/local\/bin\/backup_info.sh\tlocalhost\/info\/\r\n\r\nbackup  rsnapshot@webserver:\/etc\/   webserver\/  ssh_args=-p 22\r\nbackup  rsnapshot@webserver:\/usr\/local\/ webserver\/  ssh_args=-p 22\r\nbackup  rsnapshot@webserver:\/var\/www\/   webserver\/  ssh_args=-p 22\r\nbackup_script   \/usr\/bin\/ssh -i \/root\/.ssh\/id_rsa rsnapshot@webserver \/home\/rsnapshot\/.ssh\/backup_mysql_all.sh > db.sql webserver\/mysql\/all\/\r\n<\/pre>\n<p>En este ejemplo estamos haciendo backup tanto de directorios locales (p.ej. \/etc) como remotos del servidor &#8216;webserver&#8217;.<\/p>\n<p>Es importante que los par\u00e1metros de este fichero de configuraci\u00f3n se encuentren separados por tabulaciones y no por espacios, de lo contrario rsnapshot no podr\u00e1 procesarlo correctamente. Comprobamos que el archivo de configuraci\u00f3n sea correcto:<\/p>\n<pre>\r\n# rsnapshot configtest\r\nSyntax OK\r\n<\/pre>\n<p>Simula la creaci\u00f3n de un snapshot:<\/p>\n<pre>\r\n# rsnapshot -t hourly\r\n<\/pre>\n<p>El snapshot m\u00e1s reciente siempre se encontrar\u00e1 en el n\u00famero m\u00e1s bajo, en el caso de los snapshots realizados cada hora: \/var\/cache\/rsnapshot\/hourly.0\/<\/p>\n<p>Es recomendable evitar que slocate indexe el backup, editamos \/etc\/updatedb.conf:<\/p>\n<pre>\r\nFINDOPTIONS='-ignore_readdir_race'\r\nexport FINDOPTIONS\r\nPRUNEFS=\"NFS nfs nfs4 afs binfmt_misc proc smbfs autofs iso9660 ncpfs coda devpts ftpfs devfs mfs shfs sysfs cifs lustre_lite tmpfs usbfs udf\"\r\nexport PRUNEFS\r\nPRUNEPATHS=\"\/tmp \/usr\/tmp \/var\/tmp \/var\/spool \/media \/var\/cache\/rsnapshot \/var\/cache\/rsnapshot-tar\"\r\nexport PRUNEPATHS\r\nNETPATHS=\"\"\r\nexport NETPATHS\r\nLOCALUSER=\"nobody\"\r\nexport LOCALUSER\r\nNICE=10\r\nexport NICE\r\nIONICE_CLASS=2\r\nexport IONICE_CLASS\r\nIONICE_PRIORITY=7\r\nexport IONICE_PRIORITY\r\n<\/pre>\n<h4>Utilidades rsnapshot<\/h4>\n<p>A la hora de hacer backup, adem\u00e1s de especificar directorios concretos podemos hacer que se ejecuten scripts (p.ej. que realicen volcados de las BBDD) para que tambi\u00e9n se efectue una copia de su resultado (en el fichero de configuraci\u00f3n de ejemplo anterior, se puede observar como hay varios scripts especificados).<\/p>\n<h5>Informaci\u00f3n de estado<\/h5>\n<p>A modo de ejemplo, podemos crear un script a medida \/usr\/local\/bin\/backup_info.sh que genere varios ficheros con el estado de la m\u00e1quina en el momento de realizar la copia:<\/p>\n<pre>\r\n#!\/bin\/bash\r\n# Date\r\n\/bin\/date -R > date.out\r\n# Host name and kernel\r\n\/bin\/uname -a > uname.out\r\n# Interfaces\r\n\/sbin\/ifconfig -a > ifconfig.out\r\n# Disk space\r\n\/bin\/df -h > df.out\r\n# Processes\r\n\/bin\/ps aux > ps.out\r\n# Open ports & conections\r\n\/bin\/netstat -atunp > netstat.out\r\n\/usr\/bin\/lsof -i > lsof-i.out\r\n# Processes with lots of files open\r\n\/usr\/bin\/lsof +c 15 | awk '{printf(\"%15s  (%s)n\", $1, $2)}' | sort | uniq -c | sort -rn | head > losf-processes-with-lots-of-open-files.out\r\n# Mounted filesystems\r\n\/bin\/mount > mount.out\r\n# Connected users\r\n\/usr\/bin\/who > who.out\r\n# Firewall rules\r\n\/sbin\/iptables -L > iptables.out\r\n# Daemons & init scripts\r\n\/usr\/sbin\/sysv-rc-conf --list > sysv-rc-conf.out\r\n# Files with special permissions\r\n#\/usr\/bin\/find \/ -path \/proc -prune -o -perm -2 ! -type l -ls > find-world-writable.out\r\n#\/usr\/bin\/find \/ -path \/proc -prune -o -nouser -o -nogroup > find-files-without-owner.out\r\n#\/usr\/bin\/find \/ -path \/proc -prune -o -type f -perm +6000 -ls > find-suid-guid.out\r\n<\/pre>\n<h5>dpkg y mysql<\/h5>\n<p>Scripts que copian el listado de paquetes instalados en Ubuntu y un volcado de la MySQL:<\/p>\n<pre>\r\ncp \/usr\/share\/doc\/rsnapshot\/examples\/utils\/backup_dpkg.sh \/usr\/local\/bin\/\r\ncp \/usr\/share\/doc\/rsnapshot\/examples\/utils\/backup_mysql.sh  \/usr\/local\/bin\/\r\n<\/pre>\n<p>Editamos &#8216;\/root\/.my.cnf&#8217; para establecer el password de root y as\u00ed poder realizar volcados sin necesidad de interaccionar con la m\u00e1quina:<\/p>\n<pre>\r\n[client]\r\n  user = root\r\n  password = secret\r\n  host = localhost\r\n<\/pre>\n<p>Ejecutamos:<\/p>\n<pre>\r\nchmod 600 \/root\/.my.cnf\r\n<\/pre>\n<p>En el fichero de configuraci\u00f3n especificaremos los scripts a ejecutar y el destino de su resultado:<\/p>\n<pre>\r\nbackup_script\t\/usr\/local\/bin\/backup_dpkg.sh\tlocalhost\/dpkg\/\r\nbackup_script\t\/usr\/local\/bin\/backup_mysql.sh\tlocalhost\/mysql\/\r\n<\/pre>\n<h5>Backups remotos<\/h5>\n<p>Si queremos hacer backup de directorios remotos o incluso ejecutar scripts remotos (p.ej. volcado mysql), en el servidor donde tenemos rsnapshot debemos generar una clave SSH con ssh-keygen (ver secci\u00f3n correspondiente) para el usuario root (\/root\/.ssh\/).<\/p>\n<p>En la m\u00e1quina a la que queremos conectarnos para hacer las copias, crearemos un usuario bloqueado:<\/p>\n<pre>\r\nuseradd -d \/home\/rsnapshot -m -K PASS_MAX_DAYS=-1,PASS_MIN_DAYS=0,PASS_WARN_AGE=0,UMASK=0022 -s \/bin\/bash rsnapshot\r\npasswd -l rsnapshot\r\nmkdir -p \/home\/rsnapshot\/.ssh\r\n<\/pre>\n<p>Adem\u00e1s, permitiremos que el usuario ejecute &#8216;rsync&#8217; como root mediante &#8216;sudo&#8217; sin necesidad de contrase\u00f1a. Para ello ejecutamos &#8216;visudo&#8217; y a\u00f1adimos al final:<\/p>\n<pre>\r\nrsnapshot ALL=NOPASSWD: \/usr\/bin\/rsync\r\n<\/pre>\n<p>Para que rsnapshot funcione se conecte remotamente sin intervenci\u00f3n, necesitamos copiar la clave p\u00fablica a &#8216;\/home\/rsnapshot\/.ssh\/authorized_keys&#8217; y conviene establecer todas las limitaciones posibles (ver secci\u00f3n SSH):<\/p>\n<pre>\r\nfrom=\"71.21.5.19\",command=\"\/home\/rsnapshot\/.ssh\/validate-ssh.sh\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAUTQEbt7GOcR4jZ2bTgzxpgABIwAAAQEAwAQKRBv+ABDyOgvHfAxSVcWOEzhieC7rwrBjquLJw0W+U9vD7QgmffmuKDZksI7bAAB3NzaC1yc2EAAAdbHBOGg\/zgXcrCNsuJ5IJoDw== root@server.com\r\n<\/pre>\n<p>En este ejemplo, el usuario solo podr\u00e1 ser utilizado desde una IP concreta, siempre que tenga la clave privada y \u00fanicamente podr\u00e1 ejecutar el script &#8216;\/home\/rsnapshot\/.ssh\/validate-ssh.sh&#8217;:<\/p>\n<pre>\r\n#!\/bin\/sh\r\n\r\ncase \"$SSH_ORIGINAL_COMMAND\" in\r\n*&*)\r\necho \"Rejected\"\r\n;;\r\n*(*)\r\necho \"Rejected\"\r\n;;\r\n*{*)\r\necho \"Rejected\"\r\n;;\r\n*;*)\r\necho \"Rejected\"\r\n;;\r\n*< *)\r\necho \"Rejected\"\r\n;;\r\n*`*)\r\necho \"Rejected\"\r\n;;\r\nrsync --server*)\r\n# the calling user HAST TO BE in the sudoers list for executing rsync!\r\nsudo $SSH_ORIGINAL_COMMAND\r\n;;\r\nmysqldump *)\r\n$SSH_ORIGINAL_COMMAND\r\n;;\r\n\/home\/rsnapshot\/.ssh\/backup_mysql_all.sh)\r\n\/home\/rsnapshot\/.ssh\/backup_mysql_all.sh\r\n;;\r\n*)\r\necho \"Rejected $SSH_ORIGINAL_COMMAND\"\r\n;;\r\nesac \r\n<\/pre>\n<p>Este script permitir\u00e1 al usuario ejecutar \u00fanicamente 'rsync' (con permisos de root mediante 'sudo'), 'mysqldump' y el script '\/home\/rsnapshot\/.ssh\/backup_mysql_all.sh':<\/p>\n<pre>\r\n#!\/bin\/bash\r\n\/usr\/bin\/mysqldump --all-databases --add-drop-table --password=secret -u miusuario\r\n<\/pre>\n<p>El script anterior realiza un volcado de todas las BBDD de MySQL utilizando un usuario\/password determinado. Dado que contiene informaci\u00f3n sensible, el script debe tener permisos restrictivos:<\/p>\n<pre>\r\nchown -R rsnapshot:rsnapshot \/home\/rshapshot\r\nchmod 700 \/home\/rshapshot\/.ssh\/*.sh\r\n<\/pre>\n<p>Con esto ya tenemos preparado todo el montaje. Rsnapshot podr\u00e1 conectarse al servidor (ver fichero de configuraci\u00f3n de ejemplo anterior, donde se defin\u00edan copias del servidor &#8216;webserver&#8217;) sin contrase\u00f1a y hacer backups de directorios y MySQL. Adicionalmente, hemos establecido controles adicionales para minimizar la posibilidad de que un atacante pueda intentar aprovecharse de la configuraci\u00f3n (cifrado SSH, autenticaci\u00f3n por clave asim\u00e9trica limitada a una IP y a unos comandos concretos).<\/p>\n<h5>Tars semanales<\/h5>\n<p>De forma semanal, haremos que se cree un tar con la \u00faltima copia para poder enviarlo c\u00f3modamente a otro ordenador:<\/p>\n<pre>\r\ncp \/usr\/share\/doc\/rsnapshot\/examples\/utils\/rsnaptar \/usr\/local\/bin\/\r\nmkdir \/var\/cache\/rsnapshot-tar\/\r\n<\/pre>\n<p>Editamos \/usr\/local\/bin\/rsnaptar para especificar el lugar donde guardaremos los tar, comentamos GPG y a\u00f1adimos info al mail que se genera automaticamente.<\/p>\n<pre>\r\n# DIRECTORIES\r\nTAR_DIR=\"\/var\/cache\/rsnapshot-tar\"\r\nSNAPSHOT_DIR=\"\/var\/cache\/rsnapshot\/daily.0\/\"\r\n...\r\n#GPG=\"\/usr\/bin\/gpg\"\r\n...\r\n${CAT} &#60;&#60; EOF | ${SENDMAIL}\r\nTo: ${TO_EMAIL}\r\nSubject: [rsnapshot] Tar backup job complete - ${HOSTNAME}\r\n\r\nNow is the time to backup the latest files from rsnapshot on ${HOSTNAME}\r\n\r\nTar files created on ${TAR_DIR}\/${DATE}\/\r\nEOF\r\n<\/pre>\n<p>Editamos &#8216;\/etc\/cron.d\/rsnapshot&#8217; para que se ejecute cada semana:<\/p>\n<pre>\r\n# Weekly\r\n# At 5:00 every monday\r\n0  5      * * 1       root    \/usr\/local\/bin\/rsnaptar marble@localhost\r\n<\/pre>\n<h5>Reportes<\/h5>\n<p>Si queremos recibir un reporte del backup cada cierto tiempo como medida para saber que se est\u00e1n efectuando:<\/p>\n<pre>\r\ncp \/usr\/share\/doc\/rsnapshot\/examples\/utils\/rsnapreport.pl.gz \/usr\/local\/bin\/\r\ngzip -d \/usr\/local\/bin\/rsnapreport.pl.gz\r\nchmod 755 \/usr\/local\/bin\/rsnapreport.pl\r\n<\/pre>\n<p>Establecemos en \/etc\/rsnapshot.conf el nivel de verbose a 3 y a\u00f1adimos &#8211;stats al comando rsync_long_args:<\/p>\n<pre>\r\n# Verbose level, 1 through 5.\r\n# 1     Quiet           Print fatal errors only\r\n# 2     Default         Print errors and warnings only\r\n# 3     Verbose         Show equivalent shell commands being executed\r\n# 4     Extra Verbose   Show extra verbose information\r\n# 5     Debug mode      Everything\r\n#\r\nverbose     3\r\n\r\n...\r\n\r\n# Default rsync args. All rsync commands have at least these options set.\r\n#\r\n#rsync_short_args   -a\r\nrsync_long_args --delete --numeric-ids --relative --delete-excluded --stats --timeout=10\r\n\r\n\r\n# this script prints a pretty report from rsnapshot output\r\n# in the rsnapshot.conf you must set\r\n# verbose >= 3\r\n# and add --stats to rsync_long_args\r\n# then setup crontab 'rsnapshot daily 2>&1 | rsnapreport.pl | mail -s\"SUBJECT\" backupadm@adm.com\r\n# don't forget the 2>&1 or your errors will be lost to stderr\r\n<\/pre>\n<p>Editamos \/etc\/cron.d\/rsnapshot para hacer que el reporte se genere una vez a la semana:<\/p>\n<pre>\r\n# 4 times per day\r\n0 *\/4     * * *       root    \/usr\/bin\/rsnapshot hourly > \/dev\/null\r\n# At 3:30 every day\r\n30 3      * * *       root    \/usr\/bin\/rsnapshot daily > \/dev\/null\r\n# At 3:00 every monday\r\n0  3      * * 1       root    \/usr\/bin\/rsnapshot weekly > \/dev\/null\r\n# At 2:30 every 1st of month\r\n30 2      1 * *       root    \/usr\/bin\/rsnapshot monthly > \/dev\/null\r\n\r\n# Run rsnapshot once a week as it were hourly but with rsnapreport (send report by mail)\r\n\r\n# I use it only to validate that backups are being done.\r\n# When we execute rsnapshot daily\/weekly\/... rsync is not called, only a move is done and rsnapreport can not generate a report with that info.\r\n# At 1:00 every monday\r\n0  1      * * 1       root    \/usr\/bin\/rsnapshot hourly 2>&1 | \/usr\/local\/bin\/rsnapreport.pl | mail -s\"[rsnapshot] Weekly report\" marble@localhost\r\n<\/pre>\n<h3><a name=\"11\">11. Tests de stress<\/a><\/h3>\n<h4>Sistema<\/h4>\n<p>Para poner a prueba la resistencia del sistema, podemos utilizar la herramienta &#8216;stress&#8217; para consumir memoria RAM, CPU o disco duro de forma masiva y forzada:<\/p>\n<pre>\r\napt-get install stress\r\n<\/pre>\n<p>Opciones:<\/p>\n<pre>\r\n -t, --timeout N    timeout after N seconds\r\n -c, --cpu N        spawn N workers spinning on sqrt()\r\n -i, --io N         spawn N workers spinning on sync()\r\n -m, --vm N         spawn N workers spinning on malloc()\/free()\r\n     --vm-bytes B   malloc B bytes per vm worker (default is 256MB)\r\n     --vm-hang N    sleep N secs before free (default is none, 0 is inf)\r\n     --vm-keep      redirty memory instead of freeing and reallocating\r\n -d, --hdd N        spawn N workers spinning on write()\/unlink()\r\n     --hdd-bytes B  write B bytes per hdd worker (default is 1GB)\r\n     --hdd-noclean  do not unlink files created by hdd workers\r\n<\/pre>\n<p>Ejemplo de consumo de memoria y CPU:<\/p>\n<pre>\r\n$ stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --vm-keep --timeout 10s\r\nstress: info: [13247] dispatching hogs: 8 cpu, 4 io, 2 vm, 0 hdd\r\nstress: info: [13247] successful run completed in 10s\r\n<\/pre>\n<p>\u00danicamente consumo de memoria:<\/p>\n<pre>\r\nstress --vm 2 --vm-bytes 128M --vm-keep --timeout 10s\r\n<\/pre>\n<h4>Conexiones HTTP con httperf<\/h4>\n<p>Podemos realizar pruebas contra un servicio web para ver su capacidad de respuesta:<\/p>\n<pre>\r\napt-get install httperf\r\n<\/pre>\n<p>Por ejemplo, crear 100 conexiones con un ratio de 10 por segundo:<\/p>\n<pre>\r\nhttperf --hog --server www --num-conn 100 --rate 10 --timeout 5\r\n<\/pre>\n<p>Crear 10 sesiones a un ratio de 1 por segundo, cada sesion consisten en 5 llamadas espaciadas por 2 segundos:<\/p>\n<pre>\r\nhttperf --hog --server=www --wsess=10,5,2 --rate 1 --timeout 5\r\n<\/pre>\n<p>Ejemplo de ejecuci\u00f3n:<\/p>\n<pre>\r\n$ httperf --hog --server=localhost --port 3000 --wsess=10,5,2 --rate 1 --timeout 5\r\nhttperf --hog --timeout=5 --client=0\/1 --server=localhost --port=3000 --uri=\/ --rate=1 --send-buffer=4096 --recv-buffer=16384 --wsess=10,5,2.000\r\nMaximum connect burst length: 1\r\n\r\nTotal: connections 50 requests 90 replies 50 test-duration 30.088 s\r\n\r\nConnection rate: 1.7 conn\/s (601.8 ms\/conn, < =11 concurrent connections)\r\nConnection time [ms]: min 308.3 avg 4186.5 max 6065.9 median 4252.5 stddev 1489.6\r\nConnection time [ms]: connect 0.1\r\nConnection length [replies\/conn]: 1.000\r\n\r\nRequest rate: 3.0 req\/s (334.3 ms\/req)\r\nRequest size [B]: 86.0\r\n\r\nReply rate [replies\/s]: min 1.2 avg 1.6 max 1.8 stddev 0.2 (6 samples)\r\nReply time [ms]: response 2530.6 transfer 52.8\r\nReply size [B]: header 414.0 content 12642.0 footer 0.0 (total 13056.0)\r\nReply status: 1xx=0 2xx=0 3xx=0 4xx=0 5xx=50\r\n\r\nCPU time [s]: user 2.70 system 12.57 (user 9.0% system 41.8% total 50.8%)\r\nNet I\/O: 21.4 KB\/s (0.2*10^6 bps)\r\n\r\nErrors: total 40 client-timo 0 socket-timo 0 connrefused 0 connreset 40\r\nErrors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0\r\n\r\nSession rate [sess\/s]: min 0.00 avg 0.33 max 1.00 stddev 0.39 (10\/10)\r\nSession: avg 5.00 connections\/session\r\nSession lifetime [s]: 20.9\r\nSession failtime [s]: 0.0\r\nSession length histogram: 0 0 0 0 0 10\r\n<\/pre>\n<h4>Conexiones HTTP con Apache Benchmarking tool<\/h4>\n<p>Otra herramienta para testear la capacidad de un servicio web:<\/p>\n<pre>\r\napt-get install apache2-utils\r\n<\/pre>\n<p>Por ejemplo, enviar 1000 request mediante 5 procesos concurrentes:<\/p>\n<pre>\r\n$ ab -n 1000 -c 5 http:\/\/localhost\/\r\nBenchmarking localhost (be patient)\r\n\r\n\r\nServer Software:        Apache\r\nServer Hostname:        localhost\r\nServer Port:            80\r\n\r\nDocument Path:          \/\r\nDocument Length:        612 bytes\r\n\r\nConcurrency Level:      5\r\nTime taken for tests:   0.382452 seconds\r\nComplete requests:      1000\r\nFailed requests:        0\r\nWrite errors:           0\r\nTotal transferred:      852852 bytes\r\nHTML transferred:       612612 bytes\r\nRequests per second:    2614.71 [#\/sec] (mean)\r\nTime per request:       1.912 [ms] (mean)\r\nTime per request:       0.382 [ms] (mean, across all concurrent requests)\r\nTransfer rate:          2175.44 [Kbytes\/sec] received\r\n\r\nConnection Times (ms)\r\n              min  mean[+\/-sd] median   max\r\nConnect:        0    0   0.0      0       1\r\nProcessing:     0    1   8.6      0      98\r\nWaiting:        0    0   0.3      0       1\r\nTotal:          0    1   8.6      0      98\r\n\r\nPercentage of the requests served within a certain time (ms)\r\n  50%      0\r\n  66%      1\r\n  75%      1\r\n  80%      1\r\n  90%      1\r\n  95%      1\r\n  98%      1\r\n  99%     74\r\n 100%     98 (longest request)\r\n<\/pre>\n<p>Resulta interesante hacer la prueba con URLs que hagan diferentes tipos de procesado:<\/p>\n<ul>\n<li>P\u00e1ginas est\u00e1ticas<\/li>\n<li>P\u00e1ginas din\u00e1micas PHP<\/li>\n<li>CGIs<\/li>\n<\/ul>\n<p>Si consultamos el manual (man ab), es posible indicar a ab que utilice cookies (-C cookie-name=value) o HTTP authentication (-P proxy-auth-username:password).<br \/>\nOtro ejemplo para realizar conexiones con HTTP KeepAlive, se abriran 10 conexiones y durante 30 segundos se utilizaran para enviar peticiones al servidor:<\/p>\n<pre>\r\n# ab -kc 10 -t 30 http:\/\/localhost\/\r\n\r\nBenchmarking localhost (be patient)\r\n\r\nServer Software:        Apache\r\nServer Hostname:        localhost\r\nServer Port:            80\r\n\r\nDocument Path:          \/\r\nDocument Length:        612 bytes\r\n\r\nConcurrency Level:      10\r\nTime taken for tests:   5.824757 seconds\r\nComplete requests:      50000\r\nFailed requests:        0\r\nWrite errors:           0\r\nKeep-Alive requests:    49511\r\nTotal transferred:      44432403 bytes\r\nHTML transferred:       30603060 bytes\r\nRequests per second:    8584.05 [#\/sec] (mean)\r\nTime per request:       1.165 [ms] (mean)\r\nTime per request:       0.116 [ms] (mean, across all concurrent requests)\r\nTransfer rate:          7449.41 [Kbytes\/sec] received\r\n\r\nConnection Times (ms)\r\n              min  mean[+\/-sd] median   max\r\nConnect:        0    0   0.0      0       1\r\nProcessing:     0    0   2.6      0     127\r\nWaiting:        0    0   2.6      0     127\r\nTotal:          0    0   2.6      0     127\r\n\r\nPercentage of the requests served within a certain time (ms)\r\n  50%      0\r\n  66%      1\r\n  75%      1\r\n  80%      1\r\n  90%      2\r\n  95%      2\r\n  98%      4\r\n  99%      4\r\n 100%    127 (longest request)\r\n<\/pre>\n<h3><a name=\"12\">12. Issue tracking<\/a><\/h3>\n<p>La gesti\u00f3n de incidencias o las solicitudes de alta\/baja\/modificaci\u00f3n del sistema puede ser efectuada mediante <a href=\"http:\/\/www.marblestation.com\/blog\/?p=656\">trac<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00daltimamente he escrito varios posts sobre est\u00e1ndares y aspectos m\u00e1s estrat\u00e9gicos de negocio e IT, como por ejemplo: BS 25999-1: Gesti\u00f3n de la Continuidad del Negocio Cobit, est\u00e1ndar para el buen gobierno de los Sistemas de Informaci\u00f3n ITIL y ISO 20000, marcos de trabajo para servicios IT Metodolog\u00edas de desarrollo Estructurar las organizaciones en procesos &hellip; <a href=\"https:\/\/www.marblestation.com\/?p=674\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Securizaci\u00f3n de un sistema Ubuntu (GNU\/Linux)<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,6],"tags":[],"class_list":["post-674","post","type-post","status-publish","format-standard","hentry","category-espanyol","category-tecnologia"],"_links":{"self":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts\/674","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=674"}],"version-history":[{"count":27,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts\/674\/revisions"}],"predecessor-version":[{"id":697,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts\/674\/revisions\/697"}],"wp:attachment":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=674"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=674"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=674"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}