Skip to content

Instantly share code, notes, and snippets.

@ChrisCrossCrash
Last active November 17, 2021 14:01
Show Gist options
  • Save ChrisCrossCrash/36dbe9dce1583a39c0fd1f811f54218c to your computer and use it in GitHub Desktop.
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.
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