AWS Site-to-Site VPN의 대부분의 실수는 주소 실수이며, 패킷이 움직이기 전에 만들어진다. 터널의 외부 주소는 IPsec 피어에 닿고, 내부 주소는 둘 사이의 라우팅 링크를 이루며, 보호되는 프리픽스는 그 링크의 목적이다. 역할 하나를 다른 역할로 착각하면 터널은 올라오지만 아무것도 라우팅되지 않는다. 다음은 BGP 고객 게이트웨이에서 내가 쓰는 읽기–확인–설정 순서이며, 값은 기억이 아니라 내려받은 장비 구성에서 가져온다.

세 가지 주소 역할, 하나의 터널

외부 주소는 공인이며 IPsec 피어의 것이다. AWS 쪽은 터널마다 하나, 고객 쪽은 고객 게이트웨이의 도달 가능한 신원으로, 실제 NAT 구성에 맞춰 조정한다. 내부 주소는 사설이며 논리 링크의 것이고, AWS는 이를 169.254.0.0/16에서 가져온 /30으로 문서화한다. 보호되는 프리픽스는 그 링크를 통해 라우팅하고 광고하는 VPC, 온프레미스, 트랜짓 네트워크다.

LAN 프리픽스를 터널 인터페이스의 주소로 할당하는 것이 이 실수의 전형적인 형태다. 인터페이스는 설정된 것처럼 보이고, LAN은 광고되지 않으며, 반대편에는 그 경로가 없다. 터널 자체의 내부 ping은 통과해도 모든 애플리케이션 이름은 시간 초과가 난다. 터널 옵션 레퍼런스에는 내부 CIDR 제약이 실려 있으며, 어느 주소 범위에서 가져와야 하는지도 포함된다.

값은 내려받은 구성에서 읽는다

연결에서 자신의 장비 모델에 맞는 구성을 내려받고, 그 주소 표를 진실의 원천으로 다룬다. 콘솔도 터널마다 같은 값을 보여 준다. 외부 IP, 내부 CIDR, AWS 쪽 BGP 피어 주소다. 두 터널은 별개의 객체이며 외부 엔드포인트도, 내부 /30도 따로지만, 둘 다 같은 보호 네트워크를 나른다.

aws ec2 describe-vpn-connections --vpn-connection-ids vpn-0123456789abcdef0 \
  --query 'VpnConnections[0].Options.TunnelOptions[].[OutsideIpAddress,TunnelInsideCidr]'
aws ec2 describe-customer-gateways --customer-gateway-ids cgw-0123456789abcdef0 \
  --query 'CustomerGateways[0].[IpAddress,BgpAsn]'

내려받은 파일과 실시간 콘솔이 어긋나면 파일이 오래된 것이다. 주소를 손으로 고치는 대신 다시 내려받아야 한다. 내부 쌍과 피어에 설정한 네이버가 어긋나면 BGP가 조용히 실패하기 때문이다.

올바른 주소를 얹어 링크를 만든다

Linux 게이트웨이에서 터널은 VTI 또는 XFRM 인터페이스이고, 내부 /30은 그 인터페이스에 올라간다. 터널이 둘이면 인터페이스도 둘, BGP 네이버도 둘이며 AWS 엔드포인트마다 하나씩이다. AWS가 내려받은 장비 구성에 찍는 관례에서는 가상 프라이빗 게이트웨이가 각 내부 /30의 첫 주소, 고객 게이트웨이가 둘째 주소가 되므로, 높은 주소를 가져가고 낮은 주소와 피어를 맺는다. 여기에 LAN 주소는 필요 없다.

ip tunnel add tun0 mode vti local 203.0.113.10 remote 18.230.1.1 key 42
ip addr add 169.254.10.2/30 dev tun0
ip link set tun0 up mtu 1400
ip tunnel add tun1 mode vti local 203.0.113.10 remote 18.230.2.1 key 43
ip addr add 169.254.10.6/30 dev tun1
ip link set tun1 up mtu 1400

장비 모델 파일이 반대 짝을 찍는다면 그 숫자를 쓰고 규칙은 지킨다. 인터페이스의 주소가 내 쪽이고, 피어 주소는 AWS 쪽이다. 이를 거꾸로 하면 터널이 Established에 이르지 못한다. 설정한 네이버가 바로 내 인터페이스가 이미 가진 주소이기 때문이다.

mark와 VTI 키는 IKE 데몬이 자식 SA를 인터페이스에 묶을 때 쓰는 값과 맞춰야 한다. 그렇지 않으면 트래픽이 터널에 도착해도 내려앉을 인터페이스가 없다. MTU는 다른 사이트의 숫자를 베끼지 말고 경로와 IKE 데몬 자체 설정에 비추어 확인한다.

경로를 확인하기 전에 BGP를 확인한다

IPsec이 올라온 것은 피어가 보안 연결에 합의했다는 것만 증명한다. BGP 세션은 내부 링크 위의 별도 협상이므로 네이버 상태와 프리픽스 카운터를 읽고, 광고하려던 것과 비교한다.

ip -s addr show dev tun0
vtysh -c 'show bgp summary'
vtysh -c 'show bgp neighbors 169.254.10.1'
vtysh -c 'show ip bgp neighbors 169.254.10.1 advertised-routes'

Established 상태에서 받은 프리픽스가 없으면 터널이 아니라 정책이나 광고의 문제다. 같은 확인을 두 번째 터널에서 반복한다. 첫 터널이 동작한다는 것은 주소가 그럴듯하다는 뜻이지, 두 번째 터널이 설정되었다는 뜻이 아니다.

라우팅된 패킷을 따라가고 거기서 멈춘다

세션이 프리픽스를 나르면 게이트웨이에서 양방향으로 경로를 시험한다. 출발지 주소, 다음 홉, 그리고 트래픽을 허용하는 보안 정책이다. BGP 세션이 올라와 있어도 애플리케이션에 필요한 특정 프리픽스가 필터링되거나 요약되거나 잘못된 인터페이스로 향할 수 있다.

Reachability Analyzer는 AWS 쪽 도구로, 출발지와 목적지, 경로를 받아 지원되는 구성에서 어느 구성 요소가 막았는지 보고한다. VPC에서 고객 게이트웨이 주소까지의 경로를 시험할 때 쓰고, 애플리케이션 호스트에서는 쓰지 않는다. 구성만 분석하고 온프레미스 방화벽으로 패킷을 보내지 않으므로, 그 판정은 자신의 인터페이스 카운터와 패킷 캡처와 분리해 두어야 한다.

터널마다 외부 짝, 내부 /30, 광고하는 프리픽스를 하나의 표에 기록한다. 그 표가 있어야 다음 변경을 검토할 수 있다.

관련 글