-
Notifications
You must be signed in to change notification settings - Fork 26
OpenLI Tutorial 11: Configuring a VoIP Intercept
You may either watch the tutorial lesson on YouTube by clicking on the image above, or you can download the slides and read them alongside the transcript provided below.
Welcome back -- it is now time for the eleventh lesson in the OpenLI training series. Today, I’m going to show you how to configure a VoIP intercept using the OpenLI training lab, but before we do that I’m going to first talk a little bit about the specifics of VoIP intercepts and how they occur. This will ensure that you have a full understanding of what information you will need to successfully configure and perform a VoIP intercept.
The interception of VoIP traffic is more or less the equivalent of a traditional wire tap on a telephone service, but more suitable for the modern digital age where nobody actually has an analog telephone any more. It is entirely possible that an LEA may only ever require you to intercept VoIP calls, assuming that you provide VoIP as a service.
When you are asked to perform a VoIP intercept, then only data communications related to the VoIP service can be intercepted -- all other traffic must be ignored. Specifically, you will need to intercept traffic for the SIP, RTP and RTMP protocols, and you may be required to intercept not just audio but also any accompanying video streams as well.
The key protocol that underpins VoIP is the Session Initiation Protocol, which we have been referring to throughout this training series as SIP. The messages sent using this protocol orchestrate and control each VoIP call that takes place on your network.
What this means in practice is that we can parse the SIP traffic that is observed on your network and use it to derive key information about a VoIP call that is about to take place. Some of the more useful details include the identity of the caller, the identity of the person that they are calling, the IP addresses that will be used by each participant for the call and the UDP ports that each endpoint will use for sending the audio streams.
With that information at hand, we have everything we need to intercept the call itself without inadvertently intercepting any unrelated traffic.
Identity is a very important concept in lawful interception -- if you do not know the identity of the participants of a voice call, how can you know whether you should intercept it?
SIP typically expresses an identity using a term structured as a username followed by an ‘at’ symbol followed by a realm.
Usernames can take various forms, depending on how you have configured your VoIP service. In some networks, the username may be a conventional user string that is (hopefully) somewhat descriptive of the user’s real world identity. In other VoIP networks, the username portion of the identity might be their assigned phone number or some other unique identity number.
The definition for a realm can also vary between networks. Some operators use their network domain name as the realm, but I have also seen cases where the realm is simply the IP address of the SIP server.
As we shall see, it is going to be important for you to be able to derive the SIP identity for a user based on whatever limited information that the agency may provide on the warrant. The agency may request an interception based on the user’s real world name, or their phone number, and you will need to be able to translate that into a username@realm SIP identity.
Another important aspect of interception is being able to demarcate separate calls during the interception process. Fortunately, your SIP software should assign each VoIP call a unique Call-ID that will be present in each SIP message resulting from that call.
OpenLI, and other ETSI compliant interception systems, will leverage that information to ensure that each intercepted packet belonging to the same Call-ID will also be assigned the same communication identity number (or CIN) in the resulting intercept records. Note that the IRIs and CCs for the same call must both share the same CIN, so that they can be associated together by the receiving agency.
Every SIP message sent or received by an intercept target must be passed on to the requesting agency as IRI records over HI2. This includes not only the messages that are used to establish and manage a call, but also the indirect messages that are used to maintain the target as part of the overall voice network, such as REGISTER and OPTIONS messages.
Therefore it is crucial that you mirror all SIP traffic into your OpenLI collectors -- don’t try to be clever and filter out traffic that you may think is just noise. The LEAs still expect to receive IRI records for that traffic.
Ok, so with that in mind, let’s start looking at configuring a VoIP intercept using the training lab.
Here’s the scenario that we are going to work through: we are the operators of a network called example.com.
On this network, we are running a single SIP server. The server is located at the IP address 10.100.50.65 and it is listening on port 5060 for SIP traffic from our network users.
And now we have just received a VoIP intercept warrant asking us to intercept all voice traffic for the user with the phone number 12345678910.
So let’s make this intercept happen!
The first thing that we’ll need to do is to tell OpenLI about our SIP server, so that the collector has a way of picking out SIP traffic from the packets that it observes on the capture interface.
In a real deployment, you would have configured your SIP servers in OpenLI as soon as you had the deployment up and running, rather than waiting for a warrant to arrive from an agency. But since this is a tutorial exercise set in a lab environment, we’re going to do the SIP server and VoIP intercept configuration back to back.
SIP server configuration is performed using the REST API, in much the same way that we configured our mock agency in the previous lesson. To add a new SIP server to OpenLI, you need to send a POST request containing the SIP server details (as a JSON object) to the URL shown on the slide.
The JSON object that describes a SIP server is very simple. There are only two properties that you have to provide: the IP address and the port number that the server is listening on.
Fortunately, we already know these details from the scenario description a couple of slides back so we can easily construct the JSON object for our POST request.
And once again, we can use curl to send our POST request to the update service that is running on the provisioner.
This curl command should be fairly easy to comprehend by now, and the expected response should also be quite familiar.
If you check the logs on your OpenLI collector, you should see that the collector is now aware that 10.100.50.65, port 5060 is a SIP server and to treat all packets to and from that server as SIP traffic.
Of course, we can also use the REST API to tell OpenLI to forget about a configured SIP server. To do this, simply send a DELETE request to the REST API service with the path sipserver / SIP IP address - SIP port number.
Please pay careful attention to the hyphen that is separating the IP address from the port number in the example URL -- sometimes you may end up accidentally typing a colon here instead if you’re not paying attention, but that will not work. You must use a hyphen.
As I alluded to earlier, our collector will now be treating any captured traffic using the IP address and port that we specified in our POST request as SIP traffic. This applies to traffic using both the TCP and UDP protocols, as some operators prefer to use TCP for SIP over the more conventional UDP.
Internally, any SIP traffic captured by the collector is redirected to a separate software thread where it will be parsed to extract any relevant call identities, RTP stream details or state changes. If the SIP traffic does not belong to an active intercept target, then it will be immediately discarded. Otherwise it will be used to either create or update the status of any ongoing call that the target may be participating in.
As OpenLI relies on the information in the SIP messages to identify and follow calls made by interception targets, it is absolutely essential that OpenLI collectors can both capture and recognise the SIP traffic for your VoIP network.
For new users (and even experienced ones!) forgetting to tell OpenLI about your SIP servers is a common cause of failed VoIP intercepts.
So that’s the first step completed. Now we can use the REST API to start a new VoIP intercept, using the same principles as before.
Once again, we are going to send a POST request containing a JSON object that describes the intercept parameters. This time, we are going to send the request to the URL at ‘/voipintercept’.
The JSON object for a VoIP intercept is somewhat more complex than what we had to send to describe a SIP server, so we’re going to go through this a bit more carefully.
The first property is the LIID, which will be provided to you by the agency requesting the intercept. Each intercept should have a unique LIID, and this is what the agency software will use to keep the records from this VoIP intercept separate from any others that they may receive at the same time.
The next two properties are the authorization country code and the delivery country code. These are the ISO ALPHA 2 country codes for the jurisdiction where the intercept was authorized and where the intercept is going to be delivered to, respectively.
In most cases, these two codes will be the same -- that is, the country where the intercept was authorized is also the country where the recipient agency is located -- but the ETSI standard does allow for multi-national cooperation between law enforcement agencies.
The agency requesting the intercept should be able to provide you with the necessary values for these properties, and operators that only have a presence in one country will seldom need to use anything other than their own country code.
For the training lab exercise, the values do not matter too much so feel free to put in your own local country code -- in my example on the slide, I’ve used the country code for New Zealand.
The next property specifies the mediator that we intend to use to deliver the intercept to the requesting agency.
In this case, the value must match the mediator ID that we set when we configured our mediator back in lesson 8, which was 1. If you set your mediator ID to something else, then you’ll need to use that same number here.
Of course, if you have multiple mediators in your eventual deployment, then you would want to put the ID number of the mediator that you intend to use for this intercept in here.
Next, we have the agencyid property which we use to specify which agency will be the recipient of the IRIs and CCs that result from this intercept.
The value for this property must match the agencyid property that was set when the agency was added using the REST API. For instance, in the previous lesson, we created a mock agency using the ID of “mocklea”, so that is what we must use here to ensure that our intercept is delivered to that agency.
The OpenLI REST API allows you to specify a specific start and end time for an interception using the “starttime” and “endtime” properties, respectively. In some jurisdictions, intercept warrants will have specific time ranges that they apply for, and interception must not occur outside of the time period that the warrant has been authorized for.
Within our JSON object, the values for the time properties are expressed as Unix timestamps to avoid any confusion with relation to time zones or daylight savings time. There are many tools available to convert between a conventional date and time and a Unix timestamp.
A value of zero for the starttime can be used when the intercept is to begin immediately. Setting the endtime to zero will cause the intercept to continue until it is explicitly withdrawn via a DELETE request.
The last property required for a new VoIP intercept is the identity of the target, which is defined using the ‘siptargets’ property. Because a target may have multiple identities, or an interception warrant could in theory apply to multiple targets, ‘siptargets’ must be expressed as a JSON list (even if you only have one target identity).
Each target identity must be expressed as a JSON object within the ‘siptargets’ list, and the identity object itself supports two properties.
The first property, which is mandatory, is the username portion of the target’s SIP identity. As we discussed earlier, this might be a user string like ‘john.smith’ or it might be the target’s phone number.
Depending on how the target is specified on the warrant for the VoIP intercept, you may need to do a little work to figure out the username for the target in your voice network. For example, consider a case where the warrant may only have the target’s real name on it, but your voice network uses phone numbers as user IDs. It will be your responsibility as an operator to map the target’s name to their phone number so that you can use it as a username in a JSON object to create the corresponding intercept.
In our training scenario, we’ve already figured out that our intercept target has the username ‘12345678910’ so that is what we use here as our ‘username’ property.
The second property is the realm, which allows you to specify the realm portion of the target user’s identity. The realm property is optional. If not specified, then all voice traffic for a user with the matching username will be intercepted, regardless of their realm.
In situations where you only have one realm, or there are no shared usernames across multiple realms then you can skip the ‘realm’ property, as the username alone should be sufficient to identify the target in SIP.
Now we can put all of that together into yet another curl command which will this time add a new VoIP intercept to the OpenLI provisioner.
If your curl command is successful, you should be able to inspect the collector logs and see that there are messages acknowledging that the collector is now aware that it needs to perform a voice intercept for our specified target.
Note the asterisk in the place of the realm field in the target identity on the second log line -- this indicates that all realms will be considered when looking for SIP traffic for the target.
The other OpenLI components will also produce useful log messages to indicate that they, too, have been made aware of the new VoIP intercept.
Firstly, we see that the provisioner will log a message to indicate that the REST API service was used to add a new VoIP intercept with the LIID of TESTVOIP001.
And on the mediator there will be a log message stating that the intercept has been activated by the provisioner. This message also includes the agency ID of the intended recipient.
As with the other applications of the OpenLI REST API, you can use the PUT method to make changes to an existing VoIP intercept. There are just a few key specifics for you to remember when modifying an intercept this way.
Firstly, your JSON object must include the LIID of the intercept that you are modifying.
Second, if you are making changes to the SIP targets list, please make sure that you include all of the SIP target identities that you want to continue interception for. If a target was previously specified, but is not present in the list when you submit your PUT request then OpenLI will assume that you no longer want that identity to apply to the intercept.
However, any other unchanged fields can be safely excluded from the JSON object sent with the PUT request. You can even exclude the SIP targets list if you are not making any changes to the list at all -- in that one case, OpenLI will assume you want the list to remain unchanged.
You can use the DELETE method to forcibly withdraw an existing VoIP intercept. The DELETE request should be sent to the path ‘voipintercept’ followed by a slash, followed by the LIID of the intercept that you wish to remove.
Finally, the GET method will allow you to retrieve the details of a particular VoIP intercept, or you may also ask for the details of all known VoIP intercepts.
At this stage, it would be prudent for me to remind you once again that this is NOT an API that you want accessible to anyone outside of the few employees that manage your interception system.
That is all we have time for in this particular lesson.
We’ve made further progress towards being able to perform our first interception -- we’ve successfully used the REST API to provide OpenLI with the details for a VoIP intercept.
There’s just one missing piece remaining: we need to get the traffic for a VoIP call involving our intercept target into our OpenLI collector. In our next lesson, I will demonstrate how we can do that, as well as show you what the resulting intercept records will look like.
Until then, take care and I will hopefully see you again soon!