변경점
RFC5389 ← 기존 RFC3489 대체
- 가장 중요한 변경점: 최초 규격은 STUN 자체를 컴플리트 솔루션으로 보았으나, 보완된 규격에서는 STUN이 보조적인 도구로 제한
- 즉, Classic STUN에서는 모든 NAT에 대해 유효한 주소를 획득할 수 있을 것이라고 봤지만, 실제로는 불가능한 케이스가 많이 발생하는 것을 인지함
RFC8489 ← 기존 RFC5389 대체
- DTLS 추가 지원 및 각종 보안 관련 내용 보강
메시지
헤더 포맷
- 헤더 길이는 20바이트
- 첫 두 비트는 00 (STUN메시지 식별용)
- 뒤 14비트는 메시지 타입
- 0번 비트부터 여덟번째 비트와 열여섯번째 비트는 class를 나타냄 (이 때문에 메시지 타입 내에 함께 존재)
- 여덟번째 비트 : 0 request, 1 response
- 열여섯번째 비트 : 0 success, 1 error
- 메시지 ID는 위 두 비트를 피해서 정의해야 함
- 특별히 ID 1번은 Binding이라는 메소드로 예약됨
- 0번 비트부터 여덟번째 비트와 열여섯번째 비트는 class를 나타냄 (이 때문에 메시지 타입 내에 함께 존재)
- 뒤 16비트는 메시지 바이트 크기. 헤더 크기 제외해야 하고, 무조건 4의 배수여야 함
- 즉, 끝 두 비트가 00이므로 이 점도 STUN메시지 식별에 쓰일 수 있음
- 뒤 32비트는 Magic-Cookie : 0x2112A442 의 네트워크 오더
- 뒤 96비트는 Transaction ID : 랜덤값이면 됨
TLV(Type-Length-Value) Attributes
- 헤더 뒤로 메시지에 필요한 TLV 형태의 attribute가 연속으로 달림. 없을 수도 있음.
- 속성들은 아래의 종류가 있음
- comprehension-required : 이미 프로토콜로 약속되어 있으며 포함 필수
- comprehension-optional : 이미 프로토콜로 약속되어 있지만 선택적 포함
- known-but-unexpected : 인식 가능한 속성이지만, 상황에 맞지 않는 경우
- TLV의 헤더는 총 4바이트
- 2바이트는 attribute의 type
- 2바이트는 value의 길이
- 헤더 4바이트 후 실제 value data가 있음
- (must)4바이트 얼라인을 해줘야 하고, 잔여 길이에 따라 1 or 2 or 3바이트 제로 패딩이 필요함
- (must)헤더에 기록하는 길이는 패딩 전의 실제 크기 기재
- 약속된 속성 예 (기초)
- MAPPED-ADDRESS : Binding의 응답 데이터. 주소가 그대로 저장됨
- XOR-MAPPED-ADDRESS : Binding의 응답 데이터를 XOR 처리하여 난독화
- ERROR-CODE : 요청에 대한 에러 응답 코드. 기본적으로 http의 에러 코드 차용하고 추가 에러 정의
- UNKNOWN-ATTRIBUTES : 약속되지 않은 속성들이 존재하여 에러 발생한 경우 그에 대한 리스트
- (must)TLV 파싱 시 모르는 comprehension-optional 속성이면 무시해야 함.
- (must)문맥에 맞지 않는 known-but-unexpected 속성도 무시해야 함
- (must)모르는 comprehension-required 는 메시지 클래스에 따라 다름
- request : ERROR-CODE 속성 420 기입하고 UNKNOWN-ATTRIBUTES 속성에 모르는 속성을 넣어서 회신
- indication : 메시지를 버림
- response : 트랜잭션 실패로 판단
기타
- (should)STUN 메시지는 IP 헤더까지 포함하여 MTU보다 작아야 한다.
- (should)만약, MTU를 모른다면 IPv4는 576바이트, IPv6는 1280바이트보다 작아야 한다.
- 본 규격에서는 Binding 메소드에 대해서만 다룸
- NAT 유지 책임은 클라에게 있음. Binding을 주기적으로 호출하면 될 것
- STUN 메시지는 TCP(or TLS), UDP(or DTLS) 위에서 송수신 가능
- 클라이언트는 동일 STUN서버에 여러 개의 트랜잭션이 존재할 수 있는데, RTO(Retransmission TimeOut)로 간격을 두도록 하고, 최대 10개까지만 허용하도록 한다.
- ※ 클라이언트 제한만으로는 플러딩 공격이 가능하니, 서버에서도 제한할 방법을 찾아야 한다.
- UDP일 경우 클라이언트 측은 재전송 기능을 갖춰야 한다.
- UDP일 경우 서버 측은 재전송 기능에 맞춰 상태 관리(보낸 메시지 임시 보관)를 해주거나, 멱등성(idempotency)을 보장하여 각 요청에 대해 똑같은 응답을 만들어주는 방법이 있음. 후자를 추천.
- Binding 성공 응답 : XOR-MAPPED-ADDRESS 에 주소를 실어 보내 줌
- Binding 성공 수신 : XOR-MAPPED-ADDRESS의 주소 패밀리가 송신인이 기대하지 않았지만, 지원하는 패밀리라면 수락할 수 있음
- Binding 에러 수신 : 400~499인 경우 개별 처리. 500~599인 경우 4회 정도로 제한하여 재전송 시도
- STUN 서버의 최소 요구사항
- Binding method 지원
- UDP, TCP 모두 지원