
Domain Policy Module

Otmar Lendl

Klaus Darilion

Edited by

Otmar Lendl

Klaus Darilion

   Copyright © 2002, 2003, 2006 Juha Heinanen, Otmar Lendl, Klaus
   Darilion
     _________________________________________________________

   Table of Contents
   1. User's Guide

        1.1. Overview
        1.2. Dependencies
        1.3. Exported Parameters

              1.3.1. db_url (string)
              1.3.2. dp_table (string)
              1.3.3. dp_col_rule (string)
              1.3.4. dp_col_type (string)
              1.3.5. dp_col_att (string)
              1.3.6. dp_col_val (string)
              1.3.7. port_override_avp (string)
              1.3.8. transport_override_avp (string)
              1.3.9. domain_replacement_avp (string)
              1.3.10. domain_prefix_avp (string)
              1.3.11. domain_suffix_avp (string)
              1.3.12. send_socket_avp (string)

        1.4. Exported Functions

              1.4.1. dp_can_connect()
              1.4.2. dp_apply_policy()

        1.5. FIFO Commands
        1.6. Usage Scenarios

              1.6.1. TLS Based Federation
              1.6.2. SIP Hub based Federation
              1.6.3. Walled Garden Federation

        1.7. Known Limitations

   2. Developer's Guide
   3. Frequently Asked Questions

   List of Examples
   1-1. Setting db_url parameter
   1-2. Setting dp_table parameter
   1-3. Setting dp_col_rule parameter
   1-4. Setting dp_col_rule parameter
   1-5. Setting dp_col_att parameter
   1-6. Setting dp_col_val parameter
   1-7. Setting port_override_avp parameter
   1-8. Setting transport_override_avp parameter
   1-9. Setting domain_replacement_avp parameter
   1-10. Setting domain_prefix_avp parameter
   1-11. Setting domain_suffix_avp parameter
   1-12. Setting send_socket_avp parameter
   1-13. dp_can_connect usage
   1-14. dp_apply_policy usage
     _________________________________________________________

Chapter 1. User's Guide

1.1. Overview

   The Domain Policy module implements
   draft-lendl-domain-policy-ddds-02 in combination with
   draft-lendl-speermint-federations-02 and
   draft-lendl-speermint-technical-policy-00. These drafts define
   DNS records with which a domain can announce its federation
   memberships. A local database can be used to map policy rules
   to routing policy decisions. This database can also contain
   rules concerning destination domains independently of
   draft-lendl-domain-policy-ddds-02.

   This module requires a database. No caching is implemented.
     _________________________________________________________

1.2. Dependencies

   The module depends on the following modules (in the other
   words the listed modules must be loaded before this module):

     * database -- Any database module
     _________________________________________________________

1.3. Exported Parameters

1.3.1. db_url (string)

   This is URL of the database to be used.

   Default value is
   "mysql://openserro:openserro@localhost/openser"

   Example 1-1. Setting db_url parameter
modparam("domainpolicy", "db_url", "postgresql://openserro:pass@db_host
/openser")
     _________________________________________________________

1.3.2. dp_table (string)

   Name of table containing the local support domain policy
   setup.

   Default value is "domainpolicy".

   Example 1-2. Setting dp_table parameter
modparam("domainpolicy", "dp_table", "supportedpolicies")
     _________________________________________________________

1.3.3. dp_col_rule (string)

   Name of column containing the domain policy rule name which is
   equal to the URI as published in the domain policy NAPTRs.

   Default value is "rule".

   Example 1-3. Setting dp_col_rule parameter
modparam("domainpolicy", "dp_col_rule", "rules")
     _________________________________________________________

1.3.4. dp_col_type (string)

   Name of column containing the domain policy rule type. In the
   case of federation names, this is "fed". For standard
   referrals according to
   draft-lendl-speermint-technical-policy-00, this is "std". For
   direct domain lookups, this is "dom".

   Default value is "type".

   Example 1-4. Setting dp_col_rule parameter
modparam("domainpolicy", "dp_col_type", "type")
     _________________________________________________________

1.3.5. dp_col_att (string)

   Name of column containing the AVP's name. If the rule stored
   in this row triggers, than dp_can_connect() will add an AVP
   with that name.

   Default value is "att".

   Example 1-5. Setting dp_col_att parameter
modparam("domainpolicy", "dp_col_att", "attribute")
     _________________________________________________________

1.3.6. dp_col_val (string)

   Name of column containing the value for AVPs created by
   dp_can_connect().

   Default value is "val".

   Example 1-6. Setting dp_col_val parameter
modparam("domainpolicy", "dp_col_val", "values")
     _________________________________________________________

1.3.7. port_override_avp (string)

   This parameter defines the name of the AVP where
   dp_apply_policy() will look for an override port number.

   Default value is "portoverride".

   Example 1-7. Setting port_override_avp parameter
# string named AVP
modparam("domainpolicy", "port_override_avp", "portoverride")
     _________________________________________________________

1.3.8. transport_override_avp (string)

   Name of the AVP which contains the override transport setting.

   Default value is "transportoverride".

   Example 1-8. Setting transport_override_avp parameter
# string named AVP
modparam("domainpolicy", "transport_override_avp", "transportoverride")
     _________________________________________________________

1.3.9. domain_replacement_avp (string)

   Name of the AVP which contains a domain replacement.

   Default value is "domainreplacement".

   Example 1-9. Setting domain_replacement_avp parameter
# string named AVP
modparam("domainpolicy", "domain_replacement_avp", "domainreplacement")
     _________________________________________________________

1.3.10. domain_prefix_avp (string)

   Name of the AVP which contains a domain prefix.

   Default value is "domainprefix".

   Example 1-10. Setting domain_prefix_avp parameter
# string named AVP
modparam("domainpolicy", "domain_prefix_avp", "domainprefix")
     _________________________________________________________

1.3.11. domain_suffix_avp (string)

   Name of the AVP which contains a domain suffix.

   Default value is "domainsuffix".

   Example 1-11. Setting domain_suffix_avp parameter
# string named AVP
modparam("domainpolicy", "domain_suffix_avp", "domainsuffix")
     _________________________________________________________

1.3.12. send_socket_avp (string)

   Name of the AVP which contains a send_socket. The format of
   the send socket (the payload of this AVP) must be in the
   format [proto:]ip_address[:port]. The function dp_apply_policy
   will look for this AVP and if defined, it will force the send
   socket to its value (smilar to the force_send_socket core
   function).

   Default value is "sendsocket".

   Example 1-12. Setting send_socket_avp parameter
# string named AVP
modparam("domainpolicy", "send_socket_avp", "sendsocket")
     _________________________________________________________

1.4. Exported Functions

1.4.1. dp_can_connect()

   Checks the interconnection policy of the caller. It uses the
   domain in the request URI to perform the DP-DDDS algorithm
   according to draft-lendl-domain-policy-ddds-02 to retrieve the
   domain's policy announcements. As of this version, only
   records conforming to draft-lendl-speermint-federations-02 and
   draft-lendl-speermint-technical-policy-00 are supported.

   Non-terminal NAPTR records will cause recursion to the
   replacement domain. dp_can_connect() will thus look for policy
   rules in the referenced domain. Furthermore, an AVP for
   "domainreplacement" (containing the new domain) will be added
   to the call. This will redirect SRV/A record lookups to the
   new domain.

   In order to simplify direct domain-based peerings all
   destination domains are treated as if they contain a top
   priority "D2P+SIP:dom" rule with the domain itself as the
   value of the rule. Thus any database row with type = 'dom' and
   rule = 'example.com' will override any dynamic DNS-discovered
   rules.

   For NAPTRs with service-type "D2P+SIP:fed", the federation IDs
   (as extracted from the regexp field) are used to retrieve
   policy records from a local local database (basically: "SELECT
   dp_col_att, dp_col_val FROM dp_table WHERE dp_col_rule =
   '[federationID]' AND type = 'fed'). If records are found (and
   all other records with the same order value are fulfillable)
   then AVPs will be created from the dp_col_att and dp_col_val
   columns.

   For NAPTRs with service-type "D2P+SIP:std", the same procedure
   is performed. This time, the database lookup searched for type
   = 'std', though.

   "D2P+SIP:fed" and "D2P+SIP:std" can be mixed freely. If two
   rules with the same "order" match and try to set the same AVP,
   then the behaviour is undefined.

   The dp_col_att column specifies the AVP's name. If the AVP
   start with "s:" or "i:", the corresponding AVP type (string
   named or integer named) will be generated. If the excat
   specifier is omited, the AVP type will be guessed.

   The dp_col_val column will always be interpreted as string.
   Thus, the AVP's value is always string based.

   dp_can_connect returns:

     * -2: on errors during the evaluation. (DNS, DB, ...)
     * -1: D2P+SIP records were found, but the policy is not
       fullfillable.
     * 1: D2P+SIP records were found and a call is possible
     * 2: No D2P+SIP records were found. The destination domain
       does not announce a policy for incoming SIP calls.

   This function can be used from REQUEST_ROUTE.

   Example 1-13. dp_can_connect usage
...
dp_can_connect();
switch(retcode) {
        case -2:
                xlog("L_INFO","Errors during the DP evaluation\n");
                sl_send_reply("404", "We can't connect you.");
                break;
        case -1:
                xlog("L_INFO","We can't connect to that domain\n");
                sl_send_reply("404", "We can't connect you.");
                break;
        case 1:
                xlog("L_INFO","We found matching policy records\n");
                avp_print();
                dp_apply_policy();
                t_relay();
                break;
        case 2:
                xlog("L_INFO","No DP records found\n");
                t_relay();
                break;
}
...
     _________________________________________________________

1.4.2. dp_apply_policy()

   This function sets the destination URI according to the policy
   returned from the dp_can_connect() function. Parameter
   exchange between dp_can_connect() and dp_apply_policy() is
   done via AVPs. The AVPs can be configured in the module's
   parameter section.

   Note: The name of the AVPs must correspond with the names in
   the att column in the domainpolicy table.

   Setting the following AVPs in dp_can_connect() (or by any
   other means) cause the following actions in dp_apply_policy():

     * port_override_avp: If this AVP is set, the port in the
       destination URI is set to this port. Setting an override
       port disables NAPTR and SRV lookups according to RFC 3263.

     * transport_override_avp: If this AVP is set, the transport
       parameter in the destination URI is set to the specified
       transport ("udp", "tcp", "tls"). Setting an override
       transport also disables NAPTR lookups, but retains an SRV
       lookup according to RFC 3263.

     * domain_replacement_avp: If this AVP is set, the domain in
       the destination URI will be replaced by this domain.
       A non-terminal NAPTR and thus a referral to a new domain
       implicitly sets domain_replacement_avp to the new domain.

     * domain_prefix_avp: If this AVP is set, the domain in the
       destination URI will be prefixed with this "subdomain".
       E.g. if the domain in the request URI is "example.com" and
       the domain_prefix_avp contains "inbound", the domain in
       the destinaton URI is set to "inbound.example.com".

     * domain_suffix_avp: If this AVP is set, the domain in the
       destination URI will have the content of the AVP appended
       to it. E.g. if the domain in the request URI is
       "example.com" and the domain_suffix_avp contains
       "myroot.com", the domain in the destination URI is set to
       "example.com.myroot.com".

     * send_socket_avp: If this AVP is set, the sending socket
       will be forced to the socket in the AVP. The payload
       format of this AVP must be [proto:]ip_address[:port].

   If both prefix/suffix and domain replacements are used, then
   the replacement is performed first and the prefix/suffix are
   applied to the new domain.

   This function can be used from REQUEST_ROUTE.

   Example 1-14. dp_apply_policy usage
...
if (dp_apply_policy()) {
        t_relay();
}
...
     _________________________________________________________

1.5. FIFO Commands
     _________________________________________________________

1.6. Usage Scenarios

   This section describes how this module can be use to implement
   selective VoIP peerings.
     _________________________________________________________

1.6.1. TLS Based Federation

   This example shows how a secure peering fabric can be
   configured based on TLS and Domain Policies.

   Let's assume that an organization called "TLSFED.org" acts as
   an umbrella for VoIP providers who want to peer with each
   other but don't want to run open SIP proxies. TLSFED.org's
   secretary acts as an X.509 Certification Authority that signs
   the TLS keys of all member's SIP proxies. Each member should
   automatically allow incoming calls from other members. On the
   other hand, the configuration for this federation must not
   interfere with a member's participation in other VoIP peering
   fabrics. All this can be achieved by the following
   configuration for a participating VoIP operation called
   example.com:

     * Incoming SIP configuration
       Calls from other members are expected to use TLS and
       authenticate using a client-CERT. To implement this, we
       cannot share a TCP/TLS port with other incoming
       connection. Thus we need to use tls_server_domain[] to
       dedicate a TCP port for this federation.

tls_server_domain[1.2.3.4:5066] {
 tls_certificate   = "/path/to/tlsfed/example-com.key"
 tls_private_key   = "/path/to/tlsfed/example-com.crt"
 tls_ca_list       = "/path/to/tlsfed/ca.pem"
 tls_method        = tlsv1
 tls_verify_client = 1
 tls_require_cleint_certificate = 1
}

     * Outgoing SIP configuration
       Calls to other members also must use the proper client
       cert. Therefore, a TLS client domain must be configured.
       We use the federation name as TLS client domain
       identifier. Therefore, the content of the
       "tls_client_domain_avp" must be set to this identifier
       (e.g. by putting it as rule into the domainpolicy table).

tls_client_domain["tlsfed"] {
 tls_certificate   = "/path/to/tlsfed/example-com.key"
 tls_private_key   = "/path/to/tlsfed/example-com.crt"
 tls_ca_list       = "/path/to/tlsfed/ca.pem"
 tls_method        = tlsv1
 tls_verify_server = 1
}

     _________________________________________________________

1.6.2. SIP Hub based Federation

   This example shows how a peering fabric based on a central SIP
   hub can be configured.

   Let's assume that an organization called "HUBFED.org" acts as
   an umbrella for VoIP providers who want to peer with each
   other but don't want to run open SIP proxies. Instead,
   HUBFED.org operates a central SIP proxy which will relay calls
   between all participating members. Each member thus only needs
   to allow incoming calls from that central hub (which could be
   done by firewalling). All this can be achieved by the
   following configuration for a participating VoIP operation
   called example.com:

     * DNS configuration
       The destination network announces its membership in this
       federation.

$ORIGIN destination.example.org
@ IN NAPTR 10 50   "U"  "D2P+SIP:fed" (
                 "!^.*$!http://HUBFED.org/!" . )

     * Outgoing SIP configuration
       Calls to other members need to be redirected to the
       central proxy. The domainpolicy table just needs to list
       the federation and link it to the central proxy's domain
       name:

mysql> select * from domainpolicy;
+----+--------------------+------+-------------------+----------------+
| id | rule               | type | att               | val            |
+----+--------------------+------+-------------------+----------------+
| 1  | http://HUBFED.org/ | fed  | domainreplacement | sip.HUBFED.org |
+----+--------------------+------+-------------------+----------------+
     _________________________________________________________

1.6.3. Walled Garden Federation

   This example assumes that a set of SIP providers have
   established a secure Layer 3 network between their proxies. It
   does not matter whether this network is build by means of
   IPsec, a private Layer 2 network, or by simple firewalling. We
   will use the 10.x network (for the walled garden net) and
   "http://l3fed.org/" (as federation identifier) in this
   example.

   A member of this federation (e.g. example.com) can not
   announce its SIP proxy's 10.x address in the standard SRV / A
   records of his domain, as this address is only meaningful for
   other members of this federation. In order to facilite
   different IP address resolution paths within the federation
   vs. outside the federation, all members of "http://l3fed.org/"
   agree to prefix the destination domains with "l3fed" before
   the SRV (or A) lookup.

   Here is the configuration for example.com:

     * DNS configuration
       The destination network announces its membership in this
       federation.

$ORIGIN example.com
@ IN NAPTR 10 50   "U"  "D2P+SIP:fed" (
                 "!^.*$!http://l3fed.org/!" . )
_sip._udp      IN SRV 10 10 5060 publicsip.example.com.
_sip._udp.l3fe IN SRV 10 10 5060 l3fedsip.example.com.

publicsip      IN A   193.XXX.YYY.ZZZ
l3fedsip       IN A   10.0.0.42

     * Outgoing SIP configuration
       The domainpolicy table just needs to link the federation
       identifier to the agreed apon prefix:

mysql> select * from domainpolicy;
+----+-------------------+------+--------------+-------+
| id | rule              | type | att          | val   |
+----+-------------------+------+--------------+-------+
| 1  | http://l3fed.org/ | fed  | domainprefix | l3fed |
+----+-------------------+------+--------------+-------+
     _________________________________________________________

1.7. Known Limitations
     _________________________________________________________

Chapter 2. Developer's Guide

   The module does not provide any API to use in other OpenSER
   modules.
     _________________________________________________________

Chapter 3. Frequently Asked Questions

   3.1. Where can I find more about OpenSER?
   3.2. Where can I post a question about this module?
   3.3. How can I report a bug?

   3.1. Where can I find more about OpenSER?

   Take a look at http://openser.org/.

   3.2. Where can I post a question about this module?

   First at all check if your question was already answered on
   one of our mailing lists:

     * User Mailing List -
       http://openser.org/cgi-bin/mailman/listinfo/users
     * Developer Mailing List -
       http://openser.org/cgi-bin/mailman/listinfo/devel

   E-mails regarding any stable OpenSER release should be sent to
   <users@openser.org> and e-mails regarding development versions
   should be sent to <devel@openser.org>.

   If you want to keep the mail private, send it to
   <team@openser.org>.

   3.3. How can I report a bug?

   Please follow the guidelines provided at:
   http://sourceforge.net/tracker/?group_id=139143.
