La diversión de parsear direcciones IP
(blog.dave.tf)-
Un artículo que organiza de forma fácil de leer lo aprendido al crear un parser rápido de IPv4+v6
-
Representación canónica
→ v4 : 192.168.0.1 , un Dotted Quad de bytes de 1 byte
→ v6 : 1:2:3:4:5:6:7:8 , un Colon-Hex de palabras de 2 bytes
[IPv6]
- Como suelen aparecer muchos
0en medio,::elimina uno o más grupos de0
→ 1:2::3:4 = 1:2:0:0:0:0:3:4
- Los últimos 32 bits pueden expresarse usando la notación Dotted Quad de v4
→ 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
- Se vuelve un poco más complejo porque hay casos donde
::aparece al inicio o al final
→ ::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
- Todos los campos del Colon-Hex de IPv6 son hexadecimales de 4 dígitos, y se pueden omitir los
0iniciales
→ :: = 0000:0000:0000:0000:0000:0000:0000:0000
[IPv4]
- Lo curioso es que, antes de que en IPv6 se formalizara la representación Dotted Quad para los últimos 32 bits, nunca se estandarizó algo así en ningún documento
→ Por eso, el estándar de facto en la industria solía ser algo como "¿4.2BSD lo puede interpretar?" y "cuando otros sistemas operativos copiaron 4.2BSD, ¿qué comportamiento conservaron?"
- Pero 4.2BSD es un poco extraño
→ 192.168.140.255 = 3232271615
→ Es decir, si visitas http://3232271615 en Chrome, carga http://192.168.140.255. ¡Porque es un número de 4 bytes!
→ También funciona en octal: http://0300.0250.0214.0377
→ Entonces, por supuesto, en hexadecimal https://0xc0.0xa8.0x8c.0xff también es la misma dirección
- CIDR (Classless Inter-Domain Routing) también afecta a las direcciones IP
→ La representación clase C 192.168.140.255, si se expresa como clase B, es http://192.168.36095, y como clase A sería http://192.11046143
→ Por eso ping 127.1 = 127.0.0.1 funciona. No es que se hayan eliminado ceros repetidos como en IPv6, sino que significa el host 1 de la red clase A 127. Es decir, el número de 24 bits 1
- ¿Cuántos ceros se permiten al inicio del número de cada Quad?
→ 001.002.003.004 ? 0000000001.0000000002.0000000003.000000004 ?
→ ( Chrome también acepta http://0000000001.0000000002.0000000003.000000004 )
→ En ese caso, ¿debería leerse como octal o como hexadecimal? : las implementaciones recientes abandonan octal/hexadecimal y tratan los ceros iniciales como decimal
- Este problema de ceros iniciales también afecta a IPv6
→ 000001::00001.00002.00003.00004 = 1::1.2.3.4, o 1::102:304
→ Como la mayoría de los parsers modernos usan bibliotecas de "parse integer", aceptan sin problema muchos ceros al inicio
En otras palabras, para parsear todas las direcciones IP hay que considerar todas estas porquerías, pero...
El parser del autor solo soporta más o menos lo siguiente
-
El estilo clásico de v4: enteros separados por puntos, con una cantidad ilimitada de ceros al inicio
-
No procesa expresiones de clase A/B ni octal/hexadecimal
-
Tampoco procesa el caso de expresar todo con un solo número
uint32 -
En IPv6, permite la notación canónica colon-hex, la abreviación con
::, y también adjuntar IPv4 en los últimos 32 bits (ese IPv4 sigue las reglas anteriores). Cada campo puede tener una cantidad ilimitada de ceros iniciales
- Al principio se incluyó la forma de poner una dirección IPv4 al final para facilitar la migración de IPv4 a IPv6, pero en la práctica casi no se ve. Así que está soportado, aunque no parece muy útil
2 comentarios
Oh, qué interesante. Se ven muchas técnicas buenas para retorcer esto al atacar.
Si para escribir una dirección IP hay que usar reglas tan complicadas, me da la impresión de que no deja de ser un desperdicio innecesario de recursos de cómputo ^^;;