📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 09편
이전 글: 08. IPv4 주소 구조 · 다음 글: 10. 공인 IP와 사설 IP
참고(리눅스 시스템 기초): ss와 ip 명령어 —ip명령 기본 사용법
"우리 회사는 IPv6를 안 쓴다"는 말이 "우리 네트워크에 IPv6 트래픽이 없다"는 뜻은 아닙니다. 현대 Linux·Windows는 대부분 IPv6가 기본 활성화되어 있고, 설정하지 않아도 인터페이스마다 링크 로컬 주소(fe80::) 를 스스로 만들며, 같은 네트워크 안에서 IPv6로 이웃을 찾는 패킷을 주고받습니다.
관제에서 IPv6를 모르면 생기는 문제는 다음과 같습니다.
::ffff:192.0.2.10 같은 주소를 IPv4 주소와 같은 대상으로 연결하지 못합니다.이 글은 IPv6를 운영 설계 수준이 아니라 "로그와 패킷에서 알아보고 해석할 수 있는 수준" 으로 정리합니다.
IPv6 주소는 128비트이며, 16비트씩 8개 그룹을 16진수로 쓰고 콜론(:)으로 구분합니다.
2001:0db8:0000:0000:0000:0000:0000:0010
↓ 각 그룹 앞자리 0 생략
2001:db8:0:0:0:0:0:10
↓ 연속된 0 그룹을 :: 로 한 번만 축약
2001:db8::10
:: 축약은 주소 안에서 한 번만 쓸 수 있습니다. 두 번 쓰면 어디가 몇 그룹인지 알 수 없기 때문입니다.::로)는 RFC 5952에 정리되어 있습니다.2001:db8::/32 를 사용합니다.IPv6에는 브로드캐스트가 없습니다. 그 역할은 멀티캐스트가 대신합니다.
| 유형 | 범위(prefix) | 설명 | 관제 포인트 |
|---|---|---|---|
| 글로벌 유니캐스트 | 2000::/3 | 인터넷에서 라우팅되는 주소 | NAT 없이 외부와 직접 통신 가능 |
| 링크 로컬 | fe80::/10 | 같은 링크에서만 유효, 모든 인터페이스에 자동 생성 | 라우터를 넘지 않음, NDP·라우터 통신에 사용 |
| 고유 로컬(ULA) | fc00::/7 (실사용은 fd00::/8) | 내부망용, IPv4 사설 주소와 비슷한 용도 | 외부로 나가면 비정상 |
| 멀티캐스트 | ff00::/8 | 그룹 전달 | ff02::1 모든 노드, ff02::2 모든 라우터 |
| 루프백 | ::1 | IPv4의 127.0.0.1 | |
| 미지정 | :: | 주소가 아직 없음 / 모든 주소에서 대기 | ss 출력의 [::]:22 |
| IPv4 매핑 | ::ffff:0:0/96 | IPv6 소켓이 IPv4 연결을 받을 때 표현 | 로그에 ::ffff:192.0.2.10 형태로 등장 |
| 문서용 | 2001:db8::/32 | 예시 전용 | 실제 트래픽에 나오면 설정 오류 |
애니캐스트(anycast)는 별도 주소 대역이 아니라, 같은 유니캐스트 주소를 여러 노드에 부여해 가장 가까운 곳으로 전달되게 하는 방식입니다.
| 필드 | 크기 | IPv4 대응 / 차이 |
|---|---|---|
| Version | 4비트 | 값 6 |
| Traffic Class | 8비트 | ToS/DSCP |
| Flow Label | 20비트 | IPv4에 없음 |
| Payload Length | 16비트 | 헤더 제외 길이 (IPv4 Total Length는 헤더 포함) |
| Next Header | 8비트 | Protocol (TCP=6, UDP=17, ICMPv6=58, 또는 확장 헤더) |
| Hop Limit | 8비트 | TTL과 같은 역할 |
| Source / Destination | 각 128비트 |
IPv4 헤더에 있던 체크섬, 단편화 필드(ID·Flags·Offset)가 없습니다. 부가 기능은 확장 헤더로 Next Header를 따라 체인처럼 이어 붙입니다. 단편화는 출발지만 Fragment 확장 헤더로 수행하며, 중간 라우터는 쪼개지 않고 ICMPv6 Packet Too Big을 돌려보냅니다. IPv6 링크의 최소 MTU는 1280입니다.
IPv6에는 ARP가 없습니다. NDP(Neighbor Discovery Protocol, RFC 4861) 가 ICMPv6 메시지로 같은 역할과 그 이상을 수행합니다.
| ICMPv6 Type | 메시지 | 역할 | IPv4 대응 |
|---|---|---|---|
| 133 | Router Solicitation (RS) | "라우터 있나요?" | 없음 (DHCP 일부) |
| 134 | Router Advertisement (RA) | 라우터 존재·prefix·기본 게이트웨이 알림 | DHCP 게이트웨이 옵션과 유사 |
| 135 | Neighbor Solicitation (NS) | "이 IPv6 주소의 MAC은?" / 주소 중복 확인 | ARP Request |
| 136 | Neighbor Advertisement (NA) | "그 주소는 이 MAC입니다" | ARP Reply |
| 137 | Redirect | 더 나은 다음 홉 안내 | ICMP Redirect |
NS는 브로드캐스트 대신 대상 주소 끝 24비트로 만든 Solicited-Node 멀티캐스트 주소(ff02::1:ffXX:XXXX) 로 보내 불필요한 수신을 줄입니다.
이 때문에 IPv6 환경에서 ICMPv6를 일괄 차단하면 이웃 찾기, 게이트웨이 설정, PMTU 확인이 모두 멈춥니다. IPv4에서 ICMP를 막는 습관을 그대로 옮기면 안 되는 이유입니다.
SLAAC(Stateless Address Autoconfiguration, RFC 4862) 은 호스트가 RA에 담긴 prefix로 스스로 주소를 만드는 방식입니다. DHCPv6와 함께 쓰거나 SLAAC만 쓸 수도 있습니다.
Interface ID를 만드는 방식은 MAC 기반(EUI-64), 네트워크별로 고정된 무작위 값, 주기적으로 바뀌는 임시(Temporary/Privacy) 주소 등 OS와 설정마다 다릅니다. 임시 주소를 쓰면 같은 PC의 발신 주소가 시간에 따라 바뀌므로, IP만으로 단말을 추적하기 어려워집니다.
IPv6가 활성화된 인터페이스가 링크에 연결되면 다음 순서로 주소를 얻습니다.

그림 1. IPv6에서는 ARP 대신 ICMPv6 기반 NDP가 이웃·라우터를 찾습니다
[1] 링크 로컬 주소 생성 fe80:: + Interface ID
↓
[2] DAD (중복 주소 확인) NS 전송: 출발지 ::, 목적지 Solicited-Node 멀티캐스트
↓ → 응답(NA)이 없으면 주소 사용
[3] RS 전송 fe80::호스트 → ff02::2 (모든 라우터)
↓
[4] RA 수신 fe80::라우터 → ff02::1 (모든 노드)
↓ 내용: prefix 2001:db8:10::/64, 라우터 수명, M/O 플래그
[5] 글로벌 주소 생성 2001:db8:10:: + Interface ID → 다시 DAD
↓
[6] 기본 게이트웨이 = RA를 보낸 라우터의 링크 로컬 주소
↓
[7] 통신 시 NS/NA 로 이웃 MAC 확인 → 이웃 캐시(ip -6 neigh) 저장
기본 게이트웨이가 글로벌 주소가 아니라 링크 로컬 주소(fe80::...) 로 잡히는 것이 IPv4와 다른 점입니다. 또한 RA의 M(Managed)/O(Other) 플래그는 DHCPv6로 주소나 기타 정보(DNS 등)를 받으라는 신호입니다.
보안 측면에서 [5]~[6]은 RA를 보낸 쪽을 게이트웨이로 믿는 구조입니다. 같은 링크의 누군가가 위조 RA를 보내면 트래픽 경로가 바뀔 수 있습니다. IPv4의 ARP 위장, 가짜 DHCP와 같은 계열의 위협이며, 스위치의 RA Guard 같은 기능으로 방어합니다.
실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu), 인터페이스 이름은 ens33 예시입니다. 가상화 네트워크에 IPv6 라우터가 없으면 링크 로컬 주소만 보이는 것이 정상입니다.
# Rocky Linux
sudo dnf install -y tcpdump iproute iputils
# Ubuntu
sudo apt update && sudo apt install -y tcpdump iproute2 iputils-ping
ip -6 addr show dev ens33 # scope link / scope global 주소 확인
ip -6 route show # 'proto ra' 는 RA로 받은 경로
ip -6 neigh show dev ens33 # 이웃 캐시 (IPv4의 ip neigh / arp 역할)
ss -tln # [::]:22 처럼 IPv6로 대기 중인 서비스
sysctl net.ipv6.conf.ens33.disable_ipv6 # 0이면 IPv6 활성
sysctl net.ipv6.conf.ens33.accept_ra # RA 수용 여부
sysctl net.ipv6.bindv6only # 0이면 IPv6 소켓이 IPv4도 받음(::ffff: 표기의 원인)
# 터미널 1: ICMPv6만 캡처 (-e 로 MAC까지)
sudo tcpdump -i ens33 -nn -e icmp6
# 터미널 2: 같은 링크의 모든 노드에 ping (링크 로컬은 %인터페이스 지정 필요)
ping -6 -c 3 ff02::1%ens33
# 이웃 캐시를 비우고 다시 통신해 NS/NA 발생시키기 (본인 VM에서만)
sudo ip -6 neigh flush dev ens33
ping -6 -c 2 <응답한 이웃의 fe80 주소>%ens33
📷 [실습 화면 삽입]
ip -6 addr show dev ens33결과 — fe80 링크 로컬 주소의scope link표시와 (있다면) 글로벌 주소의dynamic·mngtmpaddr표시
# Rocky (firewalld): nftables inet 테이블 기반이라 존 규칙이 IPv4·IPv6에 함께 적용
sudo firewall-cmd --list-all
sudo nft list ruleset | grep -i icmpv6
# Ubuntu (ufw): IPv6 규칙 적용 여부
grep IPV6 /etc/default/ufw # IPV6=yes 인지 확인
sudo ufw status verbose # (v6) 규칙이 함께 보이는지 확인
# iptables를 직접 쓰는 환경이라면 IPv6는 ip6tables 규칙이 별도
sudo ip6tables -L -n -v
ip -6 addr 출력 형식 예시(값은 환경마다 다름):
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 2001:db8:10::5a1c:3f2e:91b7:4d20/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 86380sec preferred_lft 14380sec
inet6 fe80::20c:29ff:fe4a:1b2c/64 scope link noprefixroute
valid_lft forever preferred_lft forever
ip -6 route / ip -6 neigh 출력 형식 예시(값은 환경마다 다름):
default via fe80::1 dev ens33 proto ra metric 100 pref medium
fe80::1 dev ens33 lladdr 00:50:56:c0:00:08 router REACHABLE
| 확인 항목 | 해석 |
|---|---|
scope link + fe80:: | 자동 생성 링크 로컬 주소 |
scope global dynamic | RA 기반 등 수명이 있는 글로벌 주소 |
valid_lft / preferred_lft | 주소 유효 수명 / 우선 사용 수명 |
default via fe80::1 ... proto ra | RA로 받은 기본 게이트웨이(링크 로컬) |
lladdr ... router | 이웃 캐시에서 라우터로 표시된 항목 |
ss -tln에서 IPv6로 대기 중인 서비스를 확인했다| 도구 | 필터 | 의미 |
|---|---|---|
| Wireshark | ipv6 | IPv6 전체 |
| Wireshark | icmpv6.type == 134 | RA |
| Wireshark | icmpv6.type == 135 or icmpv6.type == 136 | NS / NA |
| Wireshark | ipv6.nxt == 44 | Fragment 확장 헤더 |
| tcpdump | icmp6 and ip6[40] == 134 | RA (확장 헤더가 없을 때 기준) |
| tcpdump | 'ip proto 41 or udp port 3544' | 6in4 터널(프로토콜 41), Teredo(UDP 3544) |
tcpdump의 ip6[40]은 고정 헤더 40바이트 바로 뒤, 즉 ICMPv6 Type 위치입니다. 확장 헤더가 끼어 있으면 위치가 달라지므로 Wireshark 필터가 더 정확합니다.
| 관찰 | 정상일 수 있는 경우 | 의심해야 하는 경우 |
|---|---|---|
| RA 수신 | 등록된 라우터의 링크 로컬 주소에서 주기적 RA | 라우터가 아닌 단말 MAC에서 RA, 처음 보는 prefix 광고 |
| NA 다수 | 주소 설정·DAD 과정 | 요청(NS) 없이 반복되는 NA, 한 주소에 대한 MAC 변경 |
| IPv6 글로벌 주소 통신 | IPv6를 운영 중인 망 | IPv6 미운영 망인데 외부 IPv6 통신 발생 |
| 프로토콜 41 / UDP 3544 | 명시적으로 허용한 터널 | 허가되지 않은 IPv6 터널 → IPv4 정책 우회 경로 가능성 |
::ffff: 주소 | IPv6 소켓의 IPv4 연결 표현 | (자체는 정상) 상관분석 시 IPv4와 다른 대상으로 오인하는 것이 문제 |
# pcap에서 RA를 보낸 MAC·주소 목록 → 등록된 라우터와 대조
tshark -r capture.pcap -Y 'icmpv6.type == 134' -T fields -e eth.src -e ipv6.src | sort | uniq -c
📷 [실습 화면 삽입] Wireshark에서 RA 패킷 상세 — Prefix Information 옵션과 Source link-layer address 옵션
흔적이 남는 곳
::ffff: 매핑 주소가 남습니다. SIEM 파싱 규칙이 IPv4 형식만 가정하면 필드 추출에 실패하거나 GeoIP·위협 인텔리전스 매칭이 빠질 수 있습니다.관제 판단 포인트
한계와 오탐 주의
2001:db8::10 vs 2001:0db8:0:0::0010)로 검색 누락이 생길 수 있으니 정규화 여부를 먼저 확인합니다.:: 축약은 한 번만 쓸 수 있고, 로그 분석 전 표기 정규화가 필요합니다.::ffff: 매핑 주소 정규화, RA 출발지·IP-MAC 매핑 변화, 허가되지 않은 터널을 확인합니다.