#!/bin/bash
# SSH Monitor Script
# This script monitors SSH login attempts and sends alerts via Forward Email
# Usage: Place in /usr/local/bin/ and add to crontab to run periodically
# Example crontab entry: */10 * * * * /usr/local/bin/ssh_monitor.sh

# Configuration
EMAIL_TO="admin@yourdomain.com"
EMAIL_FROM="ssh-alerts@yourdomain.com"
FORWARD_EMAIL_API_KEY="your_api_key_here" # Get from https://forwardemail.net/my-account/security
LOG_FILE="/var/log/auth.log"
FAILED_THRESHOLD=5 # Number of failed attempts to trigger alert
ALERT_LOCKFILE="/tmp/ssh_monitor_alert.lock"
LOCK_DURATION=3600 # Don't send another alert for this many seconds

# Function to send email via Forward Email HTTP API
send_email_api() {
    local subject="$1"
    local body="$2"

    curl -X POST "https://api.forwardemail.net/v1/emails" \
      -H "Content-Type: application/json" \
      -u "$FORWARD_EMAIL_API_KEY:" \
      -d '{
        "from": "'"$EMAIL_FROM"'",
        "to": "'"$EMAIL_TO"'",
        "subject": "'"$subject"'",
        "html": "'"$body"'",
        "text": "'"$body"'"
      }'

    echo "Alert email sent via API at $(date)" >> /var/log/ssh_monitor.log
}

# Function to send email via sendmail (SMTP)
send_email_smtp() {
    local subject="$1"
    local body="$2"

    echo -e "Subject: $subject\nFrom: $EMAIL_FROM\nTo: $EMAIL_TO\n\n$body" | \
    sendmail -t

    echo "Alert email sent via SMTP at $(date)" >> /var/log/ssh_monitor.log
}

# Check if we should send an alert (avoid alert flooding)
should_send_alert() {
    if [ -f "$ALERT_LOCKFILE" ]; then
        lockfile_time=$(stat -c %Y "$ALERT_LOCKFILE")
        current_time=$(date +%s)
        elapsed_time=$((current_time - lockfile_time))

        if [ $elapsed_time -lt $LOCK_DURATION ]; then
            return 1 # Don't send alert
        fi
    fi

    # Create or update lockfile
    touch "$ALERT_LOCKFILE"
    return 0 # Send alert
}

# Get hostname for the alert
HOSTNAME=$(hostname)

# Check for failed SSH login attempts in the last 10 minutes
TIMEFRAME="10 minutes ago"
FAILED_ATTEMPTS=$(grep "Failed password" $LOG_FILE | grep -i ssh | grep -v "grep" | awk '{print $1,$2,$3,$11}' | sort | uniq -c | sort -nr)
FAILED_COUNT=$(echo "$FAILED_ATTEMPTS" | wc -l)

# Check for successful logins
SUCCESSFUL_LOGINS=$(grep "Accepted password\|Accepted publickey" $LOG_FILE | grep -i ssh | grep -v "grep" | awk '{print $1,$2,$3,$9,$11}' | sort | tail -5)

# Check for unusual login times (outside business hours 8am-6pm)
HOUR=$(date +%H)
UNUSUAL_TIME=false
if [ "$HOUR" -lt 8 ] || [ "$HOUR" -gt 18 ]; then
    UNUSUAL_TIME=true
fi

# Prepare email content with HTML formatting
EMAIL_SUBJECT="SSH Security Alert: $HOSTNAME - $(date +%Y-%m-%d)"
EMAIL_BODY="<h2>SSH Security Monitoring Alert</h2>
<p><strong>Server:</strong> $HOSTNAME</p>
<p><strong>Time:</strong> $(date)</p>
<p><strong>Alert Type:</strong> Periodic SSH Activity Report</p>

<h3>Failed Login Attempts (Last 10 minutes):</h3>
<pre>$FAILED_ATTEMPTS</pre>

<h3>Recent Successful Logins:</h3>
<pre>$SUCCESSFUL_LOGINS</pre>

<p>This is an automated alert from your SSH monitoring system.</p>
<p>For more information, please check the server logs at $LOG_FILE</p>"

# Add warning for unusual login times
if [ "$UNUSUAL_TIME" = true ]; then
    EMAIL_BODY="$EMAIL_BODY
<p style='color: red;'><strong>WARNING:</strong> Login activity detected outside normal business hours!</p>"
fi

# Add warning for high number of failed attempts
if [ $FAILED_COUNT -ge $FAILED_THRESHOLD ]; then
    EMAIL_BODY="$EMAIL_BODY
<p style='color: red;'><strong>WARNING:</strong> High number of failed login attempts detected!</p>"

    # Send alert if threshold exceeded and we're not in lockout period
    if should_send_alert; then
        # Uncomment one of these methods based on your preference:
        send_email_api "$EMAIL_SUBJECT" "$EMAIL_BODY"
        # send_email_smtp "$EMAIL_SUBJECT" "$EMAIL_BODY"
    fi
fi

# Always log activity summary
echo "SSH Monitor ran at $(date) - Found $FAILED_COUNT failed attempts" >> /var/log/ssh_monitor.log

exit 0