Rejecting invalid IPv4 addresses
JavaScript (ES6),  179  178 bytes
Saved 1 byte thanks to @StackMeter's suggestion of merging the last 2 blocks
Expects a string and returns a Boolean value.

s=&gt;'00000g0chhqo3h65u64ekjyo5w90qw5yu2vg6nq96o6nq98g6o5rvk6ojr486vb4096vgz2871grvk7romqd'.match(/.{6}/g,[a,b,c]=s.split`.`).every(S=&gt;(x=parseInt(S,36))&gt;&gt;5^(a&lt;&lt;16|b&lt;&lt;8|c)&amp;-(1&lt;&lt;x))

Try it online!
How?
Encoding of address blocks
Our data string encodes all blocks of special-use addresses.
We can notice that the 4th byte is always \$0\$ and can be ignored. Given a block in CIDR notation A.B.C.D/M, what's actually encoded is:
A &lt;&lt; 21 | B &lt;&lt; 13 | C &lt;&lt; 5 | (24 - M)

This is a 29-bit value which fits in 6 characters in base 36.
For instance, 169.254.0.0/16 is encoded as:
169 &lt;&lt; 21 | 254 &lt;&lt; 13 | 0 &lt;&lt; 5 | (24 - 16) = 356499464

which is 5w90qw in base 36.
IP test
Given an IP address \$s\$, we first extract the first 3 bytes into \$(a,b,c)\$ and ignore the 4th one:
[a, b, c] = s.split`.`

For each 29-bit encoded block address \$x\$, we do the following test:
x &gt;&gt; 5 ^ (a &lt;&lt; 16 | b &lt;&lt; 8 | c) &amp; -(1 &lt;&lt; x)

where -(1 &lt;&lt; x) is our 24-bit subnet mask.
Conveniently, we can do 1 &lt;&lt; x without isolating the 5 least significant bits of \$x\$ because this is done implicitly by the shift operations, by ECMAScript specification.