IP 주소 파싱의 재미
(blog.dave.tf)- 빠른 IPv4+v6 파서를 만들면서 배운 것들을 읽기 쉽게 정리한 글
- 정식(Canonical) 표현
ㅤ→ v4 : 192.168.0.1 , 1바이트 들의 Dotted Quad
ㅤ→ v6 : 1:2:3:4:5:6:7:8 , 2바이트 들의 Colon-Hex
[IPv6]
- 중간에 0이 많이 나오게 되므로 :: 로 하면 1개 이상의 0을 제거
ㅤ→ 1:2::3:4 = 1:2:0:0:0:0:3:4
- 마지막 32비트는 v4의 Dotted Quad 방식 표현 사용 가능
ㅤ→ 1:2:3:4:5:6:77.77.88.88 = 1:2:3:4:5:6:4d4d:5858
ㅤ→ fe80::1.2.3.4 = fe80:0:0:0:0:0:102:304
- :: 가 맨앞/맨뒤에 오는 케이스가 생겨서 조금 더 복잡해짐
ㅤ→ ::1 = 0:0:0:0:0:0:0:1
ㅤ→ 1:: = 1:0:0:0:0:0:0:0
ㅤ→ :: = 0:0:0:0:0:0:0:0
- IPv6 Colon-Hex 의 모든 필드는 4자리 16진수, 앞에 0은 제거 가능
ㅤ→ :: = 0000:0000:0000:0000:0000:0000:0000:0000
[IPv4]
- 재미난건, IPv6에서 마지막 32비트의 Dotted Quad 표현을 공식화 하기전에는 어떤 문서에서도 표준화 된적이 없음
ㅤ→ 그래서 보통 업계표준(de-facto)은 "4.2BSD 에서 해석 가능한가?" "다른 OS에서 4.2BSD를 복사했을때 뭘 유지했나" 였음
- 근데 4.2BSD는 좀 이상(whacky)함
ㅤ→ 192.168.140.255 = 3232271615 와 같음
ㅤ→ 즉, 크롬에서 http://3232271615 를 방문하면 http://192.168.140.255 를 로드함. 4바이트 숫자니까!
ㅤ→ 8진수인 http://0300.0250.0214.0377 도 가능
ㅤ→ 그럼 당연히 16진수인 https://0xc0.0xa8.0x8c.0xff 도 다 같은 주소
- CIDR (Classless Inter-Domain Routing) 은 IP주소에도 영향을 줌
ㅤ→ 클래스 C 표현인 192.168.140.255 은 클래스 B로 표현하면 http://192.168.36095 , 클래스 A로 표현하면 http://192.11046143
ㅤ→ 이래서 ping 127.1 = 127.0.0.1 이 가능. IPv6 처럼 중복0을 제거한게 아니라, 클래스 A 네트웍 127의 1번째 호스트를 의미. 즉, 24비트 숫자 1임
- 각 Quad의 숫자앞에 0은 몇개까지 가능할까 ?
ㅤ→ 001.002.003.004 ? 0000000001.0000000002.0000000003.000000004 ?
ㅤ→ ( 크롬은 http://0000000001.0000000002.0000000003.000000004 도 가능 )
ㅤ→ 이때 이 숫자를 8진수로 읽어야 할지, 16진수로 읽어야 할까 ? : 최근 구현들은 8진수/16진수를 포기하고, 앞에 0들을 10진수로 처리
- 이 선행 0 문제는 IPv6에도 영향을 줌
ㅤ→ 000001::00001.00002.00003.00004 = 1::1.2.3.4, or 1::102:304
ㅤ→ 최신 파서들은 대부분 "parse integer" 라이브러리를 사용하기 때문에 앞에 0이 많아도 다 허용
즉, 모든 IP 주소를 파싱하려면 이 거지같은 것들을 다 고려해야 하지만..
필자의 파서는 다음 정도만 추려서 지원
- 클래식한 v4 방식으로 점으로 구분된 정수, 앞에 0 갯수는 무제한으로 가능
- 클래스 A/B 표현식 및 8/16진수는 처리 안함
- unit32 숫자 한개로 모든 걸 표현하는 것도 처리 안함
- IPv6는 정식 colon-hex 방식 및 :: 줄임 방식과, 마지막 32비트에 IPv4 붙이는 것까지 허용(이 IPv4 는 앞의 규칙 적용). 각 필드의 앞 0 갯수는 무제한
* 초기엔 IPv4 에서 IPv6로 쉬운 이전을 위해 마지막에 IPv4 주소를 붙이는 방식을 넣긴 했지만, 실제로 잘 보이지 않음. 그래서 지원은 하지만 그닥 유용하지는 않다고 생각함