If you will always check one IP address at a time and your forbidden ranges never overlap, you must save the starting and ending addresses of the ranges to be denied in numerical format.
Let's say you want to ban 192.168.1.0 to 192.168.1.15 , which is 192.168.1.0/28 .
You create the table as follows:
CREATE TABLE ban (start_ip INT UNSIGNED NOT NULL PRIMARY KEY, end_ip INT UNSIGNED NOT NULL)
enter range:
INSERT INTO ban VALUES (INET_ATON('192.168.1.0'), INET_ATON('192.168.1.0') + POWER(2, 32 - 28) - 1)
then check:
SELECT ( SELECT end_ip FROM ban WHERE start_ip <= INET_ATON('192.168.1.14') ORDER BY start_ip DESC LIMIT 1 ) >= INET_ATON('192.168.1.14')
Successful query execution requires the ORDER BY and LIMIT parts.
This, as stated earlier, involves disjoint blocks and one IP at a time.
If the blocks intersect (for example, you forbid 192.168.1.0/28 and 192.168.1.0/24 at the same time), the request may return false negatives.
If you want to query more than one IP at a time (say, update a table with a long list of IP addresses) then this query will be inefficient ( MySQL does not optimize range in correlated subqueries a)
In both cases, you need to save your ranges as a LineString and use spatial indexes for a quick search:
CREATE TABLE ban (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, range LINESTRING NOT NULL) ENGINE=MyISAM; CREATE SPATIAL INDEX sx_ban_range ON ban (range); INSERT INTO ban (range) VALUES ( LineString ( Point(INET_ATON('192.168.1.0'), -1), Point(INET_ATON('192.168.1.0') + POWER(2, 32 - 28) - 1), 1) ) ); SELECT * FROM ban WHERE MBRContains(range, Point(INET_ATON('192.168.1.14'), 0))