--- id: 68a848c7-eaff-4421-ad25-de21673ca40c kind: REFERENCE slug: bisect-the-packet-path-with-capture-points title: packet 이 어디서 끊겼는지는 계층마다 capture 해서 가른다 topic: network-virtualization topicName: 네트워크 가상화 project: virtualization status: 초안 studio: "https://hyeonworks.com/studio/documents/68a848c7-eaff-4421-ad25-de21673ca40c/edit" sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다 source: - final/document.md#119-실제-packet-path-추적 - final/document.md#118-실제-linux에서-확인할-명령어 - final/document.md#117-이-구조에서-발생할-수-있는-문제-117-1 - final/document.md#117-이-구조에서-발생할-수-있는-문제-117-2 - final/document.md#117-이-구조에서-발생할-수-있는-문제-117-3 - final/document.md#117-이-구조에서-발생할-수-있는-문제-117-6 - final/document.md#113-offload-최적화 - final/document.md#114-linux-bridge가-항상-host-tcp-ip-stack을-거치는-것은-아니다 - final/document.md#99-tap의-역할 --- # packet 이 어디서 끊겼는지는 계층마다 capture 해서 가른다 가상 머신이 밖과 통신하지 못할 때 게스트 안에서만 원인을 찾으면 호스트의 브리지와 TAP 연결은 마지막에야 보게 된다. 그 사이의 계층은 애플리케이션 로그에 아무것도 남기지 않는다. 그래서 패킷이 지나야 할 지점마다 캡처를 걸고 어디까지 보였는지로 구간을 좁힌다. 호스트의 물리 NIC(Network Interface Card) 와 브리지, 가상 머신에 붙은 TAP, 게스트 안의 인터페이스 넷이 그 지점이고, 보이지 않은 첫 지점의 앞 구간이 의심 구간이 된다. ## 관계 - **Guest 의 packet 이 Host Physical NIC 에 닿기까지 — virtio-net · virtqueue · vhost-net · TAP · Bridge** 이 절차가 관측 지점으로 쓰는 계층을 세운 글이다. 어느 계층이 무엇을 하는지는 그쪽에 있다. - **Keycloak 실험 결과를 애플리케이션 원인으로 읽기 전에 network 계층을 따로 검증한다** 그 기준은 문제가 네트워크인지 아닌지를 가르고, 이 절차는 네트워크 안에서 어느 구간인지를 가른다. - **이 호스트의 가상 머신 네트워크는 Bridge 인가 NAT 인가 Routing 인가** 캡처 지점 이름을 확정하는 첫 규칙이 그대로 이 물음의 확인 절차다. - **VM1 과 VM2 의 TAP/vnet interface 는 무엇이고 어디에 붙어 있는가** TAP 이름을 모르면 이 절차의 세 번째 지점에 캡처를 걸 수 없다. - **Host Nginx 에서 Keycloak 까지 packet 은 실제로 어디를 지나는가** 그 경로를 처음 확인할 때 쓰는 절차다. ## 목적 이 기준은 두 가지를 막는다. 가상 머신이 통신하지 못할 때 게스트 안쪽과 애플리케이션부터 뒤지느라 호스트의 브리지와 TAP 연결을 늦게 보는 일이 하나다. 오프로드 때문에 실제 wire 와 다르게 보이는 정상 패킷을 결함으로 판정하는 일이 다른 하나다. 이 순서는 물음 셋이 함께 쓴다. 이 호스트의 가상 머신 네트워크가 무엇으로 구성돼 있는지, TAP 인터페이스가 무엇인지, 호스트 Nginx 에서 Keycloak 까지 패킷이 어디를 지나는지 셋이 모두 이 순서 위에서 돈다. 그래서 세 곳에 같은 절차를 되풀이하지 않고 한 편에 두었다. ## 규칙 ### 1. 캡처할 지점의 이름을 먼저 확정한다 관측 지점은 넷이다. 호스트의 물리 NIC, 호스트의 브리지, 가상 머신에 붙은 tap 또는 vnet, 그리고 게스트 안의 인터페이스. 이름을 모른 채 시작하면 없는 인터페이스에 캡처를 걸어 놓고 패킷이 안 보인다고 판정하게 된다. 인터페이스 목록은 ip link 로 본다. 브리지에 무엇이 붙어 있는지는 bridge link 와 bridge fdb show 가 알려 준다. tap 목록은 ip tuntap show 로 본다. 어느 가상 머신이 어느 tap 에 붙어 있는지는 virsh domiflist 에 도메인 이름을 붙여 확인한다. libvirt 가 만든 가상 네트워크가 무엇인지는 virsh net-list --all 과 virsh net-dumpxml 로 확인한다. 라우팅이 개입하는 구성이면 ip route 와 ip rule 도 함께 본다. ### 2. 네 지점에 같은 요청을 흘리면서 캡처를 건다 호스트에서는 물리 NIC 와 브리지, tap 또는 vnet 에 각각 tcpdump -ni 로 캡처를 건다. 게스트에서는 게스트 인터페이스에 같은 방식으로 건다. ### 3. 보이지 않은 첫 지점의 앞 구간을 의심 구간으로 삼는다 판독은 어느 지점까지 보였는가로만 한다. 물리 NIC 에 보이고 브리지에도 보이는데 tap 에 안 보이면, 게스트 내부보다 먼저 호스트의 브리지와 tap 연결을 의심한다. tap 에는 보이는데 게스트 NIC 에 안 보이면 virtio 와 vhost, 게스트 NIC 계층을 의심한다. 게스트 NIC 에는 보이는데 소켓까지 오지 않으면 게스트의 라우팅과 방화벽, listen 상태를 의심한다. ### 4. 증상마다 다음에 볼 명령을 미리 정해 둔다 의심 구간이 나오면 그 구간의 증상에 맞는 확인으로 넘어간다. 가상 머신이 외부와 통신하지 못하거나 호스트와 통신하지 못하거나 특정 가상 머신만 통신하지 못하면 tap 과 브리지 연결을 본다. ip link, bridge link, bridge fdb show, virsh domiflist 가 그 확인이다. 같은 서브넷은 통신되는데 다른 서브넷이 안 되거나 게이트웨이까지는 가는데 외부 통신이 실패하면 라우팅을 본다. ip route 와 ip rule 이다. 가상 머신에서 인터넷으로 나가지 못하거나 외부에서 가상 머신에 접근하지 못하거나 특정 포트만 실패하면 nftables 와 iptables, NAT(Network Address Translation) 규칙, IP(Internet Protocol) forwarding 설정을 확인 대상으로 둔다. 증상 셋을 각각 다른 기준으로 나누지 않은 것은 셋이 모두 어느 지점에서 끊겼는가로 환원되기 때문이다. 따로 적으면 같은 규칙의 부분 증상이 셋으로 늘어난다. ### 5. 패킷 크기와 체크섬이 예상과 다르다는 이유만으로 결함이라고 읽지 않는다 오프로드가 켜져 있으면 캡처에서 보이는 패킷 크기나 체크섬이 실제 wire 에서 보이는 것과 다르게 보일 수 있다. 원인 후보는 GSO(Generic Segmentation Offload), GRO(Generic Receive Offload), TSO(TCP Segmentation Offload), checksum offload 다. 크기와 체크섬이 예상과 다르면 오프로드 설정을 먼저 확인하고, 그 값만으로 판정하지 않는다. ### 6. 호스트의 L3 쪽에서 안 보이는 것을 곧바로 실패로 읽지 않는다 브리지가 L2 전달만 하는 경우 프레임이 호스트의 일반적인 L3 TCP/IP 스택을 반드시 거치지는 않는다. 한 가상 머신의 tap 에서 브리지를 지나 다른 가상 머신의 tap 으로 가는 경로가 그렇다. 호스트가 라우팅이나 NAT, host-local termination, 방화벽 역할을 할 때 L3 와 Netfilter 경로가 개입한다. 그래서 구성에 따라 호스트의 L3 관측에서 안 보이는 것이 정상이다. ### 7. 네 지점이 모두 보이는데 느리기만 한 경우는 이 절차가 답하지 않는다 이 절차가 가르는 것은 패킷이 어디서 끊겼는가다. 끊기지 않고 느리기만 하면 다른 기준으로 넘긴다. ## 적용 조건 KVM(Kernel-based Virtual Machine)/QEMU/libvirt 로 만든 가상 머신이 외부와 통신하지 못할 때. 특정 구간에서만 통신이 실패할 때. 실제 패킷 경로를 처음 확인할 때. ## 예외 오프로드가 켜진 구성에서는 패킷 크기와 체크섬이 그대로 증거가 되지 않는데, 다섯 번째 규칙이 그 경우다. 브리지가 L2 전달만 하는 구성에서는 호스트의 L3 관측에 안 보이는 것이 정상인데, 여섯 번째 규칙이 그 경우다. 네 지점이 모두 보이는데 느린 경우는 이 기준이 다루지 않는다. Keycloak 실험 결과를 애플리케이션 원인으로 읽기 전에 network 계층을 따로 검증한다 쪽으로 넘긴다. 이 저장소에는 아직 이 절차를 실제로 돌린 출력이 없다. 여기 적은 판독은 원문 문서가 서술한 것이고 이 호스트의 캡처로 확인한 것이 아니다. ## 예시 - 물리 NIC 에 보이고 브리지에도 보이는데 tap 에 안 보임 : 호스트의 브리지와 tap 연결을 먼저 확인한다 - tap 에 보이는데 게스트 NIC 에 안 보임 : virtio 와 vhost, 게스트 NIC 계층을 확인한다 - 게스트 NIC 에 보이는데 소켓까지 안 옴 : 게스트의 라우팅과 방화벽, listen 상태를 확인한다 - 특정 가상 머신만 통신 불가 : ip link 와 bridge link, virsh domiflist 로 그 가상 머신의 tap 이 브리지에 붙어 있는지 본다 - 같은 서브넷은 되고 다른 서브넷만 실패 : ip route 와 ip rule 을 본다 - 캡처에 보이는 패킷이 예상보다 크고 체크섬이 어긋남 : 오프로드 설정을 먼저 확인한다 - 네 지점이 모두 보이는데 응답만 느림 : 이 절차를 여기서 멈춘다