Skip to content

Intercept Configuration REST API

Shane Alcock edited this page Aug 12, 2024 · 24 revisions

This page documents the REST-like API that can be used to add, modify or remove active interceptions within a running instance of OpenLI.

There is now a simple web UI available that uses this REST API for intercept configuration. More details on how to install and use the web UI can be found on this wiki page.

From OpenLI 1.0.6, it will be possible to configure the REST API to require user authentication via either Digest-Auth or an API key. See the REST API authentication wiki page for more details on how to enable this feature.

Intercept Configuration Service

By default, the OpenLI provisioner will listen on TCP port 8992 on all interfaces for requests against the REST API. You can change this by setting the updateaddr and updateport configuration options in the provisioner configuration file. See the Provisioner documentation for more details.

The service itself is implemented using libmicrohttpd.

The REST API can be used to add or modify the following provisioner configuration options:

  • IP intercepts (including UMTS / mobile intercepts)
  • VOIP intercepts
  • Email intercepts (from v1.1.0 onwards)
  • IP addresses and port numbers for "core" servers (such as SIP servers, RADIUS servers or GTP servers).
  • Law Enforcement Agencies
  • Default RADIUS usernames
  • Other options, including:
    • The default method for handling compressed email content

The running intercept configuration is stored in a file on disk, which will be updated after each REST API call has completed. Note that manual edits to this file will not take effect unless the provisioner is restarted (or receives a SIGHUP). Any manual edits will also be overwritten if the REST API is used to modify the running intercept without either restarting the provisioner or telling it to reload its configuration with a SIGHUP.

Security and access control for the REST API socket is the responsibility of the OpenLI user. We plan to add more security features (e.g. authentication) eventually, but we strongly recommend the use of access controls to prevent unwanted hosts from making connections to the REST API socket.

HTTP vs HTTPS

(only applies from OpenLI 1.0.5 onwards)

If the OpenLI provisioner is configured to use TLS to encrypt its communications with the other components, then the update socket will only accept connections that are using HTTPS. HTTP is only available if TLS is disabled entirely (but you really should be using TLS for all OpenLI components anyway).

If you are using a self-signed certificate for OpenLI TLS, then the client that you use to send requests to the update socket may require access to the certificate for the CA that you used to sign the certificate on the provisioner. For example, requests made using curl over HTTPS to a provisioner with a self-signed certificate will fail by default, if you do not explicitly provide the CA certificate to curl as well.

For curl, you can resolve this by adding the --cacert option to your curl command, e.g.

 curl --cacert /etc/openli/openli-ca-crt.pem -X DELETE https://10.100.100.1:9001/ipintercept/EXAMPLE1

You also make sure that your provisioner certificate has been created with a CN that matches the hostname / IP of the interface that your update socket will be listening on. In the above example, that means the certificate must have a CN of 10.100.100.1, but ideally you would assign a proper hostname (e.g provisioner-openli.mynetwork.net) to the provisioner host and use that as a CN when creating the provisioner certificate. See the OpenLI TLS documentation for more information about creating certificates.

Using POST to add configuration

New intercept configuration may be added to the running provisioner by using an HTTP POST to send a JSON object describing the new configuration item to the appropriate URL. Depending on the item being configured (intercept vs agency vs core server), some fields in the JSON object may be optional (in which case OpenLI will set a reasonable default value), but others will be mandatory and the request will fail if those fields are missing.

The following tables list the fields that can appear in the JSON object being POSTed for each of the configuration objects that the REST API supports. More detail on the exact meaning of each of the fields can be found in the provisioner documentation. Fields marked as "Key" are used to uniquely identify that object within the configuration system -- this becomes important when you wish to modify or delete the object (see PUT and DELETE sections further below).


POSTs for IP intercepts should be sent to the URL http://host:port/ipintercept where "host" and "port" should be replaced with the IP and port number configured for your update socket. The following fields are supported for IP intercepts:

Field Comment
"liid" Mandatory, Key
"authcc" Mandatory
"delivcc" Mandatory
"agencyid" Mandatory
"mediator" Mandatory
"vendmirrorid" Optional
"user" Mandatory
"accesstype" Optional, defaults to "undefined"
"radiusident" Optional, defaults to no restriction
"staticips" Optional, List
"starttime" Added in v1.0.10, optional, must be a unix timestamp
"endtime" Added in v1.0.10, optional, must be a unix timestamp
"outputhandovers" Added in v1.1.0, optional, must be {0, 1, or 2}
"payloadencryption" Added in v1.1.1, optional, defaults to "none"
"encryptionkey" Added in v1.1.1, mandatory if payloadencryption is NOT "none"
"mobileident" Added in v1.1.6, only applies with accesstype is "mobile", defaults to "msisdn"

Static IPs are expressed as a list of JSON objects, each containing just two fields: iprange and sessionid. iprange should be expressed as an IP prefix (e.g. 192.168.0.0/16). sessionid is the CIN that should be assigned to any intercepted traffic from that IP range.

The vendmirrorid must be expressed as a decimal integer (as opposed to the hexadecimal format used in the running intercept config file). For example, if your Vendor Mirroring Session ID is 0x50, then you will need to provide the decimal equivalent (80) in your vendmirrorid field in the JSON object that you POST to the REST API socket.

starttime and endtime, if specified, will only intercept packets between the time boundaries given by these fields. By default, each is set to 0 -- an endtime of 0 means that the intercept will continue forever.

outputhandovers, if specified, can be used to designate an intercept to produce only IRIs, only CCs, or both. By default, both handovers are produced. For IRI only intercepts, set this value to 1. For CC only intercepts, set this value to 2. Setting it to 0 will result in both IRIs and CCs being emitted for this intercept.

payloadencryption, if specified, defines which encryption method should be used to encrypt the CC and IRI contents for this intercept. By default, no encryption is performed (i.e., the option is set to none). Do not encrypt an intercept unless specifically asked to by the requesting agency -- they will also provide the encryption key that you should use. Currently, OpenLI only supports the aes-192-cbc encryption method but other methods may be implemented in the future if required by agencies.

encryptionkey must be specified if payload encryption is being used. If the authorizing agency has requested payload encryption for an intercept, then they should also provide you with the desired encryption key. That key should be provided to OpenLI using this field. Note that keys which are shorter than 24 characters will be padded out to 24 characters with null bytes. Keys which are longer than 24 characters will be truncated.

mobileident should be specified if the intercept applies to a mobile data session. This field is used to tell OpenLI if the target identifier (i.e. the user field) refers to an MSISDN, IMSI, or IMEI value. If not specified, the identifer is assumed to be a MSISDN.


POSTs for VOIP intercepts should be sent to the URL http://host:port/voipintercept where "host" and "port" should be replaced with the IP and port number configured for your update socket. The following fields are supported for VOIP intercepts:

Field Comment
"liid" Mandatory, Key
"authcc" Mandatory
"delivcc" Mandatory
"agencyid" Mandatory
"mediator" Mandatory
"siptargets" Mandatory, List
"starttime" Added in v1.0.10, optional, must be a unix timestamp
"endtime" Added in v1.0.10, optional, must be a unix timestamp
"outputhandovers" Added in v1.1.0, optional, must be {0, 1, or 2}
"payloadencryption" Added in v1.1.1, optional, defaults to "none"
"encryptionkey" Added in v1.1.1, mandatory if payloadencryption is NOT "none"

SIP targets are expressed as a list of JSON objects, each containing just two fields: username and realm. realm is an optional field -- if not included, then the intercept applies to all SIP users with the given username, regardless of their realm.

starttime and endtime, if specified, will only intercept packets between the time boundaries given by these fields. By default, each is set to 0 -- an endtime of 0 means that the intercept will continue forever.

outputhandovers, if specified, can be used to designate an intercept to produce only IRIs, only CCs, or both. By default, both handovers are produced. For IRI only intercepts, set this value to 1. For CC only intercepts, set this value to 2. Setting it to 0 will result in both IRIs and CCs being emitted for this intercept.

payloadencryption, if specified, defines which encryption method should be used to encrypt the CC and IRI contents for this intercept. By default, no encryption is performed (i.e., the option is set to none). Do not encrypt an intercept unless specifically asked to by the requesting agency -- they will also provide the encryption key that you should use. Currently, OpenLI only supports the aes-192-cbc encryption method but other methods may be implemented in the future if required by agencies.

encryptionkey must be specified if payload encryption is being used. If the authorizing agency has requested payload encryption for an intercept, then they should also provide you with the desired encryption key. That key should be provided to OpenLI using this field. Note that keys which are shorter than 24 characters will be padded out to 24 characters with null bytes. Keys which are longer than 24 characters will be truncated.


POSTs for Email intercepts should be sent to the URL http://host:port/emailintercept where "host" and "port" should be replaced with the IP and port number configured for your update socket. The following fields are supported for Email intercepts:

Field Comment
"liid" Mandatory, Key
"authcc" Mandatory
"delivcc" Mandatory
"agencyid" Mandatory
"mediator" Mandatory
"targets" Mandatory, List
"starttime" optional, must be a unix timestamp
"endtime" optional, must be a unix timestamp
"outputhandovers" Added in v1.1.0, optional, must be {0, 1, or 2}
"payloadencryption" Added in v1.1.1, optional, defaults to "none"
"encryptionkey" Added in v1.1.1, mandatory if payloadencryption is NOT "none"
"delivercompressed" Added in v1.1.2, optional, can be either as-is, decompressed, or default, defaults to default

Email targets are expressed as a list of JSON objects, each containing just the one field: address. An address is the email address of the intercept target. Multiple email addresses are expressed as additional objects in the list.

Email interception is only available in OpenLI 1.1.0 onwards.

starttime and endtime, if specified, will only intercept packets between the time boundaries given by these fields. By default, each is set to 0 -- an endtime of 0 means that the intercept will continue forever.

outputhandovers, if specified, can be used to designate an intercept to produce only IRIs, only CCs, or both. By default, both handovers are produced. For IRI only intercepts, set this value to 1. For CC only intercepts, set this value to 2. Setting it to 0 will result in both IRIs and CCs being emitted for this intercept.

payloadencryption, if specified, defines which encryption method should be used to encrypt the CC and IRI contents for this intercept. By default, no encryption is performed (i.e., the option is set to none). Do not encrypt an intercept unless specifically asked to by the requesting agency -- they will also provide the encryption key that you should use. Currently, OpenLI only supports the aes-192-cbc encryption method but other methods may be implemented in the future if required by agencies.

encryptionkey must be specified if payload encryption is being used. If the authorizing agency has requested payload encryption for an intercept, then they should also provide you with the desired encryption key. That key should be provided to OpenLI using this field. Note that keys which are shorter than 24 characters will be padded out to 24 characters with null bytes. Keys which are longer than 24 characters will be truncated.

delivercompressed defines how compressed email messages and content (i.e. when the IMAP COMPRESS extension is used) should be delivered to the agency that requested the email intercept. If set to as-is, the compressed content is delivered in its original compressed form. If set to decompressed, the content is decompressed before being placed in a CC record. If set to default or not set at all, the approach defined by the email-defaultdelivercompressed option is used.


POSTs for agencies should be sent to the URL http://host:port/agency where "host" and "port" should be replaced with the IP and port number configured for your update socket. The following fields are supported for agencies:

Field Comment
"agencyid" Mandatory, Key
"agencycountrycode" Added in version 1.1.8, optional but highly recommended.
"hi2address" Mandatory
"hi3address" Mandatory
"hi2port" Mandatory
"hi3port" Mandatory
"keepalivefreq" Optional, defaults to 300 seconds
"keepalivewait" Optional, defaults to 30 seconds

The agencycountrycode should be a 2-letter ISO 3166 code that corresponds to the country where the agency has jurisdiction. Example country codes are NZ (New Zealand), NL (Netherlands), DE (Germany).


Other configuration objects that are supported by the REST API are described in the table below, including the corresponding URL to POST to when adding a new instance of an object:

Object URL Field Comment Added in Version
RADIUS Server http://host:port/radiusserver "ipaddress" Mandatory
"port" Optional
"port_lower" Optional v1.1.6
"port_upper" Optional v1.1.6
SIP Server http://host:port/sipserver "ipaddress" Mandatory
"port" Optional
"port_lower" Optional v1.1.6
"port_upper" Optional v1.1.6
GTP Server http://host:port/gtpserver "ipaddress" Mandatory
"port" Optional
"port_lower" Optional v1.1.6
"port_upper" Optional v1.1.6
SMTP Server http://host:port/smtpserver "ipaddress" Mandatory 1.1.0
"port" Optional
"port_lower" Optional v1.1.6
"port_upper" Optional v1.1.6
IMAP Server http://host:port/imapserver "ipaddress" Mandatory 1.1.0
"port" Optional
"port_lower" Optional v1.1.6
"port_upper" Optional v1.1.6
POP3 Server http://host:port/pop3server "ipaddress" Mandatory 1.1.0
"port" Optional
"port_lower" Optional v1.1.6
"port_upper" Optional v1.1.6
Default RADIUS Username http://host:port/defaultradius "username" Mandatory
Default email compression encoding http://host:port/options "email-defaultdelivercompressed" Optional v1.1.2

Some core "server" types support the port_lower and port_upper fields. These fields allow you to express a range of ports where the server is potentially operating, i.e. a port_lower of 5050 and a port_upper of 5060 would match any traffic for that IP address on any port between 5050 and 5060 inclusive. You can continue to use the port field instead for servers that only listen on a single port. It is strongly recommended that you specify at least one of the port, port_lower or port_upper fields when adding a new core server to OpenLI.

Note that, prior to version 1.1.6, port was a mandatory field for all core server configurations.

Examples

The following examples use curl to POST JSON objects to an OpenLI configuration REST API listening on 10.100.100.1:9001. Assumes that we have a running mediator (ID: 6001).

Adding a LEA called "police", with default keepalive policy:

     curl -X POST -H "Content-Type: application/json" -d '{"agencyid": "police", "hi2address": "192.168.100.1", "hi2port": "12345", "hi3address": "192.168.100.1", "hi3port": "12346", "agencycountrycode": "AU"}' http://10.100.100.1:9001/agency

Adding a standard IP intercept for a target username "roger":

     curl -X POST -H "Content-Type: application/json" -d '{"liid": "EXAMPLE1", "authcc": "NZ", "delivcc": "NZ", "agencyid": "police", "mediator": "6001", "user": "roger", "accesstype": "fibre"}' http://10.100.100.1:9001/ipintercept

Adding an IP intercept for a target user called "benny", using static IPs:

     curl -X POST -H "Content-Type: application/json" -d '{"liid": "EXAMPLE2", "authcc": "NZ", "delivcc": "NZ", "agencyid": "police", "mediator": "6001", "user": "benny", "accesstype": "LAN", "staticips": [ {"iprange": "6.7.8.9/32", "sessionid": "11223"}, {"iprange": "2001:1234:5678:9abc::1/64", "sessionid": "11223"} ] }' http://10.100.100.1:9001/ipintercept

Adding a VOIP intercept for a target "steve@myrealm.com":

     curl -X POST -H "Content-Type: application/json" -d '{"liid": "EXAMPLE3", "authcc": "NZ", "delivcc": "NZ", "agencyid": "police", "mediator": "6001", "siptargets": [ {"username": "steve", "realm": "myrealm.com"} ] }' http://10.100.100.1:9001/voipintercept

Adding an email intercept for a target "jim@example.org":

     curl -X POST -H "Content-Type: application/json" -d '{"liid": "EXAMPLE4", "authcc": "NZ", "delivcc": "NZ", "agencyid": "police", "mediator": "6001", "targets": [ {"address": "jim@example.org"} ] }' http://10.100.100.1:9001/emailintercept

Adding 192.168.250.100:5060 as a SIP server:

    curl -X POST -H "Content-Type: application/json" -d '{"ipaddress": "192.168.250.100", "port": "5060"}' http://10.100.100.1:9001/sipserver

Adding 10.250.100.1:1845 and 10.250.100.1:1846 as a RADIUS server:

    curl -X POST -H "Content-Type: application/json" -d '{"ipaddress": "10.250.100.1", "port_lower": "1845", "port_upper": "1846"}' http://10.100.100.1:9001/radiusserver

Adding "customer@myisp.com" as a default RADIUS username:

    curl -X POST -H "Content-Type: application/json" -d '{"username": "customer@myisp.com"}' http://10.100.100.1:9001/defaultradius

Using DELETE to remove configuration

Intercepts and Agencies

Intercepts (both VOIP and IP) and agencies can be removed by sending an HTTP DELETE to the appropriate URL, where the path portion of the URL takes the format:

   :objecttype/:key

where :objecttype is one of voipintercept | ipintercept | agency and :key is the value of the "Key" field for that object type (as described in the POST section above). For intercepts, the key is the LIID. For agencies, the key is the agency ID.

For example, to remove an IP intercept which has an LIID of EXAMPLE1, we could do the following:

    curl -X DELETE http://10.100.100.1:9001/ipintercept/EXAMPLE1

Core Servers

Core servers (SIP, RADIUS, GTP, SMTP, IMAP, POP3) can be removed in a similar manner, but the key in this case takes on a slightly different format (note the dash between the IP and the port):

   :objecttype/:ipaddr-:port

For example, removing a SIP server on 192.168.250.100:5060:

   curl -X DELETE http://10.100.100.1:9001/sipserver/192.168.250.100-5060

Default RADIUS usernames

Default RADIUS usernames are also simple to remove; the key for a RADIUS username is the username itself. For example:

   curl -X DELETE http://10.100.100.1:9001/defaultradius/customer@myisp.com

Using PUT to modify configuration

Intercepts and Agencies

To modify any of the parameters of an existing intercept or agency (other than its key), you can use the HTTP PUT method to send a JSON object to the update socket containing the new field values that you would like OpenLI to adopt for that intercept or agency. The JSON object must include the Key field and that Key field must match an existing intercept or agency.

Any other unchanged fields do not need to be included in your JSON object; just the fields that are changing. One exception: if you are modifying fields that are expressed as lists, like staticips and siptargets, you will need to include all items that you want to remain in the list after modification.

The URL that you send your request to is constructed using the same rules as when sending a POST request. For example, if we had made an error when configuring the intercept for "benny" and wanted to change the IPv4 address from 6.7.8.9/32 to 6.7.8.99/32, then we would do the following:

   curl -X PUT -H "Content-Type: application/json" -d '{"liid": "EXAMPLE2", "staticips": [ {"iprange": "6.7.8.99/32", "sessionid": "11223"}, {"iprange": "2001:1234:5678:9abc::1/64", "sessionid": "11223"} ] }' http://10.100.100.1:9001/ipintercept

Three key things to note in the above example:

  • The LIID field (i.e. the Key) is present in the JSON object, so OpenLI knows which intercept to modify.
  • We've changed only the IPv4 static IP, but our list includes the IPv6 one as well. If we had left it out, OpenLI would have assumed that we wanted to remove it from the static IP list for this intercept.
  • All other fields are not modified, so they can be safely left out. There is no harm in including them, though, if we had wanted to.

Core Servers and Default RADIUS usernames

OpenLI does not support the modification of these objects using a PUT request. If you wish to modify a core server or RADIUS username, simply delete it and then use a POST to add it again with the correct parameters.

Using GET to browse configuration

The running intercept configuration can be requested using an HTTP GET request to an appropriate URL. As always, you should make sure that only authorised users can send GET requests to the REST API socket, so as to prevent unauthorised persons from browsing your list of running intercepts.

Responses to GET requests are in the JSON format, either as a list of objects or a single object (depending on the request that was made).

Intercepts and Agencies

For IP intercepts, VOIP intercepts and agencies, the REST API can be used to either request a list of all configured entities of that type or to request just the configuration for a specific intercept / agency.

All configured entities can be queried by sending a GET request to the following URLs:

Object URL
IP intercept http://host:port/ipintercept/
VOIP intercept http://host:port/voipintercept/
Email intercept http://host:port/emailintercept/
Agency http://host:port/agency/

To get the configuration for a specific intercept / agency, use the same URL with the LIID or Agency ID of the request target appended after the trailing slash. For example:

curl -X GET http://10.100.100.1:9001/ipintercept/EXAMPLE1

curl -X GET http://10.100.100.1:9001/agency/police

Core Servers and Default RADIUS usernames

Requesting the list of core servers (RADIUS, SIP, GTP etc.) and default RADIUS usernames works in much the same way as with intercepts and agencies. The difference is that you can only request the full set of servers or usernames using the base URL; requesting individual servers or usernames is not supported using the REST API.

Object URL
RADIUS servers http://host:port/radiusserver/
SIP servers http://host:port/sipserver/
GTP servers http://host:port/gtpserver/
SMTP servers http://host:port/smtpserver/
IMAP servers http://host:port/imapserver/
POP3 servers http://host:port/pop3server/
Default RADIUS usernames http://host:port/defaultradius/

Other options

The values for other configuration options that do not have their own API endpoint can be viewed by fetching the following URL: http://host:port/options

A curl example:

curl -X GET http://10.100.100.1:9001/options

The JSON object returned from this request will be a dictionary, where the keys are the option names (e.g. email-defaultdelivercompressed) and the values are the value assigned to that option (e.g. as-is).

Determine the OpenLI software version

In v1.1.2, an endpoint was added to allow users to ask the OpenLI provisioner which version it is running. This can be useful for determining whether a particular API endpoint or field is available.

To access this endpoint, send a GET request to the URL: http://host:port/openliversion.

The returned JSON object will contain the following fields:

Field Name Description Notes
fullversion The entire version string (e.g. "1.2.3")
major The major version number (e.g. 1 )
minor The minor version number (e.g. 2 )
release The release version number (e.g. 3)
Clone this wiki locally