Jump to content

how to properly store an ip address?


alexandre
Go to solution Solved by gizmola,

Recommended Posts

i have created myself a jail file sending the blocked ip addresses there , and all is working but the insert of the ip address when i am testing it , itwill only insert this ::1 as ip. ? anyone have an idea of what i am doing wrong?

<?php
session_start();
include 'connect_db2.php';
if (!isset($_POST['username'], $_POST['password'])) {
	// Could not get the data that should have been sent.
	exit('Please fill both the username and password fields!');
}
// Prepare our SQL, preparing the SQL statement will prevent SQL injection.
if ($stmt = $con->prepare('SELECT id, username, password, user_lock FROM accounts WHERE username = ?')) {
	// Bind parameters (s = string, i = int, b = blob, etc), in our case the username is a string so we use "s"
	$stmt->bind_param('s', $_POST['username']);
	$stmt->execute();
	// Store the result so we can check if the account exists in the database.
	$stmt->store_result();

	if ($stmt->num_rows > 0) {
		$stmt->bind_result($id, $username, $password, $user_lock);
		$stmt->fetch();
	}
		else if ($stmt->num_rows == 0) {
	 			// Incorrect password
	 			echo 'Incorrect username!';
				exit;
	 		}
			if ($user_lock == 1) {
				$_SESSION['loggedin'] = FALSE;
				header('location: index.html');
				session_destroy();
				exit;
			}
		// Account exists, now we verify the password.
		// Note: remember to use password_hash in your registration file to store the hashed passwords.
		if (password_verify($_POST['password'], $password)) {
			// Verification success! User has logged-in!
			// Create sessions, so we know the user is logged in, they basically act like cookies but remember the data on the server.
			session_regenerate_id();
			$_SESSION['loggedin'] = TRUE;
			$_SESSION['name'] = $username;
			$_SESSION['id'] = $id;
			header('location: home.php');
			exit;
		}
	 else {
		 echo 'Incorrect information!';
$stmt = $con->prepare("SELECT ip_address, num_login_attempts, ip_lock, tries_date FROM malicious_attempts WHERE ip_address = ?");
$stmt->bind_param('s', $_SERVER['REMOTE_ADDR']);
$stmt->execute();
$stmt->bind_result($ip_address, $tries, $lock, $tries_date);
$stmt->fetch();
$stmt->close();
$current_date = date("Y-m-d h:i:sa");
$current_date = strtotime($current_date);
$last_attempt = strtotime($tries_date);
$time_btw_attempts = $current_date - $last_attempt;
if (isset($ip_address) && $tries < 10) {
	$tries = $tries + 1;
 $stmt = $con->prepare('UPDATE malicious_attempts SET num_login_attempts = ? WHERE ip_address = ?');
 $stmt->bind_param('is', $tries, $_SERVER['REMOTE_ADDR']);
 $stmt->execute();
 $stmt->close();
 header('location: index.php');
 exit;
}
elseif (!isset($ip_address)) {
	$tries = 1;
	$stmt = $con->prepare("INSERT INTO malicious_attempts (ip_address, num_login_attempts) VALUES (?, ?)");
	$stmt->bind_param('si', $_SERVER['REMOTE_ADDR'], $tries);
	$stmt->execute();
	$stmt->close();
	header('location: index.php');
	exit;
}


	  else if ((($_SERVER['REMOTE_ADDR'] == $ip_address) && $tries >= 10) && $time_btw_attempts < 20) {
			 $stmt = $con->prepare('UPDATE malicious_attempts SET ip_lock = 1 WHERE ip_address = ?');
			 $stmt->bind_param('s', $_SERVER['REMOTE_ADDR']);
	     header("location: jail.php");
	     exit;
	   }
	$stmt->close();
}
}
?>

this is my authentication file.

Link to comment
Share on other sites

The way to do this in mysql is to store the address in a varbinary(16).  This is because the IP address is a number, and the formatting is simply to make the IP scheme understandable.

MySQL has specific functions for converting an ip address to and from this format, and handles the issue of whether the IP address is in v4 or v6 format.  Use the v6 functions as they handle both v4 and v6 ip addresses.

inet6-aton 

inet6-ntoa

 

  • Like 1
Link to comment
Share on other sites

  • Solution
13 minutes ago, alexandre said:

i understand thank you for your answers, but this ip address is the one of my server how can i do to get the actual user ip address? 

 

I'm guessing something like this might work for you (assuming you have a reverse proxy or load balancer).

 

    protected function getClientIP() {
        // This assumes a classic AWS Load Balancer is proxying
        if (filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
            !filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                $ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                return $ip[0];
            } else {
                return $_SERVER['REMOTE_ADDR'];
            }
    }

 

Link to comment
Share on other sites

i will have my hosting done with godaddy when i will be able to pay for the hosting . i already bought the domain name but apart of that i had still no idea about what i have to do server side. they work with the cpanel where i just have to upload my folder just as i am doing with xamp. thats about all i know..  i thought i could just get the user ip with a simple command but it doesnt seem like it 😂

Link to comment
Share on other sites

i see , so you are saying that if it was a normal user , the ip address would not be ::1 but a complete version of it and actually be the user ip ? that it is simply because i am working in xamp with my local server that i get this ip addres so if i store the ip address as a varchar 45 it should be ok?

Link to comment
Share on other sites

$_SERVER['REMOTE_ADDR'] will be the address of the remote socket endpoint that has connected to your server.  For local development, this is going to be ::1 (ipv6) or 127.0.0.1 (ipv4).  If you connect to the server from some other machine, you'd get that machine's endpoint.

It's worth keeping in mind that this is not necessarily the user's actual IP address.  It may be the address of a proxy or load balancers instead.  Using the function provided by gizmola will attempt to grab what would more likely be the user's IP if the proxy/lb provides it.

Link to comment
Share on other sites

i tried to implement the code from gizmola but i would like to be sure to be doing this the right way.

this is the part of the code updated

else {
		 echo 'Incorrect information!';
		 protected function getClientIP() {
		         // This assumes a classic AWS Load Balancer is proxying
		         if (filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
		             !filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
		                 $ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
		                 return $ip[0];
		             } else {
		                 return $_SERVER['REMOTE_ADDR'];
		             }
		     }
				if (isset($ip[0])) {
				 	$stmt = $con->prepare("SELECT ip_address, num_login_attempts, ip_lock, tries_date FROM malicious_attempts WHERE ip_address = ?");
				 	$stmt->bind_param('s', $ip[0]);
				 	$stmt->execute();
				 	$stmt->bind_result($ip_address, $tries, $lock, $tries_date);
				 	$stmt->fetch();
				 	$stmt->close();
				 }
				else if (isset($_SERVER['REMOTE_ADDR'])) {
$stmt = $con->prepare("SELECT ip_address, num_login_attempts, ip_lock, tries_date FROM malicious_attempts WHERE ip_address = ?");
$stmt->bind_param('s', $_SERVER['REMOTE_ADDR']);
$stmt->execute();
$stmt->bind_result($ip_address, $tries, $lock, $tries_date);
$stmt->fetch();
$stmt->close();
}
$current_date = date("Y-m-d h:i:sa");
$current_date = strtotime($current_date);
$last_attempt = strtotime($tries_date);
$time_btw_attempts = $current_date - $last_attempt;
if ((isset($ip_address) && $tries < 10) {
	$tries = $tries + 1;
 $stmt = $con->prepare('UPDATE malicious_attempts SET num_login_attempts = ? WHERE ip_address = ?');
 $stmt->bind_param('is', $tries, $ip_address);
 $stmt->execute();
 $stmt->close();
 header('location: index.php');
 exit;
}
elseif (!isset($ip_address)) {
	$tries = 1;
	$stmt = $con->prepare("INSERT INTO malicious_attempts (ip_address, num_login_attempts) VALUES (?, ?)");
	$stmt->bind_param('si', $ip_address, $tries);
	$stmt->execute();
	$stmt->close();
	header('location: index.php');
	exit;
}


	  else if (((isset($ip_address) && $tries >= 10) && $time_btw_attempts < 20) {
			 $stmt = $con->prepare('UPDATE malicious_attempts SET ip_lock = 1 WHERE ip_address = ?');
			 $stmt->bind_param('s', $ip_address);
	     header("location: jail.php");
	     exit;
	   }
	$stmt->close();
}

 

Link to comment
Share on other sites

sorry i am not the fastest one sometimes. finally got it , the thing is that i rarely use functions and this protected in front of the function is making this unexpected and expect the end of file but if i removed it , everything work fine by putting the sample in a function file including it and call the function and simply did $user_ip = the function call. 

Link to comment
Share on other sites

On 1/18/2023 at 12:39 AM, alexandre said:

sorry i am not the fastest one sometimes. finally got it , the thing is that i rarely use functions and this protected in front of the function is making this unexpected and expect the end of file but if i removed it , everything work fine by putting the sample in a function file including it and call the function and simply did $user_ip = the function call. 

I just checked in on this now.  The function I pulled is part of a utility class, and not a standalone function, so it was scoped.  I'm glad you got that figured out.  Learning a bit about PHP Object Oriented Programming would be a great next step for you.  

The main thing I wanted to contribute was the best way to store IP addresses, and it appears you've implemented that successfully.

Link to comment
Share on other sites

yes thank you very much , the blocking of the ip address is being done without problems anymore, the only question remaining about this in my head would be, if not using the feature of the database especially designed to handle the ip adresses, would it be a wrong choice or if storing the ip address as a varchar 45 is fine , i did it this way because thats the first method to do that i saw on the internet but i am still unsure if there is a downside to not be using this database feature.

Edited by alexandre
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.