Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions admin_honeypot/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@


class LoginAttemptAdmin(admin.ModelAdmin):
list_display = ('username', 'get_ip_address', 'get_session_key', 'timestamp', 'get_path')
list_display = ('username', 'get_ip_address', 'get_session_key', 'timestamp', 'get_path', 'get_country_name')
list_filter = ('timestamp',)
readonly_fields = ('path', 'username', 'ip_address', 'session_key', 'user_agent')
readonly_fields = ('path', 'username', 'ip_address', 'session_key', 'user_agent', 'record_by_address')
search_fields = ('username', 'ip_address', 'user_agent', 'path')

def get_actions(self, request):
Expand All @@ -31,6 +31,11 @@ def get_path(self, instance):
get_path.short_description = _('URL')
get_path.allow_tags = True

def get_country_name(self, instance):
return instance.get_record_by_address().get('country_name')
get_country_name.short_description = _('Country Name')
get_country_name.allow_tags = True

def has_add_permission(self, request, obj=None):
return False

Expand Down
Binary file added admin_honeypot/locale/id/LC_MESSAGES/django.mo
Binary file not shown.
106 changes: 106 additions & 0 deletions admin_honeypot/locale/id/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-18 22:19+0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Agus Makmun <agus@python.web.id>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#: admin_honeypot/admin.py:21
msgid "Session"
msgstr "Sesi"

#: admin_honeypot/admin.py:26
#: admin_honeypot/templates/admin_honeypot/email_message.txt:4
msgid "IP Address"
msgstr "Alamat IP"

#: admin_honeypot/admin.py:31
msgid "URL"
msgstr ""

#: admin_honeypot/admin.py:36
msgid "Country Name"
msgstr "Nama Negara"

#: admin_honeypot/models.py:8
msgid "username"
msgstr ""

#: admin_honeypot/models.py:9
msgid "ip address"
msgstr "alamat ip"

#: admin_honeypot/models.py:10
msgid "session key"
msgstr "key sesi"

#: admin_honeypot/models.py:11
msgid "user-agent"
msgstr ""

#: admin_honeypot/models.py:12
msgid "timestamp"
msgstr "waktu"

#: admin_honeypot/models.py:13
msgid "path"
msgstr "alamat"

#: admin_honeypot/models.py:14
msgid "record by address"
msgstr "rekaman berdasarkan alamat"

#: admin_honeypot/models.py:17
msgid "login attempt"
msgstr "percobaan login"

#: admin_honeypot/models.py:18
msgid "login attempts"
msgstr "percobaan login"

#: admin_honeypot/templates/admin_honeypot/email_message.txt:1
#, python-format
msgid ""
"This is an automatic email to notify you that someone tried to login to the "
"admin honeypot on %(host)s"
msgstr ""
"Ini adalah email otomatis untuk memberitahukan Anda bahwa ada seseorang yang "
"mencoba untuk loginadmin honeypot pada %(host)s"

#: admin_honeypot/templates/admin_honeypot/email_message.txt:3
msgid "Username"
msgstr ""

#: admin_honeypot/templates/admin_honeypot/email_message.txt:5
msgid "Timestamp"
msgstr "Waktu"

#: admin_honeypot/templates/admin_honeypot/email_message.txt:6
msgid "Record by Address"
msgstr "Rekaman berdasarkan Alamat"

#: admin_honeypot/templates/admin_honeypot/email_subject.txt:1
#, python-format
msgid "[admin-honeypot] attempted login from %(ip)s at %(host)s"
msgstr "[admin-honeypot] percobaan login dari %(ip)s ke %(host)s"

#: admin_honeypot/templates/admin_honeypot/login.html:4
msgid "Django administration"
msgstr ""

#: admin_honeypot/views.py:46
msgid "Log in"
msgstr "Masuk"
20 changes: 20 additions & 0 deletions admin_honeypot/migrations/0003_loginattempt_record_by_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-02-18 09:34
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('admin_honeypot', '0002_auto_20160208_0854'),
]

operations = [
migrations.AddField(
model_name='loginattempt',
name='record_by_address',
field=models.TextField(blank=True, null=True, verbose_name='record by address'),
),
]
13 changes: 13 additions & 0 deletions admin_honeypot/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ast
from django.db import models
from django.utils.translation import ugettext_lazy as _
from admin_honeypot import listeners
Expand All @@ -10,6 +11,7 @@ class LoginAttempt(models.Model):
user_agent = models.TextField(_("user-agent"), blank=True, null=True)
timestamp = models.DateTimeField(_("timestamp"), auto_now_add=True)
path = models.TextField(_("path"), blank=True, null=True)
record_by_address = models.TextField(_("record by address"), blank=True, null=True)

class Meta:
verbose_name = _("login attempt")
Expand All @@ -18,3 +20,14 @@ class Meta:

def __str__(self):
return self.username

def get_record_by_address(self):
"""
return dictionary from field of `record_by_address`
"""
try:
return ast.literal_eval(self.record_by_address)
except ValueError:
return {}

get_record_by_address.allow_tags = True
1 change: 1 addition & 0 deletions admin_honeypot/templates/admin_honeypot/email_message.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
{% trans "Username" %}: {{ instance.username }}
{% trans "IP Address" %}: {{ instance.ip_address }}
{% trans "Timestamp" %}: {{ instance.timestamp }}
{% trans "Record by Address" %} {{ instance.record_by_address }}

{{ admin_detail_url }}

Expand Down
31 changes: 31 additions & 0 deletions admin_honeypot/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import django
import pygeoip
import ipaddress
from admin_honeypot.forms import HoneypotLoginForm
from admin_honeypot.models import LoginAttempt
from admin_honeypot.signals import honeypot
Expand All @@ -8,6 +10,12 @@
from django.shortcuts import redirect
from django.utils.translation import ugettext as _
from django.views import generic
from django.conf import settings


ALLOW_TRACK_ADDRESS = getattr(settings, 'ADMIN_HONEYPOT_ALLOW_TRACK_ADDRESS', False)
PATH_GEOIPV4_CITY = getattr(settings, 'ADMIN_HONEYPOT_PATH_GEOIPV4_CITY', None)
PATH_GEOIPV6_CITY = getattr(settings, 'ADMIN_HONEYPOT_PATH_GEOIPV6_CITY', None)


class AdminHoneypot(generic.FormView):
Expand Down Expand Up @@ -42,13 +50,36 @@ def get_context_data(self, **kwargs):
def form_valid(self, form):
return self.form_invalid(form)

def track_ipaddres(self, ip):
"""
track detail ip address from client ip.
return None, if `ALLOW_TRACK_ADDRESS = False` or invalid ipaddress.
related issue: https://github.com/dmpayton/django-admin-honeypot/issues/41
"""
if ALLOW_TRACK_ADDRESS is False:
return None

try:
ipv_version = ipaddress.ip_address(u'%s' % ip).version
if ipv_version == 6:
gi = pygeoip.GeoIP(PATH_GEOIPV6_CITY)
else:
gi = pygeoip.GeoIP(PATH_GEOIPV4_CITY)
return gi.record_by_addr(ip)
except ValueError:
# invalid ipv4 or ipv6
return None

def form_invalid(self, form):
instance = LoginAttempt.objects.create(
username=self.request.POST.get('username'),
session_key=self.request.session.session_key,
ip_address=self.request.META.get('REMOTE_ADDR'),
user_agent=self.request.META.get('HTTP_USER_AGENT'),
path=self.request.get_full_path(),
record_by_address=self.track_ipaddres(
self.request.META.get('REMOTE_ADDR')
)
)
honeypot.send(sender=LoginAttempt, instance=instance, request=self.request)
return super(AdminHoneypot, self).form_invalid(form)
1 change: 1 addition & 0 deletions docs/manual/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Requirements

* Python 2.6+ or Python 3.3+
* Django 1.3+
* Pygeoip

Install
=======
Expand Down
19 changes: 19 additions & 0 deletions docs/manual/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,22 @@ Sent on every login attempt with the following arguments:

:instance: The LoginAttempt object created
:request: The current request object

**ADMIN_HONEYPOT_ALLOW_TRACK_ADDRESS**

Default: ``False``

Used to allow track detail address from client.
Set to ``True`` to enable tracker.

**ADMIN_HONEYPOT_PATH_GEOIPV4_CITY**

Default: ``None``

Used to set path of ``GeoLiteCity.dat`` for ``IPV_4``.

**ADMIN_HONEYPOT_PATH_GEOIPV6_CITY**

Default: ``None``

Used to set path of ``GeoLiteCityv6.dat`` for ``IPV_6``.
Binary file added geoip/GeoLiteCity.dat
Binary file not shown.
Binary file added geoip/GeoLiteCityv6.dat
Binary file not shown.
6 changes: 6 additions & 0 deletions geoip/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The GeoLite databases provides from `IP geolocation databases`_.
They are updated on the first Tuesday of each month.
These databases are offered in the same binary and csv formats.
Any code which can read the subscription databases can also read the GeoLite databases.

.. _IP geolocation databases: http://dev.maxmind.com/geoip/legacy/geolite/
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
],
keywords='django admin honeypot trap',
maintainer='Derek Payton',
maintainer_email='derek.payton@gmail.com',
Expand All @@ -37,4 +37,5 @@
include_package_data=True,
packages=find_packages(),
zip_safe=False,
)
install_requires=["pygeoip", "ipaddress"]
)