How to monitor your IP space for BGP hijacking

I’ve written the following scripts that will assist anyone in monitoring their (or anyone’s) IP space (IPv4, IPv6 and ASNs) against BGP hijacking.

The scripts rely on data provided by the Routing Information Service (RIS) which RIPE NCC have kindly opened up to the public to use. For years, RIPE have been running 25 Route Collectors around the world where they collect routing information and allow the public to download this data for analysis. In recent years, they started RIS to help users query this data via a REST API.

The script below (ris-live-prefix.py) will allow users to monitor an IPv4 or IPv6 prefix. The REST API will return JSON objects that match this request, as well as more specific BGP announcements.

ris-live-prefix.py

 import json
 import websocket
 import ssl
 ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
 ws.connect("wss://ris-live.ripe.net/v1/ws/?client=YOUR_ORG_NAME")
 params = {
     "moreSpecific": True,
     "host": "",
     "prefix": "45.146.72.0/22",
     "require": "", # can use "announcements" or "withdrawls"
     "socketOptions": {
         "includeRaw": True
     }
 }
 ws.send(json.dumps({
         "type": "ris_subscribe",
         "data": params
 }))
 for data in ws:
     parsed = json.loads(data)
     print(parsed["type"], parsed["data"])

Optional step: change “YOUR_ORG_NAME” to anything unique to you. RIS Live maintainers will appreciate that.

This RIS Live stream has the tendency of breaking on a frequent basis; hence, use the below script to start it when it breaks. The script will also fix a problem with the python client not being able to verify the REST API SSL certificate authenticity

ris-live-prefix.sh

#!/bin/bash 
while true 
do 
WEBSOCKET_CLIENT_CA_BUNDLE=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem  /usr/bin/python /path/to/your/ris-live-prefix.py | /usr/bin/sed  s/u\'/\"/g | /usr/bin/sed s/\'/\"/g | /usr/bin/sed  's/^................//g' | /usr/bin/sed  's/)$//g' > /path/to/output/prefix-monitoring.json
done

The additional sed commands are to there to filter the output and make it Logstash ready. You may have to alter that in accordance to whatever log analysis tool you’re using.

Moreover, if you want this script to run at boot time, you will have to create a cronjob for it, or run it as a service.

You can also monitor whether your ASN is being hijacked by modifying the above code slightly. The below script shows an example to monitor BGP updates for ASN 205986.

ris-live-asn.py

 import json
 import websocket
 import ssl
 ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
 ws.connect("wss://ris-live.ripe.net/v1/ws/?client=YOUR_ORG_NAME")
 params = {
     "moreSpecific": True,
     "host": "",
     "path": "205986",
     "require": "", # can use "announcements" or "withdrawls"
     "socketOptions": {
         "includeRaw": True
     }
 }
 ws.send(json.dumps({
         "type": "ris_subscribe",
         "data": params
 }))
 for data in ws:
     parsed = json.loads(data)
     print(parsed["type"], parsed["data"])

and you’ll need to use the below script to keep it persistant

ris-live-asn.sh

#!/bin/bash 
while true 
do 
WEBSOCKET_CLIENT_CA_BUNDLE=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem  /usr/bin/python /path/to/your/ris-live-asn.py | /usr/bin/sed  s/u\'/\"/g | /usr/bin/sed s/\'/\"/g | /usr/bin/sed  's/^................//g' | /usr/bin/sed  's/)$//g' > /path/to/output/asn-monitoring.json
done

Final notes

  • If your organisation has multiple ASNs and multiple prefixes, you’ll need a script for each one of them
  • RIS will show you all seen updates, including legitimate ones. So you need to use a filter in your favourite log analysis tool in order to highlight unexpected BGP updates.
    • For prefix hijacking, your fliter needs to look for annoucements not originating from your as_path
    • For ASN hijacking, your filter needs to look for annoucements where your next hop isn’t one of your transit ASNs.