Tailscale Serve와 Funnel: 링크를 실제로 열 수 있는 사람은 누구인가
Serve는 서비스를 tailnet과 공유하고, Funnel은 그것을 공개 인터넷에 노출합니다. 도달 가능한 대상, ID 헤더, Funnel이 허용하는 포트를 비교합니다.
두 명령 모두 로컬 서비스를 Tailscale HTTPS 이름으로 게시하므로 실행하는 머신에서 보면 거의 동일해 보입니다. 차이는 나중에 누가 URL에 도달할 수 있는지이며, 그 차이가 애플리케이션에 아직 필요한 제어를 결정합니다. Serve는 대상을 tailnet 안에 유지하고, Funnel은 공개 인터넷으로 옮깁니다. 먼저 대상을 고르고, 그다음 그것에 맞는 명령을 고르세요.
Serve는 tailnet 안의 질문에 답합니다
Serve는 로컬 포트를 프록시하거나 tailnet의 기기에 로컬 콘텐츠를 제공하며, tailnet의 접근 규칙은 모든 요청에 계속 적용됩니다. 포트 3000의 대시보드는 오직 당신의 기기만 확인하고 연결할 수 있는 HTTPS 이름으로 접근 가능해집니다. 이것은 대상이 이미 tailnet에 의해 인증되었고 공개 표면을 추가하지 않기 때문에 내부 도구에 맞는 기본값입니다. URL은 평범한 웹사이트처럼 보이며, 바로 그래서 사람들이 그것을 그렇게 착각합니다.
Serve는 전달하는 요청에 tailnet 사용자를 설명하는 ID 헤더를 붙일 수도 있습니다. 애플리케이션이 그 헤더를 인증으로 신뢰한다면 백엔드를 localhost에 묶어 다른 무엇도 직접 도달하지 못하게 하세요; 라우팅 가능한 주소에서 수신하는 백엔드는 프록시를 한 번도 거치지 않은 요청을 받을 수 있습니다.
Funnel은 대상을 공개 인터넷으로 바꿉니다
Funnel은 선택한 서비스를 URL을 가진 누구에게나 게시하며, 방문자에게는 클라이언트도 계정도 tailnet 구성원 자격도 필요하지 않습니다. 따라서 그 리소스에는 어떤 공개 서비스에나 적용할 인증, 속도 제한, 패치가 필요합니다. 공개 요청은 Serve의 tailnet ID 헤더를 싣지 않으므로, 그것에 의존하던 애플리케이션은 Funnel 아래에서 사용자 ID가 전혀 없습니다. 다른 게시 명령을 고르는 것이 인증 질문을 대신 답해 주지는 않습니다.
Funnel에는 오래된 릴리스의 자습서가 언급하지 않을 수 있는 제약도 있습니다. 이름에 대해 Tailscale이 받는 인증서로 TLS를 종료하고, Funnel 문서가 설명하는 대로 특정 수신 포트만 지원합니다. 서비스가 그 포트 중 하나에서 HTTPS가 아닌 프로토콜을 기대한다면 Funnel은 구성 퍼즐이 아니라 잘못된 도구입니다.
모드는 포트가 아니라 클라이언트에서 읽으세요
두 모드는 같은 로컬 포트에 대해 서로 다른 시점에 구성될 수 있으므로 무언가를 공유하기 전에 현재 상태를 확인하세요. 상태 명령은 실제로 무엇이 누구에게 게시되었는지 보고합니다. URL이 응답한다는 사실로 대상을 추론하지 마세요.
tailscale serve status
tailscale funnel status
tailscale status --json | head -40
명령 구문은 클라이언트 버전에 따라 바뀌었으므로 복사한 호출이 의도한 것과 다른 모드를 선택할 수 있습니다. 실행하는 버전에 맞는 문서화된 형식을 선호하고, 가정하는 대신 클라이언트가 출력하는 확인을 읽으세요. Serve와 Funnel 구성이 모두 있다면 노출 측면에서 중요한 것은 공개 쪽입니다. 의도하지 않은 구성을 위에 겹치는 대신 초기화하세요.
출력이 대상을 명시하지 않으면 멈추고 상태를 다시 읽으세요. 대상이 선언되지 않은 게시 URL은 추측이며, 그 추측이 내부 대시보드를 공개 인터넷에 올립니다.
실제로 의도한 대상으로 테스트하세요
서비스를 게시한 머신이 아니라 tailnet 바깥에서 테스트하세요. tailnet 기기에서 보낸 요청은 프록시가 작동함을 증명하지만, 외부인이 배제되었음을 증명하지는 않습니다. Tailscale 클라이언트가 없고 tailnet으로 가는 경로도 없는 네트워크를 사용하세요.
curl -sI https://host.tailnet-name.ts.net
curl -sI https://host.tailnet-name.ts.net --resolve host.tailnet-name.ts.net:443:203.0.113.10
내부 대시보드라면 외부 요청은 연결에 실패하거나 인가에 실패해야 하고, 내부 요청은 기대하는 ID로 성공해야 합니다. 공개 서비스라면 외부 요청이 성공하고 애플리케이션이 자체 자격 증명을 요구해야 합니다. URL만으로는 알 수 없으므로 이 두 결과 중 어느 것을 관찰했는지 기록하세요. 결과가 의도와 반대라면 먼저 공개 구성을 제거하고 그다음 조사하세요.
서비스를 게시하는 것은 나가는 트래픽이 어디서 나가는지를 제어하는 출구 노드를 고르는 것과 같은 결정이 아닙니다. Serve와 Funnel은 당신이 실행하는 무언가에 누가 도달할 수 있는지에 답하고, 출구 노드는 당신 자신의 연결이 어디서 오는 것처럼 보이는지에 답합니다. 두 질문을 분리해 두면 비교는 단순하게 유지됩니다.