Published on

Azure VM SSH 타임아웃 - NSG·UDR 진단 체크리스트

Authors

서버에 ssh user@<public-ip>를 쳤는데 비밀번호 프롬프트조차 못 보고 타임아웃이 난다면, 대개 “패킷이 VM까지 못 가거나(ingress)”, “VM이 응답을 못 내보내거나(egress/return path)”, “중간에서 드롭(NSG/UDR/NVA)”되는 문제입니다. 특히 Azure에서는 NSG(Network Security Group)UDR(User Defined Route, 라우트 테이블) 조합에서 흔히 사고가 납니다.

이 글은 VM 내부에서 sshd가 죽었는지 같은 OS 레벨 이전에, 네트워크 레이어에서 SSH 타임아웃을 가장 빠르게 진단하는 체크리스트입니다.

> VM 자체가 부팅/에이전트 문제로 접속이 안 되는 케이스(Serial Console/Boot Diagnostics 필요)는 아래 글도 참고하세요: Azure VM 부팅 불가? Boot Diagnostics로 복구

1) 증상 분류: “거절(REFUSED)” vs “타임아웃(TIMEOUT)”

먼저 로컬에서 다음처럼 확인합니다.

# 타임아웃/라우팅/방화벽 드롭 계열이면 보통 여기서 오래 멈춤
ssh -vvv -o ConnectTimeout=5 azureuser@<PUBLIC_IP>

# 포트 레벨로 빠르게 확인
nc -vz -w 3 <PUBLIC_IP> 22
  • Connection refused: VM까지는 갔는데(또는 중간 장비가 RST), VM/방화벽/sshd 문제일 가능성이 큼.
  • Connection timed out: 중간에서 드롭(NSG/UDR/NVA/온프레 방화벽) 가능성이 큼.

이 글은 “타임아웃”에 집중합니다.

2) 가장 흔한 원인: NSG 인바운드 22 미허용(또는 우선순위에 막힘)

Azure NSG는 우선순위 숫자가 낮을수록 먼저 적용됩니다. “Allow SSH 22”를 만들었는데도 타임아웃이면 아래를 봐야 합니다.

2-1) NSG가 어디에 붙어 있는지부터 확인

NSG는 서브넷에도 붙고 NIC(네트워크 인터페이스) 에도 붙을 수 있습니다. 둘 다 붙어 있으면 둘 다 통과해야 합니다.

  • VM → Networking → Network interface 클릭
  • NIC의 Effective security rules 확인
  • Subnet의 NSG도 확인

CLI로도 확인 가능합니다.

# NIC에 연결된 NSG 확인
az network nic show -g <RG> -n <NIC_NAME> --query "networkSecurityGroup.id" -o tsv

# 서브넷에 연결된 NSG 확인
az network vnet subnet show -g <RG> --vnet-name <VNET> -n <SUBNET> --query "networkSecurityGroup.id" -o tsv

2-2) “Source”가 내 공인 IP인지, 아니면 Any인지

회사/집 IP가 바뀌었는데 NSG는 예전 IP를 허용하고 있으면 그대로 타임아웃이 납니다.

권장 패턴:

  • 운영 환경: Source = <내 고정 공인 IP>/32 또는 Bastion/Jumpbox만 허용
  • 임시 진단: 잠깐 Source = Any로 열어 원인 분리 (진단 후 즉시 원복)

2-3) Deny 규칙이 Allow보다 우선 적용되는지

예: DenyAllInbound (priority 100) 같은 규칙이 있으면, AllowSSH (priority 300)은 영원히 적용되지 않습니다.

포털의 NSG 규칙 목록에서 Priority를 반드시 확인하세요.

3) UDR(라우트 테이블)로 인해 “돌아오는 길(return path)”이 끊기는 문제

SSH는 TCP이므로 3-way handshake가 성립해야 합니다.

  1. Client → VM: SYN
  2. VM → Client: SYN-ACK
  3. Client → VM: ACK

여기서 VM의 응답(SYN-ACK)이 엉뚱한 곳으로 라우팅되면, 클라이언트는 타임아웃으로 보게 됩니다. UDR이 대표 원인입니다.

3-1) 서브넷에 Route table이 연결돼 있는지 확인

az network vnet subnet show -g <RG> --vnet-name <VNET> -n <SUBNET> --query "routeTable.id" -o tsv

연결돼 있다면 해당 라우트 테이블의 라우트를 확인합니다.

az network route-table route list -g <RG> --route-table-name <ROUTE_TABLE> -o table

3-2) 0.0.0.0/0을 NVA(방화벽/가상 어플라이언스)로 보내는 경우

가장 흔한 형태:

  • 0.0.0.0/0 -> Virtual appliance (10.x.x.x)

이 구성 자체는 흔하지만, 아래 중 하나면 SSH가 타임아웃 납니다.

  • NVA가 인바운드(22) 세션을 허용하지 않음
  • NVA가 SNAT/대칭 라우팅을 보장하지 않음
  • NVA가 장애/미구성 상태

특히 “인바운드는 Public IP로 들어오는데, 아웃바운드는 NVA로 나간다” 같은 비대칭 경로(asymmetric routing) 는 TCP 세션을 망가뜨립니다.

4) Effective Routes / Effective Security Rules로 “실제 적용 상태”를 본다

Azure 네트워크 문제는 “설정 화면”보다 Effective(유효) 뷰가 훨씬 정확합니다. NIC 기준으로 확인하세요.

4-1) NIC의 Effective routes 확인

az network nic show-effective-route-table -g <RG> -n <NIC_NAME> -o table

여기서 체크할 것:

  • 0.0.0.0/0의 NextHop이 무엇인지 (Internet? VirtualAppliance?)
  • 내 클라이언트 공인 IP로의 리턴 트래픽이 어떤 경로로 나가는지(대개 기본 경로에 의존)

4-2) NIC의 Effective NSG rules 확인

az network nic list-effective-nsg -g <RG> -n <NIC_NAME> -o json

여기서 DestinationPortRange=22, Direction=Inbound, Access=Allow가 실제로 존재하는지, 그리고 더 높은 우선순위의 Deny가 없는지 확인합니다.

5) Network Watcher로 “NSG가 막는지/라우팅이 이상한지” 즉시 판별

포털에서 Network Watcher가 꺼져 있으면 켜야 합니다(리전별).

5-1) IP Flow Verify: NSG 관점에서 허용/차단 확인

  • Network Watcher → IP flow verify
  • VM, NIC 선택
  • Direction: Inbound
  • Protocol: TCP
  • Local port: 22
  • Remote IP: 내 공인 IP

CLI 예시:

az network watcher test-ip-flow \
  --resource-group <RG> \
  --vm <VM_NAME> \
  --direction Inbound \
  --protocol TCP \
  --local <VM_PRIVATE_IP> \
  --local-port 22 \
  --remote <MY_PUBLIC_IP> \
  --remote-port 50000

결과가 Deny면 NSG(또는 ASG) 규칙 문제입니다.

5-2) Next Hop: UDR/NVA로 어디로 가는지 확인

az network watcher show-next-hop \
  --resource-group <RG> \
  --vm <VM_NAME> \
  --source-ip <VM_PRIVATE_IP> \
  --dest-ip 8.8.8.8
  • NextHopType이 VirtualAppliance로 나오면 기본 경로가 NVA로 향하고 있다는 뜻입니다.
  • 이때 NVA가 리턴 트래픽을 정상 처리하는지(정책/라우팅/상태)를 함께 봐야 합니다.

5-3) Connection troubleshoot: end-to-end로 막힌 지점 찾기

  • Network Watcher → Connection troubleshoot
  • Source: 내 환경(보통은 Azure 내 다른 VM을 Source로 두는 게 정확)
  • Destination: 문제 VM의 22

외부 PC에서 Azure VM으로의 경로는 Azure가 100% 관측하지 못하므로, 가능하면 같은 VNet/피어링된 VNet의 테스트 VM에서 진단하는 편이 좋습니다.

6) “Public IP로 접속”인데도 UDR이 영향을 주는 이유

헷갈리는 지점이 하나 있습니다.

  • 인바운드: Public IP → Azure LB(SNAT/DNAT) → VM NIC
  • 아웃바운드(리턴): VM NIC → 서브넷 라우팅(UDR) → Internet 또는 NVA

즉, 인바운드는 들어왔는데 리턴이 UDR 때문에 Internet이 아닌 NVA로 빠져나가 세션이 깨질 수 있습니다. 그래서 SSH가 타임아웃처럼 보입니다.

이 패턴은 EKS에서 “Pod는 정상인데 egress만 막히는” 상황과 원인 구조가 비슷합니다(경로/보안 정책의 불일치). 네트워크 경로를 분리해 점검하는 관점은 아래 글도 도움이 됩니다: EKS에서 Pod는 정상인데 egress만 막힐 때 점검

7) 진단 순서(실전): 10분 안에 원인 좁히기

7-1) 1단계: VM 상태/공인 IP 매핑 확인

  • VM이 Running인지
  • NIC에 Public IP가 연결돼 있는지
  • Public IP가 바뀌지 않았는지(동적 할당이면 재시작/재배포로 변경 가능)
az vm show -g <RG> -n <VM_NAME> --show-details --query "{power:powerState, publicIps:publicIps, privateIps:privateIps}" -o yaml

7-2) 2단계: NSG에서 22 인바운드 허용 확인(Effective 기준)

  • NIC Effective security rules
  • Subnet NSG 포함 여부
  • Source IP, Priority, Deny 선행 여부

7-3) 3단계: UDR/Next hop 확인

  • Effective route table
  • 0.0.0.0/0이 VirtualAppliance로 가는지
  • NVA/Firewall 정책에서 22 세션/리턴 허용하는지

7-4) 4단계: Network Watcher로 교차검증

  • IP Flow Verify로 NSG 결론
  • Next Hop으로 UDR 결론

여기까지에서 대부분 결론이 납니다.

8) 자주 나오는 케이스별 처방

케이스 A) NSG에 Allow 22가 있는데도 타임아웃

  • Allow 규칙 Priority가 Deny보다 뒤에 있지 않은지
  • NIC/서브넷 양쪽 NSG 모두 통과하는지
  • Source가 내 IP로 정확한지

케이스 B) UDR로 0.0.0.0/0을 방화벽(NVA)로 보낸 뒤부터 접속 불가

  • 방화벽에서 DNAT/SNAT/세션 테이블 정책 확인
  • 방화벽 장애 여부 확인
  • 임시로 진단하려면:
    • 문제 서브넷에서 UDR 분리(테스트 서브넷)
    • 또는 특정 관리 대역만 Internet으로 예외 라우트(조직 정책에 맞게)

케이스 C) 특정 네트워크(회사)에서만 타임아웃

  • 회사 방화벽에서 22 outbound 차단 가능
  • 회사 NAT 공인 IP가 바뀌어 NSG Source mismatch
  • 해결: Azure Bastion / VPN / 허용 IP 업데이트

9) 최소한의 보안 권장안(운영 기준)

  • 22를 Internet 전체에 개방하지 말 것
  • 가능하면 Azure Bastion 또는 Jumpbox(관리 전용 서브넷) 사용
  • NSG는 Source=<관리망>/32, DestinationPort=22, Priority 명확히
  • UDR로 NVA를 쓸 경우 대칭 라우팅과 SNAT 정책을 설계 단계에서 확정

10) 마무리: “NSG냐 UDR이냐”를 빠르게 가르는 핵심

  • IP Flow Verify가 Deny면: 거의 확실히 NSG(또는 상위 정책) 문제
  • IP Flow Verify가 Allow인데도 타임아웃이면: UDR/NVA/비대칭 라우팅/중간 방화벽 문제일 확률이 큼
  • 최종적으로는 NIC의 Effective routes와 Network Watcher의 Next hop이 결론을 줍니다.

SSH 타임아웃은 답답하지만, Azure에서는 관측 도구가 잘 갖춰져 있습니다. “설정 화면”을 믿기보다 Effective(유효) 상태경로(Next hop) 를 기준으로 보면, 원인을 체계적으로 좁힐 수 있습니다.