IPv6 changes to web interface

The grids

The forms

Check address ranges

Checking IPv4 ranges

In IPv4, there are some ranges that are not allowed.

 1 $restricted_ipv4_nets = array(
 2     '0.0.0.0/8',       # broadcast messages to "this" network, RFC 1700 pg 4
 3     '127.0.0.0/8',     # Used for loopback addresses to the local host.
 4     '169.254.0.0/16',  # link local (autoconfig)
 5     '192.0.2.0/24',    # "TEST-NET" for documentation and example source code
 6     '192.88.99.0/24',  # Used by 6to4 anycast relays as specified by RFC 3068
 7     '198.18.0.0/15',   # testing of inter-network comms, RFC 2544
 8     '198.51.100.0/24', # "TEST-NET-2" for documentation and example source code
 9     '203.0.113.0/24',  # "TEST-NET-3" for documentation and example source code
10     '224.0.0.0/4',     # Reserved for multicast assignments as specified in RFC 3171
11     '240.0.0.0/4',     # 255.255.255.255 is "limited broadcast", others reserved by the IANA
12     #------------------------------------------------------------------------
13     # WE ALLOW THESE
14     #'10.0.0.0/8',      # private network, RFC 1918
15     #'172.16.0.0/12',   # private network, RFC 1918
16     #'192.168.0.0/16',  # private network, RFC 1918
17 );

Checking IPv6 ranges

Similarly, in IPv6, there are disallowed ranges.

 1 $restricted_ipv6_nets = array(
 2     '::/128',        # Unspecified address
 3     '::1/128',       # Used for loopback address to the local host.
 4     '2001::/32',     # Teredo tunneling
 5     '2001:10::/28',  # Overlay Routable Cryptographic Hash Identifiers (ORCHID)
 6     '2001:db8::/32', # Addresses used in documentation
 7     '2002::/16',     # 6to4
 8     'ff00::/8',      # Multicast
 9     #------------------------------------------------------------------------
10     # WE ALLOW THESE
11     #'fc00::/7',      # Unique local addresses, like RFC1918 (used in TKLC lab)
12     #'::ffff:0:0/96', # IPv4 mapped addresses
13 );

Don't forget IPv4-mapped ranges!

Plus, we may be looking at an IPv4 space mapped to IPv6!

IPv4-mapped addresses look like this:

  • ::ffff:10.255.255.255
  • ::ffff:0aff:ffff
  • 0000:0000:0000:0000:0000:ffff:172.31.255.255
  • 0000:0000:0000:0000:0000:ffff:ac1f:ffff

Code

 1 // Apply v4 restrictions to IPv4-mapped addresses.
 2 $expanded = self::fullyExpandIp($ip);
 3 if (strncmp($expanded,'0000:0000:0000:0000:0000:ffff:',30)==0) {
 4     // We're looking at an IPv4-mapped address.
 5     foreach ($restricted_ipv4_nets as $netplusbits) {
 6         list($v4net,$v4bits) = explode('/',$netplusbits);
 7         $v4parts = explode('.', $v4net);
 8         $v6net = "::ffff:".sprintf('%02x%02x:%02x%02x',$v4parts[0],$v4parts[1],$v4parts[2>
 9         $v6bits = $v4bits + 96;
10         array_push($restricted_nets,"$v6net/$v6bits");
11     }
12 }

Forgiving input, Pretty output

Store in fully expanded format

Store in the database like this:

  • 010.027.192.005
  • 2001:0db8:0000:0000:0000:0000:0000:0007

Sorting is easier!

New function:

1 public static function fullyExpandIp($ip)

Display in "canonical" format

Show on the screen like this:

  • 10.27.192.5
  • 2001:db8::7

Maintains user sanity!

New function:

1 public static function canonicalizeIp($ip)

Accept any format of input.

New function:

1 public static function validateIp($ip)

Uses this simple regex!

 1 $ipv6_regex = "/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|"
 2 ."(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|"
 3 ."[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]"
 4 ."{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|"
 5 ."[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|"
 6 ."(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|"
 7 ."((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)"
 8 ."(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:)"
 9 ."{3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:"
10 ."((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|"
11 ."[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4})"
12 ."{1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)"
13 ."(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:)"
14 ."{1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|"
15 ."2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
16 ."|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:"
17 ."((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|"
18 ."[1-9]?\d)){3}))|:)))(%.+)?\s*$/";

Test it!

Torture test:

 1 # 10.0.0.0/8 = 10.0.0.0 - 10.255.255.255
 2 GOOD 10.0.0.0
 3 GOOD ::ffff:10.0.0.0
 4 GOOD 10.255.255.255
 5 GOOD ::ffff:10.255.255.255
 6 
 7 # 127.0.0.0/8 = 127.0.0.0 - 127.255.255.255
 8 BAD  127.0.0.0
 9 BAD  ::ffff:127.0.0.0
10 BAD  127.255.255.255
11 BAD  ::ffff:127.255.255.255
12 
13 # 169.254.0.0/16 = 169.254.0.0 - 169.254.255.255
14 BAD  169.254.0.0
15 BAD  ::ffff:169.254.0.0
16 BAD  169.254.255.255
17 BAD  ::ffff:169.254.255.255
18 
19 # 172.16.0.0/12 = 172.16.0.0 - 172.31.255.255
20 GOOD 172.16.0.0
21 GOOD ::ffff:172.16.0.0
22 GOOD 172.31.255.255
23 GOOD ::ffff:172.31.255.255

More torture

 1 BAD  ::
 2 BAD  ::1
 3 GOOD ::ffff:100:0
 4 GOOD ::ffff:dfff:ffff
 5 
 6 # formatting
 7 BAD  1.2.3
 8 BAD  1.2.3.4.5
 9 BAD  0300.0000.0002.0353
10 BAD  0xC0.0x00.0x02.0xEB
11 BAD  0x11.0x22.0x33.0x44
12 BAD  0377.0377.0377.0377
13 BAD  2001.0db8.85a3:0000:0000.8a2e.0370.7334
14 BAD  192.0.2.128.192.0.2.128
15 BAD  192:0:2:235:192.0.2.235
16 BAD  0300:0000.0002.0353.0300:0000.0002.0353
17 GOOD fe80::204:61ff:254.157.241.86

More torture

 1 GOOD ::ffff:192.168.1.1
 2 GOOD 1:2:3:4:5:6:7:8
 3 GOOD 1:2:3:4:5:6::8   # see RFC5952
 4 GOOD 1:2:3:4:5::8
 5 GOOD 1:2:3:4::8
 6 GOOD 1:2:3::8
 7 GOOD 1:2::8
 8 GOOD 1::8
 9 GOOD 1::2:3:4:5:6:7
10 GOOD 1::2:3:4:5:6
11 GOOD 1::2:3:4:5
12 GOOD 1::2:3:4
13 GOOD 1::2:3
14 GOOD 1::8
15 BAD  ::2:3:4:5:6:7:8   # see RFC5952

Much more at http://forums.dartware.com/viewtopic.php?t=452

Thank you