내가 얻지 못한 호환성 주장
요약
Fediverse 인스턴스 관리 서비스인 Sentinel Signup을 운영하며 겪은 기술적 호환성 문제와 인프라 이슈를 다룹니다. Mastodon 중심의 문서화로 인한 Fediverse 범용성 부족, CPU 명령어 세트 미지원 문제, 그리고 프록시 환경에서의 IP 식별 오류를 분석합니다.
핵심 포인트
- Fediverse는 Mastodon 외에도 다양한 소프트웨어 조합으로 구성됨
- GoToSocial 실행 시 특정 CPU 명령어 세트(x86-64-v2) 요구 확인 필요
- Cloudflare 등 CDN 사용 시 클라이언트 실제 IP 식별 문제 발생 가능
- API 응답이 정상이라도 IP 평판 등 보안 데이터가 유실될 수 있음
Open Feed Network (Candor Network)의 설립자인 Ronny Cruz Alvarez가 작성했습니다. 1인 창업자로서, 하나의 프로덕션 플랫폼, 그리고 — 이번 주 기준으로 — 아주 작은 Fediverse 인스턴스를 운영하고 있습니다.
제 README에 적힌 문구
Sentinel Signup은 Fediverse 인스턴스를 위한 등록 심사 서비스입니다. 이 서비스는 보류 중인 가입 대기열을 읽고, 각 지원자를 점수화하며, 관리자 API를 통해 승인하거나 거부합니다.
제가 이것을 출시했을 때가 7월 스팸 물결이었습니다. 당시 인스턴스 관리자들은 가짜 승인 요청에 파묻혀 있었습니다.
제가 이 서비스와 함께 배포했던 설정 지침은 다음과 같습니다:
Mastodon: Preferences → Development → New application, scopes
admin:read admin:write.
다시 읽어보세요. 제품은 _Fediverse_라고 말합니다. 문서는 _Mastodon_이라고 말합니다. 이 두 단어는 같지 않으며, 그 사이의 간극은 제가 증거가 없는 주장(claim)이었습니다.
Fediverse는 하나의 소프트웨어가 아닙니다. Mastodon, GoToSocial, Akkoma, Pleroma, Misskey, Sharkey, Iceshrimp 등 수십 개의 조합으로 이루어져 있으며, 이들 대부분은
시작되기도 전에 두 가지 문제가 발생했으며, 두 가지 모두 기록할 가치가 있습니다.
CPU가 거부했습니다. GoToSocial의 표준 빌드는 번들로 포함된 ffmpeg와 SQLite를 WebAssembly 런타임인 wazero를 통해 실행하는데, wazero의 컴파일러는 x86-64-v2 명령어를 요구합니다. 제 VPS는 generic QEMU 가상 CPU로 보고되었습니다. 많은 저가형 및 구형 가상화 호스트들이 광고하는 방식이기 때문에 SSE4.2, SSSE3, POPCNT 등이 전혀 없었습니다. GoToSocial는 인터프리터 모드 (interpreter mode)로 성능을 낮추어 실행되지 않고, 의도적으로 패닉 (panic)을 일으킵니다. 저는 이 점을 존중합니다. 해결책은 시스템의 네이티브 ffmpeg를 대신 사용하는 공식 nowasm 빌드를 사용하는 것입니다. 저렴한 가상화 환경에서 무언가를 셀프 호스팅 (self-hosting)하고 있다면, 최신 명령어 세트를 가정하기 전에 /proc/cpuinfo를 확인하십시오. 제 서버는 몇 달 동안 조용히 구식 상태였습니다.
프록시가 누가 노크하고 있는지에 대해 거짓말을 했습니다. 인스턴스는 Cloudflare 뒤에 위치하며, 제 nginx 설정은 관습적인 방식으로 클라이언트 주소를 전달했습니다. CDN 뒤에서는 그 주소가 CDN의 주소가 됩니다. 즉, 지구상의 모든 가입 시도가 동일한 몇 개의 에지 (edge) IP에서 오는 것으로 나타날 것입니다.
이 문제는 그것이 실패하는 방식 때문에 깊이 고민해 볼 가치가 있습니다. 아무런 에러도 발생하지 않습니다. 스크리닝 서비스는 여전히 판결을 반환합니다. 로그도 여전히 정상적으로 보입니다. 단지 가장 가치 있는 차원, 즉 IP 평판 (IP reputation), 서브넷 속도 (subnet velocity), 버스트 탐지 (burst detection) — 봇 팜 (bot farm)을 잡아내는 모든 신호들이
GET /api/v2/admin/accounts— 200GET /api/v1/admin/accounts(폴백 경로 (the fallback path)) — 200GET /api/v2/instance— 200POST /api/v1/admin/accounts/{id}/reject— 200
그다음, 이 제품이 GoToSocial에서 실제로 유용할지 여부를 결정짓는 질문이 있었습니다: 관리자 API (admin API)가 가입 IP를 노출하는가? Mastodon은 노출합니다. 만약 GoToSocial가 그렇지 않다면, GTS 인스턴스에서 Sentinel은 사용자 이름과 애플리케이션 텍스트만으로 작동해야 할 것이며 — 여전히 의미는 있겠지만 방어력의 극히 일부에 불과할 것이고, 저는 이를 문서에 명시해야 했을 것입니다.
노출합니다. ip 필드에 값이 채워져서 반환되었습니다. 속도 (Velocity), 서브넷 (subnet), 평판 (reputation) 모두 정상 작동합니다. 호환성 주장은 별도의 주의 사항 없이 유지되며, — 이 부분이 중요한데 — 제가 추측했기 때문이 아니라 직접 실행해 보았기 때문에 유지되는 것입니다.
또한 문서화할 가치가 있는 두 가지 차이점도 발견했습니다. Mastodon과 달리 GoToSocial는 이메일 확인을 기다리지 않고 가입을 즉시 대기 큐 (pending queue)에 넣습니다. 그리고 GoToSocial의 관리자 CLI (admin CLI)에는 계정에 대한 delete 명령어가 아예 없으며, 오직 disable과 API를 통한 거절(rejection)만 존재합니다. 둘 다 시스템을 망가뜨리지는 않습니다. 하지만 고객 앞에서 마주했다면 둘 다 놀라운 일이었을 것입니다.
첫 번째 실제 가입
그 후, 저는 낯선 사람처럼 시크릿 창을 열어 제 인스턴스에 일회용 계정을 등록하고, 사유 (reason) 필드에 실제 문장을 작성했습니다.
30초 후, 사이드카 (sidecar)가 큐에서 이를 포착하여 실시간 스크리닝 서비스 (live screening service)로 보냈고, 다음과 같이 기록했습니다:
승인 가능 (WOULD APPROVE): @[redacted] 판정(verdict)=pass 신뢰도(confidence)=1 — 깨끗한 IP 이력 및 자연스러운 신청 언어.
드라이 런 (Dry run) 모드였기에 아무런 조치도 취하지 않았으며, 이는 정확히 드라이 런의 목적과 일치합니다. 하지만 전체 체인이 생애 처음으로 작동했습니다: 가입 대기 (pending signup) → 관리자 API (admin API) → 스크리닝 엔진 (screening engine) → 판정 (verdict) → 조치 결정 (action decision). 제가 개별적으로 구축했던 모든 조각이, 제가 한 번도 다뤄본 적 없는 서버 유형 위에서 함께 작동한 것입니다.
그 후 테스트 계정을 거절(Rejecting)하자 200 응답이 반환되었고 큐가 0으로 비워졌으며, 이는 부수적으로 마지막 엔드포인트 (endpoint)를 검증해 주었습니다.
일부러 드라이 런 (dry run) 상태로 남겨두었습니다
당연히 다음 단계는 이를 라이브 (live)로 전환하여 내 인스턴스가 자동으로 스크리닝 (screening)되도록 하는 것입니다. 하지만 그렇게 하지 않았습니다.
내 인스턴스는 커뮤니티가 아닙니다. 하나의 계정이자 테스트베드 (testbed)일 뿐입니다. 자동 승인 (auto-approval)을 켜는 것은 낯선 사람들이 계정을 갖게 된다는 것을 의미하며, 이는 곧 내가 연합 콘텐츠 (federated content)를 호스팅한다는 것을 의미합니다. 즉, 이미 5개의 프로덕션 서비스 (production services)가 실행 중인 머신에 중재 (moderation) 영역을 추가한다는 뜻입니다. 이것은 단순한 설정 플래그 (config flag)가 아니라 실제 의무가 따르는 중대한 결정이며, 저는 무언가를 테스트하는 부수 효과로 이 결정을 내리고 싶지 않습니다.
따라서 사이드카 (sidecar)는 드라이 런 (dry run) 상태로 계속 실행됩니다. 모든 향후 가입자는 스크리닝되어 로그에 기록되므로 저에게 관찰 데이터를 제공하지만, 승인은 여전히 인간의 결정으로 남습니다. 테스트베드로서의 가치는 충분히 확보되었습니다. 의무는 실수로 떠맡지 않습니다. 제가 원할 때 언제든 전환할 수 있습니다.
솔직한 한계점들
- 하나의 인스턴스, 하나의 가입, 나의 IP. 이는 배관 (plumbing)이 연결되었음을 증명합니다. 이것은 부하 테스트 (load test)도, 적대적 테스트 (adversarial test)도 아니며, 정확도에 대한 증거도 아닙니다. 아무도 이 인스턴스를 공격하지 않았는데, 왜냐하면 아무도 이것이 존재하는지 모르기 때문입니다.
- 하나의 버전. GoToSocial 0.22.1. API 커버리지 (coverage)는 릴리스 (release) 사이에 변동됩니다. 오늘 검증된 주장은 오늘에 대한 주장일 뿐입니다.
- "Fediverse 호환"은 여전히 과장된 주장이며, 저는 이 표현을 폐기합니다. 이제 제가 말할 수 있는 것은 다음과 같습니다: Mastodon과 GoToSocial는 검증되었습니다. Akkoma, Pleroma, Misskey, Sharkey, Iceshrimp는 테스트되지 않았습니다. 만약 당신이 이 중 하나를 운영 중이고 저와 함께 확인하고 싶다면, 기꺼이 함께 작업하겠습니다.
nowasm빌드는 미디어 처리용으로 공식적으로 지원되지 않습니다. 테스트베드용으로는 괜찮습니다. 실제 커뮤니티에 적용하기 전에 알아둘 가치가 있습니다.- 저는 빌드와 글쓰기(이 포스트 포함)를 위해 AI 도구(주로 Claude)를 적극적으로 사용합니다. 스크리닝 엔진 자체는 의도적으로 휴리스틱 (heuristic) 및 규칙 기반 (rule-based)으로 설계되었으며 루프 내에 모델 (model in the loop)을 포함하지 않습니다. 스팸 방지에 비용을 지불할 수 없는 인스턴스들을 위해 사실상 제로에 가까운 한계 비용 (marginal cost)으로 실행되어야 하기 때문입니다. 기계가 도움을 준 곳에서는 도움을 받았지만, 증거가 나오는 곳은 제 서버의 로그입니다.
Customer Zero(고객 제로)가 된다는 것의 의미
"우리를 위해 구축되었고, 여러분에게 제공됩니다"라는 문구는 안전 모듈(safety modules)이 제 플랫폼에서 분리된 이후 줄곧 사용해 온 홍보 문구였습니다. 이번 주에 이 문구는 더욱 문자 그대로의 의미를 갖게 되었습니다. 제 플랫폼의 등록 과정이 이 제품에 의해 스크리닝(screening)되고 있으며, 이제는 제가 운영하는 인프라 위의 두 번째 서버 유형도 스크리닝 대상이 되었기 때문입니다.
이것이 중요한 이유는 마케팅 때문이 아닙니다. 제가 방금 설명한 모든 격차들 — CPU, 가려진 IP(blinded IPs), 큐 동작(queue behavior), 누락된 CLI 동사(CLI verb) — 가 그렇지 않았다면 공격을 받고 있는 관리자에 의해, 최악의 순간에, 그리고 그들이 제 말을 믿고 신뢰했던 시스템 내에서 발견되었을 것이기 때문입니다. 이러한 격차들을 찾아내는 데 저는 저녁 시간 하나와 0달러를 소모했습니다. 하지만 다른 방식으로 이를 찾아내는 것은 누군가의 인스턴스(instance)를 잃게 만드는 비용을 치르게 합니다.
어떤 종류든 Fediverse 인스턴스를 운영 중인데 가입 큐(signup queue)가 스팸으로 가득 차 있다면, Sentinel Signup은 베타 기간 동안 무료입니다: signup.candortheopenfeednetwork.com. 만약 제가 검증하지 않은 것을 운영 중이라면, 저에게 알려주시고 제대로 테스트해 봅시다 — tips@candortheopenfeednetwork.com. 모든 질문에 제가 직접 답변합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기