5 # Applicability of this Configuration File
6 # ----------------------------------------
8 # This is default SER script as used for example at the iptel.org
9 # SIP service; it can deal with NATs, terminate calls to a PSTN
10 # gateway, and it implements a couple of basic signaling features
11 # (few types of call forwarding). In this scenario you may have
12 # multiple SIP proxies sharing one database for accessing provisioned
13 # data, which are maintained for example using serweb. The proxy
14 # servers also share write-access to user location database (and
15 # keeps a full cache of all usrloc entries synchronized using
18 # If you look for a simpler version with a lot less dependencies
19 # please refer to the ser-basic.cfg file in your SER distribution.
23 # running DB, running RTP proxy, one public IP address
24 # for SIP service, one private IP address for administrative purposes;
25 # optional: IP address of a PSTN gateway
29 # To get this config running you need to execute the following commands
30 # with the new serctl (the capital word are just place holders):
32 # $ ser_ctl domain add DOMAINNAME
33 # $ ser_ctl user add USERNAME@DOMAINNAME -p PASSWORD
35 # If you want to have P-Asserted-ID header for your user
37 # $ ser_attr add uid=UID asserted_id="PID"
39 # If you want to have (PSTN) gateway support:
41 # $ ser_db add attr_types name=gw_ip rich_type=string raw_type=2 \
42 # description="The gateway IP for the default ser.cfg" default_flags=33
43 # $ ser_attr add global gw_ip=GATEWAY-IP
45 # Alternatively, you can simple uncomment the relevant line in this file
46 # right at the beginning of the main route.
48 # You can also use serweb to set all the values above.
50 # Users with permission to call PSTN using this script must have
51 # the $gw_acl attribute set properly, and shall have $asserted_id
52 # set to indicate their caller-id for calls to PSTN. For inbound
53 # calls from PSTN, additional aliases may be also set.
57 # If this file is installed on Debian from package 'ser-oob' then some
58 # options in this configuration file may be set by post-installation
59 # script, according to values entered by user at installation time in
60 # debconf configuration. These values are then applied automatically to
61 # this file each time the 'ser-oob' package is upgraded or reconfigured by
62 # calling 'dpkg-reconfigure ser-oob'.
64 # The parts of this configuration file that may be altered by debconf are
65 # enclosed between '#DEBCONF-something-START' and '#DEBCONF-something-END'
66 # comment marks. Please do not remove them.
69 # TODO (Future possible improvements):
70 # ---------------------------------------
72 # - AVP-based diversion for call-forwarding (as opposed to specialized
74 # - add Date header in 200s to REGISTERs (to be packaged with NTP!)
80 # - Re-name all internal headers so that they start with a common prefix,
81 # such as P-SER and then wipe all such headers from requests received
82 # from untrusted sources, such as the user agents or foreign proxy
84 # * refined DB use (e.g., flatstore for acc)
86 # - dialog module for monitoring purposes
87 # - more extensive logging using xlog (controlled by gflags/gAVPs)
88 # * leveraging 2.1 features:
89 # - removal of private IP address (it takes a multicast-specific
90 # command which will allow OS to determine source IP address)
92 # * don't use exec (it takes domain.reload as script command)
93 # * compare last-stored timestamp with current timestamp (it takes
94 # assignment of gAVPs)
95 # * check multicast REGISTERs for their TTL (this is a simple and
96 # effective security check to prevent remote multicast messages
97 # to damage our traffic)
98 # - numerous fine-tuning parameters which are only available in 2.1
99 # (mlock_pages, dns_try_naptr, etc.)
100 # - better support for preloaded routes with domain name
102 # Security considerations:
103 # ------------------------
104 # The script has been tested against security leaks, but it comes
105 # under terms of GPL "as is" without any warranties; better check
107 # - IP based authentication of PSTN gateway and multicast REGISTERs
108 # is compliant to your network setup and security policy.
109 # - Multiple gateway IPs can't be provisioned as security checks
110 # are applied only to one.
114 # Copyright (C) 2005-2008 iptelorg GmbH
115 # This file is part of SER, a free SIP server. It is available under the
116 # terms of the GNU General Public License.
117 # Numerous folks have contributed to this file, including but not limited
118 # to Andrei, Jan, Jiri, Michal, Miklos, Nils.
121 # .... that's it, enough of yadiyada, here the real config begins!
124 # ----------- Global Configuration Parameters -------------------------------
126 #debug=3 # debug level (cmd line: -ddd)
127 #memdbg=10 # memory debug log level
128 #memlog=10 # memory statistics log level
129 #log_facility=LOG_LOCAL0 # the facility used for logging (see syslog(3))
131 #DEBCONF-SERVERID-START
133 #DEBCONF-SERVERID-END
135 # Uncomment these lines to enter debugging mode or start SER with
141 check_via=no # (cmd. line: -v)
142 dns=no # (cmd. line: -r)
143 rev_dns=no # (cmd. line: -R)
148 #disable_core=yes # disables core dumping
149 open_files_limit=20480 # sets the open file descriptors limit
150 #mhomed=yes # usefull for multihomed hosts, small performance
152 disable_tcp=no # be conservative about enabling TCP -- it can
153 # degrade performance a lot
154 #tcp_accept_aliases=yes # accepts the tcp alias via option
155 phone2tel=no # ignore user=phone in request-URIs -- otherwise
156 # these URIs would be interpreted as equivalent
157 # to TEL URIs, and their lookup would fail in URI
161 #DEBCONF-LISTEN-START
164 listen=224.0.1.75 # sip.mcast.net for REGISTER replication
165 # administrative interface -- needed for example for multicast source
167 #DEBCONF-LISTEN_ADMIN-START
169 #DEBCONF-LISTEN_ADMIN-END
171 #listen=tls:127.0.0.1:5061
177 # ------------------- DNS Parameters ----------------------------------------
178 # (see doc/dns.txt for more details)
184 dns_use_search_list=no
186 # dns cache & failover
190 dns_cache_negative_ttl=300
192 dns_cache_max_ttl=86400 # 1 day
193 dns_cache_mem=2048 # 2 MB
194 dns_cache_gc_interval=60 # garbage collection every minute
195 # ser 2.1 specific options
197 # dns_srv_lb=yes # srv based load balancing
198 # dns_udp_pref=3 # prefer udp (when resolving naptr record)
199 # dns_tcp_pref=2 # if no udp availbale accept tcp (for naptr)
200 # dns_tls_pref=-1 # ignore / don't accept tls (for naptr)
201 # dns_cache_delete_nonexpired=no
203 # ------------------- Blacklist Parameters ----------------------------------
204 # (see doc/dst_blacklist.txt for more details)
207 dst_blacklist_mem=1024 # 1 MB
208 dst_blacklist_expire=300 # blacklist default time
209 dst_blacklist_gc_interval=150 # 2.5 min
210 # for ser 2.1 to the above add tm blst_503* parameters and/or use the
211 # blst module (see NEWS)
213 # ------------------- TCP Parameters ----------------------------------------
214 # (see NEWS for more details)
215 tcp_connection_lifetime=3600
216 #tcp_max_connections=10240 # default is 2048
217 tcp_connect_timeout=1
219 # ------------------- TLS Parameters ----------------------------------------
221 # Enable TLS hooks so that the TLS module can be used
224 # -------------------- Custom Parameters ------------------------------------
225 # These parameters can be modified runtime via RPC interface,
226 # read the documentation of cfg_rpc module.
228 # Session Timer parameters, RFC 4028
230 # Default session interval used by the proxy if the UAC does not support
231 # session timer. Set it to "0" to disable session timer proxy support.
233 session_timer.default = "1800" desc "default session interval (in s)"
235 # Minimum session interval accepted by the proxy, it must not be less
238 session_timer.min_se = "90" desc "minimum session interval (in s)"
242 # Whether to enable or disable the rtp proxy. Possible values are:
243 # "0" -- always disable
244 # "1" -- always enable regardless of whether UAC or UAS is behind NAT
245 # "detect" -- detect whether the UAC or the UAS is behind NAT,
246 # and enable the rtp proxy when necessary
248 rtp_proxy.enable = "detect" desc "indicates whether the RTP Proxy is enabled or not (0/1/detect)"
250 # ------------------ Module Loading -----------------------------------------
252 loadpath "/usr/lib/ser/modules"
254 # load a SQL database for authentication, domains, user AVPs etc.
256 #loadmodule "postgres"
263 loadmodule "registrar"
278 loadmodule "nathelper"
280 loadmodule "speeddial"
288 # ----------------- Declaration of Script Flags -----------------------------
290 FLAG_ACC : 1, # the request will be recorded by ACC
291 FLAG_FAILUREROUTE : 2, # we are operating from the failure route
292 FLAG_NAT : 3, # the UAC is behind a NAT
293 FLAG_REPL_ENABLED : 4, # REGISTER replication is enabled if set
294 FLAG_TOTAG : 5, # request has a To tag
295 FLAG_PSTN_ALLOWED : 6, # the user is allowed to use the PSTN
296 FLAG_DONT_RM_CRED : 7, # do not remove the credentials
297 FLAG_AUTH_OK : 8, # authentication succeeded
298 FLAG_SERWEB_RSVD1 : 9, # bit reserved for use with serweb
299 FLAG_SERWEB_RSVD2 : 10, # bit reserved for use with serweb
300 FLAG_SESSIONTIMER : 11, # indicates that the UAC supports Session Timer
301 FLAG_RR_DONE : 12, # the request got already one RR header
302 FLAG_RTP_PROXY : 13; # the RTP proxy is turned on
305 dialog_cookie; # attribute will be stored in Route headers
307 # ----------------- Module-specific Parameters ------------------------------
309 # path to the database
312 modparam("speeddial|auth_db|usrloc|domain|uri_db|gflags|avp_db|db_ops",
313 "db_url", "mysql://ser:heslo@127.0.0.1/ser")
316 # specify the path to your database for accounting
317 #DEBCONF-DBURLACC-START
318 modparam("acc_db", "db_url", "mysql://ser:heslo@127.0.0.1/ser")
319 #DEBCONF-DBURLACC-END
324 # Database access mode: 0 -- memory cached, 1 -- write through,
325 # 2 -- delayed write. 1 is generally safer than 2. 2 can help
326 # to survive peaks in load. However, it creates delayed peaks that can
327 # impair request-processing latency later (usrloc would have to be
328 # re-redesigned more lock-free to avoid it).
329 #DEBCONF-DBMODE-START
330 modparam("usrloc", "db_mode", 1)
333 # Don't delete expired records from database on a per-contact basis -- that
334 # results in bulky DB operations and can lead to synchronization issues
335 # in server farm when for a time a server doesn't obtain re-reregistrations
336 modparam("usrloc","db_skip_delete",1)
341 # Maximum expires time. Forces users to re-register every 10 min.
342 modparam("registrar", "max_expires", 600)
344 # Minimum expires time. Even if they try, clients cannot register
345 # for a shorter time than this.
346 modparam("registrar", "min_expires", 240)
348 # Identify natted contacts using a flag.
349 modparam("registrar", "load_nat_flag", "FLAG_NAT")
350 modparam("registrar", "save_nat_flag", "FLAG_NAT")
352 # Maximum number of contacts.
353 modparam("registrar", "max_contacts", 10)
358 #modparam("auth_db", "calculate_ha1", yes)
359 #modparam("auth_db", "password_column", "password")
361 # Minimize replay-attack window.
362 modparam("auth", "nonce_expire", 10)
364 # Enable/disable extra authentication checks using the following modparams.
365 # The values are: 1 -- Request-URI, 2 -- Call-ID, 4 -- From tag,
366 # 8 -- source IP. The options are disabled by default.
368 # For REGISTER requests we hash the Request-URI, Call-ID, and source IP of the
369 # request into the nonce string. This ensures that the generated credentials
370 # cannot be used with another registrar, user agent with another source IP
371 # address or Call-ID. Note that user agents that change Call-ID with every
372 # REGISTER message will not be able to register if you enable this.
373 #modparam("auth", "auth_checks_register", 11)
375 # For dialog-establishing requests (such as the original INVITE, OPTIONS, etc)
376 # we hash the Request-URI and source IP. Hashing Call-ID and From tags takes
377 # some extra precaution, because these checks could render some UA unusable.
378 #modparam("auth", "auth_checks_no_dlg", 9)
380 # For mid-dialog requests, such as re-INVITE, we can hash source IP and
381 # Request-URI just like in the previous case. In addition to that we can hash
382 # Call-ID and From tag because these are fixed within a dialog and are
383 # guaranteed not to change. This settings effectively restrict the usage of
384 # generated credentials to a single user agent within a single dialog.
385 #modparam("auth", "auth_checks_in_dlg", 15)
387 # Deal with clients who can't do qop properly
388 modparam("auth", "qop", "")
389 #DEBCONF-AUTHSECRET-START
390 modparam("auth", "secret", "aqwedrftredswqwddcft")
391 #DEBCONF-AUTHSECRET-END
396 # Add value to lr param to make some broken UAs happy.
397 modparam("rr", "enable_full_lr", 1)
399 # Limit the length of the AVP cookie to necessary attributes only
400 modparam("rr", "cookie_filter", "(account|uac_nat|stimer)")
402 # You probably do not want that someone can simply read and change
403 # the AVP cookie in your Routes, thus should really change this
405 modparam("rr", "cookie_secret", "sgsatewgdbsnmpoiewh")
407 # The ftag Route parameter may be used to easily determine if a BYE
408 # is coming from caller or callee, but we prefer shorter messages
409 modparam("rr", "append_fromtag", 0)
414 # Load global attributes.
415 modparam("gflags", "load_global_attrs", 1)
420 # Load domain attributes.
421 modparam("domain", "load_domain_attrs", 1)
426 # By default, ctl listens on unixs:/tmp/ser_ctl if no other address is
427 # specified in modparams; this is also the default for sercmd.
428 modparam("ctl", "binrpc", "unixs:/tmp/ser_ctl")
429 # Listen on the "standard" fifo for backward compatibility.
430 modparam("ctl", "fifo", "fifo:/tmp/ser_fifo")
431 # Listen on tcp on localhost.
432 #modparam("ctl", "binrpc", "tcp:localhost:2046")
437 # Failed transactions (those with negative responses) should be logged, too.
438 modparam("acc_db", "failed_transactions", 1)
440 # If you don't want to have accounting entries written into the database,
441 # comment the next line out.
442 modparam("acc_db", "log_flag", "FLAG_ACC")
444 # if you would like to customize your CDRs, do it here....
445 #modparam("acc_db", "attrs",
446 # "$f.sop_billing_category,$f.isPrepaidCustomer,$f.sop_cf_orig_uid")
451 # Do not restart the resend timer with each reply. (See INBOUND route
453 modparam("tm", "restart_fr_on_each_reply", 0)
458 # Use a sub-route. This is a lot safer then relying on the request method
459 # to distinguish HTTP from SIP
460 #modparam("xmlrpc", "route", "RPC");
466 #DEBCONF-RTTPPROXY-START
467 modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:22222")
468 #DEBCONF-RTTPPROXY-END
470 # TCP keepalives as simple as CRLF
471 modparam("nathelper", "natping_crlf", 0)
473 # How often to send a NAT ping. Set this to 0 to turn NAT ping off.
474 #DEBCONF-NATPING_INTERVAL-START
475 modparam("nathelper", "natping_interval", 15)
476 #DEBCONF-NATPING_INTERVAL-END
478 # Only ping contacts that have the NAT flag set.
479 modparam("nathelper", "ping_nated_only", 1)
481 # Send an OPTIONS SIP request as NAT ping. If this is not set, a simple
482 # 4-byte ping is used.
483 modparam("nathelper", "natping_method", "OPTIONS")
485 # Temporary statefull natping test (only in future versions)
486 #modparam("nathelper", "natping_stateful", 1)
490 modparam("exec", "time_to_kill", 200);
491 modparam("exec", "setvars", 0);
495 # Register route ON_1MIN_TIMER to be called every minute.
496 modparam("timer", "declare_timer",
497 "ON_1MIN_TIMER=ON_1MIN_TIMER,60000,slow,enable");
500 #modparam("tls", "config", "tls.cfg");
504 modparam("db_ops", "declare_handle", "reload")
507 # ------------------------- Request Routing Logic --------------------------
509 # Main request route.
511 # Each request starts here.
515 # if you have a PSTN gateway just un-comment the follwoing line and
516 # specify the IP address of it to route calls to it.
519 # Alternatively (even better), set it as global persistent parameter
520 # using serweb or ser_attrs). If using a PSTN GW, per-subscriber
521 # options must ($gw_acl) or may (asserted_id) be set to enable calls
522 # to PSTN. If email-like URIs are used, having a URI alias for
523 # processing incoming PSTN-to-ip requests may be useful, too.
524 # Important: the script is assuming one global pstn-gw for all
525 # domains! Failure to allow gw_ip to be a domain-specic attribute
526 # would result in security gaps (onsend_route checks only for one
529 # First, do some initial sanity checks.
532 # Bypass the rest of the script for CANCELs if possible.
535 # Check if the request is routed via Route header.
541 # Answer OPTIONS requests to our system.
542 route(OPTIONS_REPLY);
544 # Enforce domain policy.
545 route(DOMAIN_POLICY);
547 # Handle REGISTER requests.
550 # From here on we want to know who is calling.
551 route(AUTHENTICATION);
553 # We are finished with all the precaution work -- let's
554 # try to locate the callee. The first route that matches
555 # "wins" and relays the request. If none matches, SER will
558 # Check if we should be outbound proxy for a local user.
561 # Redirect in case user dialed a speed dial entry.
564 # Place various site-specific routes here.
565 route(SITE_SPECIFIC);
567 # Check if the request is for a local user.
570 # There is SIP user for the called address. Before trying PSTN,
571 # you may have to convert the adress, for instance by using
575 # Last resort: if none of the previous route has found
576 # the recepient, try PSTN.
580 sl_reply("404", "No route matched");
583 # Forward a request to the destination set.
587 # If this is called from the failure route we need to add a new
589 if (isflagset(FLAG_FAILUREROUTE)) {
590 if (!append_branch()) {
591 t_reply("500", "Too many branches");
596 # If this is an initial INVITE (without a To-tag) we might try
597 # another target (call forwarding or voicemail) after receiving
599 if (method=="INVITE" && !@to.tag) {
600 t_on_failure("FAILURE_ROUTE");
603 # Always use the reply route to check for NATed UAS.
604 t_on_reply("REPLY_ROUTE");
606 # Insert a Record-Route header into all requests.
607 # This has to be done as one of the last steps to include all the
608 # RR cookies which might have been created during the script run.
611 # Activate the RTP proxy as the last step because it modifies the
615 # Remove credentials to keep requests shorter
616 if (isflagset(FLAG_AUTH_OK) && !isflagset(FLAG_DONT_RM_CRED) ) {
617 consume_credentials();
622 if (isflagset(FLAG_FAILUREROUTE)) {
623 # XXX This should be replaced with
624 # t_reply_error() similar to sl_reply_error()
625 # in order to return the proper failure code.
626 # Only, there is no such function yet.
627 t_reply("500", "Request cannot be forwarded");
637 # Perform initial checks on an incoming request.
639 # Rejects the request if it fails any of the checks.
643 # Messages with a Max-Forwards header of zero.
644 if (!mf_process_maxfwd_header("10")) {
645 sl_reply("483","Too Many Hops");
649 # Set flag for use in the onsend route
654 # Check if the UAC is NATed and fix the message accordingly
655 route(NAT_DETECTION);
657 # Activate accounting for all initial INVITEs. In-dialog requests
658 # are accounted by a RR cookie (see below).
659 if (method == "INVITE" && !@to.tag) {
663 # Set flag and use it instead of the attribute.
665 setflag(FLAG_REPL_ENABLED);
670 # Reply OPTIONS requests sent to the proxy itself.
674 # OPTIONS requests without a username in the Request-URI but one
675 # of our domains or IPs are addressed to the proxy itself and
676 # can be answered statelessly.
677 if (method == "OPTIONS" && !@ruri.user && (uri == myself || $t.did))
685 # Check if the sender of the request is behind a NAT device. If so,
686 # fix the request so that other devices can talk to the sender nonetheless.
690 # Lots of UAs do not include the rport parameter in there Via
691 # header, so we put it there regardless.
695 # Check if the request contains hints for a NATed UAC. Also, try to
696 # rewrite contacts using maddr. Using maddr is a really dubious
697 # technique and we better replace such with transport address.
698 # Downside: it fails for clients fronted by another server, in
699 # which case a valid contact we dislike because of maddr will be
700 # substituted inapproprietely (e.g., WM from other domains will
701 # fail). If you are worried about that, remove tests for maddr and
702 # recompile SER using HONOR_MADDR. Also note that rewriting
703 # contacts may possibly lead to client denying subseqent requests
704 # to them because they don't recognized fixed contacts as their
705 # own. Should you encounter such a case, a possible solution
706 # would be to store the original information as a contact parameter
707 # and restore it on its way back.
708 if (nat_uac_test("19")
709 || (@hf_value["contact"] && @contact.uri.params.maddr))
713 setavpflag($uac_nat, "dialog_cookie");
714 if (method == "REGISTER") {
715 # Prepare the Contact so that the registrar module
716 # saves the source address and port as well.
717 fix_nated_register();
720 # Overwrite the Contact to allow proper in-dialog
728 # Activates RTP proxy if necessary.
732 if (@cfg_get.rtp_proxy.enable == "0") {
733 # RTP Proxy is disabled
735 } else if (@cfg_get.rtp_proxy.enable == "detect") {
736 if (!isflagset(FLAG_NAT)) {
737 # If no NAT is involved we don't have to do here anything.
740 } else if (@cfg_get.rtp_proxy.enable != "1") {
741 # This is not a valid setting
742 xlog("L_ERR", "Unknown option for rtp_proxy.enable: %@cfg_get.rtp_proxy.enable\n");
744 } # else rtp proxy is permanently enabled
746 # If the message terminates a dialog turn RTP proxy off.
747 if (method == "BYE" || method == "CANCEL") {
749 append_hf("P-RTP-Proxy: UNFORCED\r\n");
753 # Turn the RTP proxy on for INVITEs and UPDATEs.
754 if (((method=="INVITE" || method == "UPDATE") && @msg.body)
755 && !isflagset(FLAG_RTP_PROXY))
757 force_rtp_proxy('r');
758 append_hf("P-RTP-Proxy: YES\r\n");
759 setflag(FLAG_RTP_PROXY);
764 # Handling of loose routed requests
766 # XXX Isn't the proper term "record routed"? This route also handles
767 # strict routed requests, doesn't it? -- martinh
770 # subsequent messages withing a dialog should take the
771 # path determined by the Route headers.
773 # Mark routing logic in request.
774 append_hf("P-hint: rr-enforced\r\n");
776 # If the Route contained the accounting AVP cookie we
777 # set the accounting flag for the acc_db module.
778 # This is more for demonstration purpose as this could
779 # also be solved without RR cookies.
780 # Note: this means all in-dialog request will show up in
781 # the accounting tables, so prepare your accounting software
783 if ($account == "yes") {
787 # Restore the NAT flag if present
792 # Restore Session Timer flag and headers.
793 if ($stimer && ($stimer != "0")) {
794 route(SESSION_TIMER);
797 # Some broken devices overide the dialog route set with the
798 # Record-Route headers from each in-dialog request. So, we
799 # better add Record-Route headers again. If we call
800 # record_route() after loose_route(), the AVP cookies are
801 # restored automatically. Additionally, there is a scenario
802 # where Record-Route headers are necessary if an initial
803 # SUBSCRIBE is forked.
805 # Note that here we forward before authentication checks
806 # are executed. Generally, we only authenticate
807 # out-of-dialog requests. Some in-dialog requests can't be
808 # authenticated at all, see the call-forwarding example in
817 # Add a Record-Route header
821 if (!isflagset(FLAG_RR_DONE) && method != "REGISTER") {
822 # We record-route all messages to make sure that
823 # subsequent messages will go through our proxy. This is
824 # particularly good if upstream and downstream entities
825 # use different transport protocols.
827 # If the ACC flag is set, store this in a Record-Route
828 # AVP cookie. This is more for demonstration purposes.
829 if (isflagset(FLAG_ACC)) {
831 setavpflag($account, "dialog_cookie");
834 # Insert the RR header.
837 # This flag allows to call this route several times
838 # without inserting several RR headers.
839 setflag(FLAG_RR_DONE);
844 # Look up the domains of the caller and the callee.
848 # Check whether the caller is from a local domain.
849 lookup_domain("$fd", "@from.uri.host");
851 # Check whether the callee is at a local domain
852 lookup_domain("$td", "@ruri.host");
856 # Check domain usage policies and reject illegal requests.
861 # If we don't know the domain of the caller nor the domain of the
862 # callee, somone tries to use our proxy as a relay. However, we
863 # can only apply this check out-of-dialog requests without a To
864 # tag. In some cases such as call-forwarding, subsequent requests
865 # may not include served domain neither as origination nor
866 # destination (a@A calls b@B who forwards to c@C. A BYE by c@C is
867 # then From b@B and To a@A. There is no mentioning of c@C despite
868 # legitimate behaviour of c@C).
869 if (!isflagset(FLAG_TOTAG) && !$t.did && !$f.did) {
870 sl_reply("403", "Relaying Forbidden");
880 # Process only REGISTERs here.
881 if (method != "REGISTER") {
885 # If this is a replica (sent to the multicast address), trust it to
886 # be secure and store it in usrloc
887 if (dst_ip==224.0.1.75) {
888 if (!isflagset(FLAG_REPL_ENABLED)) {
889 # Multicast replication administratively disabled.
894 # Read marker from master
895 if (search("^Repl-Marker: nated")) {
900 # If the replicating server added its own server id to the
901 # request, obtain the value and store it in an attribute.
902 # This is used by registrar.
903 $server_id = @msg.header["SER-Server-ID"];
905 # Assume URI in form of UID@mydomain and store contacts
906 # under this UID. Note that this only works if local policy
907 # causes UIDs to have form compliant to RFC3261 URI
909 $tu.uid = @ruri.user;
910 if (!save_mem_nr("location")) {
911 log(1, "Error while saving replicated REGISTER.\n");
916 # This is a REGISTER request received from the UA. Remove
917 # our internal header fields if they are present. The may
918 # have been added maliciously.
919 remove_hf("SER-Server-ID");
920 remove_hf("Repl-Marker");
923 # Check if the REGISTER if for one of our local domains.
925 sl_reply("403", "Register Forwarding Forbidden");
929 # The REGISTER target is in the To header, so reload the domain.
930 if (!lookup_domain("$td", "@to.uri.host")) {
931 sl_reply("404", "Unknown Domain");
935 # Useful for clients that ignore expires in 200 (OK). This is an
936 # attempt to keep them sticking to our value of 600.
937 append_to_reply("Expires: 600\r\n");
938 append_to_reply("Min-Expires: 240\r\n");
940 # We want only authenticated users to be registered.
941 if (!www_authenticate("$fd.digest_realm", "credentials")) {
943 sl_reply("500", "Internal Server Error");
946 sl_reply("400", "Bad Request");
949 if ($digest_challenge) {
950 append_to_reply("%$digest_challenge");
952 sl_reply("401", "Unauthorized");
957 # Check if the authenticated user is the same as the target user.
958 if (!lookup_user("$tu.uid", "@to.uri")) {
959 sl_reply("404", "Unknown user in To");
963 # the authentication ID does not match the ID in the To header
964 if ($f.uid != $t.uid) {
965 sl_reply("403", "Authentication and To-Header mismatch");
969 # Check if the authenticated user is the same as the request
970 # originator. You may uncomment it if you care, which URI is in
972 #if (!lookup_user("$fr.uid", "@from.uri")) {
973 # sl_reply("404", "Unknown user in From");
976 #if ($fu.uid != $fr.uid) {
977 # sl_reply("403", "Authentication and From-Header mismatch");
981 # Everything is fine. Store the binding.
982 if (!save_contacts("location")) {
983 sl_reply("400", "Invalid REGISTER Request");
986 if (isflagset(FLAG_REPL_ENABLED)) {
987 if (isflagset(FLAG_NAT)) {
988 append_hf("Repl-Marker: nated\r\n");
990 # Append this server's unique ID to the request
991 append_hf_value("SER-Server-ID", "%@sys.server_id");
992 # We are multicasting a successful REGISTER to all proxies
993 # on the multicast network to replicate the contact
994 # addresses to all of them. In case they share the same IP
995 # address (VIP) it is important to set the sending IP
996 # address to an unshared one (in the future a special mcast
997 # module may use unbound sockets for sending and leave
998 # the source IP address decision up to kernel routing
1000 #DEBCONF-REPL_SEND_ADDR-START
1001 force_send_socket(udp:127.0.0.1);
1002 #DEBCONF-REPL_SEND_ADDR-END
1003 # Put the UID in the Request-URI so that it doesn't have to
1004 # be looked up in the database by all multicast receivers.
1005 attr2uri("$tu.uid","user");
1006 forward_udp(224.0.1.75,5060);
1012 # Authentication of request originators claiming to belong to one of our
1015 route[AUTHENTICATION]
1017 # CANCELs and ACKs cannot be challenged.
1018 if (method=="CANCEL" || method=="ACK") {
1022 # Requests from non-local to local domains should be permitted.
1023 # Remove this if you want a walled garden.
1028 # Gateways are usually not able to authenticate for their requests.
1029 # You have to trust them base on some other information such as the
1030 # source IP address.
1031 # WARNING: If at all this is only safe in a local network!
1032 if (@src.ip == $gw_ip) {
1036 if (!proxy_authenticate("$fd.digest_realm", "credentials")) {
1038 sl_reply("500", "Internal Server Error");
1040 else if ($? == -3) {
1041 sl_reply("400", "Bad Request");
1044 if ($digest_challenge) {
1045 append_to_reply("%$digest_challenge");
1047 sl_reply("407", "Proxy Authentication Required");
1052 # Check if the UID derived from authentication matches that from
1054 if (!lookup_user("$fr.uid", "@from.uri")) {
1055 sl_reply("403", "Fake Identity");
1058 if ($fu.uid != $fr.uid) {
1059 sl_reply("403", "Fake Identity");
1062 setflag(FLAG_AUTH_OK);
1064 # Load the user attributes of the caller.
1065 load_attrs("$fu", "$f.uid");
1069 # Process request targeted to non-local domains.
1073 # If a local user calls to a foreign domain we play outbound
1075 # Comment this out if you want a walled garden.
1076 if ($f.did && !$t.did) {
1077 append_hf("P-hint: outbound\r\n");
1083 # Process speeddial addresses.
1087 # If the caller is local and uses two digits only, we redirect the
1088 # UA to the real target.
1089 if ($fd.did && uri =~ "sip:[0-9][0-9]@") {
1090 if (sd_lookup("speed_dial")) {
1091 sl_reply("302", "Speed Dial Redirect");
1094 sl_reply("404", "Speed Dial Not Found");
1101 # Process requests targeted to a local user.
1105 # lets see if know the callee
1106 if (!lookup_user("$tu.uid", "@ruri")) {
1110 # Load the attributes of the callee.
1111 load_attrs("$tu", "$t.uid");
1113 # You can check if the called URI is in fact an alias like this.
1114 #if (! $tu.uri_canonical) {
1115 # # If the alias URI has different attributes, you can load
1116 # # them into the URI track like this.
1117 # load_attrs("$tr", "@ruri");
1120 # Check for call forwarding of the callee.
1121 # Note: The forwarding target has to be full routable URI
1123 if ($tu.fwd_always_target) {
1124 attr2uri("$tu.fwd_always_target");
1126 # If we are forwarding to ourselves, don't remove
1127 # credentials. Otherwise the request would be challenged
1129 # Note: This doesn't apply to failure_route which may
1130 # still be problematic -- credentials are already
1131 # removed when we forward. Consider using a 3xx.
1132 lookup_domain("$td", "@ruri.host");
1134 setflag(FLAG_DONT_RM_CRED);
1139 # Native SIP destinations are handled using the usrloc database.
1140 if (lookup_contacts("location")) {
1141 append_hf("P-hint: usrloc applied\r\n");
1143 # We set the tm module timers according to the prefences
1144 # of the callee (avoid too long ringing of his phones).
1145 # Note1: Timer values have to be in ms now!
1146 # Note2: This makes even more sense if you switch to a
1147 # voicemail from the FAILURE_ROUTE below.
1148 if ($t.fr_inv_timer) {
1150 t_set_fr("$t.fr_inv_timer", "$t.fr_timer");
1153 t_set_fr("$t.fr_inv_timer");
1157 # This enables session timer support as long as one side
1158 # supports it. If you want to have session timmer support
1159 # only for calls from your PSTN gateway but not between pure
1160 # VoIP calls you can remove the comment marks from the if
1161 # clause in the next line and closing bracket below.
1162 # WARNING: If at all you should trust IP addresses only in
1163 # your local network!
1164 #if (@src.ip == $gw_ip) {
1165 route(SESSION_TIMER);
1171 sl_reply("480", "Temporarily unavailable");
1177 # Process calls for PSTN.
1181 # Check some conditions first:
1182 # PSTN is available for our own users only.
1187 # If the attribute $gw_ip isn't set, there is no PSTN service
1193 # And finally, the username of the Request-URI must look like
1195 if (!uri =~ "^sips?:\+?[0-9]{3,18}@") {
1199 # You may have to convert the number in the Request-URI into a
1200 # format that is accepted by your gateway here.
1202 # Check permissions of the caller for initial INVITEs.
1203 if (method == "INVITE" && !@to.tag) {
1204 if (!$f.gw_acl == "1") {
1205 sl_reply("403", "PSTN Not Permitted");
1210 # If the attribute $asserted_id is set, we add its contents as a
1211 # Remote-Party-ID header.
1212 # Depending on your gateway, you may have to add a
1213 # P-Asserted-Identity header here instead.
1215 xlset_attr("$rpidheader",
1216 "<sip:%$asserted_id@%@ruri.host>;screen=yes");
1217 replace_attr_hf("Remote-Party-ID", "$rpidheader");
1220 # Enable Session Timer support with the gateway.
1221 route(SESSION_TIMER);
1223 # Replace the domain part of the Request-URI with the value from
1224 # the attribute and send it out.
1225 attr2uri("$gw_ip", "domain");
1227 # Set the PSTN_ALLOWED flag. This will be checked on the
1229 setflag(FLAG_PSTN_ALLOWED);
1234 # Try to process CANCEL requests quickly.
1238 if (method == CANCEL) {
1239 # t_relay_cancel() will stop processing if a matching
1241 if (!t_relay_cancel()) {
1242 # An INVITE was found but some error occurred.
1243 sl_reply("500", "Internal Server Error");
1246 # Bad luck, no corresponding INVITE was found, we have to
1247 # continue with the script.
1252 # Site specific policy.
1254 route[SITE_SPECIFIC]
1256 # This is only relevant for requests for one of our domains.
1261 # Do site specific routing such as peering.
1263 if (uri=~"^sip:000777") {
1264 rewritehostport("sems01.iptel.org:5074");
1269 # Process Session-Timer.
1271 route[SESSION_TIMER]
1273 # We are only interested in session establishment or session
1276 if (method != "INVITE" && method != "UPDATE") {
1280 # Let's check if the Session-Expires header is already present.
1281 if (@hf_value.session_expires) {
1282 # Compare the Session-Expires header value with the
1283 # configured Min-SE.
1284 eval_push("x:%@hf_value.session_expires.uri");
1285 eval_oper("(int)", -1);
1286 eval_push("x:%@cfg_get.session_timer.min_se");
1287 eval_oper("(int)", -1);
1288 eval_oper(">=", -2);
1290 # Let's check for the Suported header.
1291 if (hf_value_exists("Supported", "timer")) {
1292 # The UAC supports Session-Timer, so we
1293 # only need to take a look at the values
1294 if (@eval.pop[-1] == "0") {
1295 # Session interval is lower than the
1297 append_to_reply("Min-SE: %@cfg_get.session_timer.min_se\r\n");
1298 sl_reply("422", "Session Interval Too Small");
1302 # We store the session expires value for the reply
1303 # route and mark the attribute for inserting as
1304 # Record-Route cookie.
1305 $stimer = @hf_value.session_expires.uri;
1306 setavpflag($stimer, "dialog_cookie");
1308 # Set the session timer flag that indicates the
1309 # UAC supports the extension.
1310 setflag(FLAG_SESSIONTIMER);
1313 # Session epxires was already inserted by some other
1315 if (@eval.pop[-1] == "0") {
1316 # Session interval is lower than the
1317 # configured Min-SE. There is no point in
1318 # sending 422 response, because the UAC
1319 # does not support the extension, the values
1320 # can be corrected instead.
1321 assign_hf_value("Session-Expires",
1322 "%@cfg_get.session_timer.min_se");
1323 remove_hf_value("Min-SE");
1324 append_hf_value("Min-SE",
1325 "%@cfg_get.session_timer.min_se");
1330 # No Session Timer is requested yet, neither by UAC nor by
1332 if (@cfg_get.session_timer.default != "0") {
1333 # Add a Session Expires header to see if the UAS
1334 # supports Session Timer. We do not insert a
1335 # Required header because then the call might fail.
1336 append_hf_value("Session-Expires",
1337 "%@cfg_get.session_timer.default");
1338 if (@cfg_get.session_timer.min_se != "90") {
1339 append_hf_value("Min-SE",
1340 "%@cfg_get.session_timer.min_se");
1343 # Mark the attribute to be inserted as a
1344 # Record-Route cookie
1345 $stimer = @cfg_get.session_timer.default;
1346 setavpflag($stimer, "dialog_cookie");
1352 # Failure route for initial INVITEs.
1354 failure_route[FAILURE_ROUTE]
1356 # Mark that we are operating from a failure route.
1357 setflag(FLAG_FAILUREROUTE);
1359 if (t_check_status("486|600")) {
1360 # If we received a busy and a busy target is set, forward
1362 # Note: Again, the forwarding target has to be a routeable
1363 # URI. We redirect using 3xx to avoid possible issues with
1364 # credentials (if we consumed them, they may be missing in
1365 # a loop, if we don't consume them, messages are bigger and
1367 if ($tu.fwd_busy_target) {
1368 #attr2uri("$tu.fwd_busy_target");
1370 attr_destination("$tu.fwd_busy_target");
1371 t_reply("302", "Redirect On Busy");
1373 # Alternatively, you could forward the request to
1374 # SEMS/voicemail here
1376 else if (t_check_status("408|480")) {
1377 # If we received no answer and the noanswer target is set,
1380 if ($tu.fwd_noanswer_target) {
1381 #attr2uri("$tu.fwd_noanswer_target");
1383 attr_destination("$tu.fwd_noanswer_target");
1384 t_reply("302", "Redirect On No Answer");
1390 # Onreply route that fixes NAT in responses.
1392 onreply_route[REPLY_ROUTE]
1394 # Fix the Contact in the reply if it contains a private IP to
1395 # allow proper routing of in-dialog messages.
1396 # Do the same if the contact is maddred. See the notes in route
1397 # [NAT_DETECTION] for more information.
1398 if (nat_uac_test("1") ||
1399 (@hf_value["contact"] && @contact.uri.params.maddr))
1401 fix_nated_contact();
1404 # If RTP proxy was activated and this is a 18x or 2xx reply with a
1405 # body, inform RTP proxy.
1406 if (isflagset(FLAG_RTP_PROXY)
1407 && status=~"(18[03])|(2[0-9][0-9])"
1410 force_rtp_proxy('r');
1413 # Let's check for session timer support.
1414 if (isflagset(FLAG_SESSIONTIMER) && status =~ "2[0-9][0-9]") {
1415 # The UAC wanted to have a session timer.
1416 if (!@hf_value.session_expires) {
1417 # But the UAS does not support it, so we will try
1418 # to convince the UAC to do it.
1419 append_hf_value("Session-Expires",
1420 "%$stimer;refresher=uac");
1421 if (!hf_value_exists("Require", "timer")) {
1422 include_hf_value("Require", "timer");
1429 # Do some final checks before a request is sent out.
1432 # Bypass check: Eliminate requests to the PSTN gateway if they have
1433 # not passed ACL checks and are not marked with FLAG_PSTN_ALLOWED
1434 # but are dialog-initiating requests (no to-tag, no CANCEL, no ACK).
1435 # This helps to stop policy bypasses (gateway IP uploaded as a
1436 # forked contact, or a call-forwarding destination, or a DNS name,
1437 # or a preloaded route, or something else possibly)
1438 if (to_ip==$g.gw_ip && !isflagset(FLAG_PSTN_ALLOWED)
1439 && !isflagset(FLAG_TOTAG)
1440 && method != "ACK" && method != "CANCEL")
1442 log(1, "ALERT: non authorized packet for PSTN, dropping...\n%mb\n");
1444 # You can't use advanced features from onsend_route.
1445 # xlog("L_ALERT", "non authorized packet for PSTN, dropping...\n%mb\n");
1449 # RFC 1918 relay protection: Useful if SER is attached to an
1450 # administrative network using private IP address space and you
1451 # wish to prevent UACs from relaying their packets there.
1453 # You will have to comment this out, if you are regularly serving
1454 # an RFC 1918 address space.
1455 if (to_ip==10.0.0.0/8 || to_ip==172.16.0.0/12
1456 || to_ip==192.168.0.0/16)
1458 log(1, "ALERT: Packet targeted to an RFC1918 address dropped\n");
1464 # Run every minute by the timer module.
1466 route[ON_1MIN_TIMER] {
1467 # Cleanup expired location records
1469 db_query("delete from location where expires<utc_timestamp()");
1470 # PostgreSQL version:
1471 #db_query("delete from location where expires<now()");
1474 # Reload domains if domain table has been changed recently.
1475 # Note: because global attributes are read-only and we can't
1476 # easily remember the "last" status, we check for changed
1477 # timestamp in 2 minute time-interval.
1479 db_query("select value from global_attrs where name='domain_data_version' and type=0 and cast(value as unsigned int) between unix_timestamp(now())-120 and unix_timestamp(now())", "reload");
1480 # PostgreSQL version:
1481 #db_query("select value from global_attrs where name='domain_data_version' and type=0 and cast(value as integer) between date_part('epoch', now() - interval '120 seconds') and date_part('epoch', now())", "reload");
1482 if (@db.fetch.reload.count=="1") {
1483 # Domain reload only available as fifo command.
1484 exec_msg("sercmd domain.reload");