내가 얻지 못했던 호환성
요약
Fediverso 인스턴스 운영 중 GoToSocial를 도입하며 겪은 기술적 시행착오를 다룹니다. CPU 명령어 세트 미지원으로 인한 패닉 문제와 Cloudflare 프록시 환경에서 클라이언트 IP가 왜곡되어 보안 필터링이 무력화되는 문제를 분석합니다.
핵심 포인트
- GoToSocial의 wazero 런타임은 x86-64-v2 명령어를 요구함
- 저가형 VPS 사용 시 /proc/cpuinfo를 통해 명령어 지원 여부 확인 필수
- CDN(Cloudflare) 뒤에서는 클라이언트 IP가 엣지 IP로 변조됨
- IP 기반 보안 시스템은 프록시 환경에서 평판 분석이 불가능해짐
Ronny Cruz Alvarez가 작성했습니다. Open Feed Network (Candor Network)의 설립자입니다. 창립자로서, 운영 중인 플랫폼과 —이번 주부터— 매우 작은 Fediverso 인스턴스를 보유하고 있습니다.
제 README에 적힌 한 줄
Sentinel Signup은 Fediverso 인스턴스의 레코드 필터링 서비스입니다. 보류 중인 요청 큐를 읽고, 각 신청자를 평가하며, 관리 API를 통해 승인하거나 거부합니다. 저는 7월 스팸 물결 동안 이 서비스를 출시했는데, 당시 인스턴스 관리자들이 가짜 요청에 허덕이고 있었습니다.
제가 함께 보낸 설정 지침은 다음과 같습니다:
Mastodon: 환경설정 → 개발 → 새 애플리케이션, 권한
admin:read admin:write.
다시 읽어보세요. 이 제품은 _Fediverso_라고 말합니다. 문서에는 _Mastodon_이라고 되어 있습니다. 두 단어는 같지 않으며, 그 사이의 거리는 제가 증거가 없는 주장을 하는 것이었습니다.
Fediverso는 하나의 프로그램이 아닙니다. Mastodon과 GoToSocial, Akkoma, Pleroma, Misskey, Sharkey, Iceshrimp 등 그리고 수십 개의 다른 플랫폼들로 구성되어 있으며, 이들 대부분은
제약 사항은 비용이 전혀 들지 않아야 한다는 것이었습니다. Mastodon은 무거운 세입자입니다. Ruby, Sidekiq, Redis, 그리고 자체 Postgres까지 필요하며, 제가 이를 설치하려는 머신은 이미 5개의 서비스를 프로덕션 환경에서 실행 중입니다. GoToSocial는 Go로 작성된 단일 바이너리에 SQLite를 사용하여 수백 메가바이트 정도의 메모리만 점유하며, Mastodon 클라이언트 API를 구현합니다. 그것이 바로 GoToSocial가 올바른 선택이었던 이유입니다. Mastodon이 아니기 때문에, 이것은 연습이 아닌 실제 테스트가 됩니다.
실행에 도달하기 전에 두 가지 문제가 발생했으며, 두 가지 모두 기록할 가치가 있습니다.
CPU가 거부했습니다. GoToSocial의 표준 빌드는 ffmpeg와 SQLite를 WebAssembly 런타임인 wazero를 통해 내장하여 실행하는데, wazero 컴파일러는 x86-64-v2 명령어를 요구합니다. 제 VPS는 QEMU의 범용 가상 CPU로 보고되었습니다. 즉, 많은 저가형 또는 오래된 가상화 호스트들이 광고하는 대로 SSE4.2, SSSE3, POPCNT가 없는 상태였습니다. GoToSocial는 인터프리터 모드로 성능을 낮추는 대신, 의도적으로 패닉 (panic)을 발생시키는데, 저는 이 점을 존중합니다. 해결책은 시스템의 네이티브 ffmpeg를 사용하는 공식 nowasm 빌드를 사용하는 것입니다. 만약 저렴한 가상화 환경에서 셀프 호스팅을 한다면, 최신 명령어를 당연하게 가정하기 전에 /proc/cpuinfo를 확인하십시오. 제 서버는 몇 달 동안 조용히 구형 상태로 방치되어 있었습니다.
프록시가 누가 문을 두드리는지에 대해 거짓말을 했습니다. 인스턴스는 Cloudflare 뒤에 있으며, 제 nginx 설정은 관습적인 방식으로 클라이언트 주소를 전달하고 있었습니다. CDN 뒤에서는 그 주소가 CDN의 주소가 됩니다. 즉, 지구상의 모든 레코드가 동일한 소수의 엣지 (edge) IP에서 도달하게 됩니다.
그것은 어떻게 실패하는지 그 방식 때문에 주목할 만합니다. 아무런 에러도 발생하지 않습니다. 필터링 서비스는 계속해서 판결(verdict)을 반환합니다. 로그는 계속해서 정상적으로 보입니다. 단지 가장 가치 있는 차원, 즉 IP 평판(reputation), 서브넷(subnet)별 속도, 버스트(burst) 탐지 — 봇 팜(bot farm)을 잡아내는 모든 신호가 정확히 "하나의 주소, 항상"이라는 상태로 눈이 멀어버릴 뿐입니다. 아무것도 측정하지 않으면서 성공을 보고하는 보안 시스템은 명백히 고장 난 시스템보다 더 나쁩니다. 이는 제가 새로운 모습으로 계속해서 재학습하고 있는 교훈입니다. 해결책은 CDN의 실제 클라이언트 헤더(client header)를 읽는 nginx 지시어(directive)였습니다. 습관으로 삼아야 할 점은 다음과 같습니다: 인프라에 어떤 변경이든 발생한 후에는, 요청이 단순히 200을 반환하는지 확인하는 것에 그치지 말고, 당신의 신호들이 여전히 정보를 제대로 전달하고 있는지 확인하십시오.
진정한 검증이 어떻게 이루어졌는가
노드가 실행 중이고 접근 가능한 상태에서, 저는 제 사이드카(sidecar)가 수행하는 네 가지 호출을 한 번도 테스트해 본 적 없는 서버를 대상으로 하나씩 확인했습니다:
GET /api/v2/admin/accounts— 200GET /api/v1/admin/accounts(백업 경로) — 200GET /api/v2/instance— 200POST /api/v1/admin/accounts/{id}/reject— 200
그다음, GoToSocial에서 이 제품이 정말로 쓸모가 있는지를 결정짓는 진짜 질문은 이것이었습니다: 관리 API가 등록된 IP를 노출하는가? Mastodon은 그렇습니다. 만약 GoToSocial가 그렇지 않다면, GTS Sentinel 인스턴스에서는 사용자 이름과 요청 텍스트만으로 작동하고 있을 것입니다. 이는 어느 정도 도움이 되겠지만 방어력의 극히 일부일 뿐이며, 저는 이를 문서에 명시해야 했을 것입니다.
예, 노출합니다. ip 필드가 값을 반환했습니다. 속도, 서브넷, 그리고 평판이 정상 작동합니다. 호환성에 대한 주장은 아무런 미묘한 차이 없이 살아남았으며 — 이것이 중요한 점인데 — 제가 그것을 가정했기 때문이 아니라, 직접 실행하여 확인했기 때문에 살아남았습니다.
또한 기록할 가치가 있는 두 가지 차이점을 발견했습니다. GoToSocial는 이메일 확인을 기다리지 않고 즉시 요청을 대기열(queue)에 배치하는데, 이는 Mastodon이 하지 않는 방식입니다. 그리고 관리용 CLI에는 계정 삭제(delete) 기능이 전혀 없으며 — 오직 비활성화(disable)와 API를 통한 거부 기능만 있습니다. 두 가지 모두 시스템을 망가뜨리지는 않습니다. 클라이언트 입장에서는 둘 다 놀라운 점이었을 것입니다.
첫 번째 실제 기록
그 후, 저는 낯선 사람처럼 시크릿 창을 열어 제 인스턴스에 일회용 계정을 등록하고, 사유(reason) 필드에 진솔한 문장을 작성했습니다.
30초 후, 사이드카(sidecar)가 대기열에서 이를 꺼내 실시간 필터링 서비스로 전송하고 다음과 같이 기록했습니다:
승인(APPROVE): @[redacted] 판정(verdict)=pass 신뢰도(confianza)=1 — 깨끗한 IP 이력 및 자연스러운 요청 언어.
테스트 모드였기 때문에 아무런 조치도 취하지 않았으며, 이는 테스트 모드의 정확한 용도이기도 합니다. 하지만 전체 파이프라인이 생애 처음으로 실행되었습니다: 요청 대기(pending request) → 관리 API(admin API) → 필터링 엔진(filtering engine) → 판정(verdict) → 조치 결정(action decision). 제가 개별적으로 구축했던 각 요소가, 제가 한 번도 다뤄본 적 없는 유형의 서버에서 함께 작동한 것입니다.
이후 테스트 계정을 거부(reject)하자 200 응답이 반환되었고 대기열이 0이 되었는데, 이는 결과적으로 마지막 엔드포인트(endpoint)를 검증해 주었습니다.
일부러 테스트 모드로 남겨두었습니다
다음 단계로 당연히 제 인스턴스에 자동으로 필터링이 적용되도록 활성화하는 것을 생각할 수 있습니다. 하지만 저는 그렇게 하지 않았습니다.
제 인스턴스는 커뮤니티가 아니라, 하나의 계정이자 테스트 베드(test bed)입니다. 자동 승인을 켠다는 것은 낯선 사람들이 계정을 얻게 된다는 것을 의미하며, 이는 제가 연합 콘텐츠(federated content)를 호스팅하게 된다는 것을 의미합니다. 즉, 이미 5개의 서비스를 프로덕션(production) 환경에서 실행 중인 머신에 모더레이션(moderation) 영역을 추가하게 된다는 뜻입니다. 이것은 단순한 설정 플래그(configuration flag)가 아니라 실제적인 의무가 따르는 실질적인 결정이며, 저는 무언가를 테스트하는 부수적인 효과로 이 결정을 내리고 싶지 않습니다.
따라서 사이드카(sidecar)는 테스트 모드로 계속 실행됩니다. 모든 미래의 로그가 필터링되고 기록되어 저에게 관찰 데이터를 제공하는 동안, 승인 여부는 여전히 인간의 결정으로 남습니다. 테스트 베드(testbed)의 가치는 완성되었습니다. 의무는 우연히 떠맡아지는 것이 아닙니다. 제가 진정으로 결정했을 때 활성화할 수 있습니다.
솔직한 한계점
- 인스턴스 하나, 로그 하나, 나의 IP 하나. 이것은 파이프라인(pipeline)이 연결되어 있음을 증명합니다. 이것은 부하 테스트(load test)도, 적대적 테스트(adversarial test)도 아니며, 정확도에 대한 증거도 아닙니다. 아무도 이 인스턴스를 공격하지 않았습니다. 왜냐하면 아직 아무도 이것이 존재한다는 사실을 모르기 때문입니다.
- 하나의 버전. GoToSocial 0.22.1. API 커버리지는 버전에 따라 변합니다. 오늘 검증된 주장은 오늘에 대한 주장일 뿐입니다.
- "페디버스(Fediverse)와 호환됨"이라는 표현은 여전히 과하며, 이를 철회합니다. 이제 제가 말할 수 있는 것은 다음과 같습니다: Mastodon과 GoToSocial는 검증되었습니다. Akkoma, Pleroma, Misskey, Sharkey, Iceshrimp는 — 테스트하지 않았습니다. 만약 당신이 이 중 하나를 운영하고 있고 저와 함께 확인해보고 싶다면, 제가 당신과 함께 작업을 수행하겠습니다.
nowasm빌드는 미디어 처리(media processing)에 대한 공식 지원이 없습니다. 테스트 베드로는 괜찮습니다. 실제 커뮤니티에 적용하기 전에 알아두어야 할 사항입니다.- AI 도구를 집중적으로 사용함 —특히 Claude— 구축과 집필을 위해 사용했으며, 이 텍스트도 포함됩니다. 필터링 엔진 자체는 의도적으로 휴리스틱(heuristic) 및 규칙 기반(rule-based)으로 설계되었으며, 모델 인 더 루프(model-in-the-loop) 방식이 아닙니다. 스팸 방지를 위해 비용을 지불할 여력이 없는 인스턴스들을 위해 사실상 제로에 가까운 한계 비용으로 작동해야 하기 때문입니다. 기계가 도움을 준 곳에서는 도움을 받았고, 증거가 나오는 곳은 제 서버의 로그입니다.
제로 클라이언트(client zero)가 된다는 것의 의미
"우리를 위해 구축되었고, 당신을 위해 제공됩니다(Construido para nosotros, disponible para ti)"는 보안 모듈이 내 플랫폼에서 추출된 이후부터 이어져 온 제안이었습니다. 이번 주에 이 말은 더욱 문자 그대로의 의미를 갖게 되었습니다. 내 플랫폼의 로그가 이 제품에 의해 필터링되고 있으며, 이제는 내가 관리하는 인프라 위의 두 번째 유형의 서버 또한 마찬가지입니다.
이것이 중요한 이유는 마케팅 때문이 아닙니다. 내가 방금 설명한 모든 허점들—CPU, 가려진 IP(IPs cegadas), 큐(queue)의 동작, CLI에서 누락된 동사(verb)—은 만약 그렇지 않았다면, 공격을 받고 있는 관리자가 최악의 순간에, 내 말을 믿었던 시스템에서 발견하게 되었을 문제들이기 때문입니다. 이 문제들을 찾는 데는 오후 한나절과 0달러가 들었습니다. 하지만 다른 방식으로 이 문제들을 발견하게 된다면, 누군가는 자신의 인스턴스(instance)를 잃게 될 것입니다.
어떤 종류든 Fediverse 인스턴스를 관리하고 있고 로그 큐(log queue)가 쓰레기로 가득 차 있다면, Sentinel Signup은 베타 기간 동안 무료입니다: signup.candortheopenfeednetwork.com. 만약 내가 검증하지 않은 무언가를 실행하고 있다면, 저에게 알려주세요. 제대로 테스트해 보겠습니다 — tips@candortheopenfeednetwork.com. 모든 답변은 제가 직접 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기