BlackRed¶
BlackRed is a dynamic blacklisting library using Redis as a fast and reliable storage backend.
How does it work?¶
Example: A user tries to log on a system and fails because of bad credentials or an inactivated account. This failure can be recorded with BlackRed. After three failures within a certain time the account gets locked for an extended period of time. This limits brute force attacks. All time periods are configurable.
In a desktop application you would record the username in question with BlackRed. In a web environment, the requester’s IP address would be the perfect.
In the redis database, two lists are kept: A watchlist that records the failures, and the blacklist that contains blocked items.
Requirements¶
BlackRed runs only under Python 3.3, 3.4, 3.5 and PyPy3. There’s no support for Python 2.
The only thing BlackRed needs is the redis package >= 2.10.
Jump Start¶
Installation can be done with pip install blackred
. Usage is as easy, here an example for a simple user login:
import blackred
def login(username, password, request_ip):
br = blackred.BlackRed()
if br.is_blocked(request_ip):
return False
if not authenticate(username, password):
br.log_fail(request_ip)
return False
return True
More examples: Example Usage.
Usage¶
Settings and Defaults¶
The default settings for new instances of BlackRed
can be defined with the
attributes of the Settings
subclass.
For all available options, see the Settings
documentation at the
blackred API docs.
Example Usage¶
BlackRed features a very simple and intuitive API. Go to API documentation.
Simple Use¶
With everything in defaults (Host is localhost
, port is 6379
and so on), you can use BlackRed right out of the
box:
import blackred
def login(username, password, request_ip):
br = blackred.BlackRed()
if br.is_blocked(request_ip):
return False
if not authenticate(username, password):
br.log_fail(request_ip)
return False
return True
The BlackRed constructor
offers a wide range of on-the-fly settings for
the new instance. To keep your code nice and clean when you use the same settings most of the time, you can use the
Settings Predefinition.
Item Selection¶
For a web or network based application, a good item to check and block is the client IP address of the requestor.
In other environments, you might choose anything else that identifies a request source uniqually. Most important: The
item must be represented by a str
.
Settings Predefinition¶
To make the using of BlackRed easier, you can change the default settings for new instances by changing the values of
the attributes of the BlackRed.Settings
class. Changes are only valid
for new instances created after the changes. Already existing instances are not changed.
Note
BlackRed versions before 0.3.0 had a different settings approach. Settings where separated into global settings and settings for new instances. With 0.3.0, all settings are only valid for new instances. Keep that in mind when upgrading from an older version.
Example: Enable Anonymization by default:
import blackred
blackred.BlackRed.Settings.ANONYMIZATION = True
def login(username, password, request_ip):
br = blackred.BlackRed()
if br.is_blocked(request_ip):
return False
if not authenticate(username, password):
br.log_fail(request_ip)
return False
return True
Use Unix Socket instead of TCP/IP connection¶
If you want to use a unix socket to connect, set the redis_use_socket
constructor parameter to True
and provide
the absolute path to the socket with the redis_host
parameter, example:
import blackred
br = blackred.BlackRed(redis_host='/var/run/redis/redis.sock', redis_use_socket=True)
As always, those settings can be predefined (see Settings Predefinition) as defaults for all new instances:
import blackred
blackred.BlackRed.Settings.REDIS_USE_SOCKET = True
blackred.BlackRed.Settings.REDIS_HOST = '/var/run/redis/redis.sock'
Anonymization¶
Sometimes it’s necessary to hash the item’s values to ensure privacy of the requester. BlackRed can easily support you.
Just set the ANONYMIZATION
attribute to True
:
import blackred
blackred.BlackRed.Settings.ANONYMIZATION = True
Use a Redis password (aka Redis AUTH feature)¶
To activate authentication, you can use the redis_auth
parameter of the constructor:
import blackred
br = blackred.BlackRed(redis_auth='my_password')
As always, this settings can be predefined (see Settings Predefinition) as default for all new instances:
import blackred
blackred.BlackRed.Settings.REDIS_AUTH = 'my_password'
API Documentation¶
blackred package¶
The complete blackred.blackred
module is imported in the __init__.py
of the
blackred
module. So you can use blackred
instead of blackred.blackred
in your code.
For usage examples, please see the Examples Page.
blackred.blackred module¶
Copyright 2015 Juergen Edelbluth
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-
class
blackred.blackred.
BlackRed
(redis_host: str=None, redis_port: int=None, redis_db: int=None, redis_use_socket: bool=None, redis_auth: str=None)[source]¶ Bases:
object
Create an Instance of BlackRed with configuration for Redis connection
Parameters: -
class
Settings
[source]¶ Bases:
object
All the attributes of this class are used as default settings for new BlackRed instances.
-
ANONYMIZATION
= False¶ If required, you can turn this on (set it to
True
) when BlackRed should not store IP addresses, usernames etc. as plain text. A hash value is used instead.This setting might be necessary to get data protection policy compliant.
Type: bool
-
BLACKLIST_KEY_TEMPLATE
= 'BlackRed:BlackList:{:s}'¶ Template for generating blacklist entries.
Defaults to
'BlackRed:BlackList:{:s}'
and should only be changed when this collides with one of your namespaces.Type: str
-
BLACKLIST_REFRESH_TTL_ON_HIT
= True¶ If an item is already on the blacklist and is checked with
BlackRed.is_blocked
orBlackRed.is_not_blocked
while on the blacklist, the time to live for the blacklist entry is reset toBlackRed.Settings.BLACKLIST_TTL_SECONDS
.So if this is set to
True
(that’s the default value) and a blocked user tries to login after 12 hours after blacklisting, his blacklist time is increased to another 24 hours.Type: bool
-
BLACKLIST_TTL_SECONDS
= 86400¶ Time in seconds for an item to stay on the blacklist.
Defaults to 86400 (24 hours). After that time, the entry is deleted automatically.
Type: int
-
REDIS_AUTH
= None¶ If the redis connection requires authentication, the password can be predefined here.
If set to
None
(which is the default), authentication will not be used.Type: str
-
REDIS_DB
= 0¶ The Redis database number, defaults to
0
Type: int
-
REDIS_HOST
= 'localhost'¶ Hostname, IP Address or socket, defaults to
'localhost'
Type: str
-
REDIS_PORT
= 6379¶ TCP-Port for Redis, defaults to
6379
Type: int
-
REDIS_USE_SOCKET
= False¶ Tell the
BlackRed
class to use a unix socket instead of a TCP/IP connection.Defaults to
False
Type: bool
-
SALT_KEY
= 'BlackRed:AnonymizationListSecret'¶ The key for saving the individual salt for anonymization.
Defaults to
BlackRed:AnonymizationListSecret
and should only be changed when it collides with one of your namespaces.Type: str
-
WATCHLIST_KEY_TEMPLATE
= 'BlackRed:WatchList:{:s}'¶ Template for generating watchlist entries.
Defaults to
'BlackRed:WatchList:{:s}'
and should only be changed when this collides with one of your namespaces.Type: str
-
WATCHLIST_TO_BLACKLIST_THRESHOLD
= 3¶ Number of fails for an item to get from the watchlist to the blacklist. Defaults to 3.
Type: int
-
WATCHLIST_TTL_SECONDS
= 180¶ Time in seconds for an item to stay on the watchlist.
If after a logged failure a new failure appears within this time frame, the fail count is increased. If not, the entry is deleted automatically. Defaults to 180 (3 minutes).
Type: int
-
-
BlackRed.
get_blacklist_ttl
(item: str) → int[source]¶ Get the amount of time a specific item will remain on the blacklist.
Parameters: item (str) – The item to get the TTL for on the blacklist Returns: Time in seconds. Returns None for a non-existing element. Return type: int
-
BlackRed.
get_watchlist_ttl
(item: str) → int[source]¶ Get the amount of time a specific item will remain on the watchlist.
Parameters: item (str) – The item to get the TTL for on the watchlist Returns: Time in seconds. Returns None for a non-existing element Return type: int
-
BlackRed.
is_blocked
(item: str) → bool[source]¶ Check if an item is on the blacklist
Parameters: item (str) – The item to check Returns: True, when the item is on the blacklist Return type: bool
-
BlackRed.
is_not_blocked
(item: str) → bool[source]¶ Check if an item is _not_ already on the blacklist
Parameters: item (str) – The item to check Returns: True, when the item is _not_ on the blacklist Return type: bool
-
class
Links¶
- Author: Juergen Edelbluth, https://juergen.rocks/, @JuergenRocks
- Build Status: https://travis-ci.org/edelbluth/blackred
- Project Homepage: https://github.com/edelbluth/blackred
- PyPi Page: https://pypi.python.org/pypi/blackred
- German Description (for 0.2 version): https://juergen.rocks/art/mit-blackred-benutzer-logins-absichern.html
- Documentation (this one): https://blackred.readthedocs.org/index.html