php - Best way to store many ip ranges?


I have 3,000 rows of IP ranges in this format:     Hetzner    SoftLayer    UA Servers

If a user visits my site I want to lookup if their IP is in this IP ranges and block them if that is the case. What is the fastest way to lookup their IP with PHP? The IP ranges are static and will never change.

I already thought of creating a .dat file to store the IPs is this a good approach?




(Previously there was a link to how to do the task in PHP. This question seems to be about MySQL.)

If you are doing IPv4 only, then store into datatypeINT UNSIGNED, and useINET_ATON() when storing andINET_NTOA() when fetching.

For IPv6, useBINARY(16) withINET6_ATON() andINET6_NTOA().




Converting the dotted quad to an integer value is only the start of a solution.

You can't dereference values in an array or from a database using a normal index. Consider the case where you want to find a record, say in your ranges. If your ranges are keyed by the start address, then you can only exclude records where the start adress is greater than your search value. If it is keyed on the end of the range, you can only exclude values where the end address is less than your search value. You still have to examine approximately half your data to find a match (or lack thereof).

You could use databuckets or nested arrays but these are somewhat kludgy solutions.

A further consderation is, if your are using a php datastructure to manage the ranges is the time it will take to load and parse the dataset before you can begin searching it. From experience, this overhead kicks in with a dataset of approx 100-200 rows compared with fetching a record from mysql.

The solution is to use mysql's geospatial capabilities to map the ranges in a one dimensional space - I get lookup times under 1ms on modest hardware searching the whole of the internet's assigned ranges (using the datasets from RIPE, APNIC etc).

The process is described here

Note: ip2long() returns a signed 32bit integer value in PHP while MySQL's inet_aton,() is unsigned (i.e. you can'tmix and match the 2 functions)

People are also looking for solutions to the problem: regex - PHP Remove all non letters


Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.