LabHub
배우기 러닝패스 코스

ネットワーク基礎 — Linux VM で手を動かす

隣人かどうか — アドレス・マスク・ARP

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

패킷을 보내기 전에 커널이 하는 첫 판단은 "상대가 같은 서브넷인가" 다. 같으면 ARP 로 상대의 MAC 을 직접 묻고, 아니면 게이트웨이의 MAC 으로 보낸다. 마스크 한 비트가 그 갈림길이다.

概念マップ: 어디에・게이트웨이의 MAC・마스크 오타.・IP 중복.

왜 이게 필요했나

IP 주소는 어디에 있는지를 말하는 논리 주소이고, 프레임을 실제로 배달하는 것은 NIC 에 박힌 MAC 주소다. 둘은 아무 관계가 없다. 그래서 같은 케이블(같은 L2)에 붙은 상대에게 보내려면 "이 IP 를 가진 사람, MAC 이 뭐야?" 를 물어야 하고, 그것이 ARP 다. 답은 이웃 테이블(ARP 캐시)에 잠시 남는다.

문제는 같은 케이블에 없는 상대다. 브로드캐스트는 링크를 넘지 못하므로 ARP 로 찾을 수 없다. 그래서 커널은 마스크로 "같은 서브넷인가" 를 먼저 판정하고, 아니면 라우팅 테이블에서 게이트웨이를 찾아 게이트웨이의 MAC 으로 프레임을 만든다. 게이트웨이가 반드시 같은 서브넷에 있어야 하는 이유가 이것이다 — 그 MAC 을 물어볼 수 있어야 하니까.

어떻게 동작하나

192.168.1.77/25 에서 192.168.1.130 으로 보낸다고 하자. /25 는 앞 25비트가 네트워크라 128 에서 갈린다. 77 은 0–127 블록, 130 은 128–255 블록이다. 다른 서브넷이므로 커널은 게이트웨이를 찾는다. 같은 두 주소를 /24 로 두면 같은 블록이 되어 ARP 로 직접 묻는다. 주소는 하나도 안 바뀌었는데 마스크 한 비트로 경로가 완전히 달라진다.

192.168.1.77 과 192.168.1.130 의 앞 24비트는 같고 마지막 옥텟의 첫 비트만 0 과 1 로 갈린다. /24 로 보면 같은 서브넷이라 ARP 로 상대 MAC 을 직접 묻고, /25 로 보면 그 첫 비트까지가 네트워크라 다른 서브넷이므로 게이트웨이의 MAC 으로 보낸다

ARP 요청은 목적지 MAC 이 ff:ff:ff:ff:ff:ff 인 브로드캐스트다. 자기 IP 를 본 호스트만 유니캐스트로 답한다. 커널은 답을 이웃 테이블에 넣고(REACHABLE), 잠시 안 쓰면 STALE 로 바꾸고, 다음에 쓸 때 다시 확인한다. nud permanent 로 정적 항목을 박으면 커널은 그것을 갱신하지 않는다 — 그래서 틀린 MAC 을 박으면 IP 도 라우팅도 멀쩡한데 통신만 조용히 죽는다. 상대 NIC 이 "내 것이 아니다" 로 버릴 뿐 아무 오류도 되돌아오지 않기 때문이다.

현장에서 만나는 모습

마스크 오타. 새 서버에 /24 를 /16 으로 적었다. 같은 /24 안의 통신은 잘 된다. 그런데 옆 대역(같은 /16 안의 다른 /24)으로 가는 패킷을 커널이 "같은 서브넷" 으로 보고 ARP 를 보내는데 답이 없다. 게이트웨이를 거치면 될 것을 직접 찾다가 실패하는 것이다. 증상은 "일부 대역만 안 됨" 이고, ip neigh 에 FAILED 항목이 쌓여 있는 것이 단서다.

IP 중복. 두 장비가 같은 IP 를 가지면 ARP 답이 둘이 오고 나중 것이 이긴다. 통신이 됐다 안 됐다 한다. 이웃 테이블의 MAC 이 바뀌는 것을 잡으면 원인이 보인다.

자주 헷갈리는 주소들

서브넷 안의 주소가 전부 호스트에 쓰이는 것은 아니다. 192.168.1.0/24 에서 .0 은 네트워크 주소, .255 는 브로드캐스트 주소라 호스트에 붙일 수 없고, 그래서 쓸 수 있는 주소는 256개가 아니라 254개다. 마스크가 좁아질수록 이 손실이 커진다. /30 은 주소 4개 중 2개만 쓸 수 있어서, 라우터끼리 잇는 구간에 예전부터 /30 을 써 왔다. 요즘은 그 구간에 /31 을 쓴다. 점대점 링크에는 브로드캐스트가 필요 없다는 것을 규약으로 정해서, 주소 2개를 둘 다 호스트에 쓴다.

몇 가지 대역은 의미가 정해져 있어서 증상만 보고도 원인을 짐작할 수 있다.

대역 이것이 보이면
127.0.0.0/8 자기 자신 밖으로 나가지 않는다. 서비스를 여기에만 바인딩하면 다른 호스트에서 못 닿는다
169.254.0.0/16 링크 로컬 DHCP 를 못 받아 스스로 붙인 주소다. 주소가 있는데 통신이 안 되는 전형
10/8·172.16/12·192.168/16 사설 대역 인터넷으로 그대로 나가지 못한다. NAT 가 반드시 끼어 있다
224.0.0.0/4 멀티캐스트 특정 그룹을 구독한 호스트만 받는다

인터페이스 하나에 주소를 여러 개 붙일 수도 있다. 이때 나가는 패킷의 출발지 주소는 커널이 고른다. 기본 규칙은 "목적지와 같은 서브넷에 있는 주소 중 첫 번째" 이고, 그래서 상대 쪽 방화벽이 특정 출발지만 허용하고 있으면 어떤 날은 통과하고 어떤 날은 막히는 것처럼 보인다. ip route get <상대 주소> 를 실행하면 커널이 실제로 어떤 출발지와 어떤 경로를 고를지 그대로 알려 주므로, 추측하지 말고 이 명령으로 확인하는 편이 빠르다.

마지막으로 ARP 의 변형 둘을 알아 두면 좋다. 불필요 ARP(gratuitous ARP) 는 아무도 묻지 않았는데 "이 IP 는 내 MAC 이다" 라고 알리는 것으로, 가상 IP 를 다른 장비로 넘길 때 주변의 이웃 테이블을 즉시 갱신시키는 용도로 쓴다. 장애 조치를 했는데 트래픽이 한동안 죽은 장비로 계속 가는 사고는 대개 이 통지가 나가지 않았거나 중간 스위치에서 걸러진 경우다. 프록시 ARP 는 라우터가 남의 IP 에 대신 답해 주는 것으로, 편해 보이지만 어느 장비가 답한 것인지 추적하기 어려워져 원인 파악을 크게 방해한다.

다음 실습에서 할 것

ip -br·ip -j 로 인터페이스와 주소를 읽고, ipcalc 와 파이썬으로 서브넷을 계산하고, 더미 인터페이스에 주소를 붙여 본다. 그다음 네임스페이스 둘을 veth 로 이어 ARP 요청과 응답을 tcpdump 로 잡고, 정적 항목에 틀린 MAC 을 넣어 통신이 죽는 것을 눈으로 본다.