ZeroBase/Infra

Linux Server SSH 접속 메일 알림(sSMTP)

Red_Horse 2025. 10. 3. 21:26

서버에 SSH로 접속할 때마다 실시간을 이메일 알림을 받는 보안 모니터링 시스템을 구현합니다.

NAT/게이트웨이 환경에서도 실제 외부 IP를 추적하여 보안을 강화합니다.

 

시스템 아키텍처

[SSH Client] → [Router/NAT] → [SSH Server] → [PAM] → [Alert Script] → [sSMTP] → [Gmail]
                     ↓
            [External IP Tracking]

 

프로세스 플로우

 

1. sSMTP 설치 및 설정

sudo apt update
sudo apt install ssmtp mailutils

 

  • sSMTP 설정 (/etc/ssmtp/ssmtp.conf)
 
# 서버 호스트명
hostname=your-server-name

# Gmail SMTP 설정
root=your-email@gmail.com
mailhub=smtp.gmail.com:587
AuthUser=your-email@gmail.com
AuthPass=your-16-digit-app-password
UseSTARTTLS=YES
FromLineOverride=YES

 

  • 발신자 설정 (/etc/ssmtp/revaliases)
root:your-email@gmail.com:smtp.gmail.com:587
username:your-email@gmail.com:smtp.gmail.com:587

 

 

보안 설정 필수

  1. Google 계정에서 2단계 인증 활성화
  2. 앱 비밀번호 생성 (https://myaccount.google.com/apppasswords)
  3. 생성된 16자리 비밀번호 사용

앱 비밀번호의 경우 생성후 다시 확인이 어려우니 저장해놓고 사용해야합니다.(외부 유출금지)

 

 

2. SSH 로그인 알림 스크립트 (외부 IP 추적 기능 포함)

/usr/local/bin/ssh-login-alert.sh

 
#!/bin/bash

# 실제 외부 IP 추출 함수
get_real_ip() {
    local ip=""
    
    # 1. auth.log에서 직접 추출 (가장 정확)
    ip=$(grep "sshd.*Accepted.*$PAM_USER" /var/log/auth.log | \
         tail -1 | \
         sed -n 's/.*from \([0-9.]*\).*/\1/p')
    
    # 2. IP가 없거나 내부 IP면 last -i 사용
    if [ -z "$ip" ] || [[ "$ip" =~ ^(192\.168\.|10\.|172\.) ]]; then
        ip=$(last -i -n 10 | grep "$PAM_USER" | \
             grep -v "192.168\|10.\|172." | \
             head -1 | awk '{print $3}')
    fi
    
    # 3. 그래도 없으면 현재 연결에서 추출
    if [ -z "$ip" ] || [[ "$ip" =~ ^(192\.168\.|10\.|172\.) ]]; then
        ip=$(ss -tn | grep ":22" | grep ESTAB | \
             awk '{print $5}' | cut -d: -f1 | \
             grep -v "192.168\|10.\|172." | head -1)
    fi
    
    # 4. 마지막으로 PAM_RHOST 사용
    if [ -z "$ip" ]; then
        ip="$PAM_RHOST"
    fi
    
    echo "$ip"
}

# 메인 실행 부분
if [ "$PAM_TYPE" = "open_session" ] && [ -n "$PAM_RHOST" ]; then
    
    # IP 정보 수집
    REAL_IP=$(get_real_ip)
    GATEWAY_IP="$PAM_RHOST"
    
    # IP 위치 정보 조회 (외부 IP인 경우)
    if [[ ! "$REAL_IP" =~ ^(192\.168\.|10\.|172\.|127\.) ]]; then
        IP_INFO=$(curl -s --max-time 3 "http://ip-api.com/json/$REAL_IP" 2>/dev/null)
        CITY=$(echo "$IP_INFO" | grep -oP '"city":"\K[^"]+' || echo "Unknown")
        COUNTRY=$(echo "$IP_INFO" | grep -oP '"country":"\K[^"]+' || echo "Unknown")
        ISP=$(echo "$IP_INFO" | grep -oP '"isp":"\K[^"]+' || echo "Unknown")
        LOCATION_INFO="$CITY, $COUNTRY (ISP: $ISP)"
    else
        LOCATION_INFO="Internal Network"
    fi
    
    # 메일 전송
    {
        echo "======================================"
        echo "⚠️ SSH 로그인 감지"
        echo "======================================"
        echo "시간: $(date '+%Y-%m-%d %H:%M:%S')"
        echo "서버: $(hostname)"
        echo "사용자: $PAM_USER"
        if [ "$REAL_IP" != "$GATEWAY_IP" ]; then
            echo "외부 IP: $REAL_IP"
            echo "게이트웨이: $GATEWAY_IP"
        else
            echo "접속 IP: $REAL_IP"
        fi
        echo "위치: $LOCATION_INFO"
        echo "======================================"
        echo ""
        echo "현재 접속자:"
        echo "$(w)"
    } | mail -s "[SSH] $(hostname) - $PAM_USER from ${REAL_IP:-$GATEWAY_IP}" your-email@gmail.com
fi

 

실행 권한 설정

sudo chmod +x /usr/local/bin/ssh-login-alert.sh

 

3. PAM 설정

/etc/pam.d/sshd 수정

sudo nano /etc/pam.d/sshd

 

파일 끝에 추가:

# SSH Login Email Alert
session optional pam_exec.so /usr/local/bin/ssh-login-alert.sh

 

4. SSH 로깅 개선 (더 정확한 IP 추적을 위해) 후 sshd 재시작

sudo nano /etc/ssh/sshd_config
LogLevel VERBOSE
sudo systemctl restart sshd

 

PAM 환경변수

변수 설명 예시
$PAM_TYPE 이벤트 타입 open_session, close_session
$PAM_USER 로그인 사용자 redhorse
$PAM_RHOST 원격 호스트 IP 192.168.0.1
$PAM_TTY 터미널 정보 ssh

 

IP-API 응답 파싱

{
  "city": "Seoul",
  "country": "South Korea",
  "isp": "Korea Telecom"
}

 

테스트 및 검증

1. sSMTP 테스트

# 기본 테스트
echo "Test" | mail -s "Test Mail" your-email@gmail.com

# 디버그 모드
echo "Test" | ssmtp -vvv your-email@gmail.com

 

 

접속시 메일 수신 결과

 

'ZeroBase > Infra' 카테고리의 다른 글

Http -> Https Domain 변경  (0) 2025.10.25