하나의 Client VPN 엔드포인트는 연결된 VPC와 피어링된 VPC에 도달할 수 있으며, 그것을 정당하게 만들기 위해 bastion이 필요하지 않다. 고민할 가치가 있는 선택은 트래픽이 어디서 주인이 바뀌는가이다. 연결 서브넷에 착지해 피어링 연결을 넘는 엔드포인트 경로인가, 아니면 피어링된 VPC 안에서 세션을 끝내는 호스트인가. 두 경로 모두 동작하고 서로 다른 곳에서 실패하므로, 결정은 AWS가 무엇을 허용하는지가 아니라 소유권과 감사에 관한 것이다. 다음은 내가 둘 사이에서 어떻게 고르는지, 그리고 라우팅 경로를 성립시키는 네 가지 항목이다.

두 경로, 하나의 엔드포인트, 서로 다른 소유자

라우팅 경로에서는 클라이언트 트래픽이 엔드포인트에 도달하고, 연결 서브넷의 Client VPN 네트워크 인터페이스 주소로 변환되며, A에서 B로 가는 피어링 연결을 넘어 그 서브넷을 떠난다. VPC B는 어떤 VPN 세션도 종료하지 않는다. VPC A에서 오는 평범한 트래픽으로 보이므로, 반환 경로는 클라이언트 풀이 아니라 VPC A를 가리킨다.

bastion 경로에서는 클라이언트가 먼저 호스트에 도달한다. A의 bastion은 마지막 홉을 여전히 피어링 연결 너머로 두므로 피어링 작업은 남고 세션이 하나 더해진다. B의 bastion도 클라이언트로부터의 경로가 필요하고, 그 경로가 같은 엔드포인트 경로라면 라우팅 설계에 홉이 하나 붙을 뿐이다. bastion이 작업을 줄이는 경우는 그것이 이미 존재하고, 이미 승인되었고, 그 뒤의 대상이 네트워크 경계가 아니라 세션 경계를 필요로 할 때뿐이다.

네 가지 항목이 라우팅 경로를 성립시킨다

AWS는 이 시나리오를 Client VPN how-it-works 페이지에 문서화하며, 실제로는 두세 팀이 소유한 네 가지 항목으로 귀결된다. 범위는 예시이다. 피어링 범위는 고유해야 하고 반환 범위는 계획과 맞아야 한다.

ControlWhat it must say
Endpoint route10.70.0.0/16 targets the association subnet
Authorization ruleThe approved group may reach 10.70.0.0/16
VPC A association-subnet table10.70.0.0/16 targets the peering connection
VPC B resource-subnet tableVPC A's range targets the same peering connection

경로와 권한은 별개의 통제다. 대응하는 승인 규칙이 없는 올바른 엔드포인트 경로는 클라이언트에게 아무것도 주지 않는다. 엔드포인트가 라우팅할 수 없는 목적지에 대한 승인 규칙은 검은 구멍만 준다. 둘 다 같은 범위를 지목해야 한다.

엔드포인트 경로는 엔드포인트 자체의 VPC 안 서브넷을 가리키며, 결코 피어링 연결을 가리키지 않는다. VPC 라우트 테이블은 피어링 연결을 가리키며, 결코 인스턴스나 인터페이스를 가리키지 않는다. 둘 사이에서 값을 복사하면 경고 없이 저장되고 아무것도 라우팅하지 않는다.

연결 서브넷이 클라이언트 원본을 변환하기 때문에, B는 클라이언트 풀이 아니라 VPC A로 되돌아가는 경로를 가져야 한다. 클라이언트 범위를 피어링 연결 너머로 보내는 것은 대칭적으로 보이고 검토도 통과하지만, B는 클라이언트 원본을 가진 패킷을 결코 보지 못하므로 조용히 실패한다.

보안 그룹과 권한의 마지막 한 미터

라우팅은 패킷을 B로 가져오지만 결정은 B가 한다. 같은 리전의 활성 피어링 연결에서는 B의 보안 그룹이 Client VPN 연결에 적용된 그룹을 참조할 수 있어 규칙을 좁게 유지하고 주소 변경에도 견딘다. 그룹 참조가 불가능한 곳에서는 0.0.0.0/0으로 넓히는 대신 연결 서브넷 범위를 명시적으로 허용한다. 넓히면 라우팅 실수가 설명 없는 타임아웃으로 바뀐다.

다음으로 라우팅이 결코 건드리지 않는 것을 확인한다. 두 서브넷의 네트워크 ACL, 애플리케이션의 허용 목록이나 토큰 대상, 그리고 DNS다. 피어링은 프라이빗 호스팅 영역을 복제하지 않으므로 노트북이 해석할 수 없는 주소로 가는 유효한 경로를 들고 있을 수 있고, 피어링 연결은 인증서에 신뢰를 더하지 않는다. 엔드포인트를 B에 응답하는 리졸버로 향하게 하고, 프라이빗 이름과 인증서가 일치하는지 확인한다.

bastion이 정직한 답인 경우

나는 의도적으로 bastion을 고르기 위한 세 가지 방아쇠를 유지한다. 피어링된 VPC가 당신의 범위에 반환 경로를 추가하지 않거나 그룹 참조를 받아들이지 않을 팀의 것이다. 접근을 세션마다 승인하거나 기록해야 하는데 애플리케이션이 그것을 스스로 감당할 수 없다. 또는 마지막 홉이 B 안에 남아야 한다. 서비스가 거기서만 해석되고 TLS 신원이 내부 이름에 고정되어 있기 때문이다.

어느 것도 피어링이 전이적이지 않다는 사실을 우회하는 것이 아니다. 비전이성은 B의 리소스가 할 수 있는 일을 제한한다. A가 피어링된 세 번째 VPC로 가는 경유지로 A를 쓸 수 없다. VPN 사용자가 직접 피어링된 VPC에 도달할 수 없다는 뜻은 결코 아니었고, 그 잘못된 해석을 피하려고 만든 bastion은 이유 없이 패치할 호스트다.

반대의 실수는 시간이 갈수록 더 비싸다. 이미 존재하는 하나의 bastion으로 모든 팀을 통과시키고 나서, 그 보안 그룹과 라우트 테이블과 패치 창이 운영 의존성임을 발견한다. 호스트가 어떤 방아쇠를 위해 존재하는지 적어 두고, 방아쇠가 사라지면 은퇴시킨다.

Transit Gateway와 여러 연결이 계산을 바꾼다

엔드포인트가 서브넷이 아니라 Transit Gateway에 직접 연결되어 있으면 모델이 바뀐다. 클라이언트는 더 이상 연결 서브넷의 인터페이스 주소로 변환되지 않고, 게이트웨이 라우트 테이블이 클라이언트 범위와 피어링된 VPC로 이어지는 연결을 함께 운반해야 한다. 규모에서는 더 깔끔하지만 작업은 네 항목에서 게이트웨이 라우트 테이블로 옮겨간다.

여러 연결은 점검을 배로 만든다. 엔드포인트 경로는 엔드포인트의 것이지만, 모든 연결 서브넷은 실제 피어링 다음 홉이 있는 라우트 테이블이 필요하다. 한 연결로 세션이 성공해도 다른 연결에 반환 경로가 없을 수 있으므로 각각을 시험한다.

고장을 빨리 찾는 검증 순서

이것들을 순서대로 실행한다. 각 단계는 다음이 실패하는 동안에도 통과할 수 있고, 클라이언트 타임아웃은 어느 것이 깨졌는지 거의 말해 주지 않는다.

  1. 클라이언트에서 애플리케이션 이름을 해석하고 주소가 피어링 범위 안에 있는지 확인한다.
  2. 연결한 뒤 세션을 끝낸 연결의 엔드포인트 연결 로그를 읽는다.
  3. 그 연결 서브넷에서 라우트 테이블이 피어링 범위를 활성 피어링 연결로 향하게 하는지 확인한다.
  4. B의 리소스 서브넷에서 인터페이스 범위의 반환 항목과 일치하는 그룹 규칙을 확인한다.
  5. 허용된 작업 하나와 도달할 수 없어야 하는 리소스 하나를 시험한다. 두 번째가 디버깅 잔여물을 잡는다.
  6. split-tunnel 경로 변경 뒤에는 반드시 다시 연결한다. 실행 중인 터널은 새 경로 집합을 받아들이지 않는다.

기억할 가치가 있는 두 가지 증상이 있다. 응답 없이 B에 도달하는 SYN은 거의 항상 빠진 반환 경로다. 완료된 뒤 재설정되는 연결은 보통 그룹, ACL, 애플리케이션 중 하나다. 둘 다 엔드포인트 로그에 원인으로 나타나지 않으므로, 네 항목을 각각의 소유자와 나란히 유지한다.

세 방아쇠 중 어느 것도 해당하지 않으면 라우팅 경로를 끝내고 그 네 항목을 기록한다. 하나라도 해당하면 bastion은 그 경계에만 남기고, 엔드포인트 경로는 앞에 세션이 필요 없는 서비스에 남긴다.

관련 글