Search | Sailfish OS | Running | PineTime | All Posts

OPNsense API

April 29, 2020 — Nico Cartron

I'm a huge fan of FreeBSD and therefore when I contemplated replacing the crappy router/firewall that comes with my ISP with a proper router, I looked at open-source software running it.

I initially started with pfsense, which was a fork of m0n0wall, but then switched to OPNsense whose approach I liked more, and which itself is a fork of pfsense. Reasons for the fork are explained here.


What I'm using OPNsense for

This OPNsense is installed on a small but powerful router which I bought on Ali Express, which comes with 4 NIC.
I'm using it to provide Internet access to my home, with different ISP: one of the (only) downsides of living in the countryside is that we don't (yet) have a fiber connection, and rely on a rather slow ADSL connection.
It works fine for daily business, but having pages loading faster and not having to wait forever for a poor Debian ISO is also nice.

So we have a 2nd ISP, using a 4G connection, and specific devices use this connection as their gateway, with a fallback to the ADSL one in case 4G is broken, or we hit the monthly quota.

I'm using Telegraf to export metrics, and graph them in the awesome Grafana.

How cool is that? :)

In addition to that, OPNsense also serves as:

  • DHCP server, with static DHCP leases for some devices,
  • VPN gateway, which I'm using to access resources when outside.

Why using the API?

Back to the title of this article: API.
Well, as a person working in IT, I am lazy^M^M^M^M I like to automate things.
And one of the things which I do quite often and which bothers me everytime since that's a lot of "clicks", is to switch my laptop from the ADSL connection to the 4G connection.

See:

  • I have created an alias in OPNsense which contains a bunch of devices (IP addresses) that get the 4G connection as gateway:

  • This alias has a specific FW rule which sets the GW as being the 4G connection:

  • When I want my laptop to use the 4G connection, I have to:

    • edit the alias,
    • add my laptop IP (in fact I'm adding another alias, which contains both the wired and wireless IP addresses of my laptop),
    • apply the changes. And of course do it the other way around once I want to revert back to the ADSL connection.

Quite boring, isn't it? So how about we automate this, using OPNsense API? :)

Using the API

Not too difficult, it's easy to find: API Reference.

You'll need to:

  • create a specific user to use with the API (recommended),
  • add an API key (you need to have the user created first, as otherwise the API keys field won't appear),
  • this will generate a key and a secret
    • save the file somewhere safe,
    • the key can be seen when editing the user,
    • but for (obvious) security reasons, the secret won't be displayed anymore.

Then the doc gives you the structure to use:

https://opnsense.local/api/<module>/<controller>/<command>/[<param1>/[<param2>/...]]

So basically, we have:

  • Module: e.g. Firewall in my case,
  • Controller: alias in my case,
  • Command: let's look at the doc:

I don't want to change anything at the moment, so am just looking at GET methods;
the export one looks interesting, so let's give it a try, using curl:

curl -k -u "<KEY>":"<SECRET>" https://IP_OPNSENSE/api/firewall/alias/export |jq .

This indeed gives the whole list of my aliases, in JSON format:

Cool! Now let's try to add an alias to see if it works.

For some reason, I kept looking at this first table ("Resources (AliasController.php)"), and tried with the addItem command, with no luck.
Any parameter I tried as input didn't work, which was frustrating since the delItem command worked, by passing it the UUID (I tried with a test alias).

Twitter to the rescue!

So basically I was kind of stuck, and decided to ask for help on Twitter:

I pinged @jpmens (Jan-Piet), who I know is a huge BSD enthusiast, and has loads of connections who can help.
And it worked! I got interesting responses, in order of interest:

  • @Alpensichtung uses the API to check DHCP leases
  • @natedamm is using the API to toggle FW aliases on/off for his kids' Internet (all of that from a Discord channel, how cool is that? :)
  • @mimu_muc gave me a link to a script which uses OPNsense API to automatically block users, leveraging Wazuh (an open-source IDS).

This last link did the trick, or at least confirmed what I suspected:
I was trying to create a new alias or enable/disable it, but what if I would just add the desired IP address(es) to an existing alias?
That would surely work! Especially since just before receiving this answer, I found a post on the OPNsense forums, detailling the usage of alias_util.

Let's try it out!

  1. Preparing - create an empty alias:
    I used test, to be sure I wouldn't break anything, and then listed its content:
    curl -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias_util/list/test

    and the result:
    {"total":0,"rowCount":9999,"current":1,"rows":[]}

    (Of course you can use jq to have a nicer output).

  2. Add an IP address to that alias:
    curl -X POST -d '{"address":"192.168.42.42"}' -H "Content-Type: application/json" -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias_util/add/test

    which returned a:
    {"status":"done"}

  3. List again the test alias:
    {"total":1,"rowCount":9999,"current":1,"rows":[{"ip":"192.168.42.42"}]}

    => Success! The IP address has been added to the alias.

  4. Delete the IP address to revert back to previous situation:
    curl -X POST -d '{"address":"192.168.42.42"}' -H "Content-Type: application/json" -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias_util/delete/test

Using it for real

I then tested it on the main alias I'm using to give the 4G connection as gateway.

/!\ Beware, you need to add one IP address at a time, so one API call per IP address to add/delete.

Once you have added the IP address(es) you need, don't forget to reconfigure (that's the same as hitting the Apply button on the OPNsense web GUI:

curl -X POST -d "" -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias/reconfigure

And it just works :)

Script it, because I'm lazy :)

The below script allows me to easily switch my laptop gateway to/from the 4G connection.
It is invoked like this:

  • ./script.sh add to add my IP address to the 4G alias
  • ./script.sh del to move it back to the ADSL connection

I can also specify a specific alias (by inputing the 2nd parameter) and a specific IP address (by inputting the 3rd parameter), e.g.:
./script.sh add 192.168.42.100 myotheralias

#!/bin/sh

# Variables
OPNS_KEY="YOUR OPNSENSE KEY"
OPNS_SECRET="YOUR OPNSENSE SECRET"
IPFW=<YOUR OPNSENSE IP ADDRESS>
GRP=<YOUR ALIAS>
IPADDR=<A DEFAULT IP YOU WANT TO ADD/DELETE>


# If additional parameters are given, use them
# Otherwise, use the variables defined above
if [ $2 ]
then
  IPADDR=$2
fi

if [ $3 ]
then
  GRP=$3
fi

add_ip()
{
  curl -X POST -d '{"address":"'$IPADDR'"}' -H "Content-Type: application/json"\
  -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias_util/add/$GRP
  curl -X POST -d ''  -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias/reconfigure
}

del_ip()
{
  curl -X POST -d '{"address":"'$IPADDR'"}' -H "Content-Type: application/json"\
  -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias_util/delete/$GRP
  curl -X POST -d '' -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias/reconfigure
}

list_ip()
{
  curl -s -k -u $OPNS_KEY:$OPNS_SECRET https://$IPFW/api/firewall/alias_util/list/$GRP | jq . | grep ip
}

case $1 in
  add)
    echo "adding"
    add_ip
    ;;
  del)
    echo "deleting"
    del_ip
    ;;
  list)
    echo "listing"
    list_ip
    ;;
  *)
    echo "Usage: $0 add|del|list {IP address} {alias}";;
esac

Next step

I'm using Domoticz as my Home Automation solution.
So the next step, which I have documented in another article, is to add a button in Domoticz, which allows me to trigger the aforementioned changes - i.e.:

  • hit the button: laptop uses the 4G connection
  • hit the button again: back to ADSL
  • cherry on the cake: having a timer which reverts back automatically (since I have a quota on the 4G connection, I don't want my laptop to use it all).

Tags: FreeBSD, IT, Automation


I don't have any commenting system, but email me (nicolas at ncartron dot org) your comments!
If you like my work, you can buy me a coffee!