>_
Terminal
🏴‍☠️
Mini CTF
📊
Activity
📅
Events
guest@dsr: ~
guest@dsr:~$ ./welcome.sh
guest@dsr:~$ cat vaya_servidor.md
Última modificación: 06-04-2026

Vaya servidor…

Justo me voy de Semana Santa, una semana entera, Dejo los servidores bien puestos, con un reinicio fresco, y todo funciona perfecto. Ese mismo día por la noche me llega este correo:

image.png

Y todo deja de estar disponible. Empiezo a investigar y todo el acceso remoto lo he perdido. La VPN y los túneles de Cloudflared estaban ahí. Y no hay manera de que pueda acceder a casa para saber cómo están las cosas.

Mi padre tiene el nuevo NAS UGREEN DH2300, pero no puedo conseguir una shell remota. Lo que sí veo es que puedo instalar Docker, pero sigo sin poder conseguir una shell remota.

image.png

Con docker instalado, puedo descargar una imagen de ubuntu y iniciar el contenedor.

image.png

Puedo iniciar una shell para ver si puedo hacer ping al portátil. No responde, pero es verdad que, por defecto, Proxmox rechaza los paquetes ICMP. Así que lo comprobamos con ARP y vemos que sí obtenemos una respuesta. Es decir, Proxmox está funcionando, pero como todos los contenedores están apagados, no podemos acceder a él.

image.png

Tampoco podemos acceder por SSH, así que se ha quedado totalmente bloqueado. Se ha quedado en proceso de apagado y está conectado y encendido, pero con todos los servicios apagados.

El otro nodo sí que vemos que está activo y puedo acceder por SSH a él. En este punto, descargo una plantilla de Ubuntu 25.05 para instalar Cloudflared y ver si podemos acceder a la GUI de Proxmox. Y lo conseguimos.

Sin embargo, el portátil está totalmente inutilizable. Solo queda esperar a volver a casa para ver qué ha pasado: si se ha quemado el SSD y por eso se ha quedado bloqueado, o si ha ocurrido otra cosa.

Una semana después, llego a casa y, según me voy acercando, empieza a sonar un ruido raro. Algo que arranca lo intenta y se para. Al principio pienso que es el disco duro secundario, que se haya estropeado la cabeza lectora y por eso suena ese clic.

Fuerzo el apagado con el botón, dejo que se enfríe porque estaba muy, muy caliente y lo vuelvo a encender. Empiezo a pensar que es posible que sea el ventilador. Eso explicaría la temperatura excesiva del ordenador, así como el correo de alerta crítica de temperatura en el disco.

Y así era: una vez enciendo el ordenador, a pesar de que suene, Proxmox arranca. Obtengo la shell y veo que ambos almacenamientos están funcionando. Cuando abro la tapa, el ventilador empieza a girar, roza y se para. Los muelles del ventilador parece que se han descolgado y por eso no funciona.

Tiene todo el sentido que haya pasado esto. El ordenador lleva encendido 24/7, los 365 días, durante 2 años seguidos. Es normal que un ventilador de portátil deje de funcionar.

Toca pedir un recambio de ventiladores y, ya que estamos, cambiamos la pasta térmica.

Mientras tanto, mientras hago la migración de servicios importantes, vamos a poner una base refrigerada con ventiladores y vamos a montarnos un script para que lea los datos de los sensores con el comando sensors:

root@proxmox:~# sensors
pch_cannonlake-virtual-0
Adapter: Virtual device
temp1:        +60.0°C

nvme-pci-0600
Adapter: PCI adapter
Composite:    +48.9°C  (low  =  -0.1°C, high = +80.8°C)
                       (crit = +81.8°C)
Sensor 1:     +48.9°C  (low  = -273.1°C, high = +65261.8°C)
Sensor 2:     +48.9°C  (low  = -273.1°C, high = +65261.8°C)

iwlwifi_1-virtual-0
Adapter: Virtual device
temp1:            N/A

coretemp-isa-0000
Adapter: ISA adapter
Package id 0:  +55.0°C  (high = +100.0°C, crit = +100.0°C)
Core 0:        +54.0°C  (high = +100.0°C, crit = +100.0°C)
Core 1:        +53.0°C  (high = +100.0°C, crit = +100.0°C)
Core 2:        +53.0°C  (high = +100.0°C, crit = +100.0°C)
Core 3:        +52.0°C  (high = +100.0°C, crit = +100.0°C)
Core 4:        +54.0°C  (high = +100.0°C, crit = +100.0°C)
Core 5:        +52.0°C  (high = +100.0°C, crit = +100.0°C)

BAT0-acpi-0
Adapter: ACPI interface
in0:          12.72 V

Vamos a montar un script que lea los datos actuales de temperatura y, si supera un umbral, me notifique por un webhook de Discord.

#!/bin/bash

# ============================================================
# monitor_temps.sh — Monitorización de temperatura en Proxmox
# Envía alertas a Discord cuando se superan umbrales de aviso
# ============================================================

DISCORD_WEBHOOK="https://discord.com/api/webhooks/1490637687038808095/gwrQx_enYLyanPX5FHeEl91B3qc9LOfJDRlpSWsQmgsu2kzwZmbT0wLVxBfv6bJSJHVt"
SSH_HOST="proxmox"
INTERVAL="${INTERVAL:-60}"  # segundos entre comprobaciones

# --- Umbrales de aviso (°C) ---
# Se avisa bastante antes de los límites críticos del hardware
THRESH_CPU=70        # CPU cores: crítico en 100°C
THRESH_NVME=60       # NVMe SSD: crítico en 81.8°C
THRESH_PCH=65        # PCH: sin límite declarado, conservador

# --- Cooldown entre alertas del mismo sensor (segundos) ---
COOLDOWN=300         # 5 minutos para no spamear

# Directorio temporal para guardar estado de cooldown
STATE_DIR="${TMPDIR:-/tmp}/proxmox_monitor"
mkdir -p "$STATE_DIR"

# ============================================================
usage() {
    echo "Uso: DISCORD_WEBHOOK='https://discord.com/api/webhooks/...' $0 [--once]"
    echo ""
    echo "  --once   Comprueba una sola vez y sale (útil para cron)"
    echo ""
    echo "Variables de entorno:"
    echo "  DISCORD_WEBHOOK  URL del webhook de Discord (obligatorio)"
    echo "  INTERVAL         Segundos entre comprobaciones (default: 60)"
    exit 1
}

# ============================================================
send_discord_alert() {
    local sensor="$1"
    local temp="$2"
    local threshold="$3"
    local level="$4"   # WARNING o CRITICAL

    local color
    local emoji
    if [[ "$level" == "CRITICAL" ]]; then
        color=15158332   # rojo
        emoji="🔴"
    else
        color=16776960   # amarillo
        emoji="🟡"
    fi

    local hostname
    hostname=$(ssh -o ConnectTimeout=10 "$SSH_HOST" hostname 2>/dev/null || echo "$SSH_HOST")

    local payload
    payload=$(cat <<EOF
{
  "embeds": [{
    "title": "${emoji} Alerta de temperatura — ${hostname}",
    "color": ${color},
    "fields": [
      {"name": "Sensor",      "value": "\`${sensor}\`",       "inline": true},
      {"name": "Temperatura", "value": "\`${temp}°C\`",       "inline": true},
      {"name": "Umbral",      "value": "\`${threshold}°C\`",  "inline": true},
      {"name": "Nivel",       "value": "${level}",            "inline": true},
      {"name": "Posible causa", "value": "Ventilador de GPU desconectado — revisar físicamente el portátil", "inline": false}
    ],
    "footer": {"text": "monitor_temps.sh • $(date '+%Y-%m-%d %H:%M:%S')"}
  }]
}
EOF
)

    curl -s -o /dev/null -w "%{http_code}" \
        -H "Content-Type: application/json" \
        -d "$payload" \
        "$DISCORD_WEBHOOK" > /dev/null
}

# ============================================================
check_cooldown() {
    local sensor_key="$1"
    local state_file="$STATE_DIR/${sensor_key//[^a-zA-Z0-9]/_}"
    local now
    now=$(date +%s)

    if [[ -f "$state_file" ]]; then
        local last
        last=$(cat "$state_file")
        if (( now - last < COOLDOWN )); then
            return 1  # en cooldown, no alertar
        fi
    fi

    echo "$now" > "$state_file"
    return 0
}

# ============================================================
parse_and_check() {
    local sensors_output="$1"
    local alerts=()

    # Extraer temperaturas con regex
    # Formato: "Label:   +XX.X°C"
    while IFS= read -r line; do

        # CPU cores y Package
        if [[ "$line" =~ ^(Package\ id\ 0|Core\ [0-9]+):[[:space:]]+\+([0-9]+\.[0-9]+)°C ]]; then
            local label="${BASH_REMATCH[1]}"
            local temp="${BASH_REMATCH[2]}"
            local temp_int="${temp%.*}"

            if (( temp_int >= THRESH_CPU )); then
                local level="WARNING"
                (( temp_int >= 85 )) && level="CRITICAL"
                if check_cooldown "cpu_${label// /_}"; then
                    alerts+=("${label}|${temp}|${THRESH_CPU}|${level}")
                fi
            fi

        # NVMe Composite
        elif [[ "$line" =~ ^Composite:[[:space:]]+\+([0-9]+\.[0-9]+)°C ]]; then
            local temp="${BASH_REMATCH[1]}"
            local temp_int="${temp%.*}"

            if (( temp_int >= THRESH_NVME )); then
                local level="WARNING"
                (( temp_int >= 75 )) && level="CRITICAL"
                if check_cooldown "nvme_composite"; then
                    alerts+=("NVMe Composite|${temp}|${THRESH_NVME}|${level}")
                fi
            fi

        # PCH
        elif [[ "$line" =~ ^temp1:.*\+([0-9]+\.[0-9]+)°C ]]; then
            local temp="${BASH_REMATCH[1]}"
            local temp_int="${temp%.*}"
            # Solo el PCH (pch_cannonlake), no iwlwifi que puede ser N/A
            if (( temp_int >= THRESH_PCH )); then
                local level="WARNING"
                (( temp_int >= 80 )) && level="CRITICAL"
                if check_cooldown "pch_temp1"; then
                    alerts+=("PCH temp1|${temp}|${THRESH_PCH}|${level}")
                fi
            fi
        fi

    done <<< "$sensors_output"

    # Enviar alertas
    for alert in "${alerts[@]}"; do
        IFS='|' read -r sensor temp threshold level <<< "$alert"
        echo "[$(date '+%H:%M:%S')] ALERTA ${level}: ${sensor} = ${temp}°C (umbral: ${threshold}°C)"
        if [[ -n "$DISCORD_WEBHOOK" ]]; then
            send_discord_alert "$sensor" "$temp" "$threshold" "$level"
        else
            echo "  (DISCORD_WEBHOOK no configurado, alerta no enviada)"
        fi
    done

    if [[ ${#alerts[@]} -eq 0 ]]; then
        echo "[$(date '+%H:%M:%S')] OK — todas las temperaturas dentro del rango"
    fi
}

# ============================================================
run_check() {
    local sensors_output
    sensors_output=$(ssh -o ConnectTimeout=10 -o BatchMode=yes "$SSH_HOST" sensors 2>&1)
    local exit_code=$?

    if [[ $exit_code -ne 0 ]]; then
        echo "[$(date '+%H:%M:%S')] ERROR: no se pudo conectar a '${SSH_HOST}' (exit ${exit_code})"
        if [[ -n "$DISCORD_WEBHOOK" ]] && check_cooldown "ssh_error"; then
            local payload
            payload=$(cat <<EOF
{
  "embeds": [{
    "title": "🔴 Error de conexión SSH — ${SSH_HOST}",
    "color": 15158332,
    "description": "No se puede conectar al servidor para leer temperaturas.\n\`\`\`${sensors_output}\`\`\`",
    "footer": {"text": "monitor_temps.sh • $(date '+%Y-%m-%d %H:%M:%S')"}
  }]
}
EOF
)
            curl -s -o /dev/null -H "Content-Type: application/json" -d "$payload" "$DISCORD_WEBHOOK"
        fi
        return 1
    fi

    parse_and_check "$sensors_output"
}

# ============================================================
# Main
# ============================================================

ONCE=false
for arg in "$@"; do
    case "$arg" in
        --once) ONCE=true ;;
        --help|-h) usage ;;
        *) echo "Argumento desconocido: $arg"; usage ;;
    esac
done

if [[ -z "$DISCORD_WEBHOOK" ]]; then
    echo "AVISO: DISCORD_WEBHOOK no está definido. Las alertas solo se mostrarán por consola."
    echo "       Exporta la variable o pásala así:"
    echo "       DISCORD_WEBHOOK='https://discord.com/api/webhooks/...' $0"
    echo ""
fi

echo "=== Monitor de temperatura Proxmox ==="
echo "Host SSH   : $SSH_HOST"
echo "Umbral CPU : ${THRESH_CPU}°C"
echo "Umbral NVMe: ${THRESH_NVME}°C"
echo "Umbral PCH : ${THRESH_PCH}°C"
echo "Cooldown   : ${COOLDOWN}s"
[[ "$ONCE" == false ]] && echo "Intervalo  : ${INTERVAL}s"
echo ""

if $ONCE; then
    run_check
else
    while true; do
        run_check
        sleep "$INTERVAL"
    done
fi

Sin embargo, después de un tiempo veo que me envía notificaciones diciendo que toda la CPU está a 100 °C, y me parece imposible porque cuando ejecuto sensors manualmente, la temperatura no llega a 50 °C.

Efectivamente, la expresión regular no lo estaba capturando bien. Así que la cambiamos para que, esta vez sí, solo mire la primera temperatura que aparece:

[...]
if [[ "$line" =~ ^(Package\ id\ 0|Core\ [0-9]+):[[:space:]]+\+([0-9]+\.[0-9]+)°C ]]; then
[...]
elif [[ "$line" =~ ^Composite:[[:space:]]+\+([0-9]+\.[0-9]+)°C ]]; then
[...]

Ahora sí nos notifica de manera correcta y vemos que las temperaturas están controladas.


<< cd ..

HackSimulator - Mini CTF

Top Hackers

  1. Loading...

OSINT Mini CTF

This is a timed competition. Your goal is to find all 4 flag fragments scattered across the simulated system using OSINT techniques.

Once you start, the timer will begin. Good luck.

Activity Monitor
Process Name ↕ % CPU ↓ % Memory ↕ Action

CPU 0.0%

30s history

Memory 0.0%

30s history
— processes CPU avg: — RAM avg: —
Events

Loading events...

>_
🏴‍☠️
📊
📅