Categoría: Servicios y servidores

  • Montando un Servidor Web con Ubuntu

    Montando un Servidor Web con Ubuntu

    En este documento veremos el proceso y comandos básicos para instalar servicios en un sistema operativo Ubuntu.


    Partiremos de un Ubuntu Server al cual accederemos vía SSH.

    Tecnologías a implementar

    SERVER – HOST

    En la primera fase prepararemos el sistema para acceso remoto con seguridad baja. En la segunda fase securizaremos el servidor.

    Servicios y herramientas:

    • SSH
    • Apache2
    • PHP
    • MySQL
    • FTP
    • CMD o PuTTY para conexión SSH
    • Workbench
    • VS Code vía SSH
    • FileZilla cliente

    1. Conexión SSH

    Primero comprobamos si SSH está instalado:

    dpkg -l | grep openssh-server
    

    Si aparece openssh-server, está instalado. Si no:

    sudo apt install ssh
    

    Una vez instalado, desde Windows o PuTTY:

    ssh usuario@ipdelservidor
    

    2. Instalación de Apache2

    Instalamos Apache:

    sudo apt install apache2
    

    Esto permitirá responder a peticiones HTTP por el puerto 80.

    Si la máquina usa IP dinámica, consulta la IP con:

    ifconfig
    

    (Instalar net-tools si no lo tienes: sudo apt install net-tools)

    Al acceder desde un navegador a la IP del servidor, deberías ver la página por defecto de Apache.

    La carpeta web se encuentra en:

    /var/www/html
    

    Aquí podrás crear tus documentos HTML.


    3. Instalación de MySQL Server

    Instalamos MySQL:

    sudo apt install mysql-server
    

    Ejecutamos script de configuración:

    mysql_secure_installation
    

    Las preguntas:

    1. Set root password? → Y
    2. Remove anonymous users? → Y
    3. Disallow root login remotely? → Y
    4. Remove test database? → Y
    5. Reload privilege tables now? → Y

    Reinicia el servicio:

    sudo systemctl restart mysql
    

    Acceso:

    sudo mysql -u root -p
    

    3.1 Conexión remota a MySQL

    Debemos modificar el archivo mysqld.cnf:

    sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
    

    Busca:

    bind-address = 127.0.0.1
    

    Cámbialo por:

    0.0.0.0
    

    (Así permitimos conexiones remotas.)

    Políticas de contraseñas MySQL

    Valores: LOW = 0, MEDIUM = 1, STRONG = 2.

    Ver configuración actual:

    SHOW VARIABLES LIKE 'validate_password%';
    

    Cambiar política:

    SET GLOBAL validate_password.policy=LOW;
    

    También puedes personalizar los requisitos:

    SET GLOBAL validate_password.length = 6;
    SET GLOBAL validate_password.number_count = 0;
    

    Según queramos podemos cambiar el valor por LOW, MEDIUM o STRONG
    Ejemplos de contraseñas:

    LOW:
    12345678
    password

    MEDIUM
    Estudiante123@
    Codificador NINZA$100
    demoPass#00

    Esta es la recomendada, por defecto solicita

    • La contraseña debe tener al menos 8 caracteres.
    • El recuento de mayúsculas y minúsculas es 1 (al menos 1 letra en minúscula y 1 letra enmayúscula)
    • El recuento de números es 1
    • El número mínimo de caracteres especiales es 1

    Otra forma de cambiar la politica de contraseñas sería:

    mysql>SET GLOBAL validate_password.policy=0;
    mysql>SET GLOBAL validate_password.policy=1;
    mysql>SET GLOBAL validate_password.policy=2;

    Tambien podemos personalizar los requisitos de cada una, ejemplo:

    mysql>SET GLOBAL validate_password.length = 6;
    mysql>SET GLOBAL validate_password.number_count = 0;

    Ahora que las reglas para una contraseña válida están claras, puedes crear un usuario con
    una contraseña válida


    3.2 Creación de usuario MySql

    Crear usuario:

    CREATE USER 'user'@'127.0.0.1' IDENTIFIED BY 'Estudiante123@';
    CREATE USER 'user'@'%' IDENTIFIED BY 'Estudiante123@';
    

    Al crear el usuario ponemos entre la @ primero el nombre y luego desde donde vamos a
    permitir que se conecte. si es desde localhost, una ip determinada o cualquier sitio.

    Ejemplos:

    CREATE USER ‘user’@’127.0.0.1’ IDENTIFIED BY ‘Estudiante123@’;

    crearemos un usuario con contraseña MEDIUM y que solo se pueda conectar desde
    localhost

    CREATE USER ‘user’@’%%’ IDENTIFIED BY ‘Estudiante123@’;

    Asignar permisos:

    GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES, RELOAD 
    ON *.* TO 'user'@'%' WITH GRANT OPTION;
    

    Aplicar cambios:

    FLUSH PRIVILEGES;
    

    3.3 Conexión desde Workbench

    Ahora que ya tenemos configurado nuestro gestor de mysql y hemos puesto que se pueda
    acceder desde cualquier Ip, instalamos Workbench en nuestro host y nos conectamos.

    En el cliente, instala Workbench y conecta usando:

    • IP del servidor
    • Puerto 3306
    • Usuario creado
    • Contraseña asignada

    4. Instalación del servicio FTP (VSFTPD)

    Instalar:

    sudo apt install vsftpd
    

    Hacemos backup del archivo de configuración:

    sudo cp /etc/vsftpd.conf /etc/vsftpd.conf_old
    

    Editar configuración:

    sudo nano /etc/vsftpd.conf
    

    Pegar:

    listen=NO
    listen_ipv6=YES
    anonymous_enable=NO
    local_enable=YES
    write_enable=YES
    local_umask=022
    dirmessage_enable=YES
    use_localtime=YES
    xferlog_enable=YES
    connect_from_port_20=YES
    chroot_local_user=YES
    secure_chroot_dir=/var/run/vsftpd/empty
    pam_service_name=vsftpd
    rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
    rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
    ssl_enable=NO
    pasv_enable=YES
    pasv_min_port=10000
    pasv_max_port=10100
    allow_writeable_chroot=YES
    

    Como hemos realizado una copia de seguridad podemos borrar su contenido, otro truco
    para muchos archivos de configuración en linux es comentar las lineas anteriores con #, o
    simplemente poner la nueva configuración al final del documento.


    *Ubuntu en algunas versiones, viene con un firewall llamado UFW. En este caso le debemos
    de decir que abra el puerto 20, 21 y los del 10000 al 10100 para su correcto funcionamiento

    Abrir puertos en UFW:

    sudo ufw allow from any to any port 20,21,10000:10100 proto tcp
    

    Reiniciar servicio:

    sudo systemctl restart vsftpd
    

    4.1 Acceso vía FTP desde el cliente

    Para transmitir archivos via FTP al servidor podemos usar cualquier programa de
    transmisión de archivos como Filezilla-client

    Utiliza FileZilla-client y conecta usando:

    • IP del servidor
    • Usuario FTP
    • Contraseña
    • Puerto 21

    Cada usuario tendrá acceso a su carpeta.


    4.2 Acceso FTP a la carpeta web de Apache

    Dado que nuestro objetivo es montar un servidor web, debemos tener la opción de poder
    acceder a las carpetas de de apache html, para poder transmitir los archivos de una web,
    imagenes, etc.


    Existe varios modos, veamos el que considero mas sencillo para inicial. Que consiste en
    crear un usuario donde su carpeta personal sea la www de Apache2 y dar permisos a esta
    carpeta.

    Creamos un usuario cuyo directorio sea la carpeta web:

    sudo useradd -m ftpuser
    sudo passwd ftpuser
    

    *Con la opción -m indicamos que nos cree una carpeta para el usuario

    Finalmente, podemos editar el archivo /etc/passwd para cambiar la carpeta al que el usuario
    tendrá acceso.

    sudo nano /etc/passwd   ← Cambia el directorio del usuario.
    

    También podrías jugar con los grupos de usuarios en Linux, para dar acceso a diferentes
    usuarios, algunos comandos útiles que podrías repasar podrían ser:

    Modificar grupos/permisos:

    sudo chgrp -R ftpuser www
    sudo groupadd grupo
    sudo adduser usuario grupo
    sudo chmod -R 775 www
    

    5. Instalación del intérprete PHP

    Instalamos PHP y módulos:

    sudo apt install php libapache2-mod-php php-mysql php-cli
    

    php: el propio interprete, si queremos una versión especifica podriamos poner php8.1, php7,
    etc.


    libapache2-mod-php: Libreria que permite trabajar a apache2 con php (Imprescindible en
    nuestro caso)

    php-mysql: Libreria que permite hacer conexiones desde php a mysql (Imprescindible si
    hacemos app con acceso a bases de datos).

    php-cli: Aunque para un servidor web no es necesario, si es util para ejecutar scripts de php
    directamente en la terminal, para temas de mantenimiento, tareas crontab, envio de
    mensajes, etc.

    Una vez instalado puede comprobar la versión instalada con:

    php -v
    

    Crear archivo de prueba:

    sudo nano /var/www/html/version.php
    

    Contenido:

    <?php
    phpinfo();
    ?>
    

    Dar permisos:

    sudo chmod 775 version.php
    

    Probar desde el navegador: http://IP/version.php


    Ejecución PHP desde terminal

    Crear archivo:

    sudo nano infosys.php
    

    Contenido:

    <?php 
    $os = php_uname(); 
    $cpu = shell_exec('cat /proc/cpuinfo | grep "model name" | head -n 1'); 
    $memTotal = shell_exec('cat /proc/meminfo | grep MemTotal'); 
    $memFree = shell_exec('cat /proc/meminfo | grep MemFree'); 
    $disk = shell_exec('df -h'); 
    
    echo "Información del Sistema:\n";
    echo "Sistema Operativo: $os\n";
    echo "Procesador: $cpu\n"; 
    echo "Memoria Total: $memTotal"; 
    echo "Memoria Libre: $memFree\n"; 
    echo "Espacio en Disco:\n$disk\n"; 
    ?>
    

    Ejecutar:

    php infosys.php
    

    6. Acceso por SSH desde un IDE – Visual Studio Code

    Instalar VSCode: https://code.visualstudio.com/Download

    Instalar extensión: Remote – SSH

    Crear conexión:

    1. Clic en icono de conexión remota.
    2. Add New SSH Host.
    3. Indicar un nombre sin espacios.
    4. Elegir dónde guardar el archivo de configuración.
    5. Indicar sistema operativo remoto (Linux).
    6. Escribir parámetros:
    Host Mi_conexion
      HostName 192.168.x.x
      User ubuntu
    

    Una vez guardado, podrás acceder desde VS Code, abrir carpetas del servidor y usar la terminal integrada.

  • UFW- Securizando  servicios de servidor WEB

    UFW- Securizando servicios de servidor WEB

    Configuración del Firewall en linux UFW

    Mediante el comando ufw podemos configurar el firewall de Linux de forma sencilla. Lo primero que debemos de hacer es ver si esta activo o no.

    sudo ufw status

    Esto nos mostrará la lista de puertos, o en su defecto si esta inactivo. El hecho de estar inactivo supone que tenemos todos los puertos abiertos, lo que es una seria vulnerabilidad.
    ![[Snag_5bd2428.png]]
    Para activarlo, escribimos:

    sudo ufw enable

    NOTA: Debemos tener en cuenta que si estamos conectados vía SSH por el puerto 22, al activar el firewall puede ser que nos expulse, si anteriormente no hemos abierto el puerto.

    Ahora podemos poner, sudo ufw status y nos retornara la configuración actual.

    ![[Snag_5c08db1.png]]
    En este caso, vemos que ya tenemos varios puertos abiertos dado que hemos instalado diferentes servicios.

    Lista de puertos comunes.
    Algunos de los puertos más importantes de los sistemas Linux suelen estar activados por defecto, aunque en algunos casos esto no se da. Hay que tener en cuenta que mantener SSH en el puerto 22 es considerado un riesgo a nivel de seguridad, por lo que se recomienda cambiarlo.

    | Puertos comunes |

    21 > FTP
    22 > SSH
    23 > SFTP
    25 > SMTP
    43 > WHOIS
    53 > Nameservers (sistema DNS)
    80 > HTTP (servidor web, ya sea Apache, Nginx u otro)
    110 > Protocolo POP utilizado para mail.
    111 > rpcbind
    143 > Protocolo IMAP utilizado para mail.
    443 > HTTP seguro (utilizado por certificados SSL a nivel web, https://)
    953 > rndc
    993 > IMAP bajo SSL
    995 > Protocolo POP con SSL
     
    2082 > Panel cPanel
    2083 > cPanel con SSL
    2086 > Panel WHM
    2087 > WHM con SSL
    2095 > Webmail
    2096 > Webmail con SSL
     
    3306 > MySQL
    4643 > Virtuosso
    9999 > Urchin
     
    Panel Plesk > 8443
    Panel DirectAdmin > 2222
    Panel Webmin > 10000 |
    Veamos ahora como abrir o cerrar los puertos según las necesidades de cada servidor.

    Una forma sencilla es indicar directamente el nombre del servicio utilizando la opción de allow.

    sudo ufw allow ssh

    Sin embargo, podemos escribir la regla equivalente especificando el puerto en vez del nombre del servicio. Por ejemplo, este comando funciona como el anterior:

    sudo ufw allow 22

    Si deseamos ver algo mas de información del estado de los puertos, podemos poner

    sudo ufw status verbose

    Otra opción si deseamos habilitar varios puertos que estan consecutivos, podemos indicar el rango.

    sudo ufw allow 6000:6007 /tcp
    sudo ufw allow 6000:6007 /udp

    Esto abriría los puertos del 6000 al 6007

    Cerrar puertos.

    Si deseamos cerrar un puerto que tengamos abierto, podemos cerrarlo con.

    sudo ufw deny 80 

    Esto cerraría el puerto 80 de http evitando conexiones al servidor.

    Habilitar o cerrar puertos con orígenes definidos.

    En ocasiones para mayor seguridad queremos abrir los puertos, pero solo para acceder desde una dirección ip concreta, esto lo realizaremos añadiendo la opción from

      sudo ufw allow from 03.0.113.4

    De este modo solo daremos acceso al equipo con la ip designada. Aunque lo mas común es determinar el o los puertos concretos que queremos que pueda acceder.

     Por ejemplo, si desea permitir que 203.0.113.4 se conecte al puerto 22 (SSH), utilice este comando:

    sudo ufw allow from 203.0.113.4 to any port 22

    Por último si estamos en una infraestructura con diferentes subredes, podemos determinar cual de ellas pueden acceder o no. Por ejemplo una subred para un departamento de una empresa en concreto.

    sudo ufw allow from 203.0.113.0/24

    o si queremos especificar el puerto

    sudo ufw allow from 203.0.113.0/24 to any port 22

    Por numero de regla

    Si utiliza el número de regla para eliminar reglas de firewall, lo primero que le convendrá hacer es obtener una lista de reglas de firewall. El comando “UFW status” tiene una opción para mostrar números junto a cada regla, como se muestra aquí:

    sudo ufw status numbered
    Numbered Output:Status: active
    
         To                         Action      From
         --                         ------      ----
    [ 1] 22                         ALLOW IN    15.15.15.0/24
    [ 2] 80                         ALLOW IN    Anywhere

    Si queremos eliminar la regla 2, que permite las conexiones del puerto 80 (HTTP), podemos especificarlo en un comando “UFW delete”

    sudo ufw delete 2

    Otra forma es hacerlo sin numerar poniendo directamente el servicio a borrar o el numero de puerto. Por ejemplo: desea eliminar la regla allow http, podría escribir lo siguiente:

    sudo ufw delete allow http

    También podría especificar la regla mediante allow 80 en vez de hacerlo por nombre de servicio:

    sudo ufw delete allow 80

    Otros comandos útiles pueden ser:

    Si decide que no desea utilizar UFW, puede desactivarlo con este comando:

    sudo ufw disable

    Si ya configuró reglas de UFW y decide que desea empezar de nuevo, puede utilizar el comando “reset”:

    sudo ufw reset
  • .htaccess EN APACHE (Control, Seguridad y SEO)

    .htaccess EN APACHE (Control, Seguridad y SEO)

    El objetivo de esta práctica es aprender a utilizar archivos .htaccess en un servidor Apache para configurar:

    • Autenticación
    • Gestión de errores
    • Redirecciones
    • Reescritura de URLs
    • Cabeceras de seguridad
    • Control de indexación en buscadores
    • Ocultación y restricción de carpetas
    • Optimización mediante caché y compresión

    Se realizará de forma práctica para observar los efectos directamente.


    Requisitos

    • Apache instalado y funcionando
    • Permisos para editar archivos en /var/www/html/ o carpeta equivalente

    Parte 1: Activación de .htaccess en Apache

    1. Editar el VirtualHost y localizar:
    <Directory /var/www/html>
       AllowOverride None
       Require all granted
    </Directory>
    
    1. Cambiar None por All:
    AllowOverride All
    
    1. Reiniciar Apache:
    sudo systemctl restart apache2
    
    1. Crear un archivo /var/www/html/.htaccess con este contenido:
    AddDefaultCharset UTF-8
    

    Si no hay errores, el .htaccess está funcionando.

    Para editar el VirtualHost típico en Ubuntu/Debian:

    1. Abrir el archivo de sitio por defecto:
    sudo nano /etc/apache2/sites-available/000-default.conf
    
    1. Buscar un bloque <VirtualHost *:80> que contiene algo como:
    <VirtualHost *:80>
        DocumentRoot /var/www/html
        ...
        <Directory /var/www/html>
            Options Indexes FollowSymLinks
            AllowOverride None
            Require all granted
        </Directory>
    </VirtualHost>
    
    1. Aquí vive la línea “AllowOverride” que decide si .htaccess es un ciudadano con derechos o un fantasma ignorado. Cambiar AllowOverride None por AllowOverride All.
    2. Guardar, cerrar y reiniciar Apache:
    sudo systemctl restart apache2
    

    Parte 2: Autenticación Básica con .htaccess

    1. Crear una carpeta /var/www/html/admin/ con un index.html.
    2. Crear /var/www/html/.htpasswd generando un usuario:
    htpasswd -c /var/www/html/.htpasswd admin
    
    1. Crear /var/www/html/admin/.htaccess:
    AuthType Basic
    AuthName "Zona restringida"
    AuthUserFile /var/www/html/.htpasswd
    Require valid-user
    

    Entrar a http://servidor/admin y probar el acceso.

    htpasswd

    htpasswd es una pequeña herramienta de Apache que fabrica archivos de credenciales para la autenticación HTTP básica. Básica significa sin florituras: usuario/contraseña codificados en Base64 y enviados en cabecera; útil para poner una puerta rápida delante de una carpeta, una página de administración o un endpoint casero.

    Funciona generando un fichero (normalmente .htpasswd) con uno o varios usuarios y sus contraseñas hash. Este fichero luego lo consumes desde .htaccess o desde la configuración del VirtualHost.

    1. Abres la terminal en tu servidor.
    2. Ejecutas:
    htpasswd -c /ruta/al/fichero/.htpasswd nombreusuario
    

    El -c crea el fichero. Si ya existe y quieres añadir otro usuario, lo omites:

    htpasswd /ruta/al/fichero/.htpasswd otro_usuario
    

    Al ejecutar, te pedirá contraseña y te la meterá en el fichero con hash. El algoritmo por defecto suele ser bcrypt/MD5 APR según versión; lo importante es que nunca guarda contraseñas en claro.

    Un .htpasswd típico se ve así:

    juan:$apr1$9tDRSv/.v8BxP1kF/Np7A.
    maria:$apr1$OQy4dRxr$2aCdBORded8HNoo.t2GxU.
    

    Luego en .htaccess pones la compuerta:

    AuthType Basic
    AuthName "Zona restringida"
    AuthUserFile /ruta/al/fichero/.htpasswd
    Require valid-user
    

    El navegador, al entrar en esa carpeta, lanzará un cuadro de login del siglo pasado (que sigue cumpliendo su función). En HTTPS está bien para control de acceso simple; en HTTP es como mandar postales sin sobre.

    Parte 3: Gestión de Errores Personalizados

    1. Crear 404.html y 403.html en la raíz.
    2. Añadir en /var/www/html/.htaccess:
    ErrorDocument 404 /404.html
    ErrorDocument 403 /403.html
    
    1. Probar introduciendo una URL inexistente.

    Parte 4: Cabeceras de Seguridad

    Añadir en /var/www/html/.htaccess:

    Header set X-Frame-Options "DENY"
    Header set X-Content-Type-Options "nosniff"
    Header set X-XSS-Protection "1; mode=block"
    Header set Referrer-Policy "no-referrer-when-downgrade"
    Header set Permissions-Policy "geolocation=()"
    

    Explicación breve:

    • X-Frame-Options: DENY Esta prohíbe que tu página se cargue dentro de un <iframe> de otra página. ¿Para qué sirve? Para evitar el clickjacking, un truco donde otra web maliciosa mete la tuya en un iframe invisible y coloca botones encima, de manera que el usuario cree estar haciendo una cosa y está pulsando otra. Con DENY, el navegador dice “no me meto en iframes de nadie” y así se acaba el truco de magia.
    • X-Content-Type-Options: nosniff Los navegadores suelen ser listillos: si reciben un archivo con un tipo incorrecto, intentan adivinarlo (“sniffing MIME”). Eso abre una puerta curiosa: si subes un .png que en realidad es JavaScript con una cabecera errónea, algunos navegadores podrían intentar ejecutarlo. Con nosniff el navegador promete no “oler” el tipo y usar sólo lo declarado. Evita ciertos vectores de XSS y descarga ejecutable camuflada.
    • X-XSS-Protection: 1; mode=block Esto es un modo antiguo del filtro anti-XSS integrado en algunos navegadores. Le indica al navegador que si detecta un ataque de Cross-Site Scripting reflejado, bloquee la carga de la página en vez de intentar sanearla. Hoy en día está un poco de capa caída (Chrome lo retiró en favor de Content-Security-Policy) pero en entornos legacy todavía es un salvavidas aceptable.
    • Referrer-Policy: no-referrer-when-downgrade Cada vez que pulsas un enlace, el navegador suele enviar una cabecera Referer (sin la segunda “r”, por herencia histórica) indicando desde qué página vienes. Esa miguita de pan puede revelar urls privadas, parámetros de sesión o rutas internas. no-referrer-when-downgrade ordena no enviar el Referer cuando pasas de HTTPS a HTTP (es decir, no “degradar” seguridad). Existen políticas más estrictas (strict-origin, no-referrer, etc.), pero esta ya reduce filtraciones triviales.
    • Permissions-Policy: geolocation=() Aquí entramos en una política moderna que controla APIs del navegador. Es como darle a tu web un panel de permisos: cámara, micrófono, geolocalización, sensores… geolocation=() significa “no concedo geolocalización a nadie, ni siquiera a mí”. Puedes ser más granular, por ejemplo geolocation=(self) permitiría sólo a tu propio dominio. Eso reduce el “exceso de curiosidad” del navegador y de scripts de terceros.
    • El resumen conceptual es que no protegen tu código del mal, sino que recortan la superficie de comportamiento del navegador, reduciendo trucos clásicos: iframes invisibles, tipos MIME engañosos, ejecución de scripts inesperados y filtración de metadatos. Es parecido a darle menos herramientas a un niño travieso: no podrá arreglar un coche, pero tampoco desmontar la casa.

    Más allá de estas cabeceras existen otras piezas más finas como Content-Security-Policy (CSP), que es una gramática entera para decir “qué scripts, imágenes, estilos y conexiones están permitidos”. CSP convierte el navegador en una especie de sandbox configurable, y ahí es donde el mundo del XSS moderno se vuelve deporte olímpico.

    Parte 5: Redirecciones HTTP

    1. Redirección permanente (301):
    Redirect 301 /viejo.html /nuevo.html
    
    1. Temporal (302):
    Redirect 302 /promo /promo-2026
    

    Recomendación: usar 301 solo cuando sea definitivo.

    Cuando haces una redirección 302 (Found / Moved Temporarily) estás diciendo dos cosas:

    — Primero: “el recurso sigue existiendo en la URL original, pero por ahora estoy sirviendo desde otra URL”.

    — Segundo: “no actualices tus mapas, no caches esto como definitivo”.

    Consecuencias prácticas:

    1. Los navegadores no la memorizan como algo fijo.
      No guardan en disco que la URL ha cambiado. Si mañana quitas la redirección, el navegador volverá a pedir la original sin pelearse contigo. Es como poner un cartel de “pasen por la puerta lateral mientras pintamos la principal”.
    2. Los buscadores no transfieren ‘peso’ SEO.
      A diferencia de un 301, Google y compañía no asumen que la URL nueva es la buena. Mantienen la original en sus índices. Es la forma de decirles: “no reorganices tu mapa, solo estoy haciendo obras”.
    3. No cambia los enlaces de terceros.
      Si un usuario sigue un enlace desde otra web, la redirección lo mueve, pero esa web no actualizará su enlace, porque no hay garantía de permanencia.
    4. Sirve para pruebas y mantenimiento.
      Si estás desplegando un nuevo diseño, probando un AB testing o moviendo tráfico durante un rato, una 302 te da una especie de reversibilidad instantánea.

    En contraste, un 301 (Moved Permanently) es como una mudanza registrada en el ayuntamiento: los navegadores pueden cachearla, los buscadores actualizan índices y pasan “autoridad” a la nueva URL, y los cambios tardan más en revertirse porque todos asumen que era definitivo.

    Lo temporal no cambia la cartografía del navegador ni del buscador, solo redirige el tráfico en tiempo real. Es útil cuando estás probando algo, cuando tienes dudas o cuando quieres mantener la puerta original como referencia verdadera. Luego, cuando estés seguro de la mudanza, ya haces el 301 y los mapas del mundo cambian de sitio.

    Parte 6: Reescritura de URLs con mod_rewrite

    La reescritura de URLs permite transformar una URL solicitada por el navegador en otra diferente de forma interna, sin que el usuario lo note. Se utiliza para crear URLs más limpias, eliminar extensiones (.php, .html) o implementar un patrón MVC (Front Controller).


    6.1 Activación del módulo

    Activar el módulo responsable de la reescritura:

    sudo a2enmod rewrite
    sudo systemctl restart apache2
    

    Sin este módulo, las reglas de reescritura no funcionarán.


    6.2 Requisito en el VirtualHost

    Dentro del VirtualHost debe estar permitido el uso de .htaccess. En el bloque <Directory> debe existir:

    AllowOverride All
    

    Si estuviera en None, Apache ignorará las reglas del .htaccess.


    6.3 Ejemplo simple: eliminar extensión

    Crear un archivo hola.html en el DocumentRoot (/var/www/html/).

    Crear o editar el .htaccess en el mismo directorio con:

    RewriteEngine On
    RewriteRule ^hola$ hola.html [L]
    

    • RewriteEngine On → activa el motor de reescritura
    • RewriteRule ^hola$ hola.html → si se solicita /hola, entregar hola.html
    • [L] → indica que esta es la última regla si coincide

    Prueba

    Acceder en el navegador:

    http://servidor/hola
    

    Aunque el archivo real sea hola.html, el navegador verá una URL sin extensión.


    6.4 Ejemplo avanzado: patrón MVC (Front Controller)

    Este patrón es común en frameworks y sitios dinámicos. La idea es que todas las peticiones que no sean archivos ni carpetas reales se envían a index.php.

    6.4.1 Código

    En el .htaccess del DocumentRoot:

    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.+)$ index.php?route=$1 [L,QSA]
    

    6.4.2 Explicación de las condiciones

    • RewriteCond %{REQUEST_FILENAME} !-f
      → si lo solicitado no es un archivo físico
    • RewriteCond %{REQUEST_FILENAME} !-d
      → si lo solicitado no es un directorio

    6.4.3 Explicación de la regla

    • ^(.+)$ → coincide con cualquier ruta solicitada
    • index.php?route=$1 → envía la ruta al script index.php mediante el parámetro route
    • [L,QSA]:
      • L → última regla si coincide
      • QSA → preserva parámetros existentes (?id=3 etc.)

    6.5 Demostración práctica

    Crear un archivo index.php con:

    <?php
    echo "Ruta solicitada: " . ($_GET['route'] ?? 'ninguna');
    ?>
    

    Acceder desde el navegador a distintas rutas:

    http://servidor/productos
    http://servidor/usuarios/editar/7
    http://servidor/pepito
    

    Salida esperada:

    Ruta solicitada: productos
    Ruta solicitada: usuarios/editar/7
    Ruta solicitada: pepito
    

    Esto confirma que index.php captura todas las rutas y puede decidir qué controlador o vista cargar.


    6.6 Caso especial: archivos reales

    Si se accede a:

    /style.css
    /logo.png
    /index.php
    

    o cualquier recurso físico, NO pasa por la reescritura porque las condiciones lo impiden:

    RewriteCond %{REQUEST_FILENAME} !-f   → archivo físico
    RewriteCond %{REQUEST_FILENAME} !-d   → directorio físico
    

    De esta forma no se rompe el funcionamiento del sitio.


    6.7 Uso habitual en aplicaciones web

    Este sistema se utiliza para:

    • URLs amigables para SEO
    • Frameworks PHP (Laravel, Symfony, CodeIgniter)
    • Paneles de administración
    • APIs REST
    • Front Controllers (único punto de entrada)

    En lugar de:

    index.php?route=usuarios/listar
    

    se obtiene:

    /usuarios/listar
    

    más limpio y apto para buscadores.

    La reescritura de URLs no cambia el archivo real que se ejecuta, solo traduce internamente la ruta.
    El usuario ve una URL limpia y el servidor recibe una ruta estructurada para procesar.

    Parte 7: Control del Listado de Directorios

    Para evitar que se muestren archivos:

    Options -Indexes
    

    Crear una carpeta sin index.html y comprobar el resultado.


    Parte 8: Forzar HTTPS

    Añadir:

    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    

    Requiere certificado SSL configurado.


    Parte 9: Cacheo y Compresión

    Cache de archivos (si mod_expires activado):

    <IfModule mod_expires.c>
       ExpiresActive On
       ExpiresByType image/jpeg "access plus 30 days"
       ExpiresByType text/css "access plus 7 days"
       ExpiresByType application/javascript "access plus 7 days"
    </IfModule>
    

    Compresión (si mod_deflate activado):

    SetOutputFilter DEFLATE
    

    Cuando decíamos “cache de archivos (si mod_expires activado)” nos referíamos a una función del servidor web Apache diseñada para decirle al navegador cuánto tiempo puede guardar ciertos archivos sin volver a descargarlos.

    En castellano llano:

    La caché es la costumbre del navegador de guardar copias locales de cosas que ya descargó (como imágenes, CSS o JavaScript) para no pedirlas de nuevo al servidor cada vez que visitas la página. Si ya tienes el logo en tu disco, ¿para qué volver a bajarlo?

    El módulo mod_expires es una parte de Apache que permite controlar cuánto dura esa copia local, poniendo un “fecha de caducidad” en las respuestas.

    Si lo activas y configurás reglas como:

    ExpiresByType image/png "access plus 30 days"
    

    Estás diciendo: “los archivos PNG pueden vivir 30 días en la caché del navegador”.

    ¿Resultado práctico? La primera visita carga todo desde el servidor, las siguientes cargan desde disco; la web vuela y el servidor descansa.

    Esencialmente, es un acuerdo temporal entre servidor y navegador, parecido a:

    – Servidor: “Este archivo apenas cambia, guárdalo un mes”.
    – Navegador: “Perfecto, no te molesto hasta que pase ese mes”.

    En el ecosistema web, la caché es una de las razones por las que las páginas parecen “instantáneas” después de la primera visita, y una forma elegante de reducir gasto de CPU, ancho de banda y tiempo de espera. Sin caché, cada visita sería como entrar por primera vez en un supermercado cada día: todo el mundo preguntando todo el rato dónde están los pasillos.

    Parte 10: Interacción con Buscadores (SEO y Indexación)

    robots.txt

    Crear en raíz del sitio:

    User-agent: *
    Disallow: /admin/
    Disallow: /backup/
    

    Nota: los bots maliciosos pueden ignorarlo.

    Evitar indexación con HTTP (X-Robots-Tag)

    En .htaccess:

    Header set X-Robots-Tag "noindex, nofollow"
    

    Usos habituales:

    • PDFs
    • Paneles internos
    • Carpetas privadas

    Bloquear bots por User-Agent

    Ejemplo:

    RewriteEngine On
    RewriteCond %{HTTP_USER_AGENT} googlebot [NC]
    RewriteRule ^ - [R=403]
    

    Parte 11: Ocultación y Restricción de Carpetas

    Impedir acceso web a una carpeta:

    Dentro de la carpeta crear .htaccess:

    Require all denied
    

    O por archivo:

    <FilesMatch "\.(sql|bak|zip|tar)$">
       Require all denied
    </FilesMatch>
    

    Restringir por IP:

    Require ip 192.168.1.0/24
    

    Evitar ejecución de PHP en carpetas de subida:

    <FilesMatch "\.(php|phtml)$">
       Require all denied
    </FilesMatch>
    

    Muy útil en uploads/ o storage/.


    Con .htaccess es posible:

    • Restringir acceso
    • Personalizar errores
    • Crear URLs amigables
    • Controlar bot y rastreadores
    • Proteger información sensible
    • Forzar HTTPS
    • Mejorar SEO
    • Mejorar rendimiento

    Advertencia para producción:

    • .htaccess se evalúa en cada petición
    • Incrementa carga del servidor
    • En grandes entornos se recomienda configurar desde VirtualHost

  • ¿Qué hace systemctl?

    ¿Qué hace systemctl?

    Un servicio es un proceso de fondo (daemon) que se ejecuta sin cliente directo: servidor web, base de datos, cupón/leche… cosas que viven en silencio.

    systemd organiza los servicios como units (unidades). Una unit puede ser:

    • service → servicios
    • timer → programadores sustitutos del cron
    • mount → puntos de montaje
    • socket → servicios socket-activados
    • y más fauna, pero hoy nos interesa el zoológico *.service.

    ¿Qué hace systemctl?

    systemctl permite:

    • Iniciar/detener un servicio.
    • Habilitarlo o deshabilitarlo en arranque.
    • Ver logs y estado.
    • Ver dependencias.

    Su sintaxis general:

    systemctl <acción> <unidad>

    Ejemplo:

    systemctl start apache2.service

    Ver servicios instalados

    Esto ayuda a explorar el sistema:

    Servicios activos ahora mismo:

    
    
    
    
    
    systemctl list-units --type=service --state=running
    

    Todos los servicios cargados (activos + inactivos):

    
    
    
    
    
    systemctl list-units --type=service
    

    Servicios instalados en el sistema (cargados y no cargados):

    
    
    
    
    
    systemctl list-unit-files --type=service
    

    Estado de un servicio

    Es la acción más frecuente.

    
    
    
    
    
    systemctl status apache2.service
    

    Muestra:

    • PID
    • Logs recientes
    • “Loaded” (si está instalado)
    • “Active” (si está corriendo)

    La magia aquí es que systemd integra parte del journal, así que ya da contexto.


    Iniciar / Detener / Reiniciar

    Aquí es donde la clase empieza a levantar humo.

    Iniciar servicio:

    
    
    
    
    
    sudo systemctl start apache2.service
    

    Detener:

    
    
    
    
    
    sudo systemctl stop apache2.service
    

    Reiniciar de forma limpia:

    
    
    
    
    
    sudo systemctl restart apache2.service
    

    Recargar configuración sin detener el servicio (si lo soporta, como Nginx):

    
    
    
    
    
    sudo systemctl reload nginx.service
    

    Para puristas: restart tira y relanza, reload solo recarga configuración.


    Habilitar en el arranque

    Esto conecta systemd con los “targets” (equivalentes modernos de runlevels).

    Habilitar:

    
    
    
    
    
    sudo systemctl enable apache2.service
    

    Deshabilitar:

    
    
    
    
    
    sudo systemctl disable apache2.service
    

    Comprobar si está habilitado:

    
    
    
    
    
    systemctl is-enabled apache2.service
    

    Esto crea o elimina enlaces simbólicos en /etc/systemd/system/.


    Ver logs de un servicio

    journalctl es el diario íntimo del sistema. Útil para debugging y para descubrir que olvidaste escapar ese símbolo en la config de Postfix.

    Logs recientes del servicio:

    
    
    
    
    
    journalctl -u apache2.service
    

    Logs en tiempo real (“modo Matrix”):

    
    
    
    
    
    journalctl -u apache2.service -f
    

    Logs de hoy con timestamps:

    
    
    
    
    
    journalctl -u apache2.service --since today
    

  • Pildora – Panel de control SSH

    Pildora – Panel de control SSH

    1. Glances — El “panel de control” más completo dentro de la terminal

    https://i.ytimg.com/vi/ZwhyLD-wquk/maxresdefault.jpg?utm_source=chatgpt.com
    https://glances.readthedocs.io/en/latest/_images/screenshot-wide.png?utm_source=chatgpt.com

    Instalas, entras por SSH y pam, un dashboard con CPU, RAM, red, procesos, temperaturas… todo dinámico.

    Instalación:

    sudo apt install glances
    glances
    

    Sirve incluso como “panel web” si lo lanzas en modo servidor:

    glances -w
    

    Luego entras desde navegador:
    http://IP:61208


    2. Ytop / Bpytop / Btop — Interfaces brutales

    https://www.both.org/wp-content/uploads/2025/02/btop-08.png?utm_source=chatgpt.com
    https://itsfoss.com/content/images/2025/06/btop-catppuccin-theme.png?utm_source=chatgpt.com
    https://www.tecmint.com/wp-content/uploads/2020/11/Bpytop-Linux-Resource-Monitor-Tool.png?utm_source=chatgpt.com

    Son dashboards animados con gráficas alucinantes.

    Instalación:

    sudo apt install btop
    btop
    

    Experiencia pura de “panel local pero en SSH”.


    3. Ncdu — Panel visual para navegar disco

    https://static.linuxblog.io/wp-content/uploads/2023/11/ncdu-linux.png?utm_source=chatgpt.com
    https://opensource.com/sites/default/files/ncdu-dark.jpg?utm_source=chatgpt.com

    Ver qué ocupa espacio, borrar, entrar en carpetas… todo navegable.

    sudo apt install ncdu
    ncdu /
    

    4. Lazydocker — Un Portainer en la terminal

    https://terminalroot.com/assets/img/docker/lazydocker.jpg?utm_source=chatgpt.com
    https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5As2oxuEBalTJiEDlhbgNdsx_6LuLmKexgePTUNE8veOLWlh_iNJtidR2Opy3dvWHrGSnBKLxGhwwLgMCDygf9nFaedxLJ7TvBaFweyz9BmU_hRmNZkpxbGZZSWxrRPQ_EO6qjON8tzA/w1200-h630-p-k-no-nu/lazydocker-screenshot.png?utm_source=chatgpt.com

    Si tienes Docker, este es tu panel completo: ver contenedores, logs, stats, reiniciar, eliminar…

    Instalación:

    curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash
    lazydocker
    
    
    source ~/.profile
    
    lazydocker


    5. Cockpit (si ya quieres panel web pero gestionado desde SSH)

    https://cockpit-project.org/images/mobilenav-desktop.png?utm_source=chatgpt.com
    https://opensource.com/sites/default/files/uploads/cockpitdashboard.png?utm_source=chatgpt.com

    No es TUI, pero sí un panel web completísimo que se instala por SSH en 30 segundos.

    sudo apt install cockpit
    sudo systemctl enable --now cockpit
    

    Luego entras:
    https://IP:9090


    6. Nmon — Monitor clásico pero potente

    sudo apt install nmon
    nmon
    

    Interfaz retro, pero muy útil para rendimiento.


    EL PANEL “ECORP CONTROL NODE” – estilo Mr. Robot

    Formato TUI, aparece automáticamente al iniciar sesión SSH.


    1. ASCII ART del servidor (para la entrada dramática)

    Pon esto en:
    /etc/motd (o lo generamos desde el script).

         __  ____                ____        _           __ 
        /  |/  (_)___ ____ _    / __ \____  (_)___  ____/ /_
       / /|_/ / / __ `/ _ `/   / /_/ / __ \/ / __ \/ __  / /
      / /  / / / /_/ /  __/   / ____/ /_/ / / / / / /_/ / / 
     /_/  /_/_/\__, /\___/   /_/    \____/_/_/ /_/\__,_/_/  
              /____/             C Y B E R  N O D E           
    

    2. Script principal del panel (dashboard)

    Guárdalo en:
    /usr/local/bin/panel-mrrobot

    Dale permisos:
    sudo chmod +x /usr/local/bin/panel-mrrobot

    Contenido:

    #!/bin/bash
    
    # =============== ASCII HEADER ===============
    clear
    echo "
      ███╗   ███╗██████╗     ██████╗  ██████╗ ██████╗ ██╗   ██╗
      ████╗ ████║██╔══██╗    ██╔══██╗██╔═══██╗██╔══██╗╚██╗ ██╔╝
      ██╔████╔██║██████╔╝    ██║  ██║██║   ██║██████╔╝ ╚████╔╝ 
      ██║╚██╔╝██║██╔══██╗    ██║  ██║██║   ██║██╔═══╝   ╚██╔╝  
      ██║ ╚═╝ ██║██║  ██║    ██████╔╝╚██████╔╝██║        ██║   
      ╚═╝     ╚═╝╚═╝  ╚═╝    ╚═════╝  ╚═════╝ ╚═╝        ╚═╝    
    "
    echo "                  PANEL PRIVADO - MODO MR.ROBOT"
    echo "--------------------------------------------------------------------------------"
    echo
    
    # =============== MENU ===============
    while true; do
      echo "Selecciona una opción:"
      echo "1) Monitor del sistema (btop)"
      echo "2) Dashboard avanzado (glances)"
      echo "3) Uso de disco (ncdu)"
      echo "4) Control Docker (lazydocker)"
      echo "5) Logs en vivo (journalctl -f)"
      echo "6) Escaneo rápido de puertos (nmap localhost)"
      echo "7) Conexiones activas (ss -tunap)"
      echo "8) Salir"
      echo
      read -p "Elige (1-8): " opcion
    
      case $opcion in
        1) btop ;;
        2) glances ;;
        3) sudo ncdu / ;;
        4) lazydocker ;;
        5) sudo journalctl -f ;;
        6) sudo nmap localhost ;;
        7) ss -tunap ;;
        8) exit 0 ;;
        *) echo "Opción inválida. Intenta otra vez." ;;
      esac
    done
    

    3. Hacer que el panel aparezca AUTOMÁTICAMENTE al entrar por SSH

    Edita tu .bashrc del usuario:

    nano ~/.bashrc
    

    Añade al final:

    # Lanzar panel automáticamente en sesión SSH interactiva
    if [ -n "$SSH_CONNECTION" ]; then
        /usr/local/bin/panel-mrrobot
    fi
    

    Guarda, cierra y reconecta por SSH.

    Cuando entres, verás:

    • ASCII art potente
    • Menú visual
    • Acceso rápido a monitorización
    • Logs en vivo
    • Herramientas estilo hacker

    Una consola viva.

  • Conexión SSH segura en Ubuntu

    Conexión SSH segura en Ubuntu

    En el servidor (Ubuntu Server)

    Comprueba que SSH está activo:

    sudo systemctl status ssh

    Si no estuviera activo:

    sudo systemctl enable --now ssh

    Averigua la IP del servidor:

    ip a

    Quédate con algo como 192.168.1.50.

    En el cliente

    • Si el alumno está en Linux/macOS: ya tiene ssh.
    • Si está en Windows: puede usar PowerShell (trae ssh) o Windows Terminal.

    1) Primera conexión “normal” (para ver que funciona)

    En el cliente, conecta:

    ssh usuario@192.168.1.50

    Ejemplo:

    ssh alumno@192.168.1.50

    La primera vez saldrá el aviso de huella:

    • Are you sure you want to continue connecting (yes/no/[fingerprint])?

    Escribe:

    yes

    Mete la contraseña del usuario.

    ✅ Resultado esperado: entras y ves el prompt del servidor.


    2) Crear usuario “de trabajo” y evitar usar root

    En el servidor, crea un usuario nuevo (si no existe):

    sudo adduser operario

    Dale permisos de administración (sudo):

    sudo usermod -aG sudo operario

    Prueba desde el cliente entrar con ese usuario:

    ssh operario@192.168.1.50

    ✅ Objetivo: que el alumno use siempre un usuario normal + sudo, no root.


    3) Generar claves SSH (cliente) y copiarlas (servidor)

    3.1 Generar clave en el CLIENTE

    En el cliente:

    ssh-keygen -t ed25519 -C "operario@lab"

    Cuando pregunte dónde guardarla, ENTER.
    Cuando pregunte passphrase, pon una (recomendado). Ejemplo: ClaveMuySecreta123!

    Esto crea:

    • ~/.ssh/id_ed25519 (privada, NO se comparte)
    • ~/.ssh/id_ed25519.pub (pública, sí se comparte)

    3.2 Copiar clave pública al SERVIDOR

    Desde el cliente:

    ssh-copy-id operario@192.168.1.50

    Luego prueba entrar sin contraseña (solo con passphrase si la pusiste):

    ssh operario@192.168.1.50

    ✅ Resultado esperado: ya no te pide la contraseña del usuario (solo la passphrase de la clave si existe).


    4) Endurecer SSH: desactivar root y contraseñas

    Ahora viene lo serio: si alguien intenta fuerza bruta, no hay contraseña que adivinar.

    En el servidor, edita configuración:

    sudo nano /etc/ssh/sshd_config

    Busca (o añade) estas líneas:

    PermitRootLogin no
    PasswordAuthentication no
    PubkeyAuthentication yes

    Opcional (muy recomendable): restringir a un usuario concreto:

    AllowUsers operario

    Guarda y reinicia SSH:

    sudo systemctl restart ssh

    Prueba crítica (NO saltársela)

    1. Mantén una sesión SSH abierta por si la lías (salvavidas).
    2. Abre otra terminal nueva e intenta entrar:
    ssh operario@192.168.1.50

    ✅ Debe entrar con clave.
    ❌ Si pide contraseña y ya la desactivaste, es que la clave no está bien instalada.


    5) Cambiar el puerto SSH (reduce ruido automático)

    Esto no es “seguridad mágica”, pero quita miles de bots tontos.

    En el servidor:

    sudo nano /etc/ssh/sshd_config

    Cambia o añade:

    Port 2222

    Reinicia:

    sudo systemctl restart ssh

    Ahora para entrar desde cliente:

    ssh -p 2222 operario@192.168.1.50

    6) Activar firewall UFW y permitir solo SSH

    En el servidor:

    sudo ufw allow 2222/tcp
    sudo ufw enable
    sudo ufw status verbose

    ✅ Debe verse permitido el puerto 2222/tcp.


    7) Verificación y “pruebas de ataque” controladas

    7.1 Ver qué está escuchando

    Servidor:

    ss -tulpn | grep ssh

    Debería verse :2222.

    7.2 Probar que root NO entra

    Cliente:

    ssh -p 2222 root@192.168.1.50

    ✅ Debe fallar.

    7.3 Probar que contraseña NO sirve

    Cliente (forzando password):

    ssh -p 2222 -o PreferredAuthentications=password -o PubkeyAuthentication=no operario@192.168.1.50

    ✅ Debe fallar.


    8) Extras opcionales de seguridad (si te da tiempo)

    A) Desactivar acceso por usuario/contraseña en el propio sistema (no solo SSH)

    No siempre interesa en clase, pero es un plus.

    B) Fail2ban (bloquea IPs tras intentos)

    Instalar:

    sudo apt update
    sudo apt install fail2ban -y

    Comprobar:

    sudo systemctl status fail2ban

    Esto es “el portero del garito”: si alguien insiste, lo echa.

  • Activar HTTPS en Apache2 (Ubuntu Server) con certificado autofirmado

    Activar HTTPS en Apache2 (Ubuntu Server) con certificado autofirmado

    1) Activar SSL/TLS en Apache

    Apache en Ubuntu usa módulos. Para HTTPS necesitas ssl.

    sudo a2enmod ssl
    sudo systemctl restart apache2

    Comprueba que el módulo está activo:

    apache2ctl -M | grep ssl

    2) Crear un certificado autofirmado (OpenSSL)

    Vamos a crear:

    • clave privada (key)
    • certificado (crt)

    2.1 Crear carpeta para certificados (ordenadito)

    sudo mkdir -p /etc/apache2/ssl
    sudo chmod 700 /etc/apache2/ssl

    2.2 Generar clave + certificado (válido 365 días)

    Cambia TU_SERVIDOR por un nombre identificable (ej: asir-01, web-lab, o el FQDN si tenéis DNS).

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/apache2/ssl/TU_SERVIDOR.key \
    -out /etc/apache2/ssl/TU_SERVIDOR.crt

    Cuando pregunte por campos, lo importante es:

    • Common Name (CN): poned el nombre o la IP con la que vais a acceder.
      • Si accederéis por IP: poned la IP (ej 192.168.1.50)
      • Si accederéis por nombre: poned ese nombre (ej asir-01.local)

    Verifica que existen:

    sudo ls -l /etc/apache2/ssl/

    3) Crear un VirtualHost HTTPS (443)

    Apache en Ubuntu suele tener el sitio por defecto en /etc/apache2/sites-available/000-default.conf.

    Vamos a crear uno nuevo: https-lab.conf.

    3.1 Crear el archivo del sitio HTTPS

    sudo nano /etc/apache2/sites-available/https-lab.conf

    Pega esto (cambia TU_SERVIDOR y, si quieres, el ServerName):

    <VirtualHost *:443>
        ServerName TU_SERVIDOR
        DocumentRoot /var/www/html
    
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/TU_SERVIDOR.crt
        SSLCertificateKeyFile /etc/apache2/ssl/TU_SERVIDOR.key
    
        ErrorLog ${APACHE_LOG_DIR}/https_error.log
        CustomLog ${APACHE_LOG_DIR}/https_access.log combined
    </VirtualHost>

    Guarda y sal.

    3.2 Habilitar el sitio y comprobar sintaxis

    sudo a2ensite https-lab.conf
    sudo apache2ctl configtest

    Si sale Syntax OK, reinicia:

    sudo systemctl reload apache2

    4) Comprobar que HTTPS funciona

    4.1 Ver que Apache escucha en 443

    sudo ss -lntp | grep ':443'

    4.2 Probar con curl (ignorando el aviso del certificado)

    Sustituye por la IP o nombre real:

    curl -kI https://192.168.1.50/

    Deberías ver algo como:

    • HTTP/1.1 200 OK (o 301/302 si rediriges)
    • cabeceras de Apache

    4.3 Probar desde navegador

    Entrad a:

    • https://IP_DEL_SERVIDOR/

    Saldrá aviso de seguridad (normal con autofirmados). La idea pedagógica: el cifrado funciona, pero el navegador no “confía” en la identidad.


    5) (Opcional) Redirigir HTTP (80) a HTTPS (443)

    Esto hace que todo lo que llegue por http:// vaya a https://.

    5.1 Activar módulo rewrite

    sudo a2enmod rewrite
    sudo systemctl reload apache2

    5.2 Editar el VirtualHost de puerto 80

    Edita el sitio por defecto (o el que uséis en 80):

    sudo nano /etc/apache2/sites-available/000-default.conf

    Dentro del <VirtualHost *:80>, añade esto antes del cierre </VirtualHost>:

    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

    Comprueba y recarga:

    sudo apache2ctl configtest
    sudo systemctl reload apache2

    Prueba:

    curl -I http://192.168.1.50/

    Debería devolver 301 Moved Permanently apuntando a https://....


    6) (Opcional) Endurecer un poco HTTPS (sin volverse loco)

    6.1 Activar HTTP/2 (si está disponible)

    sudo a2enmod http2
    sudo systemctl reload apache2

    En tu https-lab.conf, dentro del VirtualHost 443, añade:

    Protocols h2 http/1.1

    6.2 Cabeceras básicas (seguridad “visible”)

    Activa headers:

    sudo a2enmod headers
    sudo systemctl reload apache2

    Dentro del <VirtualHost *:443> añade:

    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"

    HSTS (solo si vais a usar HTTPS siempre; en lab puede dar guerra si cambiáis):

    Header always set Strict-Transport-Security "max-age=86400"

    7) Logs y troubleshooting (lo que siempre salva vidas)

    7.1 Ver errores de Apache en directo

    sudo tail -f /var/log/apache2/error.log

    7.2 Ver logs del sitio HTTPS

    sudo tail -f /var/log/apache2/https_error.log
    sudo tail -f /var/log/apache2/https_access.log

    7.3 Problemas típicos

    • No abre el 443: firewall/UFW o router/VLAN.
    • Apache no escucha en 443: revisa que ssl esté activo y que el sitio https-lab.conf esté habilitado. sudo a2query -m ssl
      sudo a2query -s https-lab
      sudo apache2ctl -S
    • Certificado no coincide (CN mal): recrea el cert con CN correcto.
    • Permisos: que Apache pueda leer el .crt y .key (en /etc/apache2/ssl suele ir bien con root y lectura adecuada; si te pasas bloqueando, falla).

  • [Reto] – Infraestructura virtualizada con Ubuntu Server

    [Reto] – Infraestructura virtualizada con Ubuntu Server

    El objetivo de esta práctica es diseñar, instalar, configurar y documentar una pequeña infraestructura virtual compuesta por varias máquinas Ubuntu Server conectadas en red local.

    Cada máquina deberá tener una función concreta dentro del sistema y deberá relacionarse con las demás. El alumno tendrá que demostrar conocimientos de instalación de sistemas operativos, virtualización, configuración de red, instalación de servicios, administración del sistema, seguridad, automatización y documentación técnica.

    Requisitos del proyecto

    Debes crear al menos 3 máquinas virtuales Ubuntu Server con IP fija:

    • un servidor web
    • un servidor de base de datos
    • un servidor de administración o mantenimiento

    Debes realizar, como mínimo, las siguientes tareas

    • instalar Ubuntu Server en las máquinas virtuales
    • configurar la red local y las IP fijas
    • instalar y configurar Apache en el servidor web
    • instalar y configurar MySQL o MariaDB en el servidor de base de datos
    • comprobar la comunicación entre el servidor web y el de base de datos
    • administrar servicios con systemctl
    • consultar registros con journalctl
    • aplicar reglas básicas de seguridad con ufw
    • crear scripts Bash de mantenimiento
    • automatizar tareas con cron
    • documentar todo el proceso en un README técnico

    La entrega deberá incluir

    • README.md principal
    • capturas o evidencias organizadas por apartados
    • scripts utilizados
    • archivos de configuración relevantes
    • comprobaciones finales de funcionamiento

    Importante

    No se valorará únicamente que “funcione”, sino que el trabajo esté bien explicado, justificado y documentado. Cada apartado debe mostrar comandos, explicación de su uso, resultado obtenido y evidencias del funcionamiento.

    Objetivos didácticos

    Con este proyecto el alumno deberá demostrar que sabe:

    • Crear y configurar máquinas virtuales
    • Instalar Ubuntu Server
    • Asignar IP fija a cada máquina
    • Configurar red local entre máquinas
    • Instalar y administrar servicios como:
      • Apache o Nginx
      • MySQL o MariaDB
    • Gestionar servicios con systemctl
    • Consultar registros con journalctl
    • Configurar reglas básicas de seguridad con ufw
    • Crear scripts Bash para tareas de mantenimiento
    • Programar tareas automáticas con cron
    • Verificar conectividad y dependencias entre sistemas
    • Documentar de forma técnica el trabajo realizado

    Propuesta de arquitectura

    ┌─────────────────────────────────────────────────────────────┐
    │                 ENTORNO DE VIRTUALIZACIÓN                   │
    │         (VirtualBox / VMware / Proxmox / similar)           │
    └─────────────────────────────────────────────────────────────┘
                               │
                               ▼
    ┌─────────────────────────────────────────────────────────────┐
    │                  RED LOCAL VIRTUALIZADA                     │
    │                     192.168.50.0/24                         │
    └─────────────────────────────────────────────────────────────┘
            │                         │                         │
            ▼                         ▼                         ▼
    
    ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
    │      web01      │     │      db01       │     │     admin01     │
    │ 192.168.50.10   │     │ 192.168.50.20   │     │ 192.168.50.30   │
    ├─────────────────┤     ├─────────────────┤     ├─────────────────┤
    │ Ubuntu Server   │     │ Ubuntu Server   │     │ Ubuntu Server   │
    │ Apache / HTTP   │     │ MySQL / MariaDB │     │ SSH / Scripts   │
    │ Página web      │     │ Base de datos   │     │ Cron / Control  │
    └─────────────────┘     └─────────────────┘     └─────────────────┘
            │                         ▲                         │
            │ consulta datos          │                         │
            └─────────────────────────┘                         │
                      conexión remota                           │
                                                                │
                                                                │ administración,
                                                                │ comprobación,
                                                                │ mantenimiento
                                                                ▼
                                            ┌──────────────────────────────┐
                                            │  Scripts + logs + cron +     │
                                            │      comprobaciones          │
                                            └──────────────────────────────┘

    Para que el proyecto tenga sentido, conviene que las máquinas tengan relación entre sí.

    Máquina 1: servidor web

    • Nombre: web01
    • IP fija: 192.168.1.10
    • Servicios:
      • Apache2
      • Página web de prueba
    • Función:
      • Servir una web que muestre información del sistema
      • Conectarse a la base de datos remota para validar que existe comunicación

    Máquina 2: servidor de base de datos

    • Nombre: db01
    • IP fija: 192.168.1.20
    • Servicios:
      • MySQL Server o MariaDB
    • Función:
      • Alojar una base de datos
      • Permitir conexión desde web01
      • Tener usuarios y permisos configurados

    Máquina 3: servidor de administración / monitorización básica

    • Nombre: admin01
    • IP fija: 192.168.1.30
    • Servicios y funciones:
      • Acceso por SSH a las otras máquinas
      • Scripts de mantenimiento
      • Tareas programadas por cron
      • Recolección de información del sistema
    • Función:
      • Ejecutar scripts
      • Hacer comprobaciones de red
      • Centralizar tareas administrativas básicas

    Relación de dependencia entre máquinas

    • web01 depende de db01 porque debe conectarse a la base de datos remota
    • admin01 depende de web01 y db01 porque debe administrarlas o comprobar su estado
    • todas deben estar en la misma red local virtual y responder entre sí
    graph TD
        A[Entorno de virtualización] --> B[Red local virtual 192.168.50.0/24]
    
        B --> C[web01<br>192.168.50.10<br>Ubuntu Server<br>Apache]
        B --> D[db01<br>192.168.50.20<br>Ubuntu Server<br>MySQL / MariaDB]
        B --> E[admin01<br>192.168.50.30<br>Ubuntu Server<br>SSH / Scripts / Cron]
    
        C -->|Consulta remota| D
        E -->|Administración y comprobación| C
        E -->|Administración y comprobación| D
    
        C --> F[Servicio web activo]
        D --> G[Base de datos activa]
        E --> H[Scripts de mantenimiento]
        E --> I[Tareas automáticas con cron]
        E --> J[Comprobación de logs y servicios]
    
        C --> K[UFW]
        D --> K
        E --> K
    
        F --> L[Documentación README]
        G --> L
        H --> L
        I --> L
        J --> L
        K --> L

    Requisitos mínimos del proyecto

    El alumno deberá cumplir, como mínimo, lo siguiente:

    Virtualización

    • Crear 3 máquinas virtuales
    • Asignar recursos coherentes
    • Instalar Ubuntu Server en todas

    Red

    • Configurar una red local virtual
    • Asignar IP fija a cada máquina
    • Verificar conectividad con ping

    Servicios

    • Instalar Apache en web01
    • Instalar MySQL o MariaDB en db01
    • Comprobar que el servicio web funciona desde navegador o con curl
    • Comprobar que la base de datos acepta conexiones

    Administración

    • Usar comandos de terminal durante todo el proyecto
    • Gestionar servicios con systemctl
    • Consultar logs con journalctl

    Seguridad

    • Activar y configurar ufw
    • Permitir solo los puertos necesarios
    • Explicar qué puertos se abren y por qué

    Automatización

    • Crear al menos 2 scripts Bash
    • Programar al menos 2 tareas con cron

    Fases del proyecto

    flowchart TD
        A[Planificación] --> B[Virtualización]
        B --> C[Instalación de sistemas]
        C --> D[Configuración de red]
        D --> E[Conectividad]
    
        E --> F[Servidor web]
        E --> G[Servidor de base de datos]
    
        F --> H[Comunicación entre servicios]
        G --> H
    
        H --> I[Administración de servicios]
        I --> J[Revisión de logs]
        J --> K[Seguridad con UFW]
        K --> L[Scripts de mantenimiento]
        L --> M[Tareas automáticas con cron]
        M --> N[Pruebas finales]
        N --> O[Documentación README y evidencias]

    Fase 1. Creación de la infraestructura virtual

    Tareas

    1. Instalar el software de virtualización
      • VirtualBox, VMware o similar
    2. Crear 3 máquinas virtuales
    3. Asignar nombre a cada una
    4. Instalar Ubuntu Server en cada una

    Evidencias obligatorias

    • Captura del software de virtualización mostrando las 3 máquinas
    • Captura del proceso de instalación o del sistema ya instalado
    • Tabla con nombre, RAM, disco y función de cada VM

    Qué debe explicar en el README

    • Qué programa de virtualización ha utilizado
    • Qué recursos ha asignado a cada VM
    • Por qué ha organizado así la infraestructura

    Fase 2. Configuración de red

    Tareas

    1. Configurar red local entre las máquinas
    2. Asignar IP fija a cada sistema
    3. Comprobar conectividad

    Ejemplo de tabla de red

    MáquinaIPMáscaraPuerta de enlaceFunción
    web01192.168.50.10255.255.255.0192.168.50.1 o vacía si no aplicaWeb
    db01192.168.50.20255.255.255.0192.168.50.1 o vacía si no aplicaBD
    admin01192.168.50.30255.255.255.0192.168.50.1 o vacía si no aplicaAdministración

    Comprobaciones que deben hacer

    • ip a
    • hostnamectl
    • ping entre máquinas

    Evidencias obligatorias

    • Archivo de configuración de red o capturas del mismo
    • Resultado de ip a
    • Resultado de pings exitosos entre las máquinas

    Qué debe explicar en el README

    • Cómo ha configurado la IP fija
    • Qué problemas encontró
    • Cómo comprobó que la red funciona

    Fase 3. Instalación y configuración del servidor web

    Tareas

    En web01:

    1. Instalar Apache2
    2. Arrancar y habilitar el servicio
    3. Crear una página de prueba
    4. Comprobar acceso desde la propia máquina y desde otra

    Comandos que deberían usar

    sudo apt update
    sudo apt install apache2 -y
    sudo systemctl enable apache2
    sudo systemctl start apache2
    sudo systemctl status apache2

    Página mínima sugerida

    Una página HTML que muestre:

    • nombre del servidor
    • IP
    • fecha
    • descripción del proyecto

    Evidencias obligatorias

    • Captura de systemctl status apache2
    • Captura del navegador o curl http://192.168.50.10
    • Captura del contenido de la página web

    Qué debe explicar en el README

    • Qué hace Apache
    • Dónde se encuentra el directorio web
    • Cómo ha comprobado que el servicio está funcionando

    Fase 4. Instalación y configuración del servidor de base de datos

    Tareas

    En db01:

    1. Instalar MySQL o MariaDB
    2. Habilitar y arrancar el servicio
    3. Crear una base de datos
    4. Crear un usuario con permisos
    5. Permitir acceso desde web01

    Posible estructura

    • Base de datos: empresa
    • Tabla: servicios
    • Usuario remoto: webuser

    Evidencias obligatorias

    • Captura de systemctl status mysql
    • Captura del acceso al cliente MySQL
    • Captura o volcado SQL con creación de base y usuario

    Qué debe explicar en el README

    • Qué motor ha instalado
    • Qué usuario creó y con qué permisos
    • Qué diferencia hay entre usuario local y remoto
    • Cómo ha validado la conexión

    Fase 5. Comunicación entre servidor web y servidor de base de datos

    Aquí está la gracia del invento. No queremos máquinas decorativas.

    Tareas

    Desde web01:

    1. Comprobar conectividad con db01
    2. Instalar cliente MySQL si hace falta
    3. Conectarse a la base de datos remota
    4. Insertar o consultar datos

    Evidencias obligatorias

    • ping 192.168.50.20
    • conexión por cliente a MySQL remoto
    • captura de consulta SQL exitosa

    Qué debe explicar en el README

    • Por qué web01 depende de db01
    • Qué configuración fue necesaria para permitir el acceso remoto
    • Qué medidas de seguridad tomó

    Fase 6. Gestión de servicios y logs

    Tareas

    En las distintas máquinas:

    1. Consultar el estado de Apache y MySQL
    2. Reiniciar y detener servicios
    3. Ver logs con journalctl

    Comandos mínimos que deben demostrar

    sudo systemctl status apache2
    sudo systemctl restart apache2
    sudo systemctl stop apache2
    sudo systemctl start apache2
    journalctl -u apache2
    journalctl -u mysql
    journalctl -xe

    Evidencias obligatorias

    • Captura de systemctl status
    • Captura de journalctl -u apache2
    • Captura de journalctl -u mysql o equivalente

    Qué debe explicar en el README

    • Qué diferencia hay entre iniciar, parar, reiniciar y habilitar un servicio
    • Para qué sirve journalctl
    • Qué información útil encontró en los logs

    Fase 7. Seguridad básica con UFW

    Tareas del alumno

    En cada máquina:

    1. Instalar o activar ufw
    2. Definir política básica
    3. Abrir solo los puertos necesarios

    Ejemplo

    • web01: permitir 22 y 80
    • db01: permitir 22 y 3306 solo si procede
    • admin01: permitir 22

    Comandos orientativos

    sudo ufw enable
    sudo ufw status verbose
    sudo ufw allow 22/tcp
    sudo ufw allow 80/tcp
    sudo ufw allow 3306/tcp

    Evidencias obligatorias

    • Captura de ufw status verbose
    • Explicación de qué puertos se han abierto
    • Justificación de seguridad

    Qué debe explicar en el README

    • Qué es un firewall
    • Qué puertos necesita cada máquina
    • Qué riesgos existirían si se abrieran más puertos de la cuenta

    Fase 8. Scripts de mantenimiento

    Tareas

    Crear al menos dos scripts Bash.

    Script 1: comprobación del sistema

    Debe mostrar:

    • hostname
    • IP
    • uso de disco
    • uso de memoria
    • fecha
    • estado de un servicio

    Script 2: copia de logs o informe de mantenimiento

    Debe:

    • crear una carpeta de copias o informes
    • guardar fecha y hora
    • copiar un log o generar un resumen del sistema a un archivo

    Ejemplo de ideas

    • check_web.sh
    • backup_logs.sh
    • estado_sistema.sh

    Evidencias obligatorias

    • Código de los scripts
    • Captura de ejecución
    • Explicación línea por línea o por bloques

    Qué debe explicar en el README

    • Para qué sirve cada script
    • Cómo se ejecuta
    • Qué permisos necesita
    • Qué salida genera

    Fase 9. Automatización con cron

    Tareas

    Programar al menos dos tareas automáticas:

    • una para ejecutar un script de mantenimiento
    • otra para generar un informe o copia

    Comandos esperados

    crontab -e
    crontab -l

    Evidencias obligatorias

    • Captura de crontab -l
    • Captura o prueba del archivo generado por cron
    • Explicación del formato del cron

    Qué debe explicar en el README

    • Qué tarea automatizó
    • Cada cuánto se ejecuta
    • Cómo verificó que realmente se ejecutó


    Plantilla de README

    Puedes darles esta estructura para obligarles a documentar bien.

    # Proyecto: infraestructura virtualizada con Ubuntu Server
    
    ## 1. Datos del alumno
    - Nombre:
    - Curso:
    - Módulo:
    - Fecha:
    
    ## 2. Introducción
    Explica brevemente en qué consiste el proyecto y cuáles son sus objetivos.
    
    ## 3. Diseño de la infraestructura
    ### 3.1 Máquinas virtuales creadas
    | Máquina | Función | IP | Sistema operativo |
    |---|---|---|---|
    
    ### 3.2 Relación entre máquinas
    Explica cómo se comunican y de qué depende cada una.
    
    ## 4. Instalación de Ubuntu Server
    Describe el proceso de creación e instalación de cada máquina virtual.
    
    ### Evidencias
    - Capturas
    - Configuración asignada
    - Observaciones
    
    ## 5. Configuración de red
    Explica cómo configuraste la IP fija en cada máquina.
    
    ### Comandos utilizados
    ~~~bash
    ip a
    ping

    Estructura de entrega recomendada

    Puedes utilizar esta estructura para la documentación:

    proyecto/
    │
    ├── README.md
    ├── evidencias/
    │   ├── 01-virtualizacion/
    │   ├── 02-red/
    │   ├── 03-web/
    │   ├── 04-bd/
    │   ├── 05-seguridad/
    │   ├── 06-scripts/
    │   └── 07-cron/
    │
    ├── scripts/
    │   ├── check_web.sh
    │   └── backup_logs.sh
    │
    ├── configuracion/
    │   ├── netplan-web01.yaml
    │   ├── netplan-db01.yaml
    │   └── netplan-admin01.yaml
    │
    └── sql/
        └── bd_inicial.sql

    Evidencias que puedes incluir en la documentación

    (capturas y explicación)

    Instalación y configuración de Apache

    Explica la instalación del servidor web en web01.

    Comandos utilizados

    sudo apt update
    sudo apt install apache2 -y

    Verificación

    Explica cómo comprobaste que funciona.

    Instalación y configuración de MySQL/MariaDB

    Explica la instalación del servidor de base de datos en db01.

    Comandos utilizados

    sudo apt install mysql-server -y

    Verificación

    Explica cómo comprobaste que funciona.

    Comunicación entre servicios

    Explica cómo el servidor web accede al servidor de base de datos.

    Pruebas realizadas

    • ping
    • conexión remota
    • consulta SQL

    Gestión de servicios con systemctl

    Explica qué comandos usaste para iniciar, parar, reiniciar y habilitar servicios.

    Consulta de logs con journalctl

    Indica qué logs revisaste y qué información encontraste.

    Seguridad con UFW

    Explica qué reglas configuraste y por qué.

    Scripts de mantenimiento

    Script 1

    • Nombre:
    • Función:
    • Código:
    • Resultado:

    Script 2

    • Nombre:
    • Función:
    • Código:
    • Resultado:

    Tareas programadas con cron

    Explica qué tareas automatizaste y cómo las comprobaste.

    Comprobaciones finales

    Incluye evidencias de:

    • IP fija
    • conectividad entre máquinas
    • Apache funcionando
    • MySQL funcionando
    • firewall activo
    • scripts funcionando
    • cron funcionando

    Problemas encontrados y soluciones

    Describe los errores o dificultades y cómo los resolviste.

    Cómo verificar que realmente ha hecho el trabajo

    Esto es clave. Hay que pedir pruebas que huelan a trabajo real y no a “copié cuatro cosas de internet y recé”. Para demostrar que es una implementación real, puedes ir incluyendo en la documentación (Donde toque) el resultado de algunso comandos.

    Identificación del sistema

    En cada máquina:

    hostnamectl
    ip a
    lsb_release -a

    Estado de servicios

    systemctl status apache2
    systemctl status mysql

    Logs reales

    journalctl -u apache2 --no-pager | tail -n 20
    journalctl -u mysql --no-pager | tail -n 20

    Firewall

    sudo ufw status verbose

    Cron

    crontab -l

    Scripts

    Ejecutar los scripts y mostrar salida:

    bash check_web.sh
    bash backup_logs.sh

    Red

    ping -c 4 192.168.50.20
    ping -c 4 192.168.50.10

    Web

    Desde otra máquina:

    curl http://192.168.50.10

    Base de datos

    Desde web01:

    mysql -h 192.168.50.20 -u webuser -p