#!/bin/bash

# ============================================================
#   VPS HARDENING - Auto Security Script v3.0
#   OS      : AlmaLinux 9 / Ubuntu 22 / Ubuntu 24
#   Author  : IKYY x CLAUDE
#   Version : 3.0 (Universal Fix)
# ============================================================

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

clear
echo -e "${CYAN}${BOLD}"
echo "  ██╗██╗  ██╗██╗   ██╗██╗   ██╗    ██╗  ██╗     ██╗  ██╗ █████╗ ██████╗ ██████╗ ███████╗███╗   ██╗"
echo "  ██║██║ ██╔╝╚██╗ ██╔╝╚██╗ ██╔╝    ╚██╗██╔╝     ██║  ██║██╔══██╗██╔══██╗██╔══██╗██╔════╝████╗  ██║"
echo "  ██║█████╔╝  ╚████╔╝  ╚████╔╝      ╚███╔╝      ███████║███████║██████╔╝██║  ██║█████╗  ██╔██╗ ██║"
echo "  ██║██╔═██╗   ╚██╔╝    ╚██╔╝       ██╔██╗      ██╔══██║██╔══██║██╔══██╗██║  ██║██╔══╝  ██║╚██╗██║"
echo "  ██║██║  ██╗   ██║      ██║       ██╔╝ ██╗     ██║  ██║██║  ██║██║  ██║██████╔╝███████╗██║ ╚████║"
echo "  ╚═╝╚═╝  ╚═╝   ╚═╝      ╚═╝       ╚═╝  ╚═╝     ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚═════╝ ╚══════╝╚═╝  ╚═══╝"
echo -e "${NC}"
echo -e "${YELLOW}  VPS Hardening v3.0 | Universal | by IKYY x CLAUDE${NC}"
echo -e "${CYAN}  ================================================================${NC}"
echo ""

if [[ $EUID -ne 0 ]]; then
  echo -e "${RED}[ERROR] Harus dijalankan sebagai root!${NC}"
  exit 1
fi

if grep -qi "almalinux" /etc/os-release; then
  OS="almalinux"; OS_NAME="AlmaLinux"; PKG="dnf"; FIREWALL="firewalld"
elif grep -qi "ubuntu" /etc/os-release; then
  OS="ubuntu"; OS_NAME="Ubuntu"; PKG="apt"; FIREWALL="ufw"
else
  echo -e "${RED}[ERROR] OS tidak didukung!${NC}"; exit 1
fi

echo -e "${GREEN}[OK] OS: ${OS_NAME}${NC}"
echo ""

# ============================================================
# INPUT KONFIGURASI
# ============================================================
echo -e "${CYAN}${BOLD}[ KONFIGURASI HARDENING ]${NC}"
echo ""

while true; do
  read -p "  SSH Port baru (default: 22, range: 1024-65535)  : " SSH_PORT
  SSH_PORT=${SSH_PORT:-22}
  if [[ "$SSH_PORT" =~ ^[0-9]+$ ]] && [ "$SSH_PORT" -ge 1 ] && [ "$SSH_PORT" -le 65535 ]; then break; fi
  echo -e "  ${RED}Port tidak valid!${NC}"
done

read -p "  Disable IPv6? (y/n, default: n)                  : " DISABLE_IPV6
DISABLE_IPV6=${DISABLE_IPV6:-n}

read -p "  Buat user non-root? (y/n, default: n)            : " CREATE_USER
CREATE_USER=${CREATE_USER:-n}

if [[ "$CREATE_USER" == "y" || "$CREATE_USER" == "Y" ]]; then
  while [[ -z "$NEW_USER" ]]; do read -p "  Nama user baru: " NEW_USER; done
  while [[ -z "$NEW_PASS" ]]; do read -s -p "  Password: " NEW_PASS; echo ""; done
fi

read -p "  Install Fail2Ban? (y/n, default: y)              : " INSTALL_F2B
INSTALL_F2B=${INSTALL_F2B:-y}

read -p "  Install ClamAV? (y/n, default: n)                : " INSTALL_AV
INSTALL_AV=${INSTALL_AV:-n}

read -p "  Auto update otomatis? (y/n, default: y)          : " AUTO_UPDATE
AUTO_UPDATE=${AUTO_UPDATE:-y}

# P1: Tanya DNS server
read -p "  VPS ini DNS server? (y/n, default: n)            : " IS_DNS_SERVER
IS_DNS_SERVER=${IS_DNS_SERVER:-n}

# P2: Tanya port email
read -p "  Aktifkan port email? (y/n, default: n)           : " ENABLE_MAIL
ENABLE_MAIL=${ENABLE_MAIL:-n}

# P4: Tanya FTP
read -p "  Aktifkan port FTP 21? (y/n, default: n)          : " ENABLE_FTP
ENABLE_FTP=${ENABLE_FTP:-n}

# U5: Validasi PANEL_TYPE
echo ""
echo -e "  Panel: ${YELLOW}1${NC}=WHM/cPanel ${YELLOW}2${NC}=CyberPanel ${YELLOW}3${NC}=Tanpa Panel"
while true; do
  read -p "  Pilih (1/2/3, default: 3): " PANEL_TYPE
  PANEL_TYPE=${PANEL_TYPE:-3}
  if [[ "$PANEL_TYPE" =~ ^[1-3]$ ]]; then break; fi
  echo -e "  ${RED}Pilihan tidak valid!${NC}"
done

echo ""
echo -e "${YELLOW}  ---- Konfigurasi ----${NC}"
echo -e "  OS: ${CYAN}${OS_NAME}${NC} | SSH Port: ${CYAN}${SSH_PORT}${NC} | Panel: ${CYAN}${PANEL_TYPE}${NC}"
echo -e "  DNS: ${CYAN}${IS_DNS_SERVER}${NC} | Email: ${CYAN}${ENABLE_MAIL}${NC} | FTP: ${CYAN}${ENABLE_FTP}${NC}"
echo ""
read -p "  Lanjutkan? (y/n): " CONFIRM
if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then echo -e "${RED}Dibatalkan.${NC}"; exit 0; fi

LOG_FILE="/var/log/hardening_ikyy.log"
exec > >(tee -a $LOG_FILE) 2>&1
echo "=== Hardening v3.0 dimulai: $(date) ==="

# ============================================================
# STEP 1: UPDATE
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 1/9] Update sistem...${NC}"
if [[ "$OS" == "almalinux" ]]; then
  dnf update -y -q && dnf install -y -q epel-release
else
  # U6: DEBIAN_FRONTEND agar tidak stuck
  DEBIAN_FRONTEND=noninteractive apt update -qq
  DEBIAN_FRONTEND=noninteractive apt upgrade -y -qq
fi
echo -e "${GREEN}  [OK] Sistem up-to-date${NC}"; echo ""

# ============================================================
# STEP 2: SSH HARDENING
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 2/9] Hardening SSH...${NC}"
SSH_CONFIG="/etc/ssh/sshd_config"
cp $SSH_CONFIG ${SSH_CONFIG}.bak.$(date +%Y%m%d)

sed -i '/^#\?Port /d' $SSH_CONFIG
echo "Port $SSH_PORT" >> $SSH_CONFIG
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' $SSH_CONFIG
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' $SSH_CONFIG
sed -i 's/^X11Forwarding yes/X11Forwarding no/' $SSH_CONFIG
sed -i '/^#\?MaxAuthTries/d' $SSH_CONFIG
echo "MaxAuthTries 3" >> $SSH_CONFIG

grep -q "LoginGraceTime" $SSH_CONFIG || cat >> $SSH_CONFIG <<EOF

# === Hardening IKYY x CLAUDE v3.0 ===
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
MaxSessions 3
IgnoreRhosts yes
HostbasedAuthentication no
PermitEmptyPasswords no
EOF

# U4: Fix sshd binary path universal
SSHD_BIN=$(which sshd 2>/dev/null || echo "/usr/sbin/sshd")
if ! $SSHD_BIN -t 2>/dev/null; then
  echo -e "${RED}  [ERROR] SSH config tidak valid! Rollback...${NC}"
  cp ${SSH_CONFIG}.bak.$(date +%Y%m%d) $SSH_CONFIG; exit 1
fi
echo -e "${GREEN}  [OK] SSH config dikeraskan, port: ${SSH_PORT}${NC}"; echo ""

# ============================================================
# STEP 3: FIREWALL
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 3/9] Setup Firewall...${NC}"

open_fw_port() {
  local PORT=$1
  if [[ "$OS" == "almalinux" ]]; then
    firewall-cmd --permanent --add-port=${PORT} 2>/dev/null
  else
    ufw allow ${PORT} 2>/dev/null
  fi
}

if [[ "$OS" == "almalinux" ]]; then
  dnf install -y -q firewalld
  systemctl enable firewalld --now
  firewall-cmd --permanent --set-default-zone=drop
else
  DEBIAN_FRONTEND=noninteractive apt install -y -qq ufw
  ufw --force reset
  ufw default deny incoming
  ufw default allow outgoing
fi

# SSH DULU
open_fw_port "${SSH_PORT}/tcp"
open_fw_port "80/tcp"
open_fw_port "443/tcp"

# P1: DNS hanya kalau DNS server
if [[ "$IS_DNS_SERVER" == "y" || "$IS_DNS_SERVER" == "Y" ]]; then
  open_fw_port "53/tcp"; open_fw_port "53/udp"
  echo -e "${GREEN}  [OK] Port 53 DNS dibuka${NC}"
else
  echo -e "${YELLOW}  [SKIP] Port 53 DNS ditutup — proteksi DNS amplification${NC}"
fi

# P4: FTP hanya kalau diminta
if [[ "$ENABLE_FTP" == "y" || "$ENABLE_FTP" == "Y" ]]; then
  open_fw_port "21/tcp"
  echo -e "${GREEN}  [OK] Port 21 FTP dibuka${NC}"
else
  echo -e "${YELLOW}  [SKIP] Port 21 FTP ditutup — gunakan SFTP${NC}"
fi

# Panel ports
if [[ "$PANEL_TYPE" == "1" ]]; then
  for PORT in 2082/tcp 2083/tcp 2086/tcp 2087/tcp 2095/tcp 2096/tcp; do
    open_fw_port "$PORT"
  done
  # P2 & P3: Email hanya SSL
  if [[ "$ENABLE_MAIL" == "y" || "$ENABLE_MAIL" == "Y" ]]; then
    for PORT in 25/tcp 465/tcp 587/tcp 993/tcp 995/tcp; do open_fw_port "$PORT"; done
    echo -e "${GREEN}  [OK] Port email dibuka (25,465,587,993,995)${NC}"
    echo -e "${YELLOW}  [INFO] Port 110/143 ditutup — pakai 993/995 (SSL)${NC}"
  fi
  echo -e "${GREEN}  [OK] Port WHM/cPanel dibuka${NC}"
elif [[ "$PANEL_TYPE" == "2" ]]; then
  open_fw_port "8090/tcp"; open_fw_port "8443/tcp"
  if [[ "$ENABLE_MAIL" == "y" || "$ENABLE_MAIL" == "Y" ]]; then
    for PORT in 25/tcp 465/tcp 587/tcp 993/tcp 995/tcp; do open_fw_port "$PORT"; done
    echo -e "${GREEN}  [OK] Port email dibuka (25,465,587,993,995)${NC}"
  fi
  echo -e "${GREEN}  [OK] Port CyberPanel dibuka${NC}"
fi

if [[ "$OS" == "almalinux" ]]; then
  firewall-cmd --reload
else
  ufw --force enable
fi

# SSH restart SETELAH firewall
if ! systemctl restart sshd 2>/dev/null && ! service ssh restart 2>/dev/null; then
  echo -e "${RED}  [ERROR] SSH gagal restart! Rollback...${NC}"
  cp ${SSH_CONFIG}.bak.$(date +%Y%m%d) $SSH_CONFIG
  systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null
  exit 1
fi

echo -e "${GREEN}  [OK] Firewall aktif${NC}"
echo -e "${GREEN}  [OK] SSH restart sukses port ${SSH_PORT}${NC}"; echo ""

# ============================================================
# STEP 4: FAIL2BAN
# ============================================================
if [[ "$INSTALL_F2B" == "y" || "$INSTALL_F2B" == "Y" ]]; then
  echo -e "${CYAN}${BOLD}[STEP 4/9] Install Fail2Ban...${NC}"
  if [[ "$OS" == "almalinux" ]]; then
    dnf install -y -q fail2ban
  else
    DEBIAN_FRONTEND=noninteractive apt install -y -qq fail2ban
  fi

  cat > /etc/fail2ban/jail.local <<EOF
[DEFAULT]
bantime  = 86400
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8

[sshd]
enabled  = true
mode     = aggressive
port     = ${SSH_PORT}
logpath  = %(sshd_log)s
maxretry = 3
bantime  = 86400
EOF

  [[ "$PANEL_TYPE" == "1" ]] && cat >> /etc/fail2ban/jail.local <<EOF

[cpanel-login]
enabled  = true
port     = 2082,2083,2086,2087
logpath  = /usr/local/cpanel/logs/login_log
maxretry = 3
EOF

  [[ "$PANEL_TYPE" == "2" ]] && cat >> /etc/fail2ban/jail.local <<EOF

[cyberpanel-login]
enabled  = true
port     = 8090,8443
logpath  = /var/log/cyberpanel.log
maxretry = 3
EOF

  systemctl enable fail2ban --now; sleep 2
  systemctl is-active --quiet fail2ban && \
    echo -e "${GREEN}  [OK] Fail2Ban aktif${NC}" || \
    echo -e "${RED}  [WARN] Fail2Ban gagal start${NC}"
else
  echo -e "${YELLOW}  [SKIP] Fail2Ban dilewati${NC}"
fi
echo ""

# ============================================================
# STEP 5: USER NON-ROOT
# ============================================================
if [[ "$CREATE_USER" == "y" || "$CREATE_USER" == "Y" ]]; then
  echo -e "${CYAN}${BOLD}[STEP 5/9] Buat User Non-Root...${NC}"
  useradd -m -s /bin/bash "$NEW_USER" 2>/dev/null || true
  echo "$NEW_USER:$NEW_PASS" | chpasswd
  # U1: Eksplisit per OS
  if [[ "$OS" == "almalinux" ]]; then
    usermod -aG wheel "$NEW_USER"
  else
    usermod -aG sudo "$NEW_USER"
  fi
  echo -e "${GREEN}  [OK] User ${NEW_USER} dibuat${NC}"
else
  echo -e "${YELLOW}  [SKIP] User non-root dilewati${NC}"
fi
echo ""

# ============================================================
# STEP 6: SYSCTL HARDENING
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 6/9] Hardening Sistem...${NC}"
SYSCTL_FILE="/etc/sysctl.d/99-hardening-ikyy.conf"
cat > $SYSCTL_FILE <<EOF
# === IKYY x CLAUDE v3.0 ===
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.tcp_syncookies = 1
# B1: Log martians dengan rate limit agar tidak overload disk
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ratelimit = 100
net.ipv4.icmp_ratemask = 88089
EOF

if [[ "$DISABLE_IPV6" == "y" || "$DISABLE_IPV6" == "Y" ]]; then
  cat >> $SYSCTL_FILE <<EOF
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
EOF
  echo -e "${GREEN}  [OK] IPv6 dinonaktifkan${NC}"
fi

sysctl -p $SYSCTL_FILE > /dev/null 2>&1
echo -e "${GREEN}  [OK] Sysctl hardening diterapkan${NC}"; echo ""

# ============================================================
# STEP 7: AUTO UPDATE
# ============================================================
if [[ "$AUTO_UPDATE" == "y" || "$AUTO_UPDATE" == "Y" ]]; then
  echo -e "${CYAN}${BOLD}[STEP 7/9] Setup Auto Update...${NC}"
  if [[ "$OS" == "almalinux" ]]; then
    dnf install -y -q dnf-automatic
    sed -i 's/^apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
    sed -i 's/^upgrade_type = default/upgrade_type = security/' /etc/dnf/automatic.conf
    grep -q "^exclude = kernel" /etc/dnf/automatic.conf || echo "exclude = kernel*" >> /etc/dnf/automatic.conf
    systemctl enable --now dnf-automatic.timer
  else
    DEBIAN_FRONTEND=noninteractive apt install -y -qq unattended-upgrades
    dpkg-reconfigure -plow unattended-upgrades <<< "yes" > /dev/null 2>&1
  fi
  echo -e "${GREEN}  [OK] Auto security update aktif${NC}"
else
  echo -e "${YELLOW}  [SKIP] Auto update dilewati${NC}"
fi
echo ""

# ============================================================
# STEP 8: CLAMAV
# ============================================================
if [[ "$INSTALL_AV" == "y" || "$INSTALL_AV" == "Y" ]]; then
  echo -e "${CYAN}${BOLD}[STEP 8/9] Install ClamAV...${NC}"
  if [[ "$OS" == "almalinux" ]]; then
    dnf install -y -q clamav clamav-update clamd
    freshclam --no-warnings 2>/dev/null || echo -e "${YELLOW}  [WARN] freshclam update otomatis nanti${NC}"
    # U2: AlmaLinux pakai clamd@scan
    systemctl enable clamav-freshclam clamd@scan --now 2>/dev/null || true
  else
    DEBIAN_FRONTEND=noninteractive apt install -y -qq clamav clamav-daemon
    systemctl stop clamav-freshclam 2>/dev/null || true
    freshclam --no-warnings 2>/dev/null || echo -e "${YELLOW}  [WARN] freshclam update otomatis nanti${NC}"
    # U2: Ubuntu pakai clamav-daemon
    systemctl enable clamav-freshclam clamav-daemon --now 2>/dev/null || true
  fi

  cat > /etc/cron.weekly/clamav-scan <<'CRONEOF'
#!/bin/bash
clamscan -r /home /var/www /public_html --log=/var/log/clamav-weekly.log --quiet
CRONEOF
  chmod +x /etc/cron.weekly/clamav-scan
  echo -e "${GREEN}  [OK] ClamAV terinstall${NC}"
else
  echo -e "${YELLOW}  [SKIP] ClamAV dilewati${NC}"
fi
echo ""

# ============================================================
# STEP 9: PROTEKSI TAMBAHAN
# ============================================================
echo -e "${CYAN}${BOLD}[STEP 9/9] Proteksi Tambahan...${NC}"

echo "" > /etc/issue
echo "" > /etc/issue.net
sed -i '/^#\?Banner/d' /etc/ssh/sshd_config
echo "Banner none" >> /etc/ssh/sshd_config

cat > /etc/modprobe.d/disable-usb.conf <<EOF
install usb-storage /bin/true
EOF

if ! grep -q "tmpfs /tmp" /etc/fstab; then
  echo "tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0" >> /etc/fstab
  echo -e "${YELLOW}  [INFO] /tmp hardening aktif setelah reboot${NC}"
fi

chmod 600 /etc/ssh/sshd_config
# B3: crontab 644 bukan 600
chmod 644 /etc/crontab 2>/dev/null || true

# U3: Hapus rlogin dari list AlmaLinux (tidak ada di repo AlmaLinux 9)
if [[ "$OS" == "almalinux" ]]; then
  dnf remove -y -q telnet rsh 2>/dev/null || true
else
  DEBIAN_FRONTEND=noninteractive apt remove -y -qq telnet rsh-client 2>/dev/null || true
fi

# U4: Fix sshd binary path
SSHD_BIN=$(which sshd 2>/dev/null || echo "/usr/sbin/sshd")
if $SSHD_BIN -t 2>/dev/null; then
  systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null
  echo -e "${GREEN}  [OK] Proteksi tambahan diterapkan${NC}"
else
  echo -e "${RED}  [WARN] SSH config ada masalah, skip restart${NC}"
fi
echo ""

# ============================================================
# HEALTH CHECK
# ============================================================
echo -e "${CYAN}${BOLD}[ HEALTH CHECK ]${NC}"; echo ""

systemctl is-active --quiet sshd 2>/dev/null || systemctl is-active --quiet ssh 2>/dev/null && \
  echo -e "  SSH              : ${GREEN}✅ Aktif (port ${SSH_PORT})${NC}" || \
  echo -e "  SSH              : ${RED}❌ MATI${NC}"

if [[ "$OS" == "almalinux" ]]; then
  systemctl is-active --quiet firewalld && \
    echo -e "  Firewall         : ${GREEN}✅ Aktif${NC}" || \
    echo -e "  Firewall         : ${RED}❌ MATI${NC}"
else
  ufw status 2>/dev/null | grep -q "Status: active" && \
    echo -e "  Firewall         : ${GREEN}✅ Aktif${NC}" || \
    echo -e "  Firewall         : ${RED}❌ MATI${NC}"
fi

[[ "$INSTALL_F2B" == "y" || "$INSTALL_F2B" == "Y" ]] && {
  systemctl is-active --quiet fail2ban && \
    echo -e "  Fail2Ban         : ${GREEN}✅ Aktif${NC}" || \
    echo -e "  Fail2Ban         : ${RED}❌ MATI${NC}"
}

[[ -f "$SYSCTL_FILE" ]] && \
  echo -e "  Sysctl Hardening : ${GREEN}✅ Aktif${NC}" || \
  echo -e "  Sysctl Hardening : ${RED}❌ Tidak ditemukan${NC}"

echo ""

# ============================================================
# RINGKASAN
# ============================================================
echo -e "${CYAN}${BOLD}"
echo "  ================================================================"
echo "   HARDENING v3.0 SELESAI! ALHAMDULILLAH"
echo "  ================================================================"
echo -e "${NC}"
echo -e "  🔐 SSH Port Baru  : ${RED}${SSH_PORT}${NC}"
echo -e "  🔑 Login SSH      : ${CYAN}ssh root@IP_SERVER -p ${SSH_PORT}${NC}"
[[ "$IS_DNS_SERVER" != "y" ]] && echo -e "  🚫 Port 53 DNS    : ${CYAN}Ditutup (proteksi DNS amplification)${NC}"
[[ "$ENABLE_FTP" != "y" ]] && echo -e "  🚫 Port 21 FTP    : ${CYAN}Ditutup (gunakan SFTP)${NC}"
[[ "$ENABLE_MAIL" == "y" ]] && echo -e "  📧 Port Email     : ${CYAN}Aktif — SSL only (465,587,993,995)${NC}"
[[ "$PANEL_TYPE" == "1" ]] && echo -e "  🌐 WHM            : ${CYAN}https://IP_SERVER:2087${NC}"
[[ "$PANEL_TYPE" == "2" ]] && echo -e "  🌐 CyberPanel     : ${CYAN}https://IP_SERVER:8090${NC}"
echo ""
echo -e "  📋 Log: ${CYAN}/var/log/hardening_ikyy.log${NC}"
echo -e "${YELLOW}  ⚠ /tmp hardening aktif setelah reboot${NC}"
echo -e "${CYAN}  ================================================================${NC}"
echo ""
echo "=== Hardening v3.0 selesai: $(date) ==="
