VoIP.ms DID를 위한 자체 호스팅 SIP 포털
요약
VoIP.ms DID를 위한 자체 호스팅 SIP 포털인 'SIP Portal'을 소개합니다. 이 웹폰은 브라우저 기반으로 모든 통신 번호(전화, 문자 등)를 통합 관리하며, TURN과 HTTPS만을 사용하여 네트워크 제약 없이 안정적인 연결을 제공합니다. WebRTC와 AI 기능을 활용하여 고급 전화/문자 기능을 구현했습니다.
핵심 포인트
- WebRTC 및 자체 서버 구동으로 네트워크 제약 극복
- 사진 포함 SMS/MMS 지원 및 링크 미리보기 기능 제공
- 로컬 LLM 기반 음성 사서함, AI 요약, 가상 리셉셔니스트 구현
- TOTP MFA와 OIDC를 통한 강력한 인증 시스템 구축
안녕하세요 여러분, 이걸 한동안 작업해 왔고 이제 보여줄 준비가 되었다고 생각했습니다. 이름은 SIP Portal입니다. VoIP.ms용 자체 호스팅 웹폰입니다. 브라우저(데스크톱 또는 휴대폰)에서 열면, VoIP.ms 서브 계정을 등록하고 전화 통화, 문자 메시지, 사진, 음성 사서함, 연락처 등 모든 번호를 한 곳에서 확인할 수 있습니다. 또한 다중 사용자용이어서 집안의 모든 사람(또는 작은 사무실)이 자신의 로그인과 자신의 번호를 갖게 되며, 관리자조차도 다른 사람의 정보를 볼 수 없습니다(사용자가 로컬 사용자인 경우 비밀번호를 변경하는 경우는 제외).
제가 이것을 만든 이유
예전에는 휴대폰으로 Groundwire를 사용했는데 캐나다에 있을 때는 어느 정도 괜찮게 작동했습니다. 그러다가 해외에서 시간을 보내면서 5G/LTE에서도, 일반 가정용 Wi-Fi에서도 제 번호들에 전혀 연결할 수 없었습니다. 일부 국가와 통신사들은 SIP와 잘 맞지 않습니다. 그래서 저는 그런 것에 구애받지 않는 것을 원했습니다. 이 포털은 자체 서버에서 VoIP.ms와 통신하고, 제 브라우저는 필요할 때 TURN을 통해 오디오를 중계하며 HTTPS를 통해서만 제 서버와 통신합니다(TURN도 443 포트를 통해 실행될 수 있습니다). 따라서 네트워크 상으로는 일반 웹 트래픽과 매우 유사하게 보입니다.
기능
- WebRTC를 통해 브라우저로 전화 걸고 받기. 각 사용자는 여러 개의 회선(DID)을 가질 수 있으며, 통화하거나 문자를 보낼 번호를 선택할 수 있습니다.
- 사진이 포함된 SMS 및 MMS. 긴 문자는 잘리지 않도록 MMS로 전송되며, 링크 미리보기 기능도 제공됩니다(브라우저가 아닌 서버에서 가져옴).
- 자체 인사말을 설정하고 Whisper를 이용해 로컬에서 전사하는 음성 사서함. 클라우드가 필요 없습니다.
- 음성 사서함 및 녹화된 통화에 대한 선택적 AI 요약 기능. Ollama, llama.cpp, LM Studio 또는 정말 원한다면 OpenAI/Anthropic과 연동하여 사용할 수 있습니다.
- 몇 번 울린 후 전화를 받는 선택적 AI 리셉셔니스트. 발신자와 통화하고(Kokoro TTS + 로컬 LLM 사용, 저는 Qwen3 30B-A3B를 실행함) 이름, 콜백 번호, 이유가 포함된 적절한 메시지를 남겨줍니다.
발신자에게 이것이 가상 비서임을 미리 알리고 통화가 녹음될 수 있음을 알려주며, 저장하기 전에 발신자와 콜백 번호를 확인합니다 (새로운 번호는 음성-텍스트 변환(speech-to-text)이 자릿수를 누락하는 경향이 있어 자릿수별로 다시 읽어줍니다).
통화 제어: 알 수 없는 발신자에게는 전화가 울리기 전에 임의의 숫자를 누르도록 요구하여 대부분의 로보콜을 차단합니다. 또한 페이지 시스템과 같은 자동화된 작업을 위한 화이트리스트와 연락처보다 우수한 블랙리스트를 제공합니다. 통화 기록은 어떤 이유로 통화가 차단되었는지(잘못된 키, 키 없음, 끊김) 알려줍니다.
스케줄에 따른 또는 브라우저 연결이 안 될 때의 착신 전환 기능과 함께, 포털에서 오는 것임을 알 수 있도록 짧은 "X로부터 Y로 전화가 옵니다"라는 안내 메시지를 제공합니다.
라인별 통화 녹음(끔, 온디맨드, 항상)을 지원하며, 선택적 안내 메시지와 함께 스테레오 Opus 형식으로 전사본과 저장됩니다.
연락처는 Nextcloud (CardDAV, 원클릭 Nextcloud 로그인), Microsoft 365 또는 vCard/CSV 파일에서 읽기 전용으로 가져옵니다. 이름과 사진은 모든 곳에 표시됩니다.
인증: TOTP MFA를 사용하는 로컬 계정 또는 Identity Provider(ID 공급자)를 통한 로그인(저는 OIDC 위에서 Authentik을 사용합니다. Google, Microsoft, GitHub용 프리셋이 있습니다). 승인이 필요한 가입, 초대 링크, 이메일 비밀번호 재설정을 지원합니다.
데스크톱 앱(PWA)으로 알림 기능과 함께 설치할 수 있으며, 모든 사용자에게 데이터 내보내기 및 계정 삭제 기능을 제공합니다.
구현 내부 구조 (Under the hood)
실제 SIP 처리는 Asterisk 22가 담당하며, 통화 처리를 위해 PJSIP와 ARI를 사용하고, 설정 재로드 및 녹음을 위해 AMI를 사용합니다. 백엔드는 Node 24 + Express + TypeScript이며, 프론트엔드는 React + Vite이고, 데이터베이스는 Postgres 18이며, Nginx가 앞에 위치합니다. 음성-텍스트 변환(speech-to-text)은 Wyoming-Whisper를 사용하고, TTS는 Kokoro를 사용하며, LLM은 연결하는 곳이라면 무엇이든 사용할 수 있습니다. 네트워크 외부의 오디오를 위해서는 Cloudflare Realtime TURN 또는 자체 coturn을 사용할 수 있습니다.
Docker Compose 스택으로 실행하거나 단일 올인원 이미지(Asterisk, Postgres, Nginx, Whisper 및 coturn을 s6-overlay 아래에 포함)로 실행할 수 있습니다. 참고로 이 이미지는 Whisper 때문에 약 3.4 GB 정도 됩니다.
AI 기능은 모두 선택 사항이며, 서비스를 실행하지 않으면 깔끔하게 비활성화됩니다.
제한 사항
현재는 VoIP.ms 전용입니다. 다른 제공업체는 별도의 작업이 필요하며, 아직 손대지 못했고 다른 곳에서는 DID를 가지고 있지 않습니다.
그룹 메시지는 불가능합니다. 왜냐하면 VoIP.ms가 멤버 목록 없이 개별적인 1:1 메시지로 전달하기 때문입니다.
SIP을 위해 서버가 VoIP.ms에 도달 가능해야 하며, VoIP.ms 서브 계정은 'IP PBX / Asterisk' 장치 유형으로 설정되어야 합니다.
향후 개발 방향 (아직 구현되지 않은 기능)
같은 포털의 사용자들이 VoIP.ms를 거치지 않고 서로 무료로 통화할 수 있는 내부 확장 번호(Internal extensions)
통화를 동료의 확장 번호로 전달하는 기능
'영업(sales)' 번호처럼 세 사람에게 울리는 공유 번호/링 그룹(Shared numbers / ring groups)
누가 온라인인지 보여주는 확장 번호 디렉토리
데스크 전화기 및 SIP 앱이 확장 번호를 등록하는 것 (Yealink, Grandstream, Android/iPhone용 소프트폰 등)
확장 번호 간의 내부 채팅
캡처 화면은 데모 데이터를 사용한 제 인스턴스입니다 (이름과 번호는 가상의 것입니다. 로고는 흐릿하게 처리했습니다).
아직 공개되지 않았습니다. 제가 다른 사람들을 위해 패키징하는 작업을 시작하기 전에 관심이 있는지 궁금할 뿐입니다. 질문에 답변해 드릴 의향이 있으며, 특히 다른 VoIP.ms 사용자들의 피드백을 환영합니다. 만약 관심이 있다면, 알파(beta, gamma, delta 등 무엇이든) 테스트를 위해 앱의 경량 버전을 공개적으로 구동할 수 있습니다. 앱 개발이 완료되고 라이선스가 정리되면 오픈 소스로 출시될 것입니다.
전체 공개: 이 앱은 Claude를 사용하여 개발되었지만, 독립적으로 확인했습니다. 또한, 문제가 생길 경우에 대비하여 네트워크 활동을 확인하기 위해 별도의 서버에서 이 앱을 실행하고 있지만, 아직 아무 문제도 없습니다. 추가 보안을 위해 Palo FW의 엄격한 위협 방지 프로파일이 인바운드/아웃바운드를 통제하고 있습니다. SIP NAT 규칙은 VoIP.ms 서버가 해당 앱과 함께 SIP 포트를 통해 통신하는 것만 허용하며, 다른 용도로는 사용되지 않습니다.
submitted by /u/mdjmrc
[link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/SelfHosted (AI filter)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기