Skip to content

Instantly share code, notes, and snippets.

@tiagomota
Last active January 1, 2024 11:46
Show Gist options
  • Save tiagomota/3bf6de8963e1730892c1d3a5a44b3a16 to your computer and use it in GitHub Desktop.
Save tiagomota/3bf6de8963e1730892c1d3a5a44b3a16 to your computer and use it in GitHub Desktop.
OPNSense: Custom cron job to automatically update an alias with CloudFlare IPs

OPNSense: Custom cron job to automatically update an alias with CloudFlare IPs

The following steps were done and tested in version 23.7.8_1.

⚠️ Disclaimer: I'm just a regular joe trying to learn and make my life easier at the same time. Use this at your own risk.

1. Create an alias

Go to Firewall > Aliases and add an alias

Enabled: checked
Name: CloudFlare_IPs
Type: External (advanced)
Description: https://www.cloudflare.com/en-gb/ips/

2. Access into your OPNSense firewall shell

There are multiple ways of achieving this, where the easiest is to use SSH.

3. Create the custom runnable script

I usually add my custom scripts in /usr/local/custom-scripts. Pick a directory for yours and run vi cloudflare-ips-alias.sh and paste the following:

#!/bin/sh

usage() {
  cat<< EOF
Usage: ./cloudflare-ips.sh [-h] [-v] -a MyAlias

Fetch CloudFlare IPs range (IPv4) and set them to the given OPNSense alias.
Note: The Alias should be of type "External (Advanced)"

Available options:

-h, --help      Print this help and exit
-v, --verbose   Print script debug info
-a, --alias     The OPNSense alias to add the IPs to
EOF
  exit
}

msg() {
  echo >&2 "${1-}"
}

die() {
  msg=$1
  code=${2-1} # default exit status 1
  msg "$msg"
  exit "$code"
}

parse_params() {
  # default values of variables set from params
  alias=''

  while :; do
    case "${1-}" in
    -h | --help) usage ;;
    -v | --verbose) set -x ;;
    -a | --alias)
      alias="${2-}"
      shift
      ;;
    -?*) die "Unknown option: $1" ;;
    *) break ;;
    esac
    shift
  done

  # check required params and arguments
  [ -z "${alias-}" ] && die "Missing required parameter: alias"

  return 0
}

cloudflare_ips() {
  curl -s \
    --request GET \
    --url https://api.cloudflare.com/client/v4/ips \
    --header 'Authorization: Bearer undefined' \
    --header 'Content-Type: application/json' | \
    python3 -c "import sys, json; print(' '.join(json.load(sys.stdin)['result']['ipv4_cidrs']))"
}

parse_params "$@"

ips=$(cloudflare_ips)
[ -z "${ips-}" ] && die "Unable to fetch CloudFlare IPs"

pfctl -T "$alias" -T flush # Clean alias
for ip in $ips
do
  pfctl -t "$alias" -T add "$ip" # Add IPs
done

4. Set execute permissions on script

chmod 700 cloudflare-ips-alias.sh

5. Define the new Backend action that will be used as a cron job

Under /usr/local/opnsense/service/conf/actions.d/ create a new file named actions_cloudflare-ips-alias.conf. The name of this file needs to start with actions_, the rest is up to you. Paste the following content:

[reload]
command:
    /usr/local/bin/flock -n -E 0 /tmp/cloudflare-ips-alias.lock /usr/local/custom-scripts/cloudflare-ips-alias.sh -a CloudFlare_IPs
type:script
message:reloading cloudflare IPs
description:Reload CloudFlare IPs alias

6. Restart the config daemon to load the new config and test out the new action

$> service configd restart
...

$> configctl cloudflare-ips-alias reload

If you go to Firewall > Diagnostics > Aliases > CloudFlare_IPs you should see the same IPs this website displays.

7. Define a new Cron job to run the update periodically

Go to System > Settings > Cron and add a new one:

Enabled: checked
Minutes: 0
Hours: 5
Days of the month: *
Months: *
Days of the week: *
Command: Reload CloudFlare IPs alias
Parameters: 
Description: Reload CloudFlare IPs alias
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment