WebRTC란?
WebRTC(Web Real-Time Communication)는 브라우저끼리 실시간 음성·영상·데이터 통신을 실현하기 위한 오픈 기술입니다. 추가적인 플러그인이나 소프트웨어를 필요로 하지 않고, JavaScript의 API만으로 P2P 통신을 가능하게 하는 구조로서, Google을 비롯한 각사에 의해 표준화가 진행되고 있습니다.
WebRTC는 다음 세 가지 주요 구성 요소로 구성됩니다.
- getUserMedia: 카메라나 마이크 등의 디바이스로부터 음성·영상을 취득하는 API.
- RTCPeerConnection: 피어끼리의 통신을 확립해, 미디어나 데이터를 교환하는 코어 API.
- RTCDataChannel: 파일 전송 및 채팅 등에 사용할 수 있는 데이터 채널.
이러한 API를 통해 화상 통화, 음성 회의, 파일 공유 등 많은 실시간 애플리케이션을 개발할 수 있습니다. 그러나 실제 통신에서는 NAT 초과나 방화벽 문제가 있기 때문에 STUN/TURN/TURNS와 같은 NAT 트래버설 기술의 이해와 도입이 필수적입니다.
STUN, TURN, TURNS의 차이와 역할
WebRTC에서 안정적인 피어 투 피어 연결을 실현하려면 NAT 초과(NAT traversal)의 메커니즘이 필수적입니다. 여기에서는 대표적인 기술인 STUN, TURN 및 TURNS에 대해 그 기술적인 차이와 사용 장면, 장점 단점을 자세하게 설명합니다.
STUN은 주로 NAT 환경에서 자신의 외부 주소를 알기 위한 프로토콜이며, TURN은 직접 연결이 불가능할 때 중계 서버 역할을 하는 프로토콜입니다. 한편 TURNS는 TURN 통신을 TLS로 암호화하고 HTTPS와 같은 443번 포트에서 실시하는 방식으로 기업 네트워크 등 엄격한 방화벽 하에서의 통신을 가능하게 합니다.
각각의 특성을 이해하고 적절하게 구분하여 WebRTC 통신의 성공률과 품질을 높일 수 있습니다.
STUN (UDP)의 역할과 특징
STUN (Session Traversal Utilities for NAT)은 클라이언트외부 IP 주소 및 포트알기위한 간단한 프로토콜입니다. 예를 들어 PC가 NAT하에 있는 경우, 스스로는 글로벌 IP를 모릅니다만, STUN서버에 문의하는 것으로 「외부로부터 본 자신의 IP:포트」를 취득할 수 있습니다.
STUN 서버는 말하면 거울과 같은 역할로 받은 요청의 소스 정보를 그대로 회신합니다. 결과적으로 클라이언트는 자신의 글로벌 IP 주소와 NAT에서 할당한 포트 번호(Server Reflexive 후보)를 알 수 있습니다.
STUN의 통신은 통상 UDP로 행해져, 디폴트 포트는 3478번(UDP/3478)입니다. UDP에서의 경량의 단발 통신으로 끝나기 때문에, 오버헤드가 작고 저지연이며, 서버측의 부하도 거의 없습니다. 따라서 UDP 통신이 허가된 환경에서는 우선 STUN에 의한 NAT 초과를 시도합니다.
STUN 사용 장면
자택 네트워크나 모바일 회선 등, NAT 초과는 필요하지만 UDP 통신 자체는 차단되어 있지 않은 환경에서 유효합니다. STUN으로 서로의 외부 IP:포트를 취득할 수 있으면, 클라이언트끼리가 직접(피어 투 피어) 통신을 확립할 수 있습니다. 통신 경로가 직접되는 분, 지연이 적고 품질도 높게 유지할 수 있습니다. 또한 서버는 IP 정보를 교환하는 데 도움이되므로 비용도 매우 낮게 유지됩니다. 예를 들어 온라인 게임이나 화상 통화에서 양쪽 장치가 상대적으로 개방된 NAT에 있는 경우 STUN에서 충분히 피어 투 피어 연결이 가능합니다.
STUN의 한계와 단점
STUN은 어디까지나 “자신의 외부 주소를 알기” 위한 수단으로, NAT 타입이나 방화벽의 제약에 따라서는 이것만으로는 접속할 수 없습니다. 특히 신메트릭 NAT(대칭형 NAT)나 엄격한 방화벽 환경에서는 STUN에서 얻은 주소로는 상대로부터의 패킷이 닿지 않고 통신할 수 없는 경우가 있습니다.
또 기업 네트워크에서는 UDP 통신 그 자체가 블록 되고 있는 경우도 있어, 그 경우 STUN 리퀘스트 자체가 도착하지 않습니다. 요컨대, STUN은 "직접 통신이 가능한지 판단하기" 위한 구조이며, 직접 통신이 물리적으로 불가능한 환경에서는 작동하지 않습니다. 그 때문에 STUN은 ICE(후술)에 있어서 제1단계의 후보 취득에 사용되어, STUN으로 충분하지 않은 경우에는 후술하는 TURN에 폴백 하는 설계가 되어 있습니다.
TURN (UDP)의 역할과 특징
TURN(Traversal Using Relays around NAT)은 STUN에서 직접 통신할 수 없는 경우 중계 릴레이로 동작하는 프로토콜입니다. TURN 서버는 글로벌 액세스 가능한 릴레이 포인트로서 통신 상대와의 사이에 들어가 패킷을 전송합니다. 클라이언트는 TURN 서버에 연결하고 Relay 후보라는 릴레이용 IP 주소와 포트를 검색합니다. 이후, 그 TURN 서버 경유로 상대와의 미디어나 데이터의 교환을 실시합니다.
TURN도 통상은 UDP로 통신하기 때문에, UDP만 통과하면 직접 통신과 가까운 형태로 미디어 패킷을 중계할 수 있습니다. 기본적으로 STUN과 동일한 3478번 포트(UDP)에서 TURN 프로토콜을 수락합니다. 방화벽 정책이 UDP 포트 번호를 제한하는 경우에도 UDP/443처럼 허용된 포트에서 TURN을 실행할 수 있습니다. UDP만 사용하면 TCP보다 실시간성이 높은 중계가 가능합니다.
TURN 사용 장면
상대방과 직접 연결할 수 없는 경우 TURN은 필수적입니다. 예를 들면하나 또는 둘 다 기업의 엄격한 방화벽에 있거나 대칭 NAT가 UDP 홀 펀치에 실패하는 경우. 이러한 환경에서는 TURN 서버를 통한 릴레이 없이 통신을 할 수 없기 때문에 TURN은 말하자면 마지막 요새 역할을 합니다.
WebRTC에서는 모든 피어가 직접 통신할 수 있는 것을 목표로 합니다만, 그것이 이루어지지 않는 경우에서도 TURN에 폴백 하는 것으로 통신 자체는 계속 가능하게 됩니다. 실제 운영에서는 먼저 STUN에서 직접 연결을 시도하고 실패한 경우에만 TURN 릴레이로 전환하는 것이 일반적인 전략입니다. 예를 들어 사내 네트워크를 넘는 화상 회의에서 서로 직접 통신할 수 없는 경우 자동으로 TURN 서버 경유의 통신으로 전환되어 사용자는 의식하지 않고 대화를 계속할 수 있게 됩니다.
TURN의 장점
가장 큰 장점은 확실성입니다. 어떠한 NAT나 방화벽 환경에서도 클라이언트에서 TURN 서버로의 통신만 확립할 수 있으면 궁극적으로 피어간 통신을 실현할 수 있습니다. 또한 TURN은 프로토콜상 STUN의 확장이기 때문에, 단일의 서버 구현(후술의 coturn 등)로 STUN 리퀘스트와 TURN 리퀘스트의 양쪽 모두를 처리 가능합니다. 일단 접속이 확립되어 버리면, 이후의 미디어는 스트림로서 중계되기 때문에, 이용자로부터 보면 다소의 지연을 제외하고 원활한 통신을 실시할 수 있습니다.
TURN의 단점
가장 큰 단점은 자원 소비와 지연입니다. TURN에서는 음성과 영상 데이터 모두가 서버를 경유하기 때문에 서버 측에서 많은 대역폭과 처리 능력이 필요합니다. 예를 들어 일대일 화상 통화에서 단방향 1Mbps 대역을 소비한다고 가정하면 1000명의 사용자가 동시에 사용하면 단순 계산에서 1Gbps의 중계 대역이 필요합니다. 이 때문에 TURN 서버의 운용 비용은 높고, 대규모 서비스에서는 다수의 TURN 중계 서버를 준비해 스케일시킬 필요가 있습니다.
또한 통신 경로가 멀어짐으로써 지연이 증가하여 영상·음성의 타임 러그나 품질 저하를 초래합니다. 게다가 STUN에 의한 피어 투 피어 통신에 비해 TURN 경유는 엄밀하게는 피어 투 피어가 아니기 때문에 기밀성의 관점에서도 약간 뒤떨어집니다.
일반적으로 TURN은 필요한 경우에만 사용해야하는 수단입니다. 사실, 많은 WebRTC 통신은 STUN으로 직접 연결되어 있으며 Google 통계는 전체 약 86% 통화가 릴레이 불필요(피어 투 피어)로 이루어진 것으로 보고되었습니다. 나머지 약 14%만이 TURN이 필요한 경우이지만, 14%를 위해 TURN 인프라를 준비하는 것이 중요합니다.
TURNS(TLS over TCP/443)의 역할과 특징
TURNS는 「TURN over TLS」의 약칭으로, TURN 프로토콜에서의 중계 통신을 한층 더 TLS(Transport Layer Security)로 암호화한 것입니다. 평평하게 말하면TLS(HTTPS)로 보호되는 TURN 통신그리고 종종 TCP 443 포트에서 서비스합니다.포트 443은 HTTPS와 동일한 포트 번호이므로 기업 방화벽에서도 통과하기 쉽고 프록시와 검열을 피하기 쉽다는 이점이 있습니다..
예를 들면 사내 네트워크에서는 외부로의 통신은 80번과 443번 밖에 허가되어 있지 않은 경우가 있습니다만, 그 경우에서도 443번으로 TLS 통신을 실시하는 TURN 서버라면 통과할 가능성이 높습니다. 게다가 TLS 암호화되어 있기 때문에 통신 내용은 제3자로부터 가로채기 어렵고 안전합니다.
WebRTC에서는 설정상"urls": "turns:턴 서버:443"
같은 URI 체계에turns:
를 지정하면 이 TLS 암호화된 TURN 서버를 사용할 수 있습니다.
TURNS 사용 장면
기업내 네트워크 등 엄격한 제한하에서의 WebRTC 통신에 있어서, 다른 수단이 모두 차단되어 버리는 경우에 TURNS가 활약합니다. 모든 UDP나 TCP의 일반 포트가 봉쇄되어 있는 환경에서도 HTTPS 통신과 같은 취급이면 허락할 방침이 많기 때문에 TLS 443 포트 상의 TURN은 사실상 마지막 수단으로서 유효하다.
또, 공중 무선 LAN등에서 특정의 포트가 닫혀 있는 상황이나, 클라이언트측에서 아무래도 TLS 통신 밖에 할 수 없는 경우에도 이용됩니다. 요컨대,우선 UDP, 그것이 안된다면 TCP, 그것도 안된다면 TLS로 443에'라고 하는 단계적인 폴백의 최종단으로 자리매김됩니다.
TURNS의 장점
방화벽 내성의 높이가 가장 큰 장점입니다. TLS의 암호화 통신은 일반적인 HTTPS와 구별하기 어렵기 때문에 엄격한 필터로도 통과할 가능성이 높아집니다. 특히 웹 회의 시스템을 기업 도입하는 경우, 사내 네트워크에서 외부로의 접속을 허가받을 필요가 있습니다만, TCP/443에서의 TLS 통신이면 보안 정책상 받아들이기 쉽습니다. 또 암호화되어 있기 때문에, 중계 서버에의 통신 자체의 비밀성도 확보할 수 있습니다(※다만 영상등의 컨텐츠 그 자체는 대부분의 경우 WebRTC 레이어로 이미 암호화되어 있습니다).
TURNS의 단점
가장 큰 단점은 성능 측면의 벌칙입니다. TURN 자체의 지연 및 부하 외에도 TLS 및 TCP 오버 헤드가 추가됩니다. TCP는 신뢰성 운송을 위해 패킷 손실 시 재전송 기구가 작동하지만, 실시간 미디어에는 적합하지 않으며, 손실이 발생하면 영상·음성이 원활하게 재생되지 않을 가능성이 있습니다.
또한 TCP는 패킷 순서 제어를 위해 헤드 오브 라인 블로킹이 발생하기 쉽고,UDP에 비해 지터(편차)도 증대. 또한 TLS 암호화·복호 처리에 의한 CPU 부하도 더해집니다. 그 결과, 실측으로 50ms 이상의 추가 지연이 발생해, 유저에게도 체감할 수 있는 러그가 발생한다고 보고되고 있습니다. 특히 화상회의에서는 이 지연 증가에 의해 대화의 템포가 나빠지거나 타이밍의 어긋남이 현저해지는 경우가 있습니다.
이와 같이 TURNS는 품질면에서는 「최종 수단」이라고 할 수 있는 수법입니다만, 통신을 성립시키기 위해서는 배에 배는 대신할 수 없는 상황에서 의지가 되는 명강이기도 합니다.
또한, 최근에는 UDP 443번으로 동작해 TLS 대신에 DTLS/QUIC등을 사용한 새로운 어프로치(TURN over QUIC)도 검토되고 있습니다만, 표준화 도상이며 일반적이지 않습니다.
UDP STUN을 사용할 수없는 경우의 통신 흐름
UDP에 의한 STUN을 이용할 수 없는 경우에 WebRTC의 ICE 처리가 어떻게 진행되는지를 단계별로 설명합니다. 기업 네트워크 등에서 UDP가 전면적으로 차단되고 있는 상황을 상정하고, ICE 협상이 어떻게 폴백하는지를 추구해 봅시다.
- 클라이언트가 STUN 서버에 외부 IP 쿼리(UDP/3478)를 보냅니다.
WebRTC 클라이언트(브라우저)는iceServers
에 지정된 STUN 서버에 UDP 포트 3478을 통해 Binding Request(외부 주소 확인 요청)를 보냅니다. 이것은 ICE 후보 수집의 첫 단계에서 이루어지며 성공하면 서버에서 자신의 글로벌 IP 주소와 포트 번호를 반환하고 Server Reflexive Candidate (srflx 후보)로 후보 목록에 추가됩니다. - UDP 패킷이 방화벽에서 차단되고 응답 없음:
이 경우 네트워크의 방화벽 설정으로 인해 UDP 통신이 외부로 전송되지 않습니다. 따라서 STUN 서버에 대한 요청이 서버에 도착하지 않거나 응답이 클라이언트로 돌아 오지 않습니다. 결과적으로 고객은STUN 응답을 수신할 수 없음, 외부 IP 주소를 알 수 없습니다. ICE 에이전트는 일정 시간 응답을 기다리지만 시간 초과를 맞습니다. 사용자로부터 보면, 이 시점에서는 아직 접속 처리중이며 특히 에러 표시는 나오지 않습니다만, 실제로는후보 수집에 실패끊임없이 있습니다. - Server Reflexive 후보를 얻을 수 없기 때문에 ICE의 직접 연결 확인 실패 :
일반적으로 STUN이 성공하면 클라이언트는 Host 후보(자신의 로컬 IP) 이외에 Server Reflexive 후보(자신의 글로벌 IP)를 갖고, 원단 피어의 동종의 후보와 조합해 접속 체크를 실시합니다. 그러나 STUN 실패로 인해 글로벌 IP 후보가 없다면,직접 피어간 접속의 후보가 극단적으로 한정됩니다. 예를 들어, 양자 모두 사설 IP만을 가지는 상태에서는, 서로 접속 시도해도 도착하지 않습니다. 그 결과 ICE는 "직통에서는 무리"라고 판단합니다. ICE 서버(TURN)가 설정되어 있지 않으면, 이 단계에서 ICE 전체가 실패 취급이 되어 WebRTC 접속은 성립하지 않습니다(개발자 콘솔에는ICE failed
やICE connection state: failed
등의 오류가 나타납니다). - TURN 릴레이 후보를 얻으려고 시도 (TCP / TLS / 443 경유) :
STUN에 의한 직접 후보 취득에 실패하더라도,iceServers
TURN 서버가 지정되면 ICE 에이전트는다음 수단로 이동합니다. 이 가정에서는 UDP가 통하지 않기 때문에 클라이언트는 TURN 서버에 대한 연결을 TCP 또는 TLS로 시도합니다 (예 :turns:turn.example.com:443
가 설정되면 TLS 핸드셰이크를 시작합니다.) 다행히도 방화벽은 TCP 443의 HTTPS 통신을 허용했기 때문에 TLS를 통한 TURN 연결이 성공합니다. 클라이언트는 TURN 서버 상에 중계용의 릴레이 주소를 확보해,Relay Candidate(relay 후보)를 가져옵니다. 이것은 "TURN 서버를 통해 통신하는 가상 후보자"입니다. 한편, 통신 상대측(리모트측)도 마찬가지로 릴레이 후보를 취득하거나, 원래 문제없는 네트워크라면 직접 후보나 STUN 후보를 가지고 있을 것입니다. 어쨌든, 적어도 한쪽이 릴레이 후보를 가지고 있으면 상대는 그 TURN 서버를 향해 접속을 시도할 수 있습니다. - 릴레이를 통한 ICE 연결 설정 (또는 최종 실패) :
두 피어가 사용 가능한 후보(이 예에서는 한쪽 또는 양쪽 릴레이 후보)를 얻으면 ICE는 이를 사용하여 연결 확인을 수행합니다. TURN 서버 경유의 통신은 일단 서버와의 사이에 확립하면 중계가 가능하기 때문에, 피어간에 직접 UDP가 통과하지 않아도 미디어 채널이 개통합니다. 이것에 의해 유저끼리의 영상·음성 통신이 개시됩니다. 접속 확립 후에는 TLS상의 TCP라고 하는 오버헤드는 있지만, 대화 자체는 가능하게 됩니다. 반대로, 만약 여기에서도 실패한다(예를 들어 기업 프록시가 비HTTP의 TLS 통신을 검지해 차단한, TURN 서버의 인증에 실패한 등) 경우, 불행하게도 ICE 종합 실패(ICE failed)가 되어 접속은 단념됩니다. 어플리케이션측에서는 이 상황을 검지해, 유저에게 「접속할 수 없었습니다」등이라고 통지할 필요가 있습니다.
이상이 UDP를 사용할 수없는 어려운 환경에서 ICE 협상의 흐름입니다. 요약하면, 「호스트→STUN→TURN」의 순서로 후보를 시험해, 그래도 안된다면 접속 실패가 됩니다. 개발자는 이 거동을 이해한 다음 최소한 TURN/TURNS 서버를 ICE 서버 리스트에 넣어두면 최악의 경우에도 통신이 성립될 가능성을 남기는 것이 중요합니다. 또, 유저로부터 문의를 받았을 때에는 「ICE failed와 나온다」라고 하는 정보로부터 네트워크 환경의 문제(UDP 차단등)를 추측해, TURN 서버의 설정 누락이 없는지 확인한다, 라고 하는 트러블 슈팅이 요구됩니다.
coturn을 사용한 STUN/TURN/TURNS 서버 구축 및 설정
스스로 STUN/TURN 서버를 세우는 경우 오픈 소스 구현이다 coturn(코턴)을 사용하는 것이 일반적입니다. coturn은 STUN과 TURN 양쪽에 대응한 서버 구현으로, 설정대로 TURNS(TLS)에도 대응할 수 있습니다. 여기에서는 Linux 서버상에 coturn을 인스톨 해, STUN/TURN/TURNS를 제공하는 서버를 구축하는 순서와 설정 포인트를 해설합니다. 또한 대표적인 설정 파일(turnserver.conf
)의 예도 표시됩니다.
설치 및 기본 설정
설치
우분투와 데비안의 경우,apt
에서 coturn 패키지를 설치할 수 있습니다. 예를 들어, 다음 명령을 사용하여 설치 및 자동 시작 설정을 수행합니다.
# Ubuntu/Debianの場合
sudo apt-get install coturn
sudo sed -i 's/#TURNSERVER_ENABLED=1/TURNSERVER_ENABLED=1/' /etc/default/coturn
sudo systemctl enable --now coturn
위에서 coturn 서버가 데몬으로 시작됩니다. 기본적으로 설정 파일 /etc/turnserver.conf
을 로드하므로 계속해서 이것을 편집해 갑니다(만약을 위해 백업을 취하고 나서 편집합시다).
기본 설정
turnserver.conf
그러면 다음과 같은 항목을 설정합니다.
- realm(영역) 및 server-name: TURN 서버의 도메인 이름과 고유 이름입니다. WebRTC 클라이언트의 인증시에 이용되는 경우가 있습니다만, 기본적으로는 임의의 캐릭터 라인으로 상관없습니다. 예:
realm=example.com
,server-name=example.com
. - listening-port: TURN 및 STUN에서 대기하는 UDP 포트 번호입니다. 기본값은 3478입니다.
listening-ip
에서 특정 NIC에 바인딩 할 수 있지만 일반적으로0.0.0.0
에서 모두 접수합니다. - tls-listening-port: TLS용(TURNS용)에 대기하는 TCP 포트 번호입니다. 일반적으로 443번이나 5349번을 지정합니다. 예:
tls-listening-port=443
. - external-ip: 서버 자체가 NAT 내부에 있으면 자체 글로벌 IP를 지정합니다 (이것은 내부 IP와 외부 IP의 매핑을 인식합니다). 직접 글로벌 IP를 가진 서버라면 불필요합니다.
- 인증 방법: WebRTC의 TURN 이용에는 장기 인증(Long-Term Credential)이 사용되므로,
lt-cred-mech
(Long Term Credential Mechanism)을 활성화합니다. 그 위에user=username:password
형식으로 사용자 이름과 비밀번호를 설정하거나,use-auth-secret
를 사용하여 동적 인증을 수행합니다 (후자는 토큰 기반 인증으로 보안 향상에 효과적이지만 여기에서는 간단한 정적 사용자 인증을 보여줍니다). - 로그 설정: 트러블 슛으로 인해
log-file
로 로그 파일 경로를 지정하고,verbose
에서 자세한 로깅을 활성화하는 것이 좋습니다.
방화벽 설정
서버측에서는 STUN/TURN용으로UDP 포트 3478, 및 TURN/TLS용TCP 포트 443(또는 5349)를 열어야합니다. 또한 TURN 릴레이는 기본적으로 UDP 10000-20000 번 범위를 사용하므로이 포트 범위도 서버에서 열립니다 (필요한 경우min-port
그리고max-port
에서 범위 변경 가능).
아래에 위의 기본 설정을 반영합니다./etc/turnserver.conf
의 예를 나타냅니다.
# TURNサーバの名称とレルム(ドメイン)
realm=example.com
server-name=example.com
# ネットワーク設定
listening-ip=0.0.0.0 # すべてのIPアドレスで待受
external-ip=203.0.113.10 # サーバのグローバルIP(必要な場合)
# ポート設定
listening-port=3478 # STUN/TURN用 UDPポート
tls-listening-port=443 # TLS用 TCPポート (443番)
min-port=10000 # 中継に使用するポート範囲(下限)
max-port=20000 # 中継に使用するポート範囲(上限)
# ログ設定
log-file=/var/log/turnserver.log
verbose # 詳細ログを有効化
fingerprint # パケットにfingerprint属性を付与
# 認証設定(長期認証方式)
lt-cred-mech # 長期認証を有効化
user=webrtcuser:secretpass123 # ユーザ名:パスワード を設定
# TLS/SSL証明書の指定
cert=/etc/letsencrypt/live/example.com/fullchain.pem # サーバ証明書
pkey=/etc/letsencrypt/live/example.com/privkey.pem # 秘密鍵
위에서 도메인example.com
에서 Let's Encrypt 인증서를 취득하여 TLS 설정에 이용하고 있습니다.lt-cred-mech
에서 장기 인증을 활성화하고,사용자
에 의해 간단한 유저명·패스워드 인증을 설정하고 있습니다. 실제 운영에서는use-auth-secret
그리고static-auth-secret
를 사용하여 토큰 방식으로 임시 자격 증명을 발행하는 방법을 권장하지만 여기에서는 생략합니다.
TLS 이용시의 주의
Coturn이 443번 포트에서 작동하는 경우 Linux 환경에서는 포트 권한에 주의해야 합니다. 1024번 미만의 포트는 특권 포트라고 불려 일반적으로 root 권한이 아니면 열 수 없습니다. 우분투의 coturn 패키지에서는 기본적으로turnserver
사용자가 실행하므로 그대로 443번을 바인딩할 수 없습니다. 대처 방법으로,/etc/default/coturn
에서 실행 사용자를 루트로 변경하거나,setcap
명령으로turnserver
실행 파일에cap_net_bind_service
권한을 부여하는 방법이 있습니다. 예를 들어 후자의 경우sudo setcap cap_net_bind_service=+ep /usr/bin/turnserver
를 실행하면 루트가 아닌 경우에도 낮은 번호 포트를 바인딩할 수 있습니다. 또한 인증서 파일 (cert / pkey)은 올바른 경로를 지정하고 파일 권한도 coturn 사용자가 읽을 수 있도록 설정하십시오. 설정 변경 후sudo systemctl restart coturn
에서 서비스를 다시 시작하고 로그에 오류가 없는지 확인합시다.
동작 확인
Coturn 서버를 시작한 후 동작 확인으로 STUN 클라이언트를 사용한 테스트나 실제로 브라우저의 WebRTC 앱에서 ICE 연결을 시도해 봅니다. 리눅스라면stunclient
명령(apt-get install stun-client
에서 도입 가능)stunclient <서버 IP> 3478
와 같이 실행하면 자신의 외부 IP를 얻을 수 있는지 시도할 수 있습니다. 또한 브라우저에서는 개발자 도구의 로그에 ICE 후보가 열거되므로,srflx
(Server Reflexive) 후보나relay
후보를 얻었는지 확인합니다. 문제가 해결되지 않으면 다음 사항을 트러블 슈트합니다.
- 서버의 방화벽 설정 (iptables 및 클라우드 보안 그룹)에서 필요한 포트가 열려 있습니까?
- 클라이언트측의 ICE 서버 설정(후술)에서 올바른 URI, 포트, 자격 증명이 설정되어 있는가.
turnserver.conf
의realm
설정이 클라이언트의 인증과 일치하는지(브라우저판 WebRTC에서는 자동적으로 realm를 부여하는 구현이 되어 있기 때문에 통상 문제는 되지 않습니다만, 커스텀 구현의 경우 주의).- coturn 로그 (
/var/log/turnserver.log
)를 확인하고 인증 오류가 발생하지 않았습니까?WRONG USER
등의 오류가 있으면 username/password 불일치).
이상의 설정이 적절하면, 자전의 STUN/TURN/TURNS 서버가 가동해, 다양한 네트워크 환경하에서 WebRTC 접속을 서포트할 수 있게 됩니다.
WebRTC 클라이언트에서의 ICE 서버 설정 예(JavaScript)
실제로 WebRTC 어플리케이션(브라우저) 측에서 방금 구축한 STUN/TURN 서버를 이용하려면ICE 서버(ICE Servers) 설정합니다. JavaScript의 WebRTC API에서,RTCPeerConnection
를 생성할 때 STUN/TURN 서버 목록을 지정할 수 있습니다. 다음에, STUN/TURN/TURNS 모두를 지정한 구체적인 코드예를 나타내, 그 의미를 해설합니다.
먼저 ICE 서버용 구성 개체를 만듭니다. 자체 서버의 도메인 이름turn.example.com
(적절하게 바꾸기)로 하고, STUN은 인증 불필요하므로 URI만, TURN/TURNS는 인증이 필요하므로 유저명과 패스워드도 포함해 지정합니다.
const iceConfig = {
iceServers: [
// 1. STUNサーバ(UDP/3478)
{ urls: 'stun:turn.example.com:3478' },
// 2. TURNサーバ(UDP/443経由)
{ urls: 'turn:turn.example.com:443?transport=udp', username: 'webrtcuser', credential: 'secretpass123' },
// 3. TURNサーバ(TCP/443 + TLS = TURNS)
{ urls: 'turns:turn.example.com:443', username: 'webrtcuser', credential: 'secretpass123' }
]
};
const pc = new RTCPeerConnection(iceConfig);
위의iceServers
배열은 세 개의 항목을 지정합니다.
- STUN:
stun:turn.example.com:3478
자체 STUN 서버의 주소를 지정합니다 (포트 생략시 3478이 사용됩니다). STUN은 NAT 초과 판정과 후보 취득에 사용되며, 브라우저는 우선 이 서버에 UDP로 문의하여 Server Reflexive 후보를 취득하려고 합니다. - TURN (UDP):
turn:turn.example.com:443?transport=udp
자신의 TURN 서버UDP의 443번 포트에서 이용하는 설정입니다. 자격 증명으로 이전에 coturn으로 설정한 사용자 이름webrtcuser
및 비밀번호secretpass123
를 지정합니다. 쿼리 매개변수?transport=udp
을 부여하면 UDP에서 TURN 연결을 시도합니다 (지정되지 않은 경우 브라우저는 먼저 UDP를 시도하고 실패하면 TCP도 시도하는 구현입니다). 이 설정은 일반 STUN에 의한 직통이 실패하더라도 UDP의 443번 포트에서 TURN 릴레이를 실시하는 후보(relay 후보)를 얻을 수 있습니다. - TURN (TLS/TCP):
turns:turn.example.com:443
TLS를 이용한 TURN즉 TURNS 서버 설정입니다. 여기도 마찬가지로 사용자 이름과 암호를 지정하고 있습니다. 브라우저는 이 엔트리에 대해 TCP 443번으로 TLS 접속을 실시해, TURN 릴레이 후보를 취득합니다. 이것은 최종 수단의 중계 후보이며, UDP에 의한 통신을 전혀 할 수 없는 경우에도 이 후보가 있으면 통신 확립의 소망이 있습니다.
RTCPeerConnection
생성되면 지정된 ICE 서버에 순차적으로 연결을 시도하고 후보를 수집합니다. ICE 에이전트는 먼저 STUN 후보(srflx)를 취득한 다음, TURN 후보(relay)도 병렬로 취득합니다. 그리고는 ICE의 알고리즘이 이러한 후보끼리를 조합해 접속 체크를 실시해, 최적의 경로를 선택해 줍니다. 개발자는 특히 더 이상의 절차를 의식할 필요가 없습니다.
포인트: 위와 같이여러 후보 준비중요합니다. 예를 들면stun:
만 밖에 지정하지 않은 경우, UDP가 블록 된 환경에서는 일절 후보를 얻을 수 없어 접속 실패가 되어 버립니다. 마찬가지로 TURN(UDP)만으로는 TCP만 통과하는 환경에서 실패합니다. 그러므로 가능하면turn:
그리고turns:
둘 다 ICE 서버에 포함하면 모든 환경에서 적어도 하나는 유효한 후보를 찾을 수 있도록 중복됩니다 (물론 TURN 서버 측에서도 UDP와 TCP / TLS를 모두 지원해야합니다). 클라이언트(브라우저)는 자동으로 사용 가능한 경로를 선택하므로 목록 순서는 큰 문제가 아닙니다. 강하게 말하면,iceTransportPolicy
을relay
하지 않는 한 브라우저는 직접 접속을 우선하기 때문에, STUN 엔트리를 넣어 두면 쓸데없이 TURN 서버를 사용하지 않고 끝납니다. 또, ICE 서버의 리스트에 무관한 서버(존재하지 않는 주소등)를 넣고 있으면 타임아웃 대기로 지연할 가능성이 있기 때문에, 확실히 이용 가능한 것만을 넣는 것이 바람직합니다.
마지막으로 이 설정을 적용한 WebRTC 응용 프로그램을 실행하여 연결 상태를 확인해 봅시다. 브라우저 개발자 도구에서peerConnection.getStats()
사용하거나chrome://webrtc-internals
(Chrome의 경우)에서 ICE Candidate 및 연결 상태를 확인할 수 있습니다. 예상대로 동작하고 있다면, UDP를 사용할 수 있는 환경에서는 direct(P2P) 접속에, 어려운 환경에서는 자동적으로 TURN/TLS 경유의 접속에 폴백하고 있을 것입니다.
SFU와 TURN의 차이
WebRTC에 있어서의 중계에는 크게 나누어 「TURN」과 「SFU」가 있습니다만, 각각의 역할·구성·용도는 크게 다릅니다. 여기서는 기술적 차이를 정리합니다.
TURN: 피어 투 피어의 대안으로 중계
TURN(Traversal Using Relays around NAT)은 WebRTC의 P2P 통신이 불가능한 환경에서 사용되는 보조 릴레이 서버입니다. 주로 NAT 또는 방화벽에서 STUN이 작동하지 않으면 TURN 서버가 각 피어 사이에 들어가는 패킷을 중계합니다. 각 피어는 각각의 통신 상대에게 개별적으로 스트림을 송신하기 때문에, 구성은 어디까지나 메쉬형이며, TURN은 「대타」와 같은 위치설정입니다.
- 구성: 각 사용자가 다른 사용자별로 중계를 통해 전송(실제 메쉬)
- 확장성: 낮음(인원수가 많을수록 부하 증가)
- 중계 내용: 단순한 패킷 포워딩만 미디어 분석이나 최적화는 수행하지 않음
SFU: 다중 인원 통화를 위한 효율적인 중계
SFU(Selective Forwarding Unit)는 다인원 참여 웹 회의에서 사용되는 지능적인 릴레이 서버입니다.각 클라이언트는 SFU에 대해 하나의 스트림을 전송하고 SFU가 다른 참가자에게 선택적으로 전송합니다.. 화자 검출이나 화질 조정, 레이턴시 최적화 등의 처리도 실시할 수 있기 때문에, 스케일러블하고 퍼포먼스가 뛰어난 중계가 가능합니다.
- 구성: 각 클라이언트가 SFU와 1개 접속하는 스타형
- 확장성: 높음(인원수가 늘어도 전송은 1개)
- 중계 내용: 전송처 제어 및 미디어 최적화 등이 가능
TURN과 SFU의 비교표
특징 | TURN | SFU |
---|---|---|
용도 | NAT 넘을 수 없을 때의 대체 수단 | 다수의 실시간 통신 |
통신 구성 | 메쉬(각 상대마다 전송) | 스타형(1개의 송신) |
중계 기능 | 단순한 릴레이(투명) | 선택 전송 · 최적화 있음 |
확장성 | 낮은 | 높은 |
미디어 제어 | 없음 | 예(예: 스피커 감지, 해상도 조정) |
TURN은 어디까지나 「P2P 통신이 불가능할 때 사용하는 최종 수단」이며, 구성적으로는 P2P 메쉬를 보완하는 중계입니다. 한편,SFU는 다인수 통화에서 처음부터 효율적인 설계를 상정하여 사용되는 중계 아키텍처입니다.. 둘 다 역할이 근본적으로 다르기 때문에 혼동하지 않고 설계하는 것이 중요합니다.
요약
본 기사에서는, WebRTC의 중급~상급자를 향해 STUN·TURN·TURNS의 기술적인 차이와 사용소, 한층 더 coturn에 의한 서버 구축 방법과 코드 예, 그리고 어려운 네트워크 환경에서의 ICE 거동에 대해 상세히 설명했습니다.
STUN는 경량이면서 NAT 환경에서의 직접 통신을 가능하게 해,TURN는 어려운 상황에서도 통신을 성립시키는 부탁의 줄다리입니다. 그리고TURNS을 조합함으로써 기업내 등 특수한 환경에서도 WebRTC를 활용할 수 있는 길을 열 수 있습니다.
각각 장점과 단점이 있기 때문에, 본래는 가능한 한 STUN으로 직접 접속해, 아무래도 필요한 경우에만 TURN릴레이를 사용하는 것이 이상적입니다. 실제의 WebRTC 어플리케이션 개발에서는, ICE 서버 설정에 이번 소개한 것 같은 복수 경로를 준비해, 또 서버측도 coturn의 설정과 운용을 적절히 실시하는 것으로, 다양한 네트워크 환경하에서도 안정된 리얼타임 통신을 제공할 수 있습니다.
WebRTC는 브라우저 API와 네트워크 기술이 결합된 복잡한 영역입니다만, STUN/TURN과 ICE의 구조를 이해하는 것은 신뢰성이 높은 어플리케이션을 만드는 데 피할 수 없습니다.
꼭 본 기사의 내용을 근거로, 자신의 제품으로 NAT 초과의 과제에 도전해 보세요. 그렇게 하면 사용자는 의식하지 않고 뒷면에서 현명하게 고안된 접속 처리에 의해 원활하게 통신을 즐길 수 있게 될 것입니다.