wavekat

SIP over TLS: 소프트폰 시그널링 암호화

· Eason Guo
#음성AI#SIP#개인정보

WaveKat Voice는 0.0.56부터 SIP over TLS를 지원합니다. 회선의 연결을 TLS로, 포트를 5061로 설정하면 소프트폰과 SIP 제공업체 사이의 SIP 시그널링(REGISTER, INVITE, REFER, BYE)이 모두 암호화된 연결로 오갑니다. Mac, Windows, Linux 모두에서 동작합니다.

TLS가 중요한 이유

모든 통화는 시그널링에서 시작합니다. 전화기가 제공업체에 등록하고, 누구에게 거는지 알리고, 통화를 설정합니다. 이 트래픽에는 SIP 계정, 거는 번호, 인증 과정이 담겨 있습니다. 평문 UDP로 보내면 같은 네트워크 경로에 있는 누구나 읽을 수 있습니다.

TLS는 이 트래픽을 보호하는 표준 방법입니다. WaveKat Voice와 제공업체 사이의 연결이 암호화되고, 무엇이든 보내기 전에 상대가 정말 내 제공업체인지 먼저 확인합니다. 비즈니스 전화를 맡는 소프트폰이라면 당연히 할 수 있어야 하는 일이고, 여러분의 통신을 지키는 것은 저희가 신뢰를 얻는 방법이기도 합니다. 그래서 WaveKat Voice의 모든 회선에서 TLS를 쓸 수 있습니다.

무엇이 암호화되나요

UDP / TCPTLS
REGISTER 인증 교환평문암호화
발신자, 수신자, 시각(INVITE 등)평문암호화
보류, 호전환, 통화 종료평문암호화
음성(RTP)평문평문
서버 신원 확인아니요예, 인증서로 확인
일반적인 포트50605061

가장 과소평가되는 것은 인증 행입니다. SIP는 Digest 인증(RFC 3261)을 쓰기 때문에 비밀번호 자체는 네트워크로 전송되지 않습니다. 하지만 Authorization 헤더의 response는 비밀번호로 계산한 해시입니다. UDP에서는 같은 네트워크의 누군가가 이 패킷을 잡아 오프라인으로 사전 대입 공격을 돌릴 수 있고, 약한 비밀번호는 오래 버티지 못합니다. TLS에서는 잡을 패킷이 없습니다.

SIP over TLS의 동작 원리

일반 SIP는 보통 UDP 5060 포트에서 동작합니다. 메시지 하나하나가 읽을 수 있는 텍스트로 된 별도의 패킷입니다. SIP over TLS는 SIP 자체가 아니라 그 아래의 전송 계층을 바꿉니다.

  1. 하나의 연결. 소프트폰이 제공업체와 TCP 연결을 하나 엽니다. 포트는 보통 5061입니다.
  2. 핸드셰이크. SIP 메시지를 보내기 전에 양쪽이 TLS 핸드셰이크를 합니다. 제공업체가 인증서를 제시하면, 소프트폰은 그 인증서가 신뢰할 수 있는 인증 기관(CA)까지 이어지는지, 그리고 해당 SIP 도메인에 발급된 것인지 확인합니다. 그런 다음 세션 키를 합의합니다.
  3. 터널 안의 SIP. 그 뒤로 양방향의 모든 SIP 메시지가 같은 연결 위에서 암호화되어 오갑니다. 메시지 자체에도 표시가 남습니다. Via: SIP/2.0/TLS, 그리고 ;transport=tls가 붙은 Contact입니다.
  4. 연결은 계속 유지됩니다. 등록이 이 연결을 살려 두고, 제공업체는 걸려 오는 전화를 이 연결로 다시 보냅니다. NAT 뒤에 있는 전화기가 포트 포워딩 없이도 수신 INVITE를 받을 수 있는 이유이기도 합니다.

SIP over TLS 시퀀스 다이어그램: WaveKat Voice가 5061 포트로 제공업체와 TCP 연결을 열고, TLS 핸드셰이크를 마친 뒤 SIP 도메인 기준으로 인증서를 확인합니다. 이후 REGISTER, 401 챌린지, 인증 정보가 담긴 REGISTER, 200 OK, 수신 INVITE가 모두 암호화된 연결로 전달됩니다.

TLS가 보호하는 것은 한 구간, 즉 WaveKat Voice와 제공업체 사이의 링크입니다. 제공업체가 그 통화를 다른 통신사나 공중 전화망으로 어떻게 넘기는지는 제공업체가 정합니다.

인증서는 어떻게 확인하나요

TLS가 중간자 공격을 막을 수 있는지는 인증서 확인이 얼마나 엄격한지에 달려 있습니다. 저희 방식은 이렇습니다.

  • 시스템 루트 인증서만 신뢰합니다. 운영체제의 신뢰할 수 있는 CA 목록으로 인증서를 확인합니다. 따로 번들한 인증서도, 예외도 없습니다.
  • 서버 주소가 아니라 SIP 도메인으로 확인합니다. 별도의 아웃바운드 서버를 설정했더라도, 인증서는 계정의 SIP 도메인에 발급된 것이어야 합니다. RFC 5922가 요구하는 방식입니다.
  • 실패하면 회선이 멈춥니다. 평문으로 되돌아가지 않고, “연결 중…”에서 끝없이 재시도하지도 않습니다. 회선은 오류와 함께 실패하며, 오류에는 원인과 인증서의 SHA-256 지문이 담깁니다.
security certificate not trusted: not signed by a trusted issuer (sha256:5941fb2b…)

TLS 구현은 Rust의 rustls를 쓰므로 어떤 플랫폼에서도 OpenSSL에 의존하지 않습니다.

자체 서명 인증서와 사설 CA는 지원하지 않으며, “이 인증서 신뢰” 같은 스위치도 없습니다. 제공업체가 사설 인증서를 쓴다면 그 회선은 UDP나 TCP로 두어야 합니다.

전환하기 전에 제공업체의 TLS 확인하기

앱에서 아무것도 바꾸기 전에, 표준 명령 두 개로 제공업체의 TLS가 제대로 동작할지 알 수 있습니다. 아래 출력은 2026년 9월 26일에 두 SIP 제공업체, 뉴질랜드의 2talk와 Telnyx를 대상으로 실제로 실행한 결과입니다.

1단계: TLS 호스트와 포트 찾기

일부 제공업체는 SIP over TLS용 SRV 레코드(RFC 3263)를 공개해 어떤 호스트와 포트를 써야 하는지 알려 줍니다. Telnyx가 그렇습니다.

$ dig +short SRV _sips._tcp.sip.telnyx.com
1 45 5061 sip-anycast1.telnyx.com.
1 95 5061 sip-anycast2.telnyx.com.

각 행은 우선순위, 가중치, 포트, 호스트 순입니다. 우선순위 숫자가 작을수록 먼저 쓰이고, 우선순위가 같은 레코드는 가중치에 따라 부하를 나눕니다. 여기서는 두 호스트 모두 우선순위 1, 포트 5061이므로 클라이언트는 연결을 두 호스트에 나누어 보내고, 대략 세 번 중 두 번은 sip-anycast2로 갑니다.

2talk는 SRV 레코드를 공개하지 않아서 같은 조회를 해도 아무것도 나오지 않습니다. 흔한 경우이니 제공업체 문서를 따르면 됩니다. 2talk 문서에는 lyra.2talk.co.nz, TLS 포트 5061로 나와 있습니다.

2단계: 엄격한 클라이언트처럼 인증서 확인하기

해당 호스트에 연결해 OpenSSL로 SIP 도메인 기준의 인증서 확인을 합니다. 2talk의 예입니다(출력 일부 생략).

$ openssl s_client -connect lyra.2talk.co.nz:5061 \
    -servername lyra.2talk.co.nz -verify_hostname lyra.2talk.co.nz </dev/null
depth=2 C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
depth=1 C=US, O=DigiCert Inc, OU=www.digicert.com, CN=RapidSSL TLS RSA CA G1
depth=0 CN=*.2talk.co.nz
Verification: OK
Protocol: TLSv1.3
Verify return code: 0 (ok)

여기서 세 가지를 알 수 있습니다. 인증서는 *.2talk.co.nz용 와일드카드 인증서라 lyra.2talk.co.nz를 포함하고, 인증서 체인은 DigiCert의 공개 루트까지 이어지며, 연결은 TLS 1.3입니다. 0 (ok)이면 인증서 확인을 통과할 것으로 보면 됩니다.

도메인이 틀리면 이렇게 나옵니다. 같은 서버를, 인증서가 포함하지 않는 이름으로 확인한 결과입니다.

$ openssl s_client -connect lyra.2talk.co.nz:5061 \
    -servername lyra.2talk.co.nz -verify_hostname sip.example.com </dev/null
Verification error: hostname mismatch
Verify return code: 62 (hostname mismatch)

WaveKat Voice는 이런 연결을 인증서 오류와 함께 거부합니다. 가장 자주 보게 되는 코드는 다음과 같습니다.

결과의미
0 (ok)신뢰할 수 있고, SIP 도메인에 유효한 인증서
62 (hostname mismatch)이 SIP 도메인에 발급된 인증서가 아님. 제공업체에 도메인을 확인
18, 19, 20자체 서명이거나 사설 CA가 발급. 시스템이 신뢰하지 않음
연결 거부 또는 시간 초과해당 호스트와 포트에서 TLS를 제공하지 않거나, 방화벽이 막고 있음

OpenSSL은 자체 CA 번들로 확인합니다. 대부분의 Linux에서는 그것이 시스템 저장소이지만 Mac에서는 그렇지 않은 경우가 많으니, Mac에서 나온 20은 결론이 아니라 참고로만 보세요.

3단계(선택): 인증서 지문 기록하기

WaveKat Voice의 인증서 오류에 표시된 지문과 비교하려면, 인증서의 SHA-256 지문과 만료일을 출력합니다.

$ openssl s_client -connect lyra.2talk.co.nz:5061 -servername lyra.2talk.co.nz </dev/null 2>/dev/null \
    | openssl x509 -noout -fingerprint -sha256 -enddate
sha256 Fingerprint=1D:64:FB:48:21:19:A1:CB:18:43:3B:20:9A:BB:03:96:A1:D2:43:9A:E6:F3:A4:B4:35:3A:33:86:E4:E0:E4:8F
notAfter=Feb 18 23:59:59 2027 GMT

OpenSSL은 콜론이 들어간 대문자로 출력하고, WaveKat Voice는 콜론 없는 소문자로 보여 줍니다. 16진수 숫자는 같습니다. 제공업체가 인증서를 갱신하면 지문이 바뀌는데, 이는 정상입니다.

설정 방법

  1. 제공업체 문서에서 TLS용 호스트 이름과 포트를 찾습니다. 대부분 5061을 쓰고, TLS용 호스트 이름을 따로 두는 곳도 있습니다. 예를 들어 뉴질랜드의 제공업체 2talk는 문서에 5061로 안내합니다.
  2. 회선을 열고 연결을 TLS로 설정합니다. 포트 칸에 5061이 제안됩니다.
  3. 계정의 SIP 도메인이 제공업체가 알려 준 값과 정확히 같은지 확인합니다. 인증서는 이 이름을 기준으로 확인됩니다.
  4. 저장합니다. 회선이 TLS로 다시 등록됩니다.

흔한 함정이 하나 있습니다. 연결을 TCP로 두고 포트만 5061로 바꾸면 TLS가 아닙니다. TLS 핸드셰이크를 기다리는 포트에 평문 SIP를 보내는 셈이라 등록이 실패합니다.

회선 설정은 WaveKat 계정에 동기화되므로, 다른 컴퓨터에서 로그인해도 그 회선은 여전히 TLS입니다.

정말 TLS인지 확인하기

회선의 연결 정보 아래에 기술 정보 링크가 있습니다. 이 페이지는 입력한 값이 아니라 실행 중인 연결에 실제로 적용된 값을 보여 줍니다.

  • 연결이 TLS입니다.
  • 수신 주소가 ;transport=tls로 끝납니다.
  • SIP 메시지에서 모든 Via가 SIP/2.0/TLS입니다.

Ubuntu의 WaveKat Voice: 회선의 기술 정보 페이지. 실제 적용된 연결이 TLS이고, 이 기기의 수신 주소가 transport=tls로 표시됩니다.

이 회선에서 보내는 REGISTER는 대략 다음과 같습니다(스크린샷과 같은 데모 회선의 예시).

Via: SIP/2.0/TLS 192.0.2.24:5066;branch=z9hG4bK…
Contact: <sip:[email protected]:5066;transport=tls>

확인할 수 없는 암호화는 믿는 수밖에 없습니다. 그래서 TLS는 실제로 쓰이는 전송 방식을 볼 수 있는 이 페이지와 함께 나왔습니다.

SIP 메시지 로그는 메모리에만 있습니다. 디스크에 기록되지 않고, 앱을 종료하면 사라집니다. Authorization과 Proxy-Authorization 헤더의 response는 기록할 때 지워지므로, 로그를 복사해 누구에게 보내더라도 비밀번호 해시가 새어 나가지 않습니다.

문제 해결

증상예상 원인해결 방법
“Your provider’s server didn’t prove it is who it says it is”(제공업체 서버가 자신의 신원을 증명하지 못했습니다)SIP 도메인이 인증서와 맞지 않거나, 제공업체가 사설 인증서를 사용SIP 도메인을 확인하세요. 사설 인증서라면 공개적으로 신뢰되는 인증서를 쓰는 접속 지점이 있는지 제공업체에 문의하세요
“The secure connection to your provider couldn’t be set up”(제공업체와의 보안 연결을 설정하지 못했습니다)포트가 틀렸거나(흔히 5060), 해당 호스트 이름에서 TLS를 제공하지 않음제공업체 문서에 나온 포트와 호스트 이름을 쓰세요
전환한 뒤 아예 등록되지 않음TCP + 5061이거나, 방화벽이 아웃바운드 5061을 막음연결을 TLS로 설정하고, 아웃바운드 TCP 5061을 허용하세요
잘 되다가 등록이 풀린 채로 있음TLS 연결이 끊긴 뒤(제공업체 재시작, 라우터의 유휴 연결 정리) 다시 맺어지지 않음회선에서 다시 로그인을 누르세요

(이 두 오류 메시지는 영어로만 제공되며, 한국어 화면에서도 영어 원문으로 표시됩니다.)

알려진 제한: TLS가 끊긴 뒤 자동으로 다시 연결하지 않음

UDP에는 끊길 연결이 없어서 네트워크가 잠깐 흔들려도 티가 나지 않습니다. TLS는 오래 유지되는 연결 하나입니다. 제공업체가 재시작하거나 라우터가 연결을 정리하면, 다시 로그인을 누를 때까지 회선은 등록되지 않은 상태로 남습니다. 사람이 지켜보지 않아도 전화를 받아야 하는 회선이라면(예를 들어 밤새 통화 플로우가 받는 회선), 전환하기 전에 이 점을 고려하세요.

자주 묻는 질문

회선 하나에만 TLS를 켤 수 있나요?

네. 연결은 회선별 설정이라, 회선마다 UDP, TCP, TLS를 따로 고를 수 있습니다.

꼭 5061 포트를 써야 하나요?

아니요. 5061은 SIP over TLS의 기본 포트이지만, 제공업체 문서를 따르세요. 다른 포트나 별도의 호스트 이름을 쓰는 곳도 있습니다.

5061 포트에 TCP로 연결하면 TLS와 같은가요?

아니요. 그러면 TLS 포트에 평문 SIP를 보내게 되어 등록이 실패합니다. 연결을 TLS로 설정하세요.

어떤 TLS 버전을 지원하나요?

TLS 1.2와 TLS 1.3, 현재 안전하다고 인정되는 두 버전입니다. TLS 1.0과 1.1은 각각 1999년과 2006년에 나왔고, MD5와 SHA-1처럼 이미 깨진 알고리즘에 의존하며, IETF가 2021년에 공식적으로 폐기했습니다(RFC 8996). 주요 브라우저도 몇 년 전에 지원을 끊었습니다. 이 두 버전을 빼면 연결이 안전하지 않은 프로토콜로 다운그레이드될 수 없습니다. 실제로 잃는 것은 없습니다. 현재의 SIP 제공업체는 TLS 1.2 이상을 지원하고, 위 테스트에서 2talk는 TLS 1.3으로 연결했습니다.

TLS를 쓰면 공유기에서 포트 포워딩을 해야 하나요?

아니요. 걸려 오는 전화는 소프트폰이 직접 연 TLS 연결을 통해 들어옵니다. 방화벽은 아웃바운드 TCP 5061(또는 제공업체가 쓰는 포트)만 허용하면 됩니다.

TLS를 쓰면 통화가 느려지나요?

체감할 정도는 아닙니다. TLS 핸드셰이크는 연결을 설정할 때 한 번만 일어나고, 이후의 등록과 모든 통화는 다시 핸드셰이크하지 않고 같은 연결을 재사용합니다.

회선이 정말 암호화되었는지 어떻게 확인하나요?

회선의 기술 정보를 여세요. 연결이 TLS이고, 수신 주소가 ;transport=tls로 끝나며, SIP 메시지에 Via: SIP/2.0/TLS가 보이면 됩니다.

제공업체의 인증서가 만료되거나 바뀌면 어떻게 되나요?

만료된 인증서는 확인에 실패합니다. 회선은 인증서 오류와 함께 멈추고, 평문으로 되돌아가지 않습니다. 제공업체가 신뢰할 수 있는 CA가 발급한 다른 유효한 인증서로 바꾸면 따로 할 일은 없습니다. WaveKat Voice는 특정 인증서 하나를 고정하지 않고, 인증서 체인과 SIP 도메인을 확인하기 때문입니다.

자체 서명 인증서를 지원하나요?

아니요. WaveKat Voice는 시스템의 루트 CA만 신뢰하므로, 사설 CA가 발급한 인증서를 쓰는 서버에는 TLS로 연결할 수 없습니다.

SIP over TLS와 sips: 주소는 무엇이 다른가요?

sips: 주소는 통화가 거치는 모든 구간에 TLS를 요구하고, ;transport=tls가 붙은 sip: 주소는 현재 구간을 보호합니다. WaveKat Voice 회선은 후자를 사용해 여러분과 제공업체 사이의 연결을 보호합니다.

직접 써 보세요

WaveKat Voice를 다운로드하거나 0.0.56으로 업데이트한 뒤, 회선 하나를 TLS로 바꾸고 기술 정보를 열어 확인해 보세요. 그 밖의 연결 설정은 SIP 설정 가이드에 있습니다.