Firewall

The firewall API plugin (os-firewall) offers a way for machine to machine interaction between custom applications and OPNsense, it can easily be installed like any other plugin via System ‣ Firmware ‣ Plugins.

Although the plugin does contains a basic user interface (in Firewall ‣ Automation), it’s mirely intended as a reference and testbed. There’s no relation to any of the rules being managed via the core system.

Tip

Use your browsers “inspect” feature to compare requests easily, the user interface in terms of communication is exactly the same as offered by the API . Rules not visible in the web interface (Firewall ‣ Automation) will not be returned by the API either.

Resources (AliasController.php) – extends : ApiMutableModelControllerBase

Method

Module

Controller

Command

Parameters

POST

firewall

alias

addItem

POST

firewall

alias

delItem

$uuid

GET

firewall

alias

export

GET

firewall

alias

get

GET

firewall

alias

getAliasUUID

$name

GET

firewall

alias

getGeoIP

GET

firewall

alias

getItem

$uuid=null

GET

firewall

alias

getTableSize

POST

firewall

alias

import

GET

firewall

alias

listCategories

GET

firewall

alias

listCountries

GET

firewall

alias

listNetworkAliases

GET

firewall

alias

listUserGroups

POST

firewall

alias

reconfigure

*

firewall

alias

searchItem

POST

firewall

alias

set

POST

firewall

alias

setItem

$uuid

POST

firewall

alias

toggleItem

$uuid,$enabled=null

<<uses>>

model Alias.xml

Resources (AliasUtilController.php) – extends : ApiControllerBase

Method

Module

Controller

Command

Parameters

POST

firewall

alias_util

add

$alias

GET

firewall

alias_util

aliases

POST

firewall

alias_util

delete

$alias

POST

firewall

alias_util

findReferences

POST

firewall

alias_util

flush

$alias

GET

firewall

alias_util

list

$alias

GET

firewall

alias_util

updateBogons

Resources (CategoryController.php) – extends : ApiMutableModelControllerBase

Method

Module

Controller

Command

Parameters

POST

firewall

category

addItem

POST

firewall

category

delItem

$uuid

GET

firewall

category

get

GET

firewall

category

getItem

$uuid=null

*

firewall

category

searchItem

$add_empty=’0’

POST

firewall

category

set

POST

firewall

category

setItem

$uuid

<<uses>>

model Category.xml

Abstract [non-callable] (FilterBaseController.php)

Method

Module

Controller

Command

Parameters

POST

firewall

filter_base

apply

$rollback_revision=null

POST

firewall

filter_base

cancelRollback

$rollback_revision

GET

firewall

filter_base

get

GET

firewall

filter_base

listCategories

GET

firewall

filter_base

listNetworkSelectOptions

POST

firewall

filter_base

revert

$revision

POST

firewall

filter_base

savepoint

POST

firewall

filter_base

set

<<uses>>

model Filter.xml

Resources (FilterController.php) – extends : FilterBaseController

Method

Module

Controller

Command

Parameters

POST

firewall

filter

addRule

POST

firewall

filter

delRule

$uuid

GET

firewall

filter

getRule

$uuid=null

*

firewall

filter

searchRule

POST

firewall

filter

setRule

$uuid

POST

firewall

filter

toggleRule

$uuid,$enabled=null

Resources (FilterUtilController.php) – extends : ApiControllerBase

Method

Module

Controller

Command

Parameters

GET

firewall

filter_util

ruleStats

Resources (GroupController.php) – extends : ApiMutableModelControllerBase

Method

Module

Controller

Command

Parameters

POST

firewall

group

addItem

POST

firewall

group

delItem

$uuid

GET

firewall

group

get

GET

firewall

group

getItem

$uuid=null

POST

firewall

group

reconfigure

*

firewall

group

searchItem

POST

firewall

group

set

POST

firewall

group

setItem

$uuid

<<uses>>

model Group.xml

Resources (NptController.php) – extends : FilterBaseController

Method

Module

Controller

Command

Parameters

POST

firewall

npt

addRule

POST

firewall

npt

delRule

$uuid

GET

firewall

npt

getRule

$uuid=null

*

firewall

npt

searchRule

POST

firewall

npt

setRule

$uuid

POST

firewall

npt

toggleRule

$uuid,$enabled=null

Resources (OneToOneController.php) – extends : FilterBaseController

Method

Module

Controller

Command

Parameters

POST

firewall

one_to_one

addRule

POST

firewall

one_to_one

delRule

$uuid

GET

firewall

one_to_one

getRule

$uuid=null

*

firewall

one_to_one

searchRule

POST

firewall

one_to_one

setRule

$uuid

POST

firewall

one_to_one

toggleRule

$uuid,$enabled=null

Resources (SourceNatController.php) – extends : FilterBaseController

Method

Module

Controller

Command

Parameters

POST

firewall

source_nat

addRule

POST

firewall

source_nat

delRule

$uuid

GET

firewall

source_nat

getRule

$uuid=null

*

firewall

source_nat

searchRule

POST

firewall

source_nat

setRule

$uuid

POST

firewall

source_nat

toggleRule

$uuid,$enabled=null

Concept

The firewall plugin injects rules in the standard OPNsense firewall while maintaining visibility on them in the standard user interface.

We use our standard ApiMutableModelControllerBase to allow crud operations on rule entries and offer a set of specific actions to apply the new configuration. Since firewall rules can be quite sensitive with a higher risk of lockout, we also support a rollback mechanism here, which offers the ability to rollback this components changes.

The diagram above contains the basic steps to change rules, apply and eventually rollback if not being able to access the machine again. When calling savepoint() a new config revision will be created and the timestamp will be returned for later use. If the cancelRollback(savepoint) is not called within 60 seconds, the firewall will rollback to the previous state identified by the savepoint timestamp (if available).

Note

The examples in this document disable certificate validation, make sure when using this in a production environment to remove the verify=False from the requests calls

Tip

The number of versions kept can be configured as “backup count” in System -> Configuration -> History. This affectively determines within how many configuration changes you can still rollback, if the backup is removed, a rollback will keep the current state (do nothing).

Administration example

Administrative endpoints are pretty standard use of ApiMutableModelControllerBase, the example below searches for a rule named “OPNsense_fw_api_testrule_1”, when not found one will be added otherwise it will print the internal uuid. Inline you will find a brief description of the steps performed.

administrative_example.py
 1#!/usr/bin/env python3.7
 2import requests
 3import json
 4
 5# key + secret from downloaded apikey.txt
 6api_key="3RhWOno+HwvtmT406I6zw8of8J6n9FOKlWK6U0B+K7stt/fDaJg7bjeF3QAshlScYqC+3o5THy3vQViW"
 7api_secret="uaBk27NKhQCZSDpfAlG6YJ473MzvsCNiED6kzbYuykzU05fCRkcJADhDm5nxbZt8yREC74ZpvD/vbcEx"
 8
 9# define the basics, hostname to use and description used to identify our test rule
10rule_description='OPNsense_fw_api_testrule_1'
11remote_uri="https://192.168.1.1"
12
13# search for rule
14r = requests.get(
15    "%s/api/firewall/filter/searchRule?current=1&rowCount=7&searchPhrase=%s" % (
16        remote_uri, rule_description
17    ),
18    auth=(api_key, api_secret), verify=False
19)
20
21if r.status_code == 200:
22    response = json.loads(r.text)
23    if len(response['rows']) == 0:
24        # create a new rule, identified by rule_description allowing traffic from
25        # 192.168.0.0/24 to 10.0.0.0/24 using TCP protocol
26        data = {"rule" :
27                    {
28                    "description": rule_description,
29                    "source_net": "192.168.0.0/24",
30                    "protocol": "TCP",
31                    "destination_net": "10.0.0.0/24"
32                    }
33                }
34        r = requests.post(
35            "%s/api/firewall/filter/addRule" % remote_uri, auth=(api_key, api_secret), verify=False, json=data
36        )
37        if r.status_code == 200:
38            print("created : %s" % json.loads(r.text)['uuid'])
39        else:
40            print("error : %s" % r.text)
41
42    else:
43        for row in response['rows']:
44            print ("found uuid %s" % row['uuid'])

Tip

Since our model contains default values for most attributes, we only need to feed the changes if we would like to keep the defaults. In this case the TCP/IP version was IPv4 by default for example. In most cases one would like to set all relevant properties in case defaults change over time.

Apply / revert example

This example will disable the rule created in the previous example and apply the changes using a savepoint, since we’re not calling cancelRollback(savepoint) it will revert after 60 seconds to the original state.

savepoint_example.py
 1#!/usr/bin/env python3.7
 2import requests
 3import json
 4
 5# key + secret from downloaded apikey.txt
 6api_key="3RhWOno+HwvtmT406I6zw8of8J6n9FOKlWK6U0B+K7stt/fDaJg7bjeF3QAshlScYqC+3o5THy3vQViW"
 7api_secret="uaBk27NKhQCZSDpfAlG6YJ473MzvsCNiED6kzbYuykzU05fCRkcJADhDm5nxbZt8yREC74ZpvD/vbcEx"
 8
 9# define the basics, hostname to use and description used to identify our test rule
10rule_description='OPNsense_fw_api_testrule_1'
11remote_uri="https://192.168.1.1"
12
13# search for rule
14r = requests.get(
15    "%s/api/firewall/filter/searchRule?current=1&rowCount=7&searchPhrase=%s" % (
16        remote_uri, rule_description
17    ),
18    auth=(api_key, api_secret), verify=False
19)
20
21if r.status_code == 200:
22    response = json.loads(r.text)
23    if len(response['rows']) > 0:
24        rule_uuid = response['rows'][0]['uuid']
25        r = requests.post("%s/api/firewall/filter/savepoint" % remote_uri, auth=(api_key, api_secret), verify=False)
26        if r.status_code == 200:
27            sp_response = json.loads(r.text)
28            # disable rule
29            r = requests.post("%s/api/firewall/filter/toggleRule/%s/0" % (remote_uri, rule_uuid),
30                              auth=(api_key, api_secret), verify=False
31            )
32            # apply changes, revert to sp_response['revision'] after 60 seconds
33            r = requests.post("%s/api/firewall/filter/apply/%s" % (remote_uri, sp_response['revision']),
34                              auth=(api_key, api_secret), verify=False
35            )
36            print("revert to revision %s in 60 seconds (%s changed)" % (sp_response['revision'], rule_uuid))
37    else:
38        print("rule %s not found" % rule_description)

Note

The savepoint will only revert this components changes, other changes won’t be affected by this revert, for example add an additional interface between savepoint and revert won’t be affected.