- Published on
AWS VPC 피어링 통신 불가? 라우트·SG·NACL 점검
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
VPC 피어링을 만들고 상태가 active인데도 핑이 안 되거나, 특정 포트만 타임아웃이 나는 경우가 꽤 흔합니다. 이유는 단순합니다. VPC 피어링은 “연결”만 제공하고, 실제 데이터 플레인은 각 VPC의 라우팅/보안 정책이 모두 맞아야 열립니다.
이 글은 “왜 안 되지?”에서 “어디가 막혔는지”로 바로 이동할 수 있도록, 라우트 테이블, Security Group, NACL, DNS/서비스별 제약을 순서대로 점검하는 실전 체크리스트를 제공합니다.
아래 내용은 같은 리전/다른 리전 피어링 모두에 적용되며, 특히 EKS나 프라이빗 서브넷 간 통신 문제에도 그대로 쓰입니다. (네트워크 타임아웃이 간헐적으로 보인다면 커널/커넥션 추적 이슈도 함께 볼 가치가 있습니다: EKS conntrack 테이블 포화로 연결 끊김 해결법)
1) 먼저 전제 확인: 피어링이 “가능한 구조”인가
CIDR 겹침(Overlapping CIDR)
VPC 피어링은 두 VPC의 CIDR이 겹치면 성립 자체가 안 되거나(생성 불가), 부분적으로 라우팅이 꼬입니다. 겹치지 않는지 먼저 확인하세요.
- VPC A:
10.0.0.0/16 - VPC B:
10.0.0.0/16또는10.0.1.0/24같은 포함 관계면 불가
CLI 예시:
aws ec2 describe-vpcs --vpc-ids vpc-aaaa vpc-bbbb \
--query 'Vpcs[*].{VpcId:VpcId,Cidr:CidrBlock}' --output table
피어링의 “전이(transitive) 라우팅” 불가
A - B, B - C 피어링이 있어도 A에서 C로는 기본적으로 못 갑니다. “B를 경유해서” 같은 구성은 피어링으로 해결되지 않습니다(Transit Gateway 같은 별도 구성 필요).
보안 장비/프록시를 통한 중간 검사 기대 금지
피어링은 라우팅 레벨 연결이라, VPC 간 트래픽을 중앙 방화벽으로 강제 우회시키는 패턴(헤어핀/인스펙션)은 설계가 따로 필요합니다.
2) 가장 흔한 원인 1순위: 라우트 테이블(양쪽 모두)
피어링은 “양쪽 라우트 테이블”에 상대 CIDR로 향하는 경로가 있어야 합니다. 한쪽만 넣으면 단방향처럼 보이거나, SYN은 가는데 SYN-ACK가 못 돌아오는 형태로 타임아웃이 납니다.
체크 포인트
- 통신 주체가 속한 서브넷의 라우트 테이블이 맞는지(연결된 RTB 확인)
- 대상 CIDR이 정확한지(너무 좁거나 넓은 CIDR 실수)
- 타겟이
pcx-...(피어링 연결)인지 - 라우트 우선순위(더 구체적인 경로가 다른 곳으로 빠지지 않는지)
CLI로 라우트 확인:
aws ec2 describe-route-tables \
--filters Name=vpc-id,Values=vpc-aaaa \
--query 'RouteTables[*].{Rtb:RouteTableId,Routes:Routes[*].{Dest:DestinationCidrBlock,Target:VpcPeeringConnectionId,State:State}}'
라우트 추가(예시):
aws ec2 create-route \
--route-table-id rtb-aaaa \
--destination-cidr-block 10.20.0.0/16 \
--vpc-peering-connection-id pcx-1234567890abcdef
“서브넷 라우트 테이블 착각” 패턴
운영에서 자주 보는 실수는, 피어링 라우트를 “메인 라우트 테이블”에만 넣고 실제 인스턴스가 붙은 서브넷은 다른 RTB를 쓰는 경우입니다.
확인 방법:
aws ec2 describe-route-tables \
--route-table-ids rtb-aaaa \
--query 'RouteTables[0].Associations[*].{Subnet:SubnetId,Main:Main,AssocId:RouteTableAssociationId}'
3) Security Group(SG): 상태 기반이지만 “기본 차단”이다
SG는 stateful이라서 “나가는 트래픽 허용 후 응답은 자동 허용” 같은 특성이 있지만, 최초 요청이 들어오는 방향(Inbound)이 막혀 있으면 끝입니다.
체크 포인트
- 대상 인스턴스/ENI에 붙은 SG의 Inbound에 소스 CIDR이 상대 VPC 대역으로 열려 있는지
- 포트가 정확한지(예: DB는
5432, Redis는6379, gRPC는 서비스 포트) - SG 참조를 VPC 간에 하려는 실수(피어링 간 SG ID 참조는 조건이 있으며, 계정/리전/설정에 따라 제약이 있어 “CIDR로 여는 편”이 진단이 쉽습니다)
예: VPC B의 DB SG에 VPC A 대역을 허용
aws ec2 authorize-security-group-ingress \
--group-id sg-db \
--ip-permissions 'IpProtocol=tcp,FromPort=5432,ToPort=5432,IpRanges=[{CidrIp=10.10.0.0/16,Description="from vpc-a"}]'
“아웃바운드는 열려 있는데 왜 안 되죠?”
클라이언트에서 서버로 접속할 때, 서버 SG Inbound가 막혀 있으면 타임아웃입니다. 반대로 서버가 클라이언트로 콜백하는 구조(웹훅, 액티브-패시브 복제 등)라면 클라이언트 쪽 SG Inbound도 필요합니다.
4) NACL: 무상태(stateless)라서 양방향/에페멀 포트까지 봐야 한다
NACL(Network ACL)은 stateless입니다. 즉, 인바운드를 열었다면 아웃바운드(응답 트래픽)도 별도로 열려 있어야 합니다. 또한 TCP는 서버 포트뿐 아니라 “클라이언트 에페멀 포트” 범위가 필요할 때가 많습니다.
체크 포인트
- 양쪽 서브넷의 NACL 규칙이 모두 허용인지
- 인바운드에 서버 포트 허용 + 아웃바운드에 에페멀 포트 허용(또는 그 반대)
- 규칙 번호 우선순위(작은 번호가 먼저 매칭)
- 마지막
DENY에 걸리지 않는지
에페멀 포트 범위(대표적으로 리눅스는 32768-60999 또는 49152-65535 등 환경마다 다를 수 있음)를 넉넉히 열어야 진단이 빠릅니다.
예시 정책(개념):
- 서버 서브넷 NACL Inbound:
tcp 5432from VPC A CIDR allow - 서버 서브넷 NACL Outbound:
tcp 1024-65535to VPC A CIDR allow
NACL 조회:
aws ec2 describe-network-acls \
--filters Name=vpc-id,Values=vpc-bbbb \
--query 'NetworkAcls[*].{Nacl:NetworkAclId,Entries:Entries}'
5) DNS/이름 해석 문제: “통신 불가”처럼 보이는 대표적 착시
피어링이 열려도 애플리케이션이 db.internal 같은 프라이빗 DNS 이름으로 접근한다면, 실제 문제는 라우팅이 아니라 DNS일 수 있습니다.
체크 포인트
- 상대 VPC의 Private Hosted Zone을 공유/연결했는지(Route 53 PHZ association)
- 피어링 연결에서 DNS resolution 옵션이 필요한지(요구되는 경우가 있음)
- 클라이언트가 어떤 DNS 서버를 쓰는지(VPC 기본 DNS인지, 커스텀인지)
진단 순서:
- 먼저 IP로 직접 접속 시도(이게 되면 네트워크는 열렸고 DNS 문제)
dig또는nslookup으로 레코드가 어디로 해석되는지 확인
dig +short db.internal.example.com
6) “핑은 안 되는데 TCP는 되네요” 또는 그 반대
- ICMP(ping)는 SG/NACL에서 별도로 허용해야 합니다. 보안 정책상 ICMP를 막아두는 경우가 많아, “핑 실패”만으로 피어링 장애라고 결론 내리면 안 됩니다.
- 반대로 TCP는 특정 포트만 열려 있으면 일부만 됩니다.
권장 테스트:
- TCP 포트 테스트:
nc또는curl
# TCP 포트 열림 확인
nc -vz 10.20.1.10 5432
# HTTP 계열이면 curl
curl -m 2 -v http://10.20.1.20:8080/health
7) MTU/단편화 이슈: “큰 패킷만” 실패하는 케이스
피어링 자체는 일반적으로 MTU 문제가 드물지만, 다음 조합에서는 이슈가 튀어나올 수 있습니다.
- 인스턴스/컨테이너가 Jumbo frame을 강제하거나
- 터널링(예: 일부 CNI/오버레이), VPN, 프록시 체인이 섞여서 실제 경로 MTU가 줄어든 경우
증상은 보통 “TLS 핸드셰이크가 간헐적으로 멈춤”, “큰 응답에서만 끊김” 같은 형태입니다. 이 경우는 tracepath나 패킷 캡처로 확인합니다.
8) 피어링으로는 안 되는 트래픽: 서비스 제약 정리
피어링은 VPC 간 사설 IP 라우팅입니다. 하지만 다음 요구사항은 피어링만으로 해결되지 않거나 별도 옵션이 필요할 수 있습니다.
- 중앙집중식 egress/ingress(전이 라우팅 필요)
- 온프레미스
-VPC A-VPC B 형태로 라우팅 공유(피어링은 전이 불가) - 일부 매니지드 서비스 접근은 PrivateLink/엔드포인트가 더 적합
EKS 환경에서 “노드에서만 되고 파드에서 안 된다” 같은 케이스는 CNI 라우팅, 소스 NAT, 보안 정책이 겹쳐 보일 수 있습니다. 이럴 때는 네트워크 자체 차단 여부를 먼저 확정한 다음, 워크로드 레벨로 내려가세요. (EKS 운영 중 보안 경계를 강화해야 한다면: EKS에서 AWS SDK의 IMDS 접근을 확실히 차단하는 법)
9) 10분 진단 체크리스트(현장용)
아래 순서대로 보면 대부분 10분 내 원인이 좁혀집니다.
1) 경로 확인
- 소스 인스턴스(또는 파드)의 IP/서브넷/라우트 테이블 ID 확인
- 대상 인스턴스의 IP/서브넷/라우트 테이블 ID 확인
- 양쪽 RTB에 상대 CIDR
->피어링(pcx-...) 라우트 존재 확인(부등호 포함 표현은 인라인 코드로 처리)
2) 보안 정책 확인
- 대상 SG Inbound: 소스 CIDR, 포트 허용
- 소스 SG Outbound: 대상 CIDR, 포트 허용(기본 전체 허용이 아니라면 필수)
- 양쪽 NACL: 인바운드/아웃바운드 모두 허용 + 에페멀 포트 고려
3) DNS 착시 제거
- IP로 먼저 접속 테스트
- 이름으로 접속이 실패하면 Route 53/피어링 DNS 옵션/리졸버 확인
4) 로그/패킷으로 확정
- 인스턴스에서
tcpdump로 SYN이 나가는지, SYN-ACK가 돌아오는지 확인 - VPC Flow Logs를 켜서
ACCEPT/REJECT확인(특히 NACL/SG에서 거부되는지)
tcpdump 예시:
sudo tcpdump -ni eth0 host 10.20.1.10 and tcp port 5432
10) 실전 예시: “A에서 B의 RDS로 접속이 안 됨”
상황:
- VPC A 앱 서버
10.10.1.50 - VPC B RDS 프라이빗 IP
10.20.2.10(또는 내부 엔드포인트) - 피어링
pcx-1234는active
점검:
- VPC A의 앱 서브넷 RTB에
10.20.0.0/16대상 라우트가pcx-1234로 있는지 - VPC B의 DB 서브넷 RTB에
10.10.0.0/16대상 라우트가pcx-1234로 있는지 - DB SG Inbound에
tcp 5432from10.10.0.0/16허용인지 - DB 서브넷 NACL에서
tcp 5432인바운드 허용,tcp 1024-65535아웃바운드 허용인지 - 앱 서버에서
nc -vz 10.20.2.10 5432로 포트 테스트
이 중 2) “리턴 라우트”가 빠져 있는 경우가 정말 많습니다. 요청은 가도 응답이 못 돌아와서 타임아웃이 나기 때문입니다.
마무리
VPC 피어링 통신 장애는 대부분 “연결 상태”가 아니라 “라우트/SG/NACL/DNS 중 하나가 빠진 상태”입니다. 특히 라우트는 반드시 양쪽에 있어야 하고, NACL은 stateless라 응답 방향과 에페멀 포트까지 같이 봐야 합니다.
운영 환경에서 증상이 간헐적이거나 특정 시간대에만 발생한다면, 네트워크 정책 외에도 커널 리소스(예: conntrack) 같은 시스템 요인을 함께 의심해야 합니다. 위 체크리스트로 먼저 ‘정책상 막힘’인지 ‘리소스/성능 이슈’인지 경계를 확정하면, 문제 해결 속도가 크게 빨라집니다.