Accueil > Logiciel, Réseau, Tutoriel > Howto: Geolocation for Fail2ban

Howto: Geolocation for Fail2ban

source: fail2ban.org

 

Using geolocation to locate your attackers.

I use fail2ban on my servers to protect them from would-be attackers, if you don’t your either insanely nieve to the fact that somebody wants in your system, or your just wanting to see if you can get hacked. Most of the attackers I would assume are just after another « bot » in their « net », or maybe a place to host files.

Durzo hosts a script that allows you to log the attacks on you into a mysql database with geocoding, I thought this would be cool to use as I could see from where I was being attacked. I then got this working and another script to display the table in a web page so I could view the data easily.

I then found some scripts from Google to pull data from MySQL in a geolocation table and generate an XML file used to import into Google Maps. With some tweaking and customizing, I now have a map with the geolocation data as markers on the map. Not all the markers are right on a building, but they are close enough for me to see the areas from which attacks are coming.

Now on to the good stuff…

I will explain how I did all this:
Download and install fail2ban and mysql-server, I will not go into this as that is outside the scope of this document. Once your jails are configured and MySQL is up and running then follow the rest here.

First download durzo’s fail2sql from http://sourceforge.net/projects/fail2sql/ and follow the instructions on installing that. He has a script there to create the SQL tables for us and a small configuration (it is documented well) On my system I had to put the action in « iptables-multiport.conf ».
Thank you durzo!

In /etc/fail2ban/action.d/iptables-multiport.conf

Find:

0
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP

Change to:

0
1
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
/usr/local/fail2sql/fail2sql <name> <protocol> <port> <ip>

This will have iptables ban the ip address and also add the information to the MySQL database.

Next thing to get working is getting the information from the database into an XML format for Google Maps to use.
You will need to configure a file called dbinfo.php. This has the database connect information in it, this keeps that info safe and can be used by multiple scripts without having to keep typing it in.

Referenced in other scripts by:

0
require("dbinfo.php");

So,
sudo nano dbinfo.php

Enter this and modify it to your database settings.

0
1
2
3
4
5
6
7
<?
$db_host = 'db_server';
$db_user = 'your_user';
$db_pwd = 'your_password';

$database = 'db_name';
$table = 'db_table';
?>

I took a script from Pamela Fox here http://code.google.com/apis/maps/articles/phpsqlajax.html and modified it to do what I needed and pull the data from my existing fields into the required fields. This generates the required XML file export to use in the Google Map API.

So,

sudo nano phpsqlajax_genxml.php
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php

require("dbinfo.php");

// Start XML file, create parent node

$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);

// Opens a connection to a MySQL server

$connection=mysql_connect ($db_host, $db_user, $db_pwd);
if (!$connection) {  die('Not connected : ' . mysql_error());}

// Set the active MySQL database

$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
  die ('Can\'t use db : ' . mysql_error());
}

// Select all the rows in the markers table

$query = "SELECT * FROM $table WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die('Invalid query: ' . mysql_error());
}

header("Content-type: text/xml");

// Iterate through the rows, adding XML nodes for each

while ($row = @mysql_fetch_assoc($result)){
  // ADD TO XML DOCUMENT NODE
  $node = $dom->createElement("marker");
  $newnode = $parnode->appendChild($node);
  $newnode->setAttribute("name",$row['geo']);
  $newnode->setAttribute("address", $row['ip']);
  $newnode->setAttribute("lat", $row['latitude']);
  $newnode->setAttribute("lng", $row['longitude']);
  $newnode->setAttribute("type", $row['name']);
}

echo $dom->saveXML();

?>

Once this is complete, you should test it out and execute in a web browser. This should give you a result something like this:

0
1
2
3
4
<markers>
<marker name="blah, United Kingdom" address="xx.xx.xx.xx" lat="00" lng="00" type="ftp"/>
<marker name="blah, Netherlands" address="xx.xx.xx.xx" lat="00" lng="00" type="tcp"/>
<marker name="...
</markers>

If the XML is generated and no errors, then we are looking good so far.

Now, to pull this into a Google Map and drop the markers in place. I used the same script from Pamela Fox’s article and modified it to my likes.

So,

sudo nano phpsqlajax_map.htm
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Title of Page Here</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=Your Google API Key goes here!"
            type="text/javascript"></script>

    <script type="text/javascript">
    //<![CDATA[

    var iconBlue = new GIcon();
    iconBlue.image = './blue-dot.png';
    iconBlue.shadow = './chart-shadow.png';
    iconBlue.iconSize = new GSize(12, 20);
    iconBlue.shadowSize = new GSize(22, 20);
    iconBlue.iconAnchor = new GPoint(6, 20);
    iconBlue.infoWindowAnchor = new GPoint(5, 1);

    var iconRed = new GIcon();
    iconRed.image = './red-dot.png';
    iconRed.shadow = './chart-shadow.png';
    iconRed.iconSize = new GSize(12, 20);
    iconRed.shadowSize = new GSize(22, 20);
    iconRed.iconAnchor = new GPoint(6, 20);
    iconRed.infoWindowAnchor = new GPoint(5, 1);

    var customIcons = [];
    customIcons["proftpd"] = iconBlue;
    customIcons["ssh"] = iconRed;

    function load() {
      if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(49.679004, 3.105462), 2);

        GDownloadUrl("phpsqlajax_genxml.php", function(data) {
          var xml = GXml.parse(data);
          var markers = xml.documentElement.getElementsByTagName("marker");
          for (var i = 0; i < markers.length; i++) {
            var name = markers[i].getAttribute("name");
            var address = markers[i].getAttribute("address");
            var type = markers[i].getAttribute("type");
            var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    parseFloat(markers[i].getAttribute("lng")));
            var marker = createMarker(point, name, address, type);
            map.addOverlay(marker);
          }
        });
      }
    }

    function createMarker(point, name, address, type) {
      var marker = new GMarker(point, customIcons[type]);
      var html = "<b>" + name + "</b> <br/>" + address;
      GEvent.addListener(marker, 'click', function() {
        marker.openInfoWindowHtml(html);
      });
      return marker;
    }
    //]]>
  </script>
  </head>
  <body onload="load()" onunload="GUnload()">
    <div id="map" style="width: 800px; height: 600px"></div>
  </body>
</html>

You will need to change a couple of lines here:

Search for (line 7):

7
8
<script src="http://maps.google.com/maps?file=api&v=2&key=Your Google API Key goes here!"
            type="text/javascript"></script>

And replace « Your Google API key goes here! » with your actual GoogleMap API key (it is specific to your website). You can go to Google and apply for one, it is pretty quick and painless to do as well.

Next,  search for (line 38):

38
GDownloadUrl("phpsqlajax_genxml.php", function(data) {

and change to the name of your page( if you followed this guide, then the name should be correct).

Pull this page up in a browser and you should have a nice map of your database of blocked ip addresses.


Some other points of interest are as follows:

You can change the center point of your map by modifying line 36 and entering your centerpoint of the map.

36
map.setCenter(new GLatLng(49.679004, 3.105462), 2);

You can change the icons of the markers (lines 14/15):

14
15
    iconBlue.image = './blue-dot.png';
    iconBlue.shadow = './chart-shadow.png';

I have modified my pins based on what protocol was being attacked, also I put the pins up on the server itself, so not to rely on Google to maintain the pins. See attached file for the pins I used.

Chaging the size of the map is as easy as modifying a couple of lines near the end of the file (line 66):

66
<div id="map" style="width: 800px; height: 600px"></div>

This is my first tutorial so if you find any errors, please let me know, I will be glad to fix, hope this all works for anyone else who wants to do this as well.

I will explain how I did all this:
Download and install fail2ban and mysql-server, I will not go into this as that is outside the scope of this document. Once your jails are configured and MySQL is up and running then follow the rest here.

First download durzo’s fail2sql from http://sourceforge.net/projects/fail2sql/ and follow the instructions on installing that. He has a script there to create the SQL tables for us and a small configuration (it is documented well) On my system I had to put the action in « iptables-multiport.conf ».
Thank you durzo!

In /etc/fail2ban/action.d/iptables-multiport.conf

Find:

0
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP

Change to:

0
1
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
/usr/local/fail2sql/fail2sql <name> <protocol> <port> <ip>

This will have iptables ban the ip address and also add the information to the MySQL database.

Next thing to get working is getting the information from the database into an XML format for Google Maps to use.
You will need to configure a file called dbinfo.php. This has the database connect information in it, this keeps that info safe and can be used by multiple scripts without having to keep typing it in.

Referenced in other scripts by:

0
require("dbinfo.php");

So,
sudo nano dbinfo.php

Enter this and modify it to your database settings.

0
1
2
3
4
5
6
7
<?
$db_host = 'db_server';
$db_user = 'your_user';
$db_pwd = 'your_password';

$database = 'db_name';
$table = 'db_table';
?>

I took a script from Pamela Fox here http://code.google.com/apis/maps/articles/phpsqlajax.html and modified it to do what I needed and pull the data from my existing fields into the required fields. This generates the required XML file export to use in the Google Map API.

So,

sudo nano phpsqlajax_genxml.php
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php

require("dbinfo.php");

// Start XML file, create parent node

$dom = new DOMDocument("1.0");
$node = $dom->createElement("markers");
$parnode = $dom->appendChild($node);

// Opens a connection to a MySQL server

$connection=mysql_connect ($db_host, $db_user, $db_pwd);
if (!$connection) {  die('Not connected : ' . mysql_error());}

// Set the active MySQL database

$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
  die ('Can\'t use db : ' . mysql_error());
}

// Select all the rows in the markers table

$query = "SELECT * FROM $table WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die('Invalid query: ' . mysql_error());
}

header("Content-type: text/xml");

// Iterate through the rows, adding XML nodes for each

while ($row = @mysql_fetch_assoc($result)){
  // ADD TO XML DOCUMENT NODE
  $node = $dom->createElement("marker");
  $newnode = $parnode->appendChild($node);
  $newnode->setAttribute("name",$row['geo']);
  $newnode->setAttribute("address", $row['ip']);
  $newnode->setAttribute("lat", $row['latitude']);
  $newnode->setAttribute("lng", $row['longitude']);
  $newnode->setAttribute("type", $row['name']);
}

echo $dom->saveXML();

?>

Once this is complete, you should test it out and execute in a web browser. This should give you a result something like this:

0
1
2
3
4
<markers>
<marker name="blah, United Kingdom" address="xx.xx.xx.xx" lat="00" lng="00" type="ftp"/>
<marker name="blah, Netherlands" address="xx.xx.xx.xx" lat="00" lng="00" type="tcp"/>
<marker name="...
</markers>

If the XML is generated and no errors, then we are looking good so far.

Now, to pull this into a Google Map and drop the markers in place. I used the same script from Pamela Fox’s article and modified it to my likes.

So,

sudo nano phpsqlajax_map.htm
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Title of Page Here</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=Your Google API Key goes here!"
            type="text/javascript"></script>

    <script type="text/javascript">
    //<![CDATA[

    var iconBlue = new GIcon();
    iconBlue.image = './blue-dot.png';
    iconBlue.shadow = './chart-shadow.png';
    iconBlue.iconSize = new GSize(12, 20);
    iconBlue.shadowSize = new GSize(22, 20);
    iconBlue.iconAnchor = new GPoint(6, 20);
    iconBlue.infoWindowAnchor = new GPoint(5, 1);

    var iconRed = new GIcon();
    iconRed.image = './red-dot.png';
    iconRed.shadow = './chart-shadow.png';
    iconRed.iconSize = new GSize(12, 20);
    iconRed.shadowSize = new GSize(22, 20);
    iconRed.iconAnchor = new GPoint(6, 20);
    iconRed.infoWindowAnchor = new GPoint(5, 1);

    var customIcons = [];
    customIcons["proftpd"] = iconBlue;
    customIcons["ssh"] = iconRed;

    function load() {
      if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(49.679004, 3.105462), 2);

        GDownloadUrl("phpsqlajax_genxml.php", function(data) {
          var xml = GXml.parse(data);
          var markers = xml.documentElement.getElementsByTagName("marker");
          for (var i = 0; i < markers.length; i++) {
            var name = markers[i].getAttribute("name");
            var address = markers[i].getAttribute("address");
            var type = markers[i].getAttribute("type");
            var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    parseFloat(markers[i].getAttribute("lng")));
            var marker = createMarker(point, name, address, type);
            map.addOverlay(marker);
          }
        });
      }
    }

    function createMarker(point, name, address, type) {
      var marker = new GMarker(point, customIcons[type]);
      var html = "<b>" + name + "</b> <br/>" + address;
      GEvent.addListener(marker, 'click', function() {
        marker.openInfoWindowHtml(html);
      });
      return marker;
    }
    //]]>
  </script>
  </head>
  <body onload="load()" onunload="GUnload()">
    <div id="map" style="width: 800px; height: 600px"></div>
  </body>
</html>

You will need to change a couple of lines here:

Search for (line 7):

7
8
<script src="http://maps.google.com/maps?file=api&v=2&key=Your Google API Key goes here!"
            type="text/javascript"></script>

And replace « Your Google API key goes here! » with your actual GoogleMap API key (it is specific to your website). You can go to Google and apply for one, it is pretty quick and painless to do as well.

Next,  search for (line 38):

38
GDownloadUrl("phpsqlajax_genxml.php", function(data) {

and change to the name of your page( if you followed this guide, then the name should be correct).

Pull this page up in a browser and you should have a nice map of your database of blocked ip addresses.


Some other points of interest are as follows:

You can change the center point of your map by modifying line 36 and entering your centerpoint of the map.

36
map.setCenter(new GLatLng(49.679004, 3.105462), 2);

You can change the icons of the markers (lines 14/15):

14
15
    iconBlue.image = './blue-dot.png';
    iconBlue.shadow = './chart-shadow.png';

I have modified my pins based on what protocol was being attacked, also I put the pins up on the server itself, so not to rely on Google to maintain the pins. See attached file for the pins I used.

Chaging the size of the map is as easy as modifying a couple of lines near the end of the file (line 66):

66
<div id="map" style="width: 800px; height: 600px"></div>

This is my first tutorial so if you find any errors, please let me know, I will be glad to fix, hope this all works for anyone else who wants to do this as well.

Print Friendly, PDF & Email

Related Post

Les commentaires sont fermés.