#!/bin/bash
# 실습 #16 ② — fail2ban: SSH 무차별 자동 차단 (동작 원리 검증)
# 사용: bash setup_02_fail2ban.sh [nftables|iptables]
#
# backend  = 로그 소스       (systemd / polling / pyinotify)
# banaction = 차단 방식     (nftables-multiport / iptables-multiport / ufw)
# - 패턴 매칭: /var/log/auth.log 의 "Failed password ..." 라인 정규식 탐지
# - 카운팅:   findtime 안에 maxretry 초과 → 차단
# - 차단:    banaction 으로 룰 추가
# - 해제:    bantime 후 자동 unban
set -e

BANACTION="${1:-nftables}"      # nftables 또는 iptables

case "$BANACTION" in
    nftables) ACTION="nftables-multiport" ;;
    iptables) ACTION="iptables-multiport" ;;
    *) echo "사용: bash $0 {nftables|iptables}"; exit 1 ;;
esac

# 1) fail2ban + 차단 도구 설치
sudo apt install -y fail2ban
if [ "$BANACTION" = "iptables" ]; then
    sudo apt install -y iptables iptables-persistent || true
fi

# 2) jail.local 생성 (banaction 분기)
sudo tee /etc/fail2ban/jail.local >/dev/null <<EOF
[DEFAULT]
bantime  = 10m              # 차단 유지 시간
findtime = 10m              # 이 시간 안에
maxretry = 3                # 3번 실패 → 차단
banaction = $ACTION
backend = systemd           # 로그 소스 (auto / systemd / polling / pyinotify)

[sshd]
enabled  = true
port     = 22
filter   = sshd
logpath  = %(sshd_log)s
EOF

sudo systemctl restart fail2ban
sleep 2

echo
echo "=== 적용 결과 ==="
echo "  banaction = $ACTION"
echo "  backend   = systemd"
echo

echo "=== 1) fail2ban 상태 ==="
sudo fail2ban-client status

echo
echo "=== 2) sshd jail 상세 ==="
sudo fail2ban-client status sshd

echo
echo "=== 3) 내부 동작 원리 — filter regex (어떤 로그 패턴이 매칭되는지) ==="
sudo grep -E "^failregex|^ignoreregex" /etc/fail2ban/filter.d/sshd.conf | head -10

echo
echo "=== 4) 차단 chain 확인 ($BANACTION) ==="
if [ "$BANACTION" = "nftables" ]; then
    sudo nft list table inet f2b-table 2>/dev/null | head -20 || echo "→ 아직 차단된 IP 없음"
else
    sudo iptables -L f2b-sshd -n 2>/dev/null | head -10 || echo "→ 아직 차단된 IP 없음"
fi

echo
echo "=== 5) banaction 비교 표 ==="
cat <<'TBL'
| banaction              | 도구             | 특징                                              |
|------------------------|------------------|--------------------------------------------------|
| iptables-multiport     | iptables (레거시) | 호환성 ↑ · 시스템에 룰 누적 형태로 추가             |
| iptables-allports      | iptables         | 차단 대상 IP 의 모든 포트                          |
| nftables-multiport     | nftables (최신)   | 우분투 22.04+ 권장 · set 기반 효율 차단            |
| nftables-allports      | nftables         | 모든 포트 차단                                     |
| ufw                    | UFW              | ufw 사용 환경                                      |
| firewallcmd-multiport  | firewalld        | RHEL/CentOS                                       |
| route                  | 라우팅            | 차단 IP 를 blackhole 라우트 (방화벽 없는 환경)     |
TBL

echo
echo "=== 6) 차단 시뮬 + 관리 명령 ==="
echo "→ 같은 LAN 다른 머신에서:"
echo "   for i in 1 2 3 4; do sshpass -p WRONG ssh -o StrictHostKeyChecking=no lab@$(hostname -I | awk '{print \$1}') ; done"
echo "→ 4번째에서 connection refused"
echo
echo "→ 차단 확인: sudo fail2ban-client status sshd"
echo "→ 차단 해제: sudo fail2ban-client set sshd unbanip 1.2.3.4"
echo "→ 수동 차단: sudo fail2ban-client set sshd banip   1.2.3.4"

echo
echo "=== 7) 동작 흐름 ==="
cat <<EOF
  공격자 → ssh fail × 3
       ↓
  /var/log/auth.log  ← backend (systemd journal 또는 file polling)
       ↓
  filter.d/sshd.conf regex 매칭
       ↓
  jail counter 3/3 within findtime(10m)
       ↓
  banaction = $ACTION
       ↓
  $([ "$BANACTION" = "nftables" ] && echo "nft add element inet f2b-table f2b-sshd { X.X.X.X }" || echo "iptables -I f2b-sshd -s X.X.X.X -j REJECT")
       ↓
  bantime(10m) 후 자동 unban
EOF
