대량 스팸으로 인해 도움이 필요합니다

이 문제는 골치 아픈 싸움이었습니다. 배경 설명을 좀 드리겠습니다.

저는 상당한 화제와 관심이 모인 커뮤니티를 운영하고 있습니다. 우리 프로젝트를 추적하는 사람이 100만 명을 훨씬 넘으며, 커뮤니티 내 개발자들을 돕기 위해 Discourse 포럼을 설정했습니다. 본질적으로 이는 우리 프로젝트와 상호작용하기 위한 개발자 지원 포럼이며, 개발 관련 콘텐츠 이외의 내용은 게시할 수 없도록 규정되어 있습니다.

약 3일 전, 유명 유튜버/트위터 인물이 우리 지원 포럼에 가입하고 게시물을 작성하면 팀에서 보상이나 선물을 받을 자격이 생긴다는 잘못된 주장을 했습니다. 이는 완전히 사실이 아니며, 그 결과 3일 동안 거의 끊임없는 가입이 이어졌고 포럼에는 대량의 스팸 게시물과 주제가 올라왔습니다.

현재 하루 2,500명에서 7,500명 사이의 가입자가 발생하고 있으며, 주로 아시아와 중동 국가들(특히 2개 국가가 주요 문제 지역으로 두드러집니다)에서 유입되고 있습니다.

가입하는 사용자들은 봇과 실제 사용자의 혼합인 것으로 보입니다. 거의 모든 IP가 고유하며(IPv4와 IPv6의 건강한 혼합), IPv4 측에서 대량으로 차단하기 위한 뚜렷한 서브넷이 보이지 않습니다(IPv6의 경우 /24 블록을 차단하는 데 약간의 성과를 거두었지만, 우회가 용이해 보입니다). 이메일 주소는 모두 Gmail이며, 상당수가 일회성/봇용 이메일 주소로 보입니다. 이 계정들이 봇임을 나타내는 유일한 징후는 많은 계정이 프로필에 동일한 배너 이미지를 재사용하고, "저는 학생입니다"와 같은 일반적인 자기소개 문구를 사용한다는 점입니다.

이 목록은 문자/숫자를 변경하여 익명화했지만, 이러한 가입과 연결된 이메일 유형의 예를 들어 드리면 다음과 같습니다:

  1. syedaleem435@gmail.com
  2. kksam362@gmail.com
  3. julik8641@gmail.com
  4. eishanihal253@gmail.com
  5. subir2426@gmail.com
  6. meeagle38103@gmail.com

이 사용자들은 가입한 후 우리 커뮤니티와 무관한 새 주제를 생성합니다. 종종 이러한 주제는 단어조차 아니며, 마치 어린아이가 키보드를 부수어 놓은 것 같습니다. 주제 자체를 탐지하고 삭제하는 것은 그리 어렵지 않지만, 더 큰 문제는 기존 주제에 스팸/저품질 콘텐츠를 스팸하는 것입니다. 우리 인기 주제 중 많은 곳에 500개에서 1,500개 사이의 새 스팸/저품질 게시물이 추가되었습니다.

현재 저는 가입 기능을 완전히 비활성화했지만, 다음 사항에 대한 도움을 구하고 있습니다:

  1. 회원들을 대량으로 정리할 방법이 있나요? 지난 72시간 동안 가입한 모든 TL0 사용자를 삭제할 수 있나요?
  2. 스팸/일회성 이메일을 감지하고 해당 이메일로부터의 가입을 거부하는 방법이 있나요? 이 시점에서는 당분간 3~5자리 숫자로 끝나는 모든 이메일을 차단하는 것도 고려하고 있습니다.
  3. 자동 무음(auto-silence) 값을 3000밀리초보다 큰 값으로 설정하는 것을 권장하시나요?
  4. 대량의 스팸을 대응하는 데 도움이 되는 다른 팁이나 트릭이 있을까요? 지난 2~3일간 이것이 전일제 업무처럼 느껴졌습니다. 저는 Akismet을 사용 중인데, 저를 도울 수 있는 추가 플러그인이 있을까요?

최소 한시적으로라도 모든 카테고리의 생성/답글 권한을 TL1 또는 심지어 TL2로 설정하거나, Custom Wizard를 사용하여 신규 사용자들이 특정 조건(예: "보상을 받지 못할 수 있음을 이해합니다"라는 10개 선택지 중 하나만 정답인 문제)을 통과해야만 게시할 수 있는 그룹에 추가되도록 하는 방법을 고려해 보겠습니다.

회원가입 페이지에 여러 개의 답변 옵션이 있는 필수 멀티셀렉트 커스텀 사용자 필드를 사용하여, 그중 하나만 허용되는 방식으로 설정해 보실 수 있습니다. 이렇게 하면 봇의 속도를 조금 늦추거나, 최소한 가짜 가입자를 삭제하는 데 도움이 되는 쉽게 필터링할 수 있는 필드를 확보할 수 있을 것입니다. (참고: 다시 생각해 보니, 특정 답변을 요구하는 장치가 없어서 이 방법은 작동하지 않을 것 같습니다. 이전 답변에서 언급한 방법이 더 잘 작동할 수 있습니다.)

요즘에는 캡차(CAPTCHA) 유형의 함정이 효과적이지 않다고 느낍니다. 봇이 제가 풀기 전에 더 빨리 해결해 버리거든요.

Rails에서 새로 생성된 L0 사용자를 삭제하는 방법이 있을 것입니다. 하지만 먼저 백업을 꼭 해 두세요. 게시물을 작성했다면, 해당 게시물을 먼저 삭제해야 합니다.

다른 사용자들은 회원가입 시 2단계 인증을 요구하면 스팸을 거의 없앨 수 있다고 말합니다. 아직까지는 제가 그 방법을 동원할 필요가 없었습니다.

지금까지의 답변에 감사드립니다.

1일 동안 등록을 비활성화했을 때, 우리는 다시 숨을 고를 수 있었습니다.

@RGJ 님, 게시 권한이 있는 그룹에 추가되기 위해 거쳐야 하는 여러 단계(hoops to jump through)라는 아이디어가 좋습니다. 이것을 검토해 볼 예정입니다.

데이터 탐색기를 사용하여, 지금까지 눈에 띄지 않았던 약 5,000개의 추가 봇 계정을 식별할 수 있었습니다.

@MikeNolan 님, 아직 rails 콘솔에 액세스 권한이 있는지 불분명합니다. 우리는 discourse에서 직접 호스팅을 하고 있으며, 구매/온보딩 과정에 참여하지 않았기 때문에, 우리가 어떤 액세스 권한을 가지고 있는지 확인하기 위해 상부에 이 질문을 올리고 있습니다.

API를 통해 삭제 작업을 수행할 수도 있을 것 같습니다. API 자격 증명을 쉽게 생성할 수 있는 것을 확인했습니다.

다음과 유사한 방식으로:

import csv
import requests
import time

api_key = 'api_key'
api_username = 'api_username'
base_url = 'https://mydomain.com'
headers = {
    'Api-Key': api_key,
    'Api-Username': api_username
}

def delete_user(user_id):
    delete_url = f'{base_url}/admin/users/{user_id}.json'
    response = requests.delete(delete_url, headers=headers)
    
    if response.status_code == 200:
        print(f'Successfully deleted user {user_id}')
    else:
        print(f'Failed to delete user {user_id}. Status code: {response.status_code}, Response: {response.text}')

with open('user_ids_to_delete.csv', 'r') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        user_id = row[0]
        try:
            delete_user(user_id)
        except Exception as e:
            print(f'Error occurred while deleting user {user_id}: {e}')
        
        time.sleep(1)  # 서버에 요청이 과부하되지 않도록 지연을 추가합니다

몇 년 전, 저희 구식 포럼(phpbb3)에 가짜 가입이 대량으로 유입되었습니다. 많은 이메일 주소가 님이 나열하신 Gmail 주소와 유사했지만, .ru 도메인, 특히 Yandex에서 온 주소도 상당수 있었습니다.

한때 하루에 1,000건 이상의 가짜 가입이 발생하기도 했습니다. 사태를 통제할 때쯤이면 이미 80,000건 이상의 가짜 기록이 쌓여 있었습니다.

저희는 문제를 해결하기 위해 이미 포럼 기록 생성에 사용되지 않은 유효한 최신 회원 ID(저희 회원 시스템은 완전히 분리되어 있었습니다)를 요구하도록 설정했습니다. 이렇게 하면 회원 기록에 접근할 수 있는 사람(기록은 온라인에 있습니다)이라 하더라도 한 ID는 단 한 번만 사용할 수 있었습니다. 그 결과 가짜 가입은 사실상 제로가 되었습니다.

저는 데이터 탐색기를 충분히 사용해본 적이 없어 그 한계를 정확히 파악하지는 못했습니다. 20년 넘게 PostgreSQL DBA로 일해왔기 때문에 psql에 직접 접근하는 것은 저에게 문제가 되지 않지만,那里的 활동은 읽기 전용 쿼리로 제한해 왔습니다.

지문 추출(Fingerprinting)이 여전히 실행 가능한 기법인지, 아니면 브라우저들이 이를 사실상 무력화한 도구로 만들었는지 궁금합니다.

진짜 질문은 이 기법이 과연 실현 가능했는지가 아니에요 :wink:

(그리고 참고로: EU에서는 불법입니다)

rails에서 (docker exec -it my_container rails c):

spammers = User.where(trust_level: 0).where("created_at > ?",  Date.today - 3)
puts "found #{spammers.length} spammers"

destroyer = UserDestroyer.new(Discourse.system_user)
spammers.each do |spammer|
  destroyer.destroy(spammer, delete_posts: true)
end

스팸 방지 목적으로만 사용되며 사용자 행동 추적에는 사용되지 않는다면, GDPR에서 "정당한 이익"으로 허용됩니다.

그렇다면 본인 확인 없이 어떻게 사용하게 되나요?

‘식별’이 정확히 무엇을 의미하는지 잘 모르겠습니다.

만약 내 포럼의 사용자이고 제가 당신을 차단했다면, 지문 인식 플러그인을 통해 다른 이름으로 새 계정을 만들었는지 확인할 수 있습니다. 그러면 그 계정도 함께 차단할 수 있습니다. 이 경우 저는 포럼 운영자로서 자신의 이익을 보호하기 위해 지문 인식을 사용하는 것뿐입니다. 당신에게 무언가를 판매하는 것도 아니고, 불필요하게 당신의 사생활을 침해하는 것도 아닙니다. 이는 IP 주소를 저장하고 비교하는 것과 동일한 방식으로 작동하지만, 프록시나 VPN을 사용하면 IP 주소를 쉽게 변경할 수 있다는 점이 다릅니다.

지문 추출 플러그인 토픽의 댓글들은 지문 추출의 합법성과 EU 관련해서 여러분과 완전히 일치하지 않을 수 있습니다.

다행히도 저는 현재 지문 추출이 유용한 스팸 방지 조치로 여겨질 만한 사이트를 운영하지 않고 있습니다.

신규 사용자 승인을 켜는 것을 고려해 보셨나요? 커뮤니티에 신규 회원은 이메일 링크 초대장이 필요하다는 안내도 할 수 있습니다.

유튜버가 여전히 문제가 된다면 해당 영상을 신고하고 유튜브에 클레임을 접수하세요.

다시 돌아와서 이 문제를 마무리하겠습니다 - 이 문제는 PM을 통해 후속 조치하여 해결되었습니다. :partying_face:

하지만 유사한 상황에 있는 분들을 위해, 관리형 호스팅을 사용 중이므로 rails 콘솔에 접근 권한이 없더라도 API를 통해 사용자를 삭제할 수 있습니다. :+1: