2

I'm writing a feature for an admin panel that blocks ip addresses on the apache level. The file is called blacklist.txt and looks like 10.0.0.1,10.0.0.2,10.0.0.3, ... All a single line, with each ip address separated by a comma. After reading What is the best way to write a large file to disk in PHP?, I am still unsure of the best practices on the matter.

Here's what I want to do: IF an administrator presses the 'ban hammer', the file is read looking for strpos($file, $ip), if it's not found, append to the end of the file and the .htaccess file blocks accordingly.

Question: is a .txt file suitable for this potentially large amount of data? I do not want to execute a query to check if someone is banned every time a page is requested

EDIT: The purpose is to block single ip addresses that have 10 failed login attempts in the past 12 hours. I would think that the 'recover my password' would prevent a normal client from doing this.

Community
  • 1
  • 1
visevo
  • 791
  • 7
  • 23
  • 4
    You don't want to read a file (without any organization/optimization/index) every time a page is requested. – enapupe Feb 26 '14 at 19:27
  • 1
    why are you blocking ip's? its easy to get around and ip!=person, one person can have many ip's and one IP can be thousands of people. if its your server ther are much better methods. iptables et al –  Feb 26 '14 at 19:27
  • 1
    And what is so wrong with executing a query to database? Keep in mind that database is nothing but an abstract to work on files. – Tymoteusz Paul Feb 26 '14 at 19:28
  • 1
    @Puciek - It is my understanding that you want to block malicious users / bots at the highest level possible. If I can block with apache it's better than allowing the PHP script to run, or so I am told – visevo Feb 26 '14 at 19:30
  • `strpos('1.1.1.1', '121.1.1.1') -> TRUE`. Ooops... banned an inocent user. – Marc B Feb 26 '14 at 19:31
  • a little knowledge is a dangerous thing. how do you plan to identify theses "malicious users / bots" what about others that share the same IP's, what about whne they change IP ? –  Feb 26 '14 at 19:31
  • @visevo then you can do it on IPtables leve, or even on the router on top of server - just drop all packets from certain ip addresses. It's a simple rule to add to iptables and will work like a dream (and will be blazing fast). – Tymoteusz Paul Feb 26 '14 at 19:33
  • @Dagon IP addresses that have 10 failed login attempts in the past 12 hours show up in the admin panel. I would consider these malicious. – visevo Feb 26 '14 at 19:36
  • so ban that ip, which may be the ip of a university student, which is probably shared by thousands, so you just banned thousand's of people - great work! –  Feb 26 '14 at 19:38
  • I get what you're saying, but this is not a social media site. It's an application that is built for businesses in our area, and is managed by said businesses in our area. – visevo Feb 26 '14 at 19:42
  • business are the same, every one in my office has the same external ip (and when we reboot the router the same NEW ip) –  Feb 26 '14 at 19:45
  • Blocking ip address might still be sensible, but after a much bigger number of attempts. If you almost remember the password, ten or even larger number of tries is not that much. Maybe a 1000 tries or so, but even that could be too few in case there are many users behind one ip. – Tero Lahtinen Feb 26 '14 at 19:49
  • Your point has been made, but for the sake of this application, blocking a large number of IP addresses after X number of failed login attempts is acceptable. – visevo Feb 26 '14 at 20:15
  • :( at least unblock it after X hours –  Feb 26 '14 at 20:19

2 Answers2

3

Question: is a .txt file suitable for this potentially large amount of data?

No, it is not. A database with proper indexing is.

Tero Lahtinen
  • 514
  • 6
  • 16
1

First for reading your File in CSV format

you can use many ways. example:

$rows = array_map('str_getcsv', file('myfile.csv'));
$header = array_shift($rows);
$csv = array();
foreach ($rows as $row) {
   $csv[] = array_combine($header, $row);
}

src: http://steindom.com/articles/shortest-php-code-convert-csv-associative-array

for checking that on each page load and to minimize the Reading of that file

you can use a memory cache , something like memCache, then search the array for the incoming ip. note: memory cache is faster then Database query.

PHP shared memory ref: http://www.php.net/manual/en/book.shmop.php

memCache php.net/memcache

Array Search php.net/in_array

also to return the key if value found php.net/array_search

note: in 1 mb file you can store ~65K IP considering an ip is the following format: "255.255.255.255,"

it's even better if you put the key of the array the ip, then instead of searching the array for that ip you can Check if the Key exist with this: php.net/array_key_exists‎

Falanso
  • 33
  • 7