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 は少し変わっている
→ 192.168.140.255 は 3232271615 と同じ
→ つまり、Chrome で 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 ?
→ (Chrome は 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 進数は処理しない
-
uint32の数値 1 個で全体を表す形式も処理しない -
IPv6 は正式な colon-hex 方式、
::の短縮表記、そして最後の 32 ビットに IPv4 を付ける形式まで許容(この IPv4 には前述の規則を適用)。各フィールドの先頭 0 の個数は無制限
- 当初は IPv4 から IPv6 への移行を容易にするため、末尾に IPv4 アドレスを付ける方式を入れたが、実際にはあまり見かけない。そのためサポートはしているものの、あまり有用ではないと考えている
2件のコメント
おお、面白いですね! 攻撃時にひねって使いやすそうな手法がたくさん見えますね!
IPアドレスの表記にこんなに複雑なルールを使わなければならないなら、無駄なコンピューティングリソースの浪費ではないかという気がしますね ^^;;