As I look and play with loose_route functionality it seems that by simply placing a route: proxyip;lr header in my invite I can bypass any and all security otherwise built into the configuration. Is this the way everyone has it? I have been unable to find any configuration examples online that show how to secure/restrict access to loose_route?
Ideas or suggestions? Thanks, Eric
Eric,
On 04/10/2011 08:09 PM, Eric Hiller wrote:
As I look and play with loose_route functionality it seems that by simply placing a route: proxyip;lr header in my invite I can bypass any and all security otherwise built into the configuration. Is this the way everyone has it? I have been unable to find any configuration examples online that show how to secure/restrict access to loose_route?
You are quite correct, but this concern is overplayed because ultimate security responsibility is incumbent upon the UAS; you have to remember, Kamailio's still a proxy, and proxies just pass messages. The loose-routed sequential request does not somehow gain ipso facto authenticity simply by virtue of having been relayed by a proxy. A spoofed request will be invalidated by the UAS the same way as any request sent to it directly.
You could digest-challenge sequential requests (with proxy_authorize() and proxy_challenge()), and some people choose to do that as a matter of security policy. There is, however, often conceptual reluctance to challenge requests such as BYE; it seems like there could be some drawbacks to not passing along a call hangup just because digest authentication fails. This is a contested matter.
Another approach is to check if the message belongs to a known (tracked) dialog, if you are using the dialog module:
http://www.kamailio.org/docs/modules/3.1.x/modules_k/dialog.html#id2966270
I actually submitted the patch that implemented is_known_dlg() out of the very same concerns that you have.
In practical terms, however, to spoof a sequential message successfully, the sender would have to provide the right Call-ID, To tag, and branch ID at least. Failure to provide any of these correctly down to the letter should result in the UAS rejecting the request.
So, the only big deal that I can see with having a proxy relay these messages willingly is that it could become a vector for some sort of DDoS attack, but to work, the attack is reliant on the coincidence of an awful lot of factors. In practice, it's not that big of a deal for most installations.
Hi Eric!
Am 11.04.2011 02:09, schrieb Eric Hiller:
As I look and play with loose_route functionality it seems that by simply placing a route: proxyip;lr header in my invite I can bypass any and all security otherwise built into the configuration.
True!
Is this the way everyone has it?
Hopefully not!
I have been unable to find any configuration examples online that show how to secure/restrict access to loose_route?
The default configuration of Kamailio 3.1 is save. (I think the default configurations of older Openser releases were unsafe)
The basic principle is: allow loose routing only for in-dialog requests and make sure that the UAS (the node where Kamailio forwards the request) rejects in-dilaog requests to unknown dialog (if you use Asterisk make sure to have pendantic=yes).
Thus: Check for to-tag. This is how you can differ out-of-dialog requests from in-dialog requests. Only if the to-tag is present, call loose_route(). If the to-tag is not present, then do not call loose_route and reject the request or handle it according the local routing policies.
regards Klaus
11 apr 2011 kl. 09.25 skrev Klaus Darilion:
Hi Eric!
Am 11.04.2011 02:09, schrieb Eric Hiller:
As I look and play with loose_route functionality it seems that by simply placing a route: proxyip;lr header in my invite I can bypass any and all security otherwise built into the configuration.
True!
Is this the way everyone has it?
Hopefully not!
I have been unable to find any configuration examples online that show how to secure/restrict access to loose_route?
The default configuration of Kamailio 3.1 is save. (I think the default configurations of older Openser releases were unsafe)
The basic principle is: allow loose routing only for in-dialog requests and make sure that the UAS (the node where Kamailio forwards the request) rejects in-dilaog requests to unknown dialog (if you use Asterisk make sure to have pendantic=yes).
Thus: Check for to-tag. This is how you can differ out-of-dialog requests from in-dialog requests. Only if the to-tag is present, call loose_route(). If the to-tag is not present, then do not call loose_route and reject the request or handle it according the local routing policies.
It's harder when routing outbound. You don't want to be a reflector used in a DDOS attack. YOu either limit who can use your kamailio by authorization or keep some kind of dialog state.
/O
On 04/11/2011 03:25 AM, Klaus Darilion wrote:
Thus: Check for to-tag. This is how you can differ out-of-dialog requests from in-dialog requests. Only if the to-tag is present, call loose_route().
I suppose in principle the problem here is that has_totag() only checks if there is *a* To-tag, not whether it is a valid To-tag associated with a known dialog.
Am 11.04.2011 10:17, schrieb Alex Balashov:
On 04/11/2011 03:25 AM, Klaus Darilion wrote:
Thus: Check for to-tag. This is how you can differ out-of-dialog requests from in-dialog requests. Only if the to-tag is present, call loose_route().
I suppose in principle the problem here is that has_totag() only checks if there is *a* To-tag, not whether it is a valid To-tag associated with a known dialog.
Yes, that's the disadvantage of a transaction-only stateful proxy.
Takeing a look at the previous problems with dialog module, and the recent problems, I prefer to not use dialog module even in the case someone my abuse my proxy as reflector. ;-)
regards Klaus
On Apr 11, 2011, at 6:23 AM, Klaus Darilion klaus.mailinglists@pernau.at wrote:
Takeing a look at the previous problems with dialog module, and the recent problems, I prefer to not use dialog module even in the case someone my abuse my proxy as reflector. ;-)
Out of curiosity, to which problems info you refer? What have I missed lately? :)
Alex Balashov writes:
Takeing a look at the previous problems with dialog module, and the recent problems, I prefer to not use dialog module even in the case someone my abuse my proxy as reflector. ;-)
Out of curiosity, to which problems info you refer? What have I missed lately? :)
there is a theory that past number of bugs in a program strongly correlates with number of remaining bugs. just wait a few weeks and something new pops up.
-- juha
Hello,
On 4/11/11 12:23 PM, Klaus Darilion wrote:
Am 11.04.2011 10:17, schrieb Alex Balashov:
On 04/11/2011 03:25 AM, Klaus Darilion wrote:
Thus: Check for to-tag. This is how you can differ out-of-dialog requests from in-dialog requests. Only if the to-tag is present, call loose_route().
I suppose in principle the problem here is that has_totag() only checks if there is *a* To-tag, not whether it is a valid To-tag associated with a known dialog.
Yes, that's the disadvantage of a transaction-only stateful proxy.
Takeing a look at the previous problems with dialog module, and the recent problems, I prefer to not use dialog module even in the case someone my abuse my proxy as reflector. ;-)
first, skipping authentication for within dialog requests in default configuration file comes mainly from the early years when not many sip endpoints supported that. But can be done, of course and perhaps it should be enabled (or at least added as a #!define option).
We all know that Kamailio has a programable configuration file, the default one is given to address most common (and basic) needs and be a reliable starting point to add more actions to it, but surely can be improved a lot in terms of security and features. For example, one can tighten the checks by allowing traffic/calls only from registered endpoints (checking source IP and port using $ulc(...)) and from trusted peers. When allowing traffic from external untrusted networks, then for sure you have to analyze and add more security checks.
In Debian-like OS-es, kamailio does not start by default when it is installed from packages -- people have to edit the defaults file for it, making in this way sure that the admins at least know they started the service -- hopefully, also they understand what the config is doing.
To ship kamailio with most secure config it would be very easy, here it is that one:
route { exit; }
Then let the people build from this one so they are fully aware of what they add there :-) ...
Regarding dialog states, it is not really needed to use dialog module, I use a lot htable for this purpose -- using call-id and the tags to build the keys, you can track lot of attributes, as you need, e.g., the IP addresses, auth state, a.s.o.
Cheers, Daniel
o Daniel-Constantin Mierla on 04/11/2011 12:53 PM:
Regarding dialog states, it is not really needed to use dialog module, I use a lot htable for this purpose -- using call-id and the tags to build the keys, you can track lot of attributes, as you need, e.g., the IP addresses, auth state, a.s.o.
what about load balancing and fail-over, do you replicate that state to the other proxy instances?
stefan
On 4/11/11 1:06 PM, Stefan Sayer wrote:
o Daniel-Constantin Mierla on 04/11/2011 12:53 PM:
Regarding dialog states, it is not really needed to use dialog module, I use a lot htable for this purpose -- using call-id and the tags to build the keys, you can track lot of attributes, as you need, e.g., the IP addresses, auth state, a.s.o.
what about load balancing and fail-over, do you replicate that state to the other proxy instances?
The load balancing is not affected, since there is record-routing taking care of routing to the right proxy. For failover purposes, you can use memcached module instead of htable, use db can be used to states or replicate at SIP level using uac_req_send().
Cheers, Daniel
2011/4/11 Daniel-Constantin Mierla miconda@gmail.com:
first, skipping authentication for within dialog requests in default configuration file comes mainly from the early years when not many sip endpoints supported that. But can be done, of course and perhaps it should be enabled (or at least added as a #!define option)
I don't think that is a good option. It would break lot of scenarios:
- An incoming INVITEl with RURI sip:alice@domain.org and To URI sip:200@domain.org arrives to Kamailio which does lookup and routes the call to alice.
- The call is established.
- Later alice sends a REFER or a re-INVITE. Note that the request would contain "From: sip:200@domain.org" (even if the AoR of alice us "sip:alice@domain.org". This is because From/To URI are usually unchanged whithin a dialog.
- Kamailio ask for authentication to such REFER or re-INVITE.
- alice's device adds "Proxy-Authorization: Digest username="alice", .....".
- If Kamailio does "check_from" the request would be rejected (as "alice" doesn't match "200").
Iñaki Baz Castillo writes:
- Later alice sends a REFER or a re-INVITE. Note that the request
would contain "From: sip:200@domain.org" (even if the AoR of alice us "sip:alice@domain.org". This is because From/To URI are usually unchanged whithin a dialog.
inaki,
refer would contain header
Referred-By: sip:alice@domain.org
which k would use for Proxy-Authorization.
-- juha
2011/4/16 Juha Heinanen jh@tutpro.com:
- Later alice sends a REFER or a re-INVITE. Note that the request
would contain "From: sip:200@domain.org" (even if the AoR of alice us "sip:alice@domain.org". This is because From/To URI are usually unchanged whithin a dialog.
inaki,
refer would contain header
Referred-By: sip:alice@domain.org
which k would use for Proxy-Authorization.
Hi Juha, Referred-By header is not part of REFER specification but an extension (RFC 3892) and it's not mandatory:
2.1. Referrer Behavior
A UA sending a REFER request (a referrer) MAY provide a Referred-By header field value in the request.
Iñaki Baz Castillo writes:
Hi Juha, Referred-By header is not part of REFER specification but an extension (RFC 3892) and it's not mandatory:
2.1. Referrer Behavior
A UA sending a REFER request (a referrer) MAY provide a Referred-By header field value in the request.
if refer does not contain referred-by header, then there is no other choice than to refuse it. otherwise (unless you keep call state) you don't have any chance to know who sent the refer and what rights the sender might have.
-- juha
2011/4/17 Juha Heinanen jh@tutpro.com:
if refer does not contain referred-by header, then there is no other choice than to refuse it. otherwise (unless you keep call state) you don't have any chance to know who sent the refer and what rights the sender might have.
Keeping call state within a proxy is not reliable, even using dialog module. The proxy doesn't check that the RURI of an in-dialog Request matches the remote target of the existing dialog, neither matches the Route values in the in-dialog request.
Anyhow I don't think the proxy should do all this stuf.
Depending on our topology we can just ask for authentication for every in-dialog request (unless it comes from a trusted node as a PSTN gw) but without trying to check the identity of the in-dialog request originator. Well, the identity is asserted by the proxy after authentication success. During an in-dialog request it doesn't matter the From/To URI value (this is not true in an initial INVITE in which
From is usually used for accounting and CLI.
Iñaki Baz Castillo writes:
Depending on our topology we can just ask for authentication for every in-dialog request (unless it comes from a trusted node as a PSTN gw) but without trying to check the identity of the in-dialog request originator. Well, the identity is asserted by the proxy after authentication success. During an in-dialog request it doesn't matter the From/To URI value (this is not true in an initial INVITE in which From is usually used for accounting and CLI.
inaki,
lets say that a sip ua has dialog established with pstn gw and the sip ua sends refer to pstn gateway for the purpose of transferring the call to another pstn destination. in that case, referred-by uri is used for accounting of the new pstn leg.
-- juha
2011/4/17 Juha Heinanen jh@tutpro.com:
lets say that a sip ua has dialog established with pstn gw and the sip ua sends refer to pstn gateway for the purpose of transferring the call to another pstn destination. in that case, referred-by uri is used for accounting of the new pstn leg.
I've never seen a PSTN gw properly handling a REFER, neither I think a PSTN gw should handle it (but a B2BUA/PBX) between the UA and the PSTN gw(s).
The REFER with "Referred-by" headers tells the receipt of such REFER to generate an INVITE with destination indicated in "Refer-To" header and mirroring the "Referred-By" header (so the UAS receiving the INVITE knows that it arrives from user in From header but is a transfer from user in "Referred-By").
Honestly I can imagine how a PSTN gw is supposed to assert the value of "Referred-By". Perhaps it just allows the REFER if it contains a Referred-By matching the From URI header?
Cheers.
Iñaki Baz Castillo writes:
I've never seen a PSTN gw properly handling a REFER, neither I think a PSTN gw should handle it (but a B2BUA/PBX) between the UA and the PSTN gw(s).
i don't see any problem if gw charges the call based on referred-by that proxy has verified. i think that even cisco ios gws with rather current software can do that.
Honestly I can imagine how a PSTN gw is supposed to assert the value of "Referred-By". Perhaps it just allows the REFER if it contains a Referred-By matching the From URI header?
gw does not assert the refer. it is the proxy that does that. gw simply generates a call to pstn and places the number in referred-by header to the charged party field of isdn or isup message. exactly the same as it does with diversion header, which has worked fine forever.
-- juha
Iñaki Baz Castillo writes:
I've never seen a PSTN gw properly handling a REFER, neither I think a PSTN gw should handle it (but a B2BUA/PBX) between the UA and the PSTN gw(s).
inaki,
your suggestion would mean that proxy would need to route every call between sip ua and pstn gw via a b2bua, because you cannot know in advance, if refer will be used or not.
-- juha
2011/4/17 Juha Heinanen jh@tutpro.com:
Iñaki Baz Castillo writes:
I've never seen a PSTN gw properly handling a REFER, neither I think a PSTN gw should handle it (but a B2BUA/PBX) between the UA and the PSTN gw(s).
inaki,
your suggestion would mean that proxy would need to route every call between sip ua and pstn gw via a b2bua, because you cannot know in advance, if refer will be used or not.
Yes. But IMHO this is typicall in any PBX environment in which users have short extensions (200, 201...) and the PSTN gws are not aware of them.
Iñaki Baz Castillo writes:
Yes. But IMHO this is typicall in any PBX environment in which users have short extensions (200, 201...) and the PSTN gws are not aware of them.
you certainly don't need b2bua in order to map short extension numbers to e.164 numbers. that is very easy to handle in sr and i have been doing it for years.
-- juha
Am 17.04.2011 13:54, schrieb Juha Heinanen:
Iñaki Baz Castillo writes:
Depending on our topology we can just ask for authentication for every in-dialog request (unless it comes from a trusted node as a PSTN gw) but without trying to check the identity of the in-dialog request originator. Well, the identity is asserted by the proxy after authentication success. During an in-dialog request it doesn't matter the From/To URI value (this is not true in an initial INVITE in which From is usually used for accounting and CLI.
inaki,
lets say that a sip ua has dialog established with pstn gw and the sip ua sends refer to pstn gateway for the purpose of transferring the call to another pstn destination. in that case, referred-by uri is used for accounting of the new pstn leg.
I use Asterisk as AS/GW and I do not trust Refered-By (especially within Asterisk it is not authenticated thus it can contain anything) - I use the peer information in Asterisk internally for accounting.
Of course it should be safe to use Refered-By header if you requires authentication and check auth-user with Refered-By. (maybe i should add this to my proxy :)
regards klaus
Klaus Darilion writes:
Takeing a look at the previous problems with dialog module, and the recent problems, I prefer to not use dialog module even in the case someone my abuse my proxy as reflector. ;-)
i agree. dialog modules in sip-router and opensips have always had lots of problems and bugs due to complexity of the issue.
-- juha
On Monday 11 April 2011, Klaus Darilion wrote:
Am 11.04.2011 10:17, schrieb Alex Balashov:
On 04/11/2011 03:25 AM, Klaus Darilion wrote:
Thus: Check for to-tag. This is how you can differ out-of-dialog requests from in-dialog requests. Only if the to-tag is present, call loose_route().
I suppose in principle the problem here is that has_totag() only checks if there is *a* To-tag, not whether it is a valid To-tag associated with a known dialog.
Yes, that's the disadvantage of a transaction-only stateful proxy.
Takeing a look at the previous problems with dialog module, and the recent problems, I prefer to not use dialog module even in the case someone my abuse my proxy as reflector. ;-)
Hi Klaus,
sure, there are issues. But we're using the dialog module since now since some time in our production setup and it works fine for this particular feature set.
Cheers,
Henning
On 04/11/2011 01:10 PM, Henning Westerholt wrote:
Hi Klaus,
sure, there are issues. But we're using the dialog module since now since some time in our production setup and it works fine for this particular feature set.
Oh, yeah. I'm a happy and extensive long-time user of the dialog module too.
I think what I am going to do is use a combination of:
1. Whitelist my gateway IPs.
2. Any initial INVITES from non-gateway IPs will be authorized and the dialog be added to a simple htable based on callid
3. Any in-dialog will do a lookup on the htable so that authorization isn't required on bye and the like.
Does this seem a reasonable course of action?
One question, what is the best way to whitelist a few (3) gateways? I'd rather not do if($si == "ip1" || $si == "ip2" || $si == "ip3"){ Is there any sort of if(in_array($si,"whitelist")){ functionality or a way to iterate through an array of whitelisted ips? (I do not want to configure database support if possible)
Thanks for the help so far! -Eric
Date: Mon, 11 Apr 2011 13:18:10 -0400 From: abalashov@evaristesys.com To: sr-users@lists.sip-router.org Subject: Re: [SR-Users] loose_route security
On 04/11/2011 01:10 PM, Henning Westerholt wrote:
Hi Klaus,
sure, there are issues. But we're using the dialog module since now since some time in our production setup and it works fine for this particular feature set.
Oh, yeah. I'm a happy and extensive long-time user of the dialog module too.
-- Alex Balashov - Principal Evariste Systems LLC 260 Peachtree Street NW Suite 2200 Atlanta, GA 30303 Tel: +1-678-954-0670 Fax: +1-404-961-1892 Web: http://www.evaristesys.com/
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
On Monday 11 April 2011, Eric Hiller wrote:
I think what I am going to do is use a combination of:
Whitelist my gateway IPs.
Any initial INVITES from non-gateway IPs will be authorized and the
dialog be added to a simple htable based on callid
- Any in-dialog will do a lookup on the htable so that authorization isn't
required on bye and the like.
Does this seem a reasonable course of action?
Hi Eric,
sounds fine.
One question, what is the best way to whitelist a few (3) gateways? I'd rather not do if($si == "ip1" || $si == "ip2" || $si == "ip3"){ Is there any sort of if(in_array($si,"whitelist")){ functionality or a way to iterate through an array of whitelisted ips? (I do not want to configure database support if possible)
If your gateways are in one subnet, you could just specify a network in the configuration, like this: $si == 192.168.1.1/26
Cheers,
Henning