tun0과 VPN 프로토콜을 하나로 취급하면 사람들이 엉뚱한 로그로 향하게 된다. 인터페이스는 사용자 공간의 프로그램이 커널과 IP 패킷을 주고받는 로컬 경계다. 프로토콜은 패킷을 받은 뒤 그 프로그램이 패킷으로 하는 일, 곧 전송, 인증, 암호화, 그리고 상대다. 장치를 만드는 것은 그중 어느 것도 선택하지 않는다.

두 구성 요소, 하나의 패킷 경로

커널은 IP 패킷을 장치에 쓰고, 프로그램은 파일 디스크립터에서 그것을 읽는다. 반대 방향에서는 프로그램이 패킷을 다시 쓰고 커널은 그것을 실제 인터페이스에 도착한 것처럼 라우팅한다. TUN은 IP를 나르고, TAP은 이더넷 프레임을 나른다. 그 경계에서 패킷을 읽으면 프레이밍이 보이며, 장치는 바로 그런 용도다.

그 경계 너머의 모든 것은 프로그램의 일이다. 두 프로그램이 같은 인터페이스 개념을 쓰면서 패킷으로 전혀 다른 일을 할 수 있다. 장치 자체는 다음에 무슨 일이 일어나는지에 대한 의견이 없다. 파일 디스크립터는 프로그램이 커널 쪽에서 가진 유일한 손잡이다.

장치를 만들고 나서 경계를 관찰하라

경계를 시험할 때는 의도적으로 장치를 만들어라. 영속 장치는 그것을 만든 프로세스가 끝난 뒤에도 남는데, 실험에 유용하고 이후에는 흔한 혼란의 원인이 된다. VPN을 탓하기 전에 플래그와 소유자를 확인하라.

sudo ip tuntap add dev tun9 mode tun user alice
ip -d link show tun9

링크 세부 정보는 장치 유형과 연결된 소유자를 보여 준다. 어느 프로세스도 그것을 열어 두지 않으면 그 안에 쓰인 패킷은 아무 데도 가지 않는다. 프로세스가 연결되지 않은 장치는 링크 목록에서 건강해 보이면서도 아무것도 통과시키지 않을 수 있다.

인터페이스 이름이 보장할 수 없는 것

인터페이스 이름은 암호화나 인증에 대해 아무것도 말하지 않는다. 프로그램은 패킷을 TLS로, 자체 프로토콜로, IPsec으로, 또는 아무것도 아닌 것으로 감쌀 수 있다. TAP 대신 TUN을 고르는 것은 경계의 프레이밍을 바꿀 뿐 보안 설계를 바꾸지 않는다. 프레이밍 선택은 실재하며, 보안 질문보다 훨씬 작다.

탐지도 같은 방식으로 작동한다. 관찰자는 회선에서 바깥 프로토콜을 보며, 어느 로컬 장치가 그것을 만들었는지 알려 주는 라벨은 보지 못한다. 다른 무엇처럼 보이는 터널이 그렇게 보이는 것은 바깥 프로토콜 때문이며 인터페이스 이름 때문이 아니다. 관찰자는 어느 로컬 장치가 패킷을 만들었는지 볼 수 없고 패킷이 어떻게 보이는지만 보므로, 제품을 비교할 때는 이 두 질문을 분리해 두어야 하며 한쪽 답이 다른 쪽을 함축하는 일은 결코 없다.

실패하는 단계에 수정을 맞춰라

무언가 고장 났을 때는 실패 단계를 분리하라. 장치 부재, 권한 오류, 거부된 로그인은 서로 다른 증거와 서로 다른 수정을 낳는다. 먼저 로컬 상태를 읽고, 다음으로 프로그램 자체의 로그를, 다음으로 상대의 시각을 읽어라. 무엇이든 바꾸기 전에 셋 모두를 읽어라.

ip -d link show tun0
journalctl -u openvpn-client@corp --since '10 min ago'

장치가 있고 프로세스가 그것을 잡고 있으면 로컬 경계는 작동하며 문제는 더 바깥에 있다. 장치가 없으면 아무리 자격 증명을 확인해도 도움이 되지 않는다. 이름 붙일 수 있는 단계는 시험할 수 있는 단계다. TUN/TAP 문서가 경계와 장치 모델을 설명한다.

관련 글