⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

스팸 필터링 완벽 가이드 SpamAssassin과 Rspamd 실전 활용 - 슬라이드 1/7
A

AI Generated

2025. 11. 26. · 5 Views

스팸 필터링 완벽 가이드 SpamAssassin과 Rspamd 실전 활용

이메일 서버 운영에서 필수적인 스팸 필터링 기술을 다룹니다. SpamAssassin과 Rspamd의 차이점부터 베이지안 필터, 블랙리스트 연동, 커스텀 룰 작성까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.


목차

  1. SpamAssassin_vs_Rspamd_비교
  2. 스팸_점수_시스템_이해
  3. 베이지안_필터_학습
  4. RBL_DNSBL_블랙리스트_연동
  5. 커스텀_룰_작성
  6. 오탐지_처리_및_화이트리스트

1. SpamAssassin vs Rspamd 비교

김개발 씨는 회사에서 메일 서버를 담당하게 되었습니다. 하루에 수천 통의 스팸 메일이 쏟아지는 것을 보고 깜짝 놀랐습니다.

선배에게 물어보니 "스팸 필터를 설정해야 하는데, SpamAssassin으로 할지 Rspamd로 할지 고민이야"라고 합니다.

SpamAssassin은 Perl로 작성된 오래된 스팸 필터로 안정성과 풍부한 룰셋이 장점입니다. 반면 Rspamd는 C와 Lua로 작성되어 훨씬 빠른 처리 속도를 자랑합니다.

마치 오래된 경험 많은 베테랑 경비원과 최신 AI 보안 시스템의 차이와 같습니다.

다음 코드를 살펴봅시다.

# SpamAssassin 설정 예제 (local.cf)
required_score   5.0
rewrite_header   Subject [SPAM]
report_safe      0
use_bayes        1
bayes_auto_learn 1

# Rspamd 설정 예제 (actions.conf)
actions {
    reject = 15;
    add_header = 6;
    greylist = 4;
}

# Python에서 SpamAssassin 연동
import subprocess

def check_spam_spamassassin(email_content):
    # spamc 클라이언트로 스팸 검사 요청
    result = subprocess.run(
        ['spamc', '-c'],
        input=email_content.encode(),
        capture_output=True
    )
    # 반환값 0은 정상, 1은 스팸
    return result.returncode == 1

김개발 씨는 입사 6개월 차 시스템 엔지니어입니다. 어느 날 팀장님이 불쑥 다가와 말했습니다.

"이번에 메일 서버 스팸 필터 구축을 맡아줘. 하루에 스팸이 몇 천 통씩 오거든." 김개발 씨는 검색을 시작했습니다.

스팸 필터링 솔루션을 찾아보니 크게 두 가지가 눈에 들어왔습니다. 바로 SpamAssassinRspamd입니다.

둘 다 오픈소스이고, 둘 다 많이 사용된다는데 무엇이 다른 걸까요? 쉽게 비유하자면, SpamAssassin은 마치 20년 경력의 베테랑 경비원과 같습니다.

경험이 풍부하고 어떤 상황에서도 흔들리지 않습니다. 수많은 보안 위협을 겪어왔기에 대응 매뉴얼도 두텁습니다.

다만 나이가 있어서 젊은 경비원보다는 조금 느립니다. 반면 Rspamd는 최신 AI 보안 시스템에 비유할 수 있습니다.

속도가 빠르고 최신 기술을 적극 활용합니다. 실시간으로 여러 검사를 동시에 수행하며, 메모리 사용량도 적습니다.

다만 상대적으로 역사가 짧아서 커뮤니티 규모는 SpamAssassin보다 작습니다. 구체적인 차이점을 살펴보겠습니다.

SpamAssassin은 1997년에 시작되어 거의 30년의 역사를 가지고 있습니다. Perl로 작성되어 있어 룰 작성이 직관적이고, 문서화가 잘 되어 있습니다.

하지만 단일 스레드로 동작하기 때문에 대량의 메일을 처리할 때 병목이 생길 수 있습니다. Rspamd는 2010년대에 등장한 비교적 새로운 솔루션입니다.

C 언어로 핵심 엔진을 작성하고 Lua로 확장 기능을 구현했습니다. 비동기 처리와 멀티스레딩을 지원하여 같은 하드웨어에서 SpamAssassin보다 10배 이상 빠른 처리량을 보여줍니다.

선택 기준은 무엇일까요? 하루에 처리해야 할 메일이 수만 통 이상이라면 Rspamd가 유리합니다.

반면 이미 SpamAssassin 룰셋을 많이 구축해놓은 환경이거나, 안정성이 최우선이라면 SpamAssassin이 나을 수 있습니다. 위의 코드를 살펴보면, SpamAssassin은 설정 파일이 단순한 키-값 형태입니다.

required_score는 스팸으로 판정할 기준 점수이고, use_bayes는 베이지안 필터 사용 여부를 결정합니다. Rspamd는 JSON과 유사한 형태로 설정하며, 점수에 따라 reject, add_header, greylist 등 다양한 액션을 지정할 수 있습니다.

실무에서는 어떻게 할까요? 많은 기업에서 두 솔루션을 함께 사용하기도 합니다.

Rspamd를 1차 필터로 두고, 의심스러운 메일만 SpamAssassin으로 2차 검증하는 방식입니다. 이렇게 하면 속도와 정확도를 모두 잡을 수 있습니다.

김개발 씨는 고민 끝에 결정을 내렸습니다. 회사의 메일 트래픽이 하루 5만 통이 넘기 때문에 Rspamd를 선택하기로 했습니다.

물론 SpamAssassin의 풍부한 룰셋도 함께 활용할 계획입니다.

실전 팁

💡 - 소규모 서버라면 SpamAssassin으로 시작하고, 트래픽이 늘면 Rspamd로 전환을 고려하세요

  • Rspamd는 웹 UI를 기본 제공하여 모니터링이 편리합니다

2. 스팸 점수 시스템 이해

스팸 필터를 설치한 김개발 씨는 이상한 점을 발견했습니다. 어떤 메일은 스팸 점수가 3.2점이고, 어떤 메일은 15.7점입니다.

"이 점수는 대체 어떻게 계산되는 거지?" 김개발 씨의 궁금증이 시작되었습니다.

스팸 점수 시스템은 여러 가지 검사 규칙을 적용하여 각 규칙에 해당할 때마다 점수를 부여하는 방식입니다. 마치 시험에서 오답마다 감점을 받는 것처럼, 스팸의 특징이 발견될 때마다 점수가 쌓입니다.

최종 점수가 임계값을 넘으면 해당 메일은 스팸으로 분류됩니다.

다음 코드를 살펴봅시다.

# SpamAssassin 룰별 점수 확인 예제
# 메일 헤더에서 점수 분석

import re

def parse_spam_score(email_headers):
    # X-Spam-Status 헤더에서 점수 추출
    status = email_headers.get('X-Spam-Status', '')

    # 총점 추출: "score=7.3"
    score_match = re.search(r'score=([0-9.]+)', status)
    total_score = float(score_match.group(1)) if score_match else 0

    # 개별 룰 점수 추출
    # 형식: "RULE_NAME=2.1, OTHER_RULE=1.5"
    rules = re.findall(r'([A-Z_]+)=([0-9.]+)', status)

    return {
        'total': total_score,
        'rules': {rule: float(score) for rule, score in rules},
        'is_spam': total_score >= 5.0
    }

# 사용 예시
headers = {'X-Spam-Status': 'Yes, score=7.3 BAYES_99=3.5, HTML_IMAGE_RATIO=1.8, MISSING_MID=2.0'}
result = parse_spam_score(headers)

박시니어 씨가 김개발 씨 옆에 앉았습니다. "점수 시스템이 궁금하구나?

이건 스팸 필터링의 핵심이야. 잘 이해해두면 좋아." 스팸 점수 시스템을 이해하려면 먼저 시험 채점을 떠올려보면 됩니다.

학교에서 시험을 볼 때 여러 문제가 있고, 각 문제마다 배점이 다릅니다. 스팸 필터도 마찬가지입니다.

수십에서 수백 개의 검사 규칙이 있고, 각 규칙마다 점수가 다릅니다. 예를 들어 BAYES_99라는 규칙은 베이지안 필터가 99퍼센트 이상의 확률로 스팸이라고 판단했을 때 적용됩니다.

이 규칙의 기본 점수는 3.5점입니다. HTML_IMAGE_RATIO는 메일 본문에 텍스트 대비 이미지가 너무 많을 때 적용되며 약 1.8점입니다.

이런 규칙들이 하나씩 적용될 때마다 점수가 쌓입니다. 최종 점수가 임계값인 5점을 넘으면 그 메일은 스팸으로 분류됩니다.

임계값은 관리자가 조정할 수 있는데, 낮추면 더 많은 메일이 스팸으로 분류되고, 높이면 더 적은 메일이 스팸으로 분류됩니다. 점수 시스템의 장점은 유연성입니다.

단 하나의 규칙만으로 스팸을 판단하면 오탐이 많아집니다. 하지만 여러 규칙의 점수를 합산하면 종합적인 판단이 가능합니다.

마치 의사가 여러 검사 결과를 종합해서 진단을 내리는 것과 같습니다. 코드를 살펴보면, X-Spam-Status 헤더에서 정보를 추출하고 있습니다.

스팸 필터는 검사 결과를 이 헤더에 기록합니다. 총점과 함께 어떤 규칙이 적용되었는지도 확인할 수 있습니다.

이 정보는 디버깅할 때 매우 유용합니다. 실무에서 중요한 것은 임계값 설정입니다.

너무 낮게 설정하면 정상 메일도 스팸으로 분류되는 **오탐(False Positive)**이 증가합니다. 반대로 너무 높게 설정하면 스팸이 통과하는 **미탐(False Negative)**이 늘어납니다.

일반적으로 5점을 기본값으로 사용하고, 상황에 따라 조정합니다. 고객 문의 메일을 받는 서버라면 오탐을 줄이기 위해 6점이나 7점으로 올리기도 합니다.

반대로 내부용 서버라면 4점으로 낮춰서 스팸을 철저히 걸러내기도 합니다. 김개발 씨는 점수 시스템을 이해하고 나니 스팸 필터가 어떻게 동작하는지 명확해졌습니다.

이제 각 규칙의 점수를 조정하면 필터의 동작을 세밀하게 제어할 수 있다는 것도 알게 되었습니다.

실전 팁

💡 - X-Spam-Status 헤더를 분석하면 왜 해당 메일이 스팸으로 분류되었는지 알 수 있습니다

  • 임계값은 한 번에 크게 변경하지 말고 0.5점씩 조금씩 조정하세요

3. 베이지안 필터 학습

김개발 씨가 스팸 필터를 운영한 지 일주일이 지났습니다. 그런데 이상한 현상이 발견되었습니다.

처음에는 잘 걸러지던 스팸이 점점 통과하기 시작한 것입니다. 박시니어 씨가 말했습니다.

"베이지안 필터를 학습시켜야 해."

베이지안 필터는 확률 기반으로 스팸을 판별하는 기술입니다. 과거의 스팸 메일과 정상 메일을 학습하여 새로운 메일이 스팸일 확률을 계산합니다.

마치 오랜 경험을 통해 사기꾼을 알아보는 베테랑 형사와 같습니다. 학습량이 많을수록 판별 정확도가 높아집니다.

다음 코드를 살펴봅시다.

# SpamAssassin 베이지안 필터 학습 스크립트
import subprocess
import os

def train_bayes_spam(spam_folder):
    """스팸 메일로 베이지안 필터 학습"""
    # sa-learn 명령어로 스팸 학습
    result = subprocess.run(
        ['sa-learn', '--spam', spam_folder],
        capture_output=True, text=True
    )
    return result.stdout

def train_bayes_ham(ham_folder):
    """정상 메일(햄)로 베이지안 필터 학습"""
    result = subprocess.run(
        ['sa-learn', '--ham', ham_folder],
        capture_output=True, text=True
    )
    return result.stdout

def check_bayes_status():
    """베이지안 데이터베이스 상태 확인"""
    result = subprocess.run(
        ['sa-learn', '--dump', 'magic'],
        capture_output=True, text=True
    )
    # 학습된 토큰 수와 메일 수 반환
    return result.stdout

# 사용 예시
train_bayes_spam('/var/mail/spam/')
train_bayes_ham('/var/mail/inbox/')
print(check_bayes_status())

베이지안 필터라는 이름이 어렵게 느껴질 수 있습니다. 하지만 원리는 생각보다 단순합니다.

18세기 영국의 수학자 토마스 베이즈가 만든 확률 이론을 메일 필터링에 적용한 것입니다. 쉽게 설명해보겠습니다.

여러분이 편지를 많이 받는다고 가정해봅시다. 어느 날 "무료", "당첨", "지금 바로"라는 단어가 가득한 편지를 받았습니다.

경험상 이런 편지는 대부분 광고였습니다. 그래서 이 편지도 광고일 가능성이 높다고 판단합니다.

이것이 바로 베이지안 필터의 원리입니다. 베이지안 필터는 과거에 받은 스팸 메일에서 자주 등장하는 단어들을 기억합니다.

"비아그라", "복권", "무료 선물" 같은 단어들이 스팸에서 자주 나타났다면, 이 단어들이 포함된 새 메일은 스팸일 확률이 높다고 판단합니다. 반대로 정상 메일에서 자주 등장하는 단어들도 학습합니다.

"회의", "보고서", "검토 부탁" 같은 단어가 많은 메일은 정상 메일일 확률이 높습니다. 이렇게 스팸 단어와 정상 단어의 확률을 종합하여 최종 판정을 내립니다.

중요한 점은 학습이 필요하다는 것입니다. 베이지안 필터는 처음에는 아무것도 모릅니다.

스팸 메일과 정상 메일을 충분히 학습시켜야 제대로 동작합니다. SpamAssassin의 경우 최소 200통의 스팸과 200통의 정상 메일을 학습시키는 것을 권장합니다.

코드를 보면 sa-learn 명령어를 사용합니다. --spam 옵션은 해당 폴더의 메일을 스팸으로 학습시키고, --ham 옵션은 정상 메일로 학습시킵니다.

여기서 **햄(ham)**은 스팸의 반대말로, 정상 메일을 의미합니다. 실무에서 주의할 점이 있습니다.

학습 데이터의 균형이 중요합니다. 스팸만 많이 학습시키면 정상 메일도 스팸으로 오인하기 쉽습니다.

반대로 정상 메일만 학습시키면 스팸을 놓치게 됩니다. 스팸과 햄을 비슷한 비율로 학습시켜야 합니다.

또 하나 중요한 것은 자동 학습(auto-learn) 기능입니다. SpamAssassin은 점수가 매우 높은 메일은 자동으로 스팸으로 학습하고, 점수가 매우 낮은 메일은 자동으로 햄으로 학습합니다.

이렇게 하면 시간이 지날수록 필터가 똑똑해집니다. 김개발 씨는 지난 한 달간 쌓인 스팸 메일과 정상 메일을 모아 학습을 시작했습니다.

2시간 후, 5천 통의 메일 학습이 완료되었습니다. 다음 날부터 스팸 탐지율이 눈에 띄게 향상되었습니다.

실전 팁

💡 - 베이지안 데이터베이스는 주기적으로 백업해두세요. 학습 데이터가 날아가면 처음부터 다시 시작해야 합니다

  • 오탐이 발생한 메일은 수동으로 햄으로 재학습시키면 비슷한 메일의 오탐을 줄일 수 있습니다

4. RBL DNSBL 블랙리스트 연동

어느 날 김개발 씨는 특정 IP에서 하루에 수천 통의 스팸이 쏟아지는 것을 발견했습니다. 일일이 차단하기도 힘들고, 새로운 스팸 발송 IP가 계속 나타납니다.

박시니어 씨가 해결책을 알려주었습니다. "RBL을 연동해봐.

전 세계 스팸 발송 IP 목록을 실시간으로 활용할 수 있어."

RBL(Real-time Blackhole List) 또는 **DNSBL(DNS-based Blackhole List)**은 스팸 발송으로 알려진 IP 주소 목록을 DNS 방식으로 제공하는 서비스입니다. 마치 전 세계 경찰이 공유하는 수배자 명단과 같습니다.

메일이 도착하면 발송 서버의 IP가 이 명단에 있는지 실시간으로 확인합니다.

다음 코드를 살펴봅시다.

# Rspamd RBL 설정 예제 (rbl.conf)
# SpamAssassin은 기본적으로 여러 RBL을 사용함

rbls {
    # Spamhaus ZEN (무료 사용 제한 있음)
    spamhaus {
        symbol = "RBL_SPAMHAUS";
        rbl = "zen.spamhaus.org";
        ipv4 = true;
        ipv6 = true;
    }

    # Barracuda RBL
    barracuda {
        symbol = "RBL_BARRACUDA";
        rbl = "b.barracudacentral.org";
    }
}

# Python으로 RBL 조회하기
import dns.resolver

def check_rbl(ip_address, rbl_server):
    """IP가 RBL에 등록되어 있는지 확인"""
    # IP를 역순으로 변환 (1.2.3.4 -> 4.3.2.1)
    reversed_ip = '.'.join(reversed(ip_address.split('.')))
    query = f"{reversed_ip}.{rbl_server}"

    try:
        dns.resolver.resolve(query, 'A')
        return True  # 블랙리스트에 등록됨
    except dns.resolver.NXDOMAIN:
        return False  # 등록되지 않음

# 사용 예시
ip = "192.168.1.100"
is_blocked = check_rbl(ip, "zen.spamhaus.org")
print(f"IP {ip} 블랙리스트 여부: {is_blocked}")

인터넷에는 스팸만 전문적으로 발송하는 서버들이 있습니다. 이런 서버들의 IP 주소는 보안 커뮤니티에서 수집하고 공유합니다.

RBL은 바로 이런 정보를 실시간으로 활용할 수 있게 해주는 서비스입니다. RBL의 동작 원리를 살펴보겠습니다.

메일이 도착하면 스팸 필터는 발송 서버의 IP 주소를 추출합니다. 그리고 이 IP를 RBL 서버에 조회합니다.

조회 방식이 독특한데, DNS 프로토콜을 사용합니다. 예를 들어 192.0.2.1이라는 IP를 spamhaus에서 조회한다고 가정해봅시다.

먼저 IP를 역순으로 뒤집어 1.2.0.192로 만듭니다. 그리고 RBL 도메인을 붙여 1.2.0.192.zen.spamhaus.org를 DNS로 조회합니다.

응답이 오면 블랙리스트에 등록된 것이고, NXDOMAIN(존재하지 않음) 응답이 오면 등록되지 않은 것입니다. DNS를 사용하는 이유는 속도 때문입니다.

DNS 조회는 매우 빠르고, 전 세계에 캐시 서버가 분산되어 있어 부하도 적습니다. 수천 통의 메일을 처리하면서도 실시간 조회가 가능합니다.

주요 RBL 서비스를 알아보겠습니다. Spamhaus ZEN은 가장 유명하고 신뢰도가 높습니다.

SBL(스패머), XBL(악성코드 감염), PBL(동적 IP) 목록을 통합 제공합니다. Barracuda도 많이 사용됩니다.

SORBS, SpamCop 등도 있습니다. 주의할 점이 있습니다.

RBL마다 정책과 정확도가 다릅니다. 어떤 RBL은 공격적으로 IP를 등록해서 오탐이 많고, 어떤 RBL은 보수적이어서 스팸을 놓치기도 합니다.

따라서 여러 RBL을 조합해서 사용하고, 각각에 다른 점수를 부여하는 것이 좋습니다. 코드를 보면 Python의 dnspython 라이브러리를 사용하여 RBL을 조회합니다.

IP를 역순으로 변환하고 RBL 서버 주소를 붙여 DNS 조회를 수행합니다. 실제 스팸 필터에서는 이런 조회를 자동으로 수행합니다.

무료 RBL 서비스에는 사용량 제한이 있는 경우가 많습니다. Spamhaus의 경우 하루 30만 쿼리 이상이면 유료 계약이 필요합니다.

대량의 메일을 처리하는 서버라면 이 점을 고려해야 합니다. 김개발 씨는 Spamhaus와 Barracuda RBL을 연동했습니다.

즉시 효과가 나타났습니다. 이미 알려진 스팸 발송 서버에서 오는 메일이 바로 걸러지기 시작했습니다.

스팸 처리량의 30퍼센트가 RBL에서 걸러졌습니다.

실전 팁

💡 - 여러 RBL을 사용하되, 각각 다른 점수를 부여하세요. 신뢰도가 높은 RBL에 높은 점수를 주면 됩니다

  • 자사 IP가 실수로 RBL에 등록되지 않았는지 주기적으로 확인하세요

5. 커스텀 룰 작성

김개발 씨 회사에 특이한 스팸이 들어오기 시작했습니다. 경쟁사를 사칭한 피싱 메일이었습니다.

기본 룰로는 잡히지 않았습니다. 박시니어 씨가 말했습니다.

"우리 회사에 맞는 커스텀 룰을 만들어야 할 때가 됐어."

커스텀 룰은 기본 제공되는 규칙 외에 관리자가 직접 작성하는 스팸 탐지 규칙입니다. 마치 경비원에게 "우리 건물에 특별히 조심해야 할 사람이 있어요"라고 알려주는 것과 같습니다.

회사 특성에 맞는 맞춤형 필터링이 가능해집니다.

다음 코드를 살펴봅시다.

# SpamAssassin 커스텀 룰 예제 (local.cf)

# 본문에 특정 문구 포함 시 점수 부여
body     COMPETITOR_PHISHING  /경쟁사이름.*계정.*확인/i
describe COMPETITOR_PHISHING  경쟁사 사칭 피싱 의심
score    COMPETITOR_PHISHING  5.0

# 헤더 검사 룰
header   SUSPICIOUS_SENDER  From =~ /support@.*경쟁사\.com/i
describe SUSPICIOUS_SENDER  의심스러운 발신자 주소
score    SUSPICIOUS_SENDER  3.0

# 메타 룰 (여러 조건 조합)
meta     DEFINITE_PHISHING  COMPETITOR_PHISHING && SUSPICIOUS_SENDER
describe DEFINITE_PHISHING  확실한 피싱 메일
score    DEFINITE_PHISHING  10.0

# Rspamd Lua 커스텀 룰 예제
local rspamd_regexp = require "rspamd_regexp"

local function check_custom_spam(task)
    local dominated = task:get_from(1)
    if dominated and dominated[1] then
        local from = dominated[1].addr
        if from:match("경쟁사%.com$") then
            return true, 1.0, "의심스러운 발신자"
        end
    end
    return false
end

rspamd_config:register_symbol({
    name = "CUSTOM_SPAM_CHECK",
    callback = check_custom_spam,
    score = 5.0
})

기본 제공되는 스팸 룰은 전 세계 공통으로 발생하는 스팸을 대상으로 합니다. 하지만 각 회사에는 고유한 스팸 패턴이 있습니다.

경쟁사 사칭, 특정 키워드를 포함한 악성 메일, 업계 특유의 피싱 등이 그렇습니다. SpamAssassin의 룰 문법을 살펴보겠습니다.

기본 구조는 세 줄로 이루어집니다. 첫 번째 줄은 룰 타입과 이름, 그리고 패턴입니다.

두 번째 줄은 describe로 룰에 대한 설명입니다. 세 번째 줄은 score로 이 룰이 적용될 때 부여할 점수입니다.

body 룰은 메일 본문을 검사합니다. 정규표현식을 사용하여 특정 패턴을 찾습니다.

위 예제에서는 "경쟁사이름"과 "계정", "확인"이 함께 나타나는 패턴을 찾습니다. 이런 조합은 피싱 메일의 전형적인 특징입니다.

header 룰은 메일 헤더를 검사합니다. From, Subject, Reply-To 등 다양한 헤더를 검사할 수 있습니다.

위 예제에서는 발신자 주소가 경쟁사 도메인을 포함하는지 확인합니다. meta 룰은 다른 룰들을 조합합니다.

AND, OR, NOT 등의 논리 연산자를 사용할 수 있습니다. 위 예제에서는 본문 패턴과 헤더 패턴이 모두 일치할 때만 적용됩니다.

이렇게 하면 더 정확한 탐지가 가능합니다. Rspamd는 Lua 스크립트로 더 복잡한 룰을 작성할 수 있습니다.

Lua는 프로그래밍 언어이므로 조건문, 반복문, 함수 등을 자유롭게 사용할 수 있습니다. 외부 API를 호출하거나 데이터베이스를 조회하는 것도 가능합니다.

커스텀 룰을 작성할 때 주의할 점이 있습니다. 너무 광범위한 패턴은 오탐을 유발합니다.

예를 들어 "무료"라는 단어만으로 스팸을 판단하면 정상적인 비즈니스 메일도 걸릴 수 있습니다. 가능한 구체적인 패턴을 사용해야 합니다.

점수 설정도 중요합니다. 단독으로 스팸을 확정할 수 있는 룰이면 높은 점수를, 보조적인 판단 기준이면 낮은 점수를 부여합니다.

그리고 반드시 테스트 기간을 거쳐야 합니다. 과거 메일에 룰을 적용해보고 오탐 여부를 확인하세요.

김개발 씨는 커스텀 룰을 작성하고 지난 한 달간의 메일에 테스트를 돌렸습니다. 경쟁사 사칭 메일 47통이 정확히 탐지되었고, 오탐은 단 2건이었습니다.

룰을 조금 수정한 후 실제 운영에 적용했습니다.

실전 팁

💡 - 커스텀 룰은 반드시 테스트 환경에서 충분히 검증한 후 운영에 적용하세요

  • 정규표현식 테스트 도구를 활용하면 패턴 작성이 쉬워집니다

6. 오탐지 처리 및 화이트리스트

드디어 안정적으로 운영되던 스팸 필터에 문제가 생겼습니다. 중요한 고객사의 메일이 스팸으로 분류된 것입니다.

고객이 "왜 답장이 없냐"고 항의했고, 영업팀에서 난리가 났습니다. 김개발 씨는 식은땀을 흘리며 해결책을 찾아야 했습니다.

**오탐(False Positive)**은 정상 메일을 스팸으로 잘못 분류하는 것입니다. 스팸 필터에서 가장 심각한 문제입니다.

이를 방지하기 위해 화이트리스트를 설정합니다. 마치 VIP 손님 명단을 만들어 경비원에게 주는 것과 같습니다.

명단에 있는 사람은 검사 없이 바로 통과시킵니다.

다음 코드를 살펴봅시다.

# SpamAssassin 화이트리스트 설정 (local.cf)

# 특정 발신자 화이트리스트
whitelist_from  *@trusted-partner.com
whitelist_from  ceo@important-client.co.kr

# 특정 도메인 화이트리스트 (와일드카드)
whitelist_from  *@*.government.go.kr

# 점수 조정 (완전 면제가 아닌 점수 감소)
score USER_IN_WHITELIST -100

# Rspamd 화이트리스트 설정 (whitelist.conf)
whitelist {
    rules {
        "WHITELIST_PARTNER" {
            from = "/.*@trusted-partner\\.com$/";
            score = -10.0;
        }
    }
}

# Python 오탐 처리 자동화 스크립트
import subprocess
import os

def rescue_false_positive(message_path, learn_as_ham=True):
    """오탐된 메일 복구 및 재학습"""

    # 1. 스팸 폴더에서 받은편지함으로 이동
    inbox_path = message_path.replace('/spam/', '/inbox/')
    os.rename(message_path, inbox_path)

    # 2. 베이지안 필터에 햄으로 재학습
    if learn_as_ham:
        subprocess.run(['sa-learn', '--ham', inbox_path])

    # 3. 발신자를 화이트리스트에 추가 (선택적)
    return inbox_path

def add_to_whitelist(email_address, config_path='/etc/spamassassin/local.cf'):
    """발신자를 화이트리스트에 추가"""
    with open(config_path, 'a') as f:
        f.write(f"\nwhitelist_from {email_address}")

스팸 필터 운영에서 가장 무서운 것은 미탐이 아니라 오탐입니다. 스팸이 통과하면 귀찮지만, 정상 메일이 스팸으로 분류되면 비즈니스에 직접적인 손해가 발생합니다.

중요한 계약서가 스팸함에 묻혀버린다면 어떻게 될까요? 오탐이 발생하는 원인은 다양합니다.

정상적인 마케팅 메일인데 스팸과 비슷한 단어를 사용하는 경우, 해외에서 온 메일인데 발송 서버가 RBL에 등록된 경우, 첨부파일이 많아서 의심받는 경우 등이 있습니다. 오탐을 발견하면 어떻게 해야 할까요?

세 단계로 처리합니다. 첫째, 해당 메일을 스팸함에서 꺼내 받은편지함으로 복구합니다.

사용자가 직접 할 수도 있고, 관리자가 대신 해줄 수도 있습니다. 둘째, 베이지안 필터에 햄으로 재학습시킵니다.

이렇게 하면 비슷한 패턴의 메일이 다시 오탐되는 것을 방지할 수 있습니다. sa-learn --ham 명령어를 사용합니다.

셋째, 필요하다면 발신자나 도메인을 화이트리스트에 등록합니다. 화이트리스트에 등록된 발신자의 메일은 스팸 검사를 통과하거나 매우 낮은 점수를 받습니다.

화이트리스트 설정 방법을 알아보겠습니다. SpamAssassin에서는 whitelist_from 지시어를 사용합니다.

특정 이메일 주소나 도메인을 지정할 수 있고, 와일드카드도 사용 가능합니다. *.government.go.kr처럼 설정하면 정부 기관 도메인 전체를 화이트리스트에 등록할 수 있습니다.

Rspamd에서는 whitelist.conf 파일에 설정합니다. 정규표현식을 사용하여 더 복잡한 패턴도 지정할 수 있습니다.

점수를 음수로 설정하면 해당 발신자의 메일 점수가 낮아져 스팸으로 분류될 확률이 줄어듭니다. 화이트리스트를 남용하면 안 됩니다.

너무 많은 도메인을 화이트리스트에 등록하면 보안 허점이 생깁니다. 화이트리스트에 등록된 도메인을 사칭한 스팸이 통과할 수 있기 때문입니다.

정말 필요한 경우에만 등록하고, 주기적으로 검토해야 합니다. 더 안전한 방법은 SPF, DKIM, DMARC와 같은 이메일 인증 기술과 연동하는 것입니다.

화이트리스트와 함께 발신자 인증을 확인하면 사칭 메일을 걸러낼 수 있습니다. 김개발 씨는 고객사 도메인을 화이트리스트에 등록하고, 해당 메일을 햄으로 재학습시켰습니다.

그리고 오탐 발생 시 빠르게 대응할 수 있는 프로세스를 문서화했습니다. 영업팀에게도 스팸함을 주기적으로 확인해달라고 요청했습니다.

실전 팁

💡 - 화이트리스트는 최소한으로 유지하고, 분기별로 검토하여 불필요한 항목은 제거하세요

  • 사용자가 직접 스팸 신고와 오탐 신고를 할 수 있는 시스템을 구축하면 필터 정확도가 향상됩니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#SpamAssassin#Rspamd#EmailSecurity#BayesianFilter#Antispam,Security

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.