브라우저로 사내 포털을 열면 불러온다. 같은 호스트를 호출하는 앱을 실행하면 실패하고, 어느 계층인지도 말하지 않는 메시지가 나온다. 터널이 브라우저를 실어 나르고 있으니 터널이 첫 용의자는 아니다. 요청과 서비스 사이에는 네 가지가 있고, 각각 다른 흔적을 남긴다. VPN 클라이언트의 설정 화면이 아니라 앱이 실제로 보내는 요청부터 시작하는, 내가 밟는 순서는 이렇다.

앱이 실제로 보내는 요청을 본다

설정을 건드리기 전에 앱이 무엇을 하는지 말하게 한다. 프록시를 명시적으로 끈 상태의 요청 한 번 캡처와 단순한 포트 시험으로, 이후 단계와 비교할 두 개의 기준선이 생긴다. 프록시를 끄고 성공한다면 네 계층 중 세 개는 이미 끝난 셈이다.

env | grep -i proxy            # Linux/macOS
netsh winhttp show proxy       # Windows, machine-wide
curl -sv --noproxy '*' https://svc.internal/
nc -vz svc.internal 8080

마지막 두 개를 같은 목적지로 실행하고 어디서 갈라지는지 본다. 동작하는 브라우저에 동작하는 curl, 거기에 동작하지 않는 앱이 더해지면 문제는 앱이 덧붙이는 무언가, 즉 프록시, 전송 방식, 메시지 크기 중 하나로 좁혀진다.

앱은 아무도 설정하지 않은 프록시를 상속했다

대부분의 HTTP 스택은 기본적으로 운영체제에서 프록시 설정을 읽는다. 기업 VPN 클라이언트는 접속 프로필의 일부로 프록시를 설치하는 경우가 많아, 개발자가 코드에서 한 번도 언급하지 않은 프록시로 요청이 나간다. .NET에서는 기본 처리기가 IE/WinHTTP 설정을 읽고, Java는 -Dhttp.proxyHost를 읽으며, Node는 라이브러리가 더해 주기 전까지 프록시를 내장하지 않는다. 실패는 깔끔한 거부인 경우가 드물어서 사람들이 서버를 들여다보기 시작한다.

시험 비용은 요청 하나다. 처리기 하나에서 프록시를 명시적으로 끄고 비교한다.

var handler = new HttpClientHandler { UseProxy = false };
using var client = new HttpClient(handler);

그것이 통하면 고칠 곳은 터널이 아니라 앱의 설정이다. 프로젝트의 실행 환경마다 감사를 반복한다. 각기 다른 출처를 읽고, 고장 난 것은 하나뿐일 수 있다.

고른 포트는 정책이 허용하는 포트가 아니다

경로가 있는 호스트가 허용된 서비스는 아니다. 기업 정책은 보통 나가는 웹 포트만 허용하고 나머지는 버리므로, 8080이나 1883의 서비스는 닿지 않지만 443은 잘 통한다. 브라우저는 여기서 아무것도 증명하지 않는다. 정의상 443을 쓰기 때문이다.

같은 서비스를 443 뒤에 공개하고, 예외를 요청하기 전에 이름으로 닿아 본다. 예외가 정말 필요하다면 하나의 출발지 범위와 하나의 목적지로 한정하고, 누군가의 개인적 우회가 아니라 서비스 정의의 일부로 다룬다.

경로가 재설정하는 원시 TCP

오래 유지되는 원시 TCP 연결은 가장 헷갈리는 방식으로 실패하는 계층이다. 웹 트래픽을 허용하는 경로도 드문 아웃바운드 TCP를 재설정하거나 다시 쓸 수 있고, 클라이언트는 장애처럼 읽히는 소켓 오류를 보고한다. 메시징과 이벤트 서비스는 바로 이런 네트워크를 위해 WebSocket 전송을 제공하며, 전환은 터널 변경이 아니라 클라이언트의 선택지다.

전송을 바꾸고 다시 시험하고, 같은 실행에서 다른 것은 바꾸지 않는다. 그 단일 변수 시험이 재설정이 경로에서 왔는지 서비스에서 왔는지 알려 준다.

큰 페이로드에서만 끊기는 연결

성공한 뒤 약 일 초 후에 죽지만 본문이 클 때만 죽는 요청은 중간 어딘가의 크기 한도를 가리킨다. 메시지 바이트를 세는 중간 장치는 전송 도중 연결을 떨어뜨릴 수 있고, 클라이언트는 시간 초과가 아니라 비정상 종료로 보고한다.

페이로드를 앱 계층에서 나눈다. 이것은 MTU 작업과 분리해 둔다. 터널의 패킷 크기를 낮추는 것은 보통의 TCP 세션이 일정한 바이트 수에서 멈출 때 도움이 되고, 중간 장치가 너무 크다고 보는 메시지에는 아무 효과가 없다.

네 가지를 한 번에 구분하는 방법

세 가지 관찰로 대부분의 사례가 정리된다. 실패가 즉시 일어나는가, 큰 본문에서만인가. 프록시를 끄면 같은 요청이 통하는가. 포트나 전송을 바꾸면 결과가 달라지는가. 다음 변경 전에 답을 적어 둔다. 기업 VPN에 상속된 프록시에 앱의 기본값이 겹치면 그럴듯한 원인이 한꺼번에 세 개가 된다.

시험마다 변수를 하나로 유지하고 사용한 목적지 호스트를 기록한다. 그 기준선이 없으면 다음 사람이 네 단계를 처음부터 다시 반복한다.

관련 글