3

I'm using PHP and MySQL, and I want to store users' IP addresses into the database for comparison purposes (e.g. allowing only one flag to a thread per IP). Would it be okay to do it the following way?

Retrieving it in PHP:

$ipAddress = md5($_SERVER["REMOTE_ADDR"]);

And then saving it into the database as a VARCHAR(32).

If I had to make a more comprehensive use of the IPs this wouldn't be the proper way to do it I guess, but if it's only to make sure that the same IP didn't do something twice would be okay to use the md5 encryption to simplify things (unifying IPv4 and IPv6 addresses into one)?

federico-t
  • 12,014
  • 19
  • 67
  • 111
  • 6
    Nitpick comment, but md5 is a hash algorithm, not encryption. Encryption is different. – Rich Adams Apr 29 '12 at 04:55
  • 1
    why encrypt? why reference IPS? they are un-predictable. – Philip Apr 29 '12 at 04:57
  • 2
    why encrypt? IPs aren't sensitive information. – Joe Flynn Apr 29 '12 at 04:58
  • There is absolutely no sense in whatever "encrypting" or "hashing" IPs. Just leave it as is. -1 for the pointless question – Your Common Sense Apr 29 '12 at 14:46
  • 3
    re downvotes: I think it's perfectly legitimate to store peer addresses in hashed form instead of plain, so that you can still enforce a usage policy (one "flag" whatever that is per address) without the posibility of associating the annotation back to a particular address. I don't think MD5(peer address) is sufficient for all but a modest level of privacy, though. perhaps sha1(affected resource + peer_address) would be better. – SingleNegationElimination Apr 29 '12 at 15:02
  • @TokenMacGuy exactly, I don't _need_ to know the actual IP address, I just want to make sure that a certain activity it's not repeated from the same IP. I'm glad some people actually read the question. – federico-t Apr 30 '12 at 07:03
  • 1
    One thing to bear in mind is that legacy (or v4) IP addresses are fairly short, only 32 bits. As a result any hash you use will be trivially brute-forced back to the legacy IP address itself. It's fine if this is just a protection against casual observation by system admins or similar, but if you need real protection of the information you should just not store it. – Kristof Provost Apr 30 '12 at 07:15

2 Answers2

5

Yes, this is fine, though your terminology is wrong: this is hashing, and hashing is not encryption.

You should also parse the X-FORWARDED-FOR and Client-IP headers unless you want to block everyone behind a proxy as if they were a single user (e.g. everyone at large companies, high schools, etc).

Dan Grossman
  • 51,866
  • 10
  • 112
  • 101
  • Thanks for the advice. Yes, my terminology was wrong. I wasn't trying to emphasize on the `md5` hash algorithm or security but on "uniformize" (or normalizing) the IPs to make them easier to store – federico-t Apr 29 '12 at 05:40
  • @YourCommonSense calm down, you might think that this is a pointless question, but it's not. It's something I need for a Web application and it's been already answered. What it's pointless is making comments like yours – federico-t Apr 30 '12 at 06:58
  • @JohnDoe thank you for your comment, I got the matter. Please read my answer. – Your Common Sense Apr 30 '12 at 07:11
  • Trusting XFF and similar headers sent by outside servers is a terrible idea. It makes it really easy to spoof your IP by just sending the header yourself. – ThiefMaster Dec 19 '15 at 11:23
3

You might want to consider converting the IP to a number. A little quicker on the lookup because it's numeric data and you can use INET_ATON() and INET_NTOA() in your queries.

http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_inet-aton

mysql> SELECT INET_ATON('10.0.5.9');
        -> 167773449

http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_inet-ntoa

mysql> SELECT INET_NTOA(167773449);
        -> '10.0.5.9'

PHP to Convert to a number

$ipA = $_SERVER["REMOTE_ADDR"];
$octets = split ("\.", $ipA);
$ipN = ($octets[3] + $octets[2] * 256 + $octets[1] * pow(256,2) + $octets[0] * pow(256,3);

Also, you might want to consider the IP Address you're using with this function:

/* Get Actual IP Address, in spite of proxy server */
function getRealIpAddr() {
    if (!empty($_SERVER['HTTP_CLIENT_IP']))   //check ip from share internet
    {   $ip=$_SERVER['HTTP_CLIENT_IP']; }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //to check ip is pass from proxy
    {   $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; }
    else
    {   $ip=$_SERVER['REMOTE_ADDR']; }
    return $ip;
}

RE-Edit for IPv6:

Principles all still apply, but IPv6 Conversions already answered at How to convert IPv6 from binary for storage in MySQL

Community
  • 1
  • 1
GDP
  • 8,109
  • 6
  • 45
  • 82
  • No. You're not going to get the IPv6 address in dotted octets like that. Your code will simply not work. – Dan Grossman May 01 '12 at 22:24
  • fair enough - didn't respond to the comment correctly, so changed my answer to reflect link to IPv6 conversion, though I believe the answer to the original question still applies. – GDP May 02 '12 at 14:11