카메라 포트 하나를 열고 플레이어를 그쪽으로 향하게 한 뒤 인터넷 문제가 해결되었다고 가정한다. 그러다 휴대폰에서는 재생되지 않고, 브라우저에서도 재생되지 않으며, 카메라의 관리 페이지는 공개 경계에서 잘못 입력한 경로 하나만큼 떨어져 있다. 선택한 전달 모델, RTSP 또는 HLS가 방화벽 규칙을 하나도 쓰기 전에 그 대부분을 결정한다. VPN은 사설 구간만 제공한다.

VPN은 원본 경로를 고치지, 시청자 경로를 고치지 않는다

터널을 통해 카메라의 LAN에 연결된 VPS는 카메라의 사설 주소로 접근할 수 있고, 그것은 정말 유용하다. 이는 카메라에 자체 인바운드 포트가 필요 없고 가정용 공유기가 닫힌 채로 남는다는 뜻이다. 그렇다고 시청자가 어떤 프로토콜을 쓸지는 알려주지 않는다. 데스크톱 플레이어, 브라우저, 휴대폰, 스마트 TV는 서로 다른 프로토콜을 지원하며, 각각 TLS, 인증, 코덱에 대한 기대가 다르다.

여기 버릴 만한 가정은 게시란 원본을 접근 가능하게 만드는 일이라는 것이다. 게시는 실제로 정의된 시청자에게 미디어를 소비하는 지원되는 방법을 주는 일이다. 게시된 스트림에는 형식과 시청자와 자격 증명이 있지만 접근 가능한 카메라에는 그중 어느 것도 없다. 접근 가능성은 터널이 해결하는 부분이고, 시청자 진입점은 당신이 아직 설계해야 하는 부분이다.

RTSP는 협상이지 단일 포트가 아니다

RTSP는 세션 제어를 나르는데, 클라이언트가 설명을 요청하고, 하나 이상의 미디어 트랙을 설정한 다음 재생한다. 미디어 자체의 전송은 그 설정 과정에서 협상되므로, 전달된 TCP 포트 하나로는 프로토콜을 잘 설명할 수 없다. 그 협상이야말로 사람들이 방화벽 규칙을 비교할 때 놓치는 부분이다.

엔드포인트에 따라 RTP는 별도의 UDP 포트로 도착하거나 제어 연결에 인터리브될 수 있다. 554만 전달하고 나머지는 동작할 것이라고 가정하는 중계는 대개 연결되고, 트랙을 보고한 다음 아무것도 보여주지 않는 세션을 만든다. 규칙을 쓰기 전에 카메라가 실제로 어떤 전송을 협상하는지 확인하라. 사설 측에서 한 번 캡처하면 일 분 만에 답이 나오고, 추측은 저녁 하나를 잡아먹는다.

호환되는 플레이어를 가진 작고 알려진 시청자라면 의도적으로 구성한 RTSP 중계가 정답일 수 있다. 어떤 원본에서 당길 수 있는지 제한하고 중계에서 인증을 요구하라. 테스트한 플레이어를 적어 두어라, VLC에서 동작하는 RTSP 스트림도 브라우저에서는 실패할 수 있기 때문이다.

HLS는 재생 목록과 리소스다

HLS 시청자는 재생 목록을 가져오고, 이어서 그 목록이 지목하는 미디어 세그먼트를 가져온다. HLS 명세가 그 리소스 모델을 정의하며, 중요한 운영상의 세부는 재생 목록이 다른 URL을 참조한다는 점이다. 상대 참조는 재생 목록의 위치를 기준으로 해석되므로, 경로를 다시 쓰는 프록시는 이를 일관되게 다시 써야 한다.

카메라가 이미 쓸 만한 HLS를 제공한다면 공개 프런트엔드가 그 재생 목록과 세그먼트 요청을 터널 너머로 전달할 수 있다. 애플리케이션이 생성하는 키, 리디렉션, URL을 주의하라. 사설 호스트를 가리키는 절대 URL은 LAN 밖의 시청자가 그것을 따라가는 순간 깨진다. 프록시 재작성을 견디는 것은 상대 경로이므로, 생성되는 출력을 통제하는 곳에서는 상대 경로를 우선하라.

카메라가 RTSP만 말한다면 무언가가 원본을 시청자 형식으로 변환해야 한다, 재패키징과 트랜스코딩은 다른 작업이다. 재패키징은 코덱을 유지하고, 트랜스코딩은 호환성을 위해 다시 인코딩하며, 후자만이 심각한 CPU를 쓴다. 경로에 VPN이 있다는 것만으로 둘 중 어느 것도 필수가 되지는 않는다.

배포가 일어나는 지점을 기준으로 업링크를 계획하라. 공개 미디어 서비스를 먹이는 단일 사설 인제스트는 각 시청자가 자기 스트림을 터널 너머로 당기는 것과 전혀 다르게 동작한다. 두 번째 패턴은 대개 포화된 가정 연결과 무작위로 실패하는 것처럼 보이는 카메라로 끝난다.

인증을 당신이 게시하는 경계에 두라

TLS, 시청자 인증, 접근 기록은 공개 진입점에 속하고 카메라에 속하지 않는다. 이렇게 하면 카메라의 자격 증명이 스트림의 자격 증명과 분리된다. 시청자가 떠날 때 접근을 취소할 한 곳도 생긴다. 그 통제를 대신 카메라에 두면, 시청자 변경이 일어날 때마다 공개적으로 접근 가능해서는 안 되는 기기에 대한 관리 변경이 된다.

VPN과 카메라의 관리 권한을 게시 경로와 분리하라. 스트림을 당기기 위해 카메라의 웹 인터페이스에 접근할 수 있는 VPS가 그 인터페이스를 노출하는 기기여서도 안 된다. 시청자는 카메라의 주소를 절대 알면 안 된다.

다음으로 체인이 동작한다고 가정하지 말고 실제로 구축한 두 끝을 검증하라:

$ ffprobe -v error -rtsp_transport tcp rtsp://10.50.0.9:554/stream1
$ curl -sI https://stream.example.net/live/index.m3u8
HTTP/2 200
content-type: application/vnd.apple.mpegurl

사설 원본에 대한 성공적인 프로브와 공개 경계에서의 성공적인 재생 목록 가져오기는 설계의 서로 다른 절반을 증명한다. 그것들을 따로 테스트하라. 시청자가 쓰는 것과 같은 종류의 클라이언트에서 재생하는 것이 전체 체인을 덮는 유일한 테스트다.

결국 남는 것은 각 고리에 목적이 있는 체인이다, 사설 원본, 제한된 인제스트, 선택된 패키징, 승인된 시청자 진입. 그 고리 중 어느 것도 선택 사항이 아니며, 어느 것도 포트를 여는 것으로 만들어지지 않는다.

관련 글