Last active
November 17, 2021 14:01
-
-
Save ChrisCrossCrash/36dbe9dce1583a39c0fd1f811f54218c to your computer and use it in GitHub Desktop.
Two helper functions for dealing with abuseive IPs. `ip_is_abusive` checks if a provided IP address is abusive by using the AbuseIPDB API. `block_abusive_ips()` is a decorator for DRF view functions, which causes the view to respond with a 403 error if the IP is found to be abusive.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import json | |
from functools import wraps | |
from django.conf import settings | |
from rest_framework.exceptions import PermissionDenied | |
def ip_is_abusive(ip_addr: str, api_key: str, threshold: int = 50) -> bool: | |
"""Check if the given IP has an abuse confidence score greater than the given threshold percentage.""" | |
# The AbuseIPDB API endpoint | |
url = "https://api.abuseipdb.com/api/v2/check" | |
querystring = {"ipAddress": ip_addr, "maxAgeInDays": "90"} | |
headers = { | |
"Accept": "application/json", | |
"Key": api_key, | |
} | |
response = requests.request( | |
method="GET", url=url, headers=headers, params=querystring | |
) | |
data = json.loads(response.text) | |
return data["data"]["abuseConfidenceScore"] > threshold | |
def block_abusive_ips(threshold: int = 50, detail: str = None): | |
"""Check if the request is from an abusive IP and return a 403 error if it is. | |
Since the request uses DRF's `Response`, you'll need to place the decorator after | |
DRF's @api_view() decorator. For example: | |
@api_view(['POST']) | |
@block_abusive_ips() | |
def contact_form(request): | |
""" | |
if detail is None: | |
detail = ( | |
"Your IP has been blocked since it has been reported to have a high risk of abuse." | |
" If you think this is a mistake, try messaging us from another network and let us know." | |
) | |
def inner(orig_func): | |
@wraps(orig_func) | |
def _wrapper(request, *args, **kwargs): | |
if ip_is_abusive( | |
request.META["REMOTE_ADDR"], | |
settings.ABUSEIPDB_API_KEY, | |
threshold=threshold, | |
): | |
raise PermissionDenied(detail=detail) | |
return orig_func(request, *args, **kwargs) | |
return _wrapper | |
return inner |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment