403Webshell
Server IP : 119.195.102.159  /  Your IP : 216.73.217.134
Web Server : nginx/1.18.0
System : Linux picell 5.15.0-181-generic #191-Ubuntu SMP Fri May 22 19:09:02 UTC 2026 x86_64
User : altablue ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/altablue/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/altablue/watch_fpm.sh
#!/bin/bash
# ============================================================
#  πŸ’š PHP-FPM ν—¬μŠ€μ²΄ν¬ + λ³΄μ•ˆ 톡합 μ›ŒμΉ˜λ…
#  μ„œλ²„ 배포 경둜: /home/altablue/watch_fpm.sh
#
#  κΈ°μ‘΄ κΈ°λŠ₯: μ›Ήμ‚¬μ΄νŠΈ 응닡 확인 β†’ PHP-FPM μž¬μ‹œμž‘
#  μΆ”κ°€ κΈ°λŠ₯: 연속 μ‹€νŒ¨ μ—μŠ€μ»¬λ ˆμ΄μ…˜, 응닡 μ‹œκ°„ λͺ¨λ‹ˆν„°λ§,
#            λ³΄μ•ˆ μ‹œμŠ€ν…œ μƒνƒœ 확인, 일일 μš”μ•½ 보고
#
#  크둠: * * * * * /home/altablue/watch_fpm.sh
# ============================================================

# ── μ„€μ • λ‘œλ“œ ─────────────────────────────────────
CONFIG_FILE="/etc/security-watchdog/config"
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
else
    # 폴백 μ„€μ •
    HEALTH_CHECK_URL="https://www.picell.biz/about-us/"
    HEALTH_CHECK_TIMEOUT=5
    FPM_SERVICE="php8.3-fpm"
    LOG_DIR="/home/altablue/logs"
fi

# ── 경둜 μ„€μ • ─────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
NOTIFY="$SCRIPT_DIR/telegram_notify.sh"
LOGFILE="${LOG_DIR:-/home/altablue/logs}/fpm_watchdog.log"
FAIL_COUNT_FILE="/tmp/.fpm_watchdog_fail_count"
SLOW_LOG="${LOG_DIR:-/home/altablue/logs}/slow_response.log"
DAILY_STATS_FILE="/tmp/.fpm_daily_stats"

# ── 느린 응닡 κ΄€λ ¨ μƒνƒœ 파일 ─────────────────────
SLOW_COUNT_FILE="/tmp/.fpm_slow_count"         # 연속 느린 응닡 횟수
SLOW_ALERT_FILE="/tmp/.fpm_slow_alerted"        # λ§ˆμ§€λ§‰ 느린 응닡 μ•Œλ¦Ό μ‹œκ°
SLOW_ATTACK_FILE="/tmp/.fpm_slow_attack"        # 슬둜우 어택 탐지 μ•Œλ¦Ό μ‹œκ°
SLOW_THRESHOLD="${SLOW_RESPONSE_THRESHOLD:-5.0}"  # λŠ”λ¦° 응닡 κΈ°μ€€(초)
SLOW_RESTART_THRESHOLD="${SLOW_RESTART_THRESHOLD:-10.0}" # μžλ™ μž¬μ‹œμž‘ κΈ°μ€€(초)
SLOW_ALERT_COOLDOWN=1800                        # 느린 응닡 μ•Œλ¦Ό μΏ¨λ‹€μš΄(30λΆ„)
SLOW_ALERT_COUNT_TRIGGER=3                      # N연속 노릴 λ•Œλ§Œ μ•Œλ¦Ό
ATTACK_CONN_THRESHOLD="${SLOW_ATTACK_CONN_THRESHOLD:-300}" # 슬둜우 어택 ESTABLISHED μž„κ³„κ°’

mkdir -p "$(dirname "$LOGFILE")" 2>/dev/null

TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
HOUR=$(date "+%H")
MINUTE=$(date "+%M")

# ── μ›Ήμ‚¬μ΄νŠΈ 응닡 확인 (응닡 μ‹œκ°„ 포함) ──────────
RESPONSE=$(curl -s -o /dev/null \
    -w "%{http_code}|%{time_total}|%{time_connect}|%{time_starttransfer}" \
    --max-time "${HEALTH_CHECK_TIMEOUT:-5}" \
    "${HEALTH_CHECK_URL}" 2>/dev/null)

STATUS=$(echo "$RESPONSE" | cut -d'|' -f1)
TIME_TOTAL=$(echo "$RESPONSE" | cut -d'|' -f2)
TIME_CONNECT=$(echo "$RESPONSE" | cut -d'|' -f3)
TIME_TTFB=$(echo "$RESPONSE" | cut -d'|' -f4)

# ── 연속 μ‹€νŒ¨ 카운트 관리 ─────────────────────────
FAIL_COUNT=0
if [ -f "$FAIL_COUNT_FILE" ]; then
    FAIL_COUNT=$(cat "$FAIL_COUNT_FILE" 2>/dev/null || echo 0)
fi

# ── 일일 톡계 관리 ────────────────────────────────
TODAY=$(date "+%Y-%m-%d")
if [ -f "$DAILY_STATS_FILE" ]; then
    STATS_DATE=$(head -1 "$DAILY_STATS_FILE" 2>/dev/null || echo "")
    if [ "$STATS_DATE" != "$TODAY" ]; then
        # μƒˆλ‘œμš΄ λ‚  β†’ μ–΄μ œ 톡계 리셋
        echo "$TODAY" > "$DAILY_STATS_FILE"
        echo "0" >> "$DAILY_STATS_FILE"  # 총 체크 수
        echo "0" >> "$DAILY_STATS_FILE"  # μ‹€νŒ¨ 수
        echo "0" >> "$DAILY_STATS_FILE"  # μž¬μ‹œμž‘ 수
        echo "0" >> "$DAILY_STATS_FILE"  # 느린 응닡 수
    fi
else
    echo "$TODAY" > "$DAILY_STATS_FILE"
    echo "0" >> "$DAILY_STATS_FILE"
    echo "0" >> "$DAILY_STATS_FILE"
    echo "0" >> "$DAILY_STATS_FILE"
    echo "0" >> "$DAILY_STATS_FILE"
fi

# 톡계 읽기
STATS_CHECKS=$(sed -n '2p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
STATS_FAILS=$(sed -n '3p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
STATS_RESTARTS=$(sed -n '4p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
STATS_SLOW=$(sed -n '5p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)

# 총 체크 수 증가
STATS_CHECKS=$((STATS_CHECKS + 1))

# ── 응닡 뢄석 ─────────────────────────────────────
if [ "$STATUS" != "200" ]; then
    # ────── μ‹€νŒ¨ 처리 ──────
    FAIL_COUNT=$((FAIL_COUNT + 1))
    echo "$FAIL_COUNT" > "$FAIL_COUNT_FILE"
    STATS_FAILS=$((STATS_FAILS + 1))

    echo "[$TIMESTAMP] ❌ 응닡 이상 (Status: $STATUS, μ—°μ†μ‹€νŒ¨: $FAIL_COUNT)" >> "$LOGFILE"

    # PHP-FPM μž¬μ‹œμž‘
    systemctl restart "${FPM_SERVICE}" 2>/dev/null
    STATS_RESTARTS=$((STATS_RESTARTS + 1))

    echo "[$TIMESTAMP] πŸ”„ ${FPM_SERVICE} μž¬μ‹œμž‘ μ™„λ£Œ" >> "$LOGFILE"

    # μ—μŠ€μ»¬λ ˆμ΄μ…˜ 둜직
    if [ "$FAIL_COUNT" -ge 5 ]; then
        # 5회 연속 μ‹€νŒ¨ β†’ CRITICAL
        "$NOTIFY" "CRITICAL" "🚨 <b>PHP-FPM 연속 μ‹€νŒ¨ (${FAIL_COUNT}회)</b>

🌐 URL: ${HEALTH_CHECK_URL}
πŸ“Š Status: ${STATUS}
πŸ”„ ${FPM_SERVICE} μž¬μ‹œμž‘ ${FAIL_COUNT}회 μ‹œλ„

⚠️ μ„œλ²„ μƒνƒœλ₯Ό μ¦‰μ‹œ ν™•μΈν•΄μ£Όμ„Έμš”!
κ°€λŠ₯ν•œ 원인:
β€’ μ„œλ²„ κ³ΌλΆ€ν•˜
β€’ λ””μŠ€ν¬ μš©λŸ‰ λΆ€μ‘±
β€’ MySQL λ‹€μš΄
β€’ DDoS 곡격"

        # 10회 이상이면 nginx도 μž¬μ‹œμž‘ μ‹œλ„
        if [ "$FAIL_COUNT" -ge 10 ]; then
            systemctl restart nginx 2>/dev/null
            echo "[$TIMESTAMP] πŸ”„ nginx μž¬μ‹œμž‘ μ‹œλ„ (연속 μ‹€νŒ¨ ${FAIL_COUNT}회)" >> "$LOGFILE"
        fi

    elif [ "$FAIL_COUNT" -ge 3 ]; then
        # 3회 연속 μ‹€νŒ¨ β†’ WARNING
        "$NOTIFY" "WARNING" "⚠️ <b>PHP-FPM 반볡 μ‹€νŒ¨ (${FAIL_COUNT}회 연속)</b>

🌐 URL: ${HEALTH_CHECK_URL}
πŸ“Š Status: ${STATUS}
πŸ”„ ${FPM_SERVICE} μž¬μ‹œμž‘λ¨"

    else
        # 1~2회 β†’ 일반 κ²½κ³ 
        "$NOTIFY" "WARNING" "⚠️ PHP-FPM μž¬μ‹œμž‘λ¨
πŸ“Š 응닡: ${STATUS}
πŸ”„ 연속 μ‹€νŒ¨: ${FAIL_COUNT}회"
    fi

else
    # ────── 성곡 처리 ──────

    # μ‹€νŒ¨ 카운트 리셋 (이전에 μ‹€νŒ¨ν–ˆλ‹€λ©΄ 볡ꡬ μ•Œλ¦Ό)
    if [ "$FAIL_COUNT" -gt 0 ]; then
        echo "[$TIMESTAMP] βœ… 볡ꡬ됨 (이전 μ—°μ†μ‹€νŒ¨: ${FAIL_COUNT}회)" >> "$LOGFILE"
        "$NOTIFY" "INFO" "βœ… <b>μ„œλΉ„μŠ€ 볡ꡬ 확인</b>

🌐 ${HEALTH_CHECK_URL}
πŸ“Š Status: 200 OK
⏱️ 응닡 μ‹œκ°„: ${TIME_TOTAL}s
πŸ”„ 이전 연속 μ‹€νŒ¨: ${FAIL_COUNT}νšŒμ—μ„œ 볡ꡬ"

        echo "0" > "$FAIL_COUNT_FILE"
    fi

    # ── 느린 응닡 감지 ─────────────────────────────────
    if [ -n "$TIME_TOTAL" ] && (( $(echo "$TIME_TOTAL > $SLOW_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
        STATS_SLOW=$((STATS_SLOW + 1))
        echo "[$TIMESTAMP] 🐌 느린 응닡: ${TIME_TOTAL}s (TTFB: ${TIME_TTFB}s)" >> "$SLOW_LOG"

        # 연속 느린 응닡 횟수 μ—…λ°μ΄νŠΈ
        SLOW_COUNT=0
        [ -f "$SLOW_COUNT_FILE" ] && SLOW_COUNT=$(cat "$SLOW_COUNT_FILE" 2>/dev/null || echo 0)
        SLOW_COUNT=$((SLOW_COUNT + 1))
        echo "$SLOW_COUNT" > "$SLOW_COUNT_FILE"

        echo "[$TIMESTAMP] 🐌 느린 응닡 (${TIME_TOTAL}s, TTFB: ${TIME_TTFB}s, 연속: ${SLOW_COUNT}회)" >> "$LOGFILE"

        # ── ESTABLISHED μ—°κ²° 수 확인 (슬둜우 HTTP 어택 νŒλ‹¨) ────
        CONN_COUNT=$(ss -s 2>/dev/null | grep -oP 'estab \K[0-9]+' | head -1 || echo 0)
        IS_ATTACK=0
        if (( CONN_COUNT > ATTACK_CONN_THRESHOLD )) && \
           (( $(echo "$TIME_TOTAL > $SLOW_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
            IS_ATTACK=1
        fi

        # ── μžλ™ μž¬μ‹œμž‘: 10초 이상 OR 슬둜우 어택 탐지 ────
        SHOULD_RESTART=0
        RESTART_REASON=""
        if (( $(echo "$TIME_TOTAL > $SLOW_RESTART_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
            SHOULD_RESTART=1
            RESTART_REASON="μ‘λ‹΅μ‹œκ°„ ${TIME_TOTAL}s 초과 (μž„κ³„: ${SLOW_RESTART_THRESHOLD}s)"
        elif [ "$IS_ATTACK" -eq 1 ]; then
            SHOULD_RESTART=1
            RESTART_REASON="슬둜우 HTTP 어택 탐지 (ESTABLISHED: ${CONN_COUNT}, 응닡: ${TIME_TOTAL}s)"
        fi

        if [ "$SHOULD_RESTART" -eq 1 ]; then
            systemctl restart "${FPM_SERVICE}" 2>/dev/null
            STATS_RESTARTS=$((STATS_RESTARTS + 1))
            echo "[$TIMESTAMP] πŸ”„ ${FPM_SERVICE} μž¬μ‹œμž‘: $RESTART_REASON" >> "$LOGFILE"

            # 슬둜우 어택 μ•Œλ¦Ό (30λΆ„ μΏ¨λ‹€μš΄)
            NOW=$(date +%s)
            LAST_ATTACK_ALERT=0
            [ -f "$SLOW_ATTACK_FILE" ] && LAST_ATTACK_ALERT=$(cat "$SLOW_ATTACK_FILE" 2>/dev/null || echo 0)
            if (( NOW - LAST_ATTACK_ALERT > SLOW_ALERT_COOLDOWN )); then
                "$NOTIFY" "CRITICAL" "🚨 <b>PHP-FPM μžλ™ μž¬μ‹œμž‘</b>

⚑ 원인: $RESTART_REASON
πŸ”— ν™œμ„± μ—°κ²°: ${CONN_COUNT}개
⏱️ μ‘λ‹΅μ‹œκ°„: ${TIME_TOTAL}s (TTFB: ${TIME_TTFB}s)

πŸ”„ ${FPM_SERVICE} μž¬μ‹œμž‘ μ™„λ£Œ
⚠️ λ‹€μŒ μ•Œλ¦Ό: 30λΆ„ ν›„"
                date +%s > "$SLOW_ATTACK_FILE"
            fi
            echo "0" > "$SLOW_COUNT_FILE"
        fi

        # ── 일반 느린 응닡 μ•Œλ¦Ό (μΏ¨λ‹€μš΄ + N회 연속 쑰건) ────
        # μΏ¨λ‹€μš΄ 내이면 μ•Œλ¦Ό μ•ˆ 보냄 β†’ μ•Œλ¦Ό ν”Όλ‘œλ„ ν•΄μ†Œ
        NOW=$(date +%s)
        LAST_SLOW_ALERT=0
        [ -f "$SLOW_ALERT_FILE" ] && LAST_SLOW_ALERT=$(cat "$SLOW_ALERT_FILE" 2>/dev/null || echo 0)
        COOLDOWN_ELAPSED=$(( NOW - LAST_SLOW_ALERT ))

        if [ "$SHOULD_RESTART" -eq 0 ] && \
           [ "$SLOW_COUNT" -ge "$SLOW_ALERT_COUNT_TRIGGER" ] && \
           (( COOLDOWN_ELAPSED > SLOW_ALERT_COOLDOWN )); then
            "$NOTIFY" "WARNING" "🐌 <b>지속적 느린 응닡</b>

🌐 ${HEALTH_CHECK_URL}
⏱️ μ‘λ‹΅μ‹œκ°„: ${TIME_TOTAL}s
πŸ”— TTFB: ${TIME_TTFB}s
πŸ”€ ESTABLISHED: ${CONN_COUNT}개
πŸ”„ 연속 ${SLOW_COUNT}회 노릴

⚠️ λ‹€μŒ μ•Œλ¦Ό: 30λΆ„ ν›„"
            date +%s > "$SLOW_ALERT_FILE"
        fi

    else
        # 응닡 정상 β†’ 느린 응닡 μΉ΄μš΄ν„° 리셋
        if [ -f "$SLOW_COUNT_FILE" ]; then
            PREV_SLOW=$(cat "$SLOW_COUNT_FILE" 2>/dev/null || echo 0)
            if [ "$PREV_SLOW" -gt 0 ]; then
                echo "[$TIMESTAMP] βœ… 느린 응닡 ν•΄μ†Œ (연속 ${PREV_SLOW}회)"
            fi
            echo "0" > "$SLOW_COUNT_FILE"
        fi
        echo "[$TIMESTAMP] βœ… 정상 (Status: $STATUS, Time: ${TIME_TOTAL}s)" >> "$LOGFILE"
    fi

    echo "0" > "$FAIL_COUNT_FILE"
fi

# ── 일일 톡계 μ €μž₯ ────────────────────────────────
cat > "$DAILY_STATS_FILE" << EOF
$TODAY
$STATS_CHECKS
$STATS_FAILS
$STATS_RESTARTS
$STATS_SLOW
EOF

# ── 일일 μš”μ•½ 보고 (맀일 23:59에 μ‹€ν–‰) ────────────
if [ "$HOUR" = "23" ] && [ "$MINUTE" = "59" ]; then
    UPTIME_PERCENT=0
    if [ "$STATS_CHECKS" -gt 0 ]; then
        UPTIME_PERCENT=$(echo "scale=2; (($STATS_CHECKS - $STATS_FAILS) * 100) / $STATS_CHECKS" | bc 2>/dev/null || echo "N/A")
    fi

    # λ³΄μ•ˆ μ‹œμŠ€ν…œ μƒνƒœ 확인
    FIM_STATUS="❌ 쀑지됨"
    if systemctl is-active --quiet file-integrity-monitor 2>/dev/null; then
        FIM_STATUS="βœ… μ‹€ν–‰ 쀑"
    fi

    # 였늘의 λ³΄μ•ˆ 이벀트 수
    SECURITY_EVENTS=0
    if [ -f "${LOG_DIR}/alert_history.log" ]; then
        SECURITY_EVENTS=$(grep -c "$(date +%Y-%m-%d)" "${LOG_DIR}/alert_history.log" 2>/dev/null || echo 0)
    fi

    # 격리된 파일 수
    QUARANTINE_COUNT=0
    if [ -d "$QUARANTINE_DIR" ]; then
        QUARANTINE_COUNT=$(find "$QUARANTINE_DIR" -maxdepth 1 -type f -newer "$DAILY_STATS_FILE" 2>/dev/null | wc -l)
    fi

    "$NOTIFY" "DAILY" "πŸ“Š <b>일일 μ„œλ²„ λ³΄μ•ˆ λ³΄κ³ μ„œ</b>
━━━━━━━━━━━━━━━━━━━━

πŸ’š <b>μ„œλΉ„μŠ€ μƒνƒœ:</b>
β€’ 가동λ₯ : ${UPTIME_PERCENT}%
β€’ 총 체크: ${STATS_CHECKS}회
β€’ μ‹€νŒ¨: ${STATS_FAILS}회
β€’ FPM μž¬μ‹œμž‘: ${STATS_RESTARTS}회
β€’ 느린 응닡: ${STATS_SLOW}회

πŸ›‘οΈ <b>λ³΄μ•ˆ μƒνƒœ:</b>
β€’ 파일 κ°μ‹œ: ${FIM_STATUS}
β€’ λ³΄μ•ˆ 이벀트: ${SECURITY_EVENTS}건
β€’ 격리 파일: ${QUARANTINE_COUNT}개

πŸ“… λ‚ μ§œ: ${TODAY}"
fi

# ── 둜그 크기 관리 (50MB 초과 μ‹œ 트림) ────────────
if [ -f "$LOGFILE" ]; then
    LOG_SIZE=$(stat -c%s "$LOGFILE" 2>/dev/null || echo 0)
    if [ "$LOG_SIZE" -gt 52428800 ]; then
        tail -n 10000 "$LOGFILE" > "${LOGFILE}.tmp"
        mv "${LOGFILE}.tmp" "$LOGFILE"
    fi
fi

Youez - 2016 - github.com/yon3zu
LinuXploit