FIELD NOTES / SEOUL

CharmingGroot

NAT 뒤의 두 컴퓨터는 어떻게 연결되나 — STUN과 홀펀칭

집이나 사무실 컴퓨터에는 바깥에서 부를 수 있는 주소가 없다. 공유기 뒤에 숨어 있기 때문이다. 그래서 공유기 뒤의 두 컴퓨터는 서로에게 먼저 연결할 수 없다.

이 글은 그 문제를 어떻게 푸는지 정리한다. 순서는 NAT → STUN → 홀펀칭 → 중계 서버다.

공유기는 나간 것만 기억한다

집에 컴퓨터가 여러 대 있어도 바깥에 보이는 주소는 하나뿐이다. 공유기가 주소를 바꿔치기해서 내보낸다.

내 컴퓨터가 보냄:   192.168.0.5 의 40000번 →  구글
공유기가 바꿔서:     1.2.3.4 의 54321번    →  구글

공유기가 적어둠:    54321번으로 오는 답장 = 192.168.0.5 의 40000번

답장이 오면 이 메모를 보고 내 컴퓨터로 넘겨준다.

메모는 나갈 때만 만들어진다. 그래서 바깥에서 갑자기 뭔가 들어오면 공유기는 집 안 누구에게 줘야 할지 모른다. 그냥 버린다.

이것이 “바깥에서 먼저 연결할 수 없다”의 전부다. 메모를 만드는 방법은 내가 먼저 나가는 것 하나뿐이다.

메모를 관리하는 건 공유기 자신이다. 바깥에서는 그 메모에 손댈 수 없다.

내 바깥 주소는 내가 모른다

공유기가 54321번을 골랐다는 걸 내 컴퓨터는 모른다. 공유기가 알려주지 않기 때문이다.

그래서 바깥에 있는 서버에 물어본다. 아무 메시지나 하나 보내면 이렇게 답해준다.

너는 나한테 1.2.3.454321번으로 보인다.

이 역할을 하는 서버를 STUN이라고 부른다. 하는 일은 이것뿐이다. 거울 같은 것이다.

주의할 점이 하나 있다. STUN은 물어본 사람에게만 답한다. 상대에게 알려주지 않는다. 알아낸 주소를 상대에게 전달하는 건 다른 일이다.

서로 동시에 두드린다

이제 A와 B가 각자의 바깥 주소를 알았다. 서로 알려주고 연결을 시도한다.

A가 B에게 보낸다.

A쪽 공유기를 나갈 때  →  메모 생김          → A쪽 문 열림
B쪽 공유기에 도착     →  메모 없음          → 버려짐

A가 보낸 것은 B에게 도착하지 못한다. 하지만 A쪽 공유기에 메모가 생겼다.

B가 A에게 보낸다.

B쪽 공유기를 나갈 때  →  메모 생김          → B쪽 문 열림
A쪽 공유기에 도착     →  아까 만든 메모 있음 → 통과

이제 서로 통한다.

첫 번째 메시지는 상대에게 닿으려고 보내는 것이 아니다. 내 쪽 문을 열려고 보내는 것이다. 그래서 양쪽이 다 보내야 한다. 한쪽만 보내면 영원히 안 된다.

이 방식을 홀펀칭(구멍 뚫기)이라고 부른다.

안 되는 경우도 있다

공유기 중에는 보내는 상대가 바뀔 때마다 번호를 새로 고르는 것이 있다.

그러면 STUN에게 물어봤을 때 들은 번호(54321)와, 실제로 상대에게 보낼 때 쓰는 번호가 다르다. 상대에게 알려준 번호가 틀린 번호가 되는 것이다. 이런 공유기 뒤에서는 홀펀칭이 실패한다.

처음 만나는 자리가 필요하다

여기서 문제가 하나 더 있다. A와 B는 서로의 주소를 어떻게 주고받나? 아직 연결이 없는데 주소를 알려줄 방법이 없다.

그래서 양쪽이 다 접속할 수 있는 중계 서버를 하나 둔다. 둘 다 그곳으로 먼저 나간다. 나가는 연결이니까 공유기가 막지 않는다.

  • A가 중계 서버에 접속해 기다린다
  • B도 접속해서 “A에게 이 주소를 전해달라”고 부탁한다
  • 중계 서버가 전달한다
  • 둘이 동시에 두드린다 (홀펀칭)

성공하면 이제 직접 통신한다. 실패하면 계속 중계 서버를 거쳐서 통신한다.

뚫고 나서도 중계 서버는 남는다

여기가 흔히 오해하는 부분이다. 직접 연결이 되면 중계 서버가 필요 없어질 것 같지만 그렇지 않다. 세 가지 이유가 있다.

기다리는 쪽은 계속 접속해 있어야 한다. A의 주소를 아무도 모르기 때문에, 누군가 A를 찾으려면 중계 서버를 통할 수밖에 없다. A가 중계 서버와의 연결을 끊으면 아무도 A를 찾을 수 없다.

뚫어놓은 구멍은 저절로 막힌다. 공유기의 메모에는 유효기간이 있다. 보통 30초에서 몇 분 사이다. 조용하면 지워진다. 그래서 양쪽이 주기적으로 아무 메시지나 보내서 메모를 새로 고쳐야 한다.

여기서 방향을 헷갈리기 쉽다. 내 쪽 메모는 내가 보내야 갱신된다. 상대가 보내주는 걸 받는 것으로는 안 된다. 그래서 양쪽이 각자 보낸다.

주소가 바뀌면 다시 알려야 한다. 노트북을 와이파이에서 휴대폰 테더링으로 바꾸면 바깥 주소가 달라진다. 새 주소를 알리는 통로가 또 중계 서버다.

정리

  • 공유기는 나가는 연결만 기억한다. 그래서 바깥에서 먼저 들어올 수 없다.
  • 내 바깥 주소는 내가 모른다. STUN 서버에 물어봐야 안다.
  • 양쪽이 동시에 보내야 뚫린다. 첫 메시지는 내 쪽 문을 여는 용도다.
  • 상대가 바뀔 때마다 번호를 바꾸는 공유기 뒤에서는 뚫리지 않는다.
  • 뚫려도 중계 서버는 계속 필요하다. 기다리는 쪽의 주소이자, 구멍을 다시 여는 통로이기 때문이다.

중계 서버를 직접 운영한다면 이 마지막 항목이 사양을 정한다. 트래픽이 직접 경로로 빠져도 접속 수는 줄지 않는다. 대역폭이 아니라 동시 접속 수를 기준으로 잡아야 한다.