1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762 |
- #
- # $Id$
- #
- #
- # Applicability of this Configuration File
- # ----------------------------------------
- #
- # This is default SER script as used for example at the iptel.org
- # SIP service; it can deal with NATs, terminate calls to a PSTN
- # gateway, and it implements a couple of basic signaling features
- # (few types of call forwarding). In this scenario you may have
- # multiple SIP proxies sharing one database for accessing provisioned
- # data, which are maintained for example using serweb. The proxy
- # servers also share write-access to user location database (and
- # keeps a full cache of all usrloc entries synchronized using
- # multicast).
- #
- # If you look for a simpler version with a lot less dependencies
- # please refer to the sip-router-basic.cfg file in your SER distribution.
- #
- # If you look for documentation, try http://sip-router.org/wiki/.
- # The right mailing lists for questions about this file is
- # <[email protected]>.
- #
- # Requirements:
- # ---------------
- # running DB, running RTP proxy, one public IP address
- # for SIP service, one private IP address for administrative purposes;
- # optional: IP address of a PSTN gateway
- #
- # HOWTOs:
- # ---------
- # To get this config running you need to execute the following commands
- # with the new serctl (the capital word are just place holders):
- #
- # $ ser_ctl domain add DOMAINNAME
- # $ ser_ctl user add USERNAME@DOMAINNAME -p PASSWORD
- #
- # (ser_ctl can be obtained from
- # http://ftp.iptel.org/pub/serctl/daily-snapshots/ )
- #
- # If you want to have P-Asserted-ID header for your user
- #
- # $ ser_attr add uid=UID asserted_id="PID"
- #
- # If you want to have (PSTN) gateway support:
- #
- # $ ser_db add attr_types name=gw_ip rich_type=string raw_type=2 \
- # description="The gateway IP for the default ser.cfg" default_flags=33
- # $ ser_attr add global gw_ip=GATEWAY-IP
- #
- # Alternatively, you can simple uncomment the relevant line in this file
- # right at the beginning of the main route.
- #
- # You can also use serweb to set all the values above
- # (http://ftp.iptel.org/pub/serweb/daily-snapshots/ or
- # http://developer.berlios.de/projects/serweb).
- #
- # Users with permission to call PSTN using this script must have
- # the $gw_acl attribute set properly, and shall have $asserted_id
- # set to indicate their caller-id for calls to PSTN. For inbound
- # calls from PSTN, additional aliases may be also set.
- #
- # Warning:
- # -----------
- # If this file is installed on Debian from package 'ser-oob' then some
- # options in this configuration file may be set by post-installation
- # script, according to values entered by user at installation time in
- # debconf configuration. These values are then applied automatically to
- # this file each time the 'ser-oob' package is upgraded or reconfigured by
- # calling 'dpkg-reconfigure sip-router-oob'.
- #
- # The parts of this configuration file that may be altered by debconf are
- # enclosed between '#DEBCONF-something-START' and '#DEBCONF-something-END'
- # comment marks. Please do not remove them.
- #
- #
- # TODO (Future possible improvements):
- # ---------------------------------------
- # * protocol tuning
- # - AVP-based diversion for call-forwarding (as opposed to specialized
- # module)
- # - add Date header in 200s to REGISTERs (to be packaged with NTP!)
- # * more security:
- # - pike/rate-limit
- # - identity
- # - TLS
- # - permissions
- # - Re-name all internal headers so that they start with a common prefix,
- # such as P-SER and then wipe all such headers from requests received
- # from untrusted sources, such as the user agents or foreign proxy
- # servers
- # * refined DB use (e.g., flatstore for acc)
- # * miscellanous:
- # - dialog module for monitoring purposes
- # - more extensive logging using xlog (controlled by gflags/gAVPs)
- # * leveraging 2.1 features:
- # - removal of private IP address (it takes a multicast-specific
- # command which will allow OS to determine source IP address)
- # - timer route:
- # * don't use exec (it takes domain.reload as script command)
- # * compare last-stored timestamp with current timestamp (it takes
- # assignment of gAVPs)
- # * check multicast REGISTERs for their TTL (this is a simple and
- # effective security check to prevent remote multicast messages
- # to damage our traffic)
- # - numerous fine-tuning parameters which are only available in 2.1
- # (mlock_pages, dns_try_naptr, etc.)
- # - better support for preloaded routes with domain name
- #
- # Security considerations:
- # ------------------------
- # The script has been tested against security leaks, but it comes
- # under terms of GPL "as is" without any warranties; better check
- # yourself that:
- # - IP based authentication of PSTN gateway and multicast REGISTERs
- # is compliant to your network setup and security policy.
- # - Multiple gateway IPs can't be provisioned as security checks
- # are applied only to one.
- #
- # Licensing
- # ----------
- # Copyright (C) 2005-2008 iptelorg GmbH
- # This file is part of SER, a free SIP server. It is available under the
- # terms of the GNU General Public License.
- # Numerous folks have contributed to this file, including but not limited
- # to Andrei, Jan, Jiri, Michal, Miklos, Nils.
- #
- #
- # .... that's it, enough of yadiyada, here the real config begins!
- # ----------- Global Defines / Extra Features -------------------------------
- # (can be enabled either by uncommenting the corresponding #!define
- # statement or by starting with -A WITH_<FEATURE_NAME>, e.g.
- # ser -A WITH_TLS -f /etc/ser/ser-oob.cfg )
- # enable TLS
- ##!define WITH_TLS
- #enable xmlrpc support
- ##!define WITH_XMLRPC
- # xmlrpc allowed only if it comes on TLS from a client with a valid cert
- ##!define XMLRPC_TLS_ONLY
- # xmlrpc allowed subnets (if defined XMLRPC requests with source ip matching
- # this network addresses will be allowed, if no XMLRPC_ALLOWED_SUBNETx is
- # defined only requests coming from localhost will be allowed).
- # E.g.: ser -A XMLRPC_ALLOW_NET1=192.168.1.0/24 -f ser-oob.cfg
- ##!define XMLRPC_ALLOW_NET1 192.168.0.0/16
- ##!define XMLRPC_ALLOW_NET2 10.0.0.0/255.0.0.0
- ##!define XMLRPC_ALLOW_NET3 172.16.0.0/12
- # started from compile directory (not installed)
- ##!define LOCAL_TEST_RUN
- # ----------- Global Configuration Parameters -------------------------------
- #debug=3 # debug level (cmd line: -ddd)
- #memdbg=10 # memory debug log level
- #memlog=10 # memory statistics log level
- #log_facility=LOG_LOCAL0 # the facility used for logging (see syslog(3))
- #DEBCONF-SERVERID-START
- server_id=0
- #DEBCONF-SERVERID-END
- # Uncomment these lines to enter debugging mode or start SER with
- # sip-router -ED
- #
- #fork=no
- #log_stderror=yes
- check_via=no # (cmd. line: -v)
- dns=no # (cmd. line: -r)
- rev_dns=no # (cmd. line: -R)
- #port=5060
- #children=4
- #user=sip-router
- #group=sip-router
- #disable_core=yes # disables core dumping
- #open_files_limit=20480 # sets the open file descriptors limit
- #mhomed=yes # usefull for multihomed hosts, small performance
- # penalty
- disable_tcp=no # be conservative about enabling TCP -- it can
- # degrade performance a lot
- #tcp_accept_aliases=yes # accepts the tcp alias via option
- phone2tel=no # ignore user=phone in request-URIs -- otherwise
- # these URIs would be interpreted as equivalent
- # to TEL URIs, and their lookup would fail in URI
- # database
- reply_to_via=no
- sip_warning=yes
- # public IP address
- #DEBCONF-LISTEN-START
- listen=127.0.0.1
- #DEBCONF-LISTEN-END
- # sip.mcast.net for REGISTER replication
- #DEBCONF-LISTEN_REPL-START
- listen=udp:224.0.1.75
- #DEBCONF-LISTEN_REPL-END
- # administrative interface -- needed for example for multicast source
- # or XML-RPC
- #DEBCONF-LISTEN_ADMIN-START
- listen=udp:127.0.0.1
- #DEBCONF-LISTEN_ADMIN-END
- #listen=tls:127.0.0.1:5061
- mlock_pages=yes
- shm_force_alloc=yes
- real_time=7
- # ------------------- DNS Parameters ----------------------------------------
- # (see doc/dns.txt for more details)
- #
- # minimum timeouts
- dns_retr_time=1
- dns_retr_no=1
- dns_servers_no=1
- dns_use_search_list=no
- dns_try_ipv6=no
- # dns cache & failover
- use_dns_cache=on
- use_dns_failover=on
- # dns_cache_flags=0
- dns_cache_negative_ttl=300
- dns_cache_min_ttl=60
- dns_cache_max_ttl=86400 # 1 day
- dns_cache_mem=2048 # 2 MB
- dns_cache_gc_interval=60 # garbage collection every minute
- # ser 2.1 specific options
- dns_try_naptr=yes
- dns_srv_lb=yes # srv based load balancing
- dns_udp_pref=3 # prefer udp (when resolving naptr record)
- dns_tcp_pref=2 # if no udp available accept tcp (for naptr)
- dns_sctp_pref=2 # same preference as tcp
- #!ifdef WITH_TLS
- dns_tls_pref=1 # low preference (heavy resource use)
- #!else
- dns_tls_pref=-1 # ignore / don't accept tls (for naptr)
- #!endif
- # dns_cache_delete_nonexpired=no
- # ------------------- Blacklist Parameters ----------------------------------
- # (see doc/dst_blacklist.txt for more details)
- #
- use_dst_blacklist=on
- dst_blacklist_mem=1024 # 1 MB
- dst_blacklist_expire=300 # blacklist default time
- dst_blacklist_gc_interval=150 # 2.5 min
- # for sip-router 2.1 to the above add tm blst_503* parameters and/or use the
- # blst module (see NEWS)
- # ------------------- TCP Parameters ----------------------------------------
- # (see NEWS for more details)
- tcp_connection_lifetime=3600
- #tcp_max_connections=10240 # default is 2048
- tcp_connect_timeout=1
- tcp_async=yes
- # ------------------- TLS Parameters ----------------------------------------
- #!ifdef WITH_TLS
- # Enable TLS hooks so that the TLS module can be used
- tls_enable=yes
- #!endif
- # -------------------- Custom Parameters ------------------------------------
- # These parameters can be modified runtime via RPC interface,
- # read the documentation of cfg_rpc module.
- # Session Timer parameters, RFC 4028
- #
- # Default session interval used by the proxy if the UAC does not support
- # session timer. Set it to "0" to disable session timer proxy support.
- #
- session_timer.default = "1800" desc "default session interval (in s)"
- #
- # Minimum session interval accepted by the proxy, it must not be less
- # than 90 seconds.
- #
- session_timer.min_se = "90" desc "minimum session interval (in s)"
- # RTP Proxy options
- #
- # Whether to enable or disable the rtp proxy. Possible values are:
- # "0" -- always disable
- # "1" -- always enable regardless of whether UAC or UAS is behind NAT
- # "detect" -- detect whether the UAC or the UAS is behind NAT,
- # and enable the rtp proxy when necessary
- #
- #DEBCONF-RTP_ENABLE-START
- rtp_proxy.enabled = "detect" desc "indicates whether the RTP Proxy is enabled or not (0/1/detect)"
- #DEBCONF-RTP_ENABLE-END
- # ------------------ Module Loading -----------------------------------------
- #!ifdef LOCAL_TEST_RUN
- loadpath "modules:modules_s"
- #!else
- loadpath "/usr/lib/sip-router/modules:/usr/lib/sip-router/modules_s"
- #!endif
- # load a SQL database for authentication, domains, user AVPs etc.
- loadmodule "db_mysql"
- #loadmodule "postgres"
- loadmodule "tm"
- loadmodule "sl"
- loadmodule "rr"
- loadmodule "maxfwd"
- loadmodule "usrloc"
- loadmodule "registrar"
- loadmodule "xlog"
- loadmodule "textops"
- loadmodule "ctl"
- loadmodule "auth"
- loadmodule "auth_db"
- loadmodule "gflags"
- loadmodule "domain"
- loadmodule "uri_db"
- loadmodule "avp"
- loadmodule "avp_db"
- loadmodule "acc_db"
- #!ifdef WITH_XMLRPC
- loadmodule "xmlrpc"
- #!endif
- loadmodule "options"
- loadmodule "sanity"
- loadmodule "nathelper"
- loadmodule "uri"
- loadmodule "speeddial"
- loadmodule "timer"
- loadmodule "db_ops"
- loadmodule "exec"
- loadmodule "cfg_rpc"
- loadmodule "eval"
- loadmodule "enum"
- #!ifdef WITH_TLS
- loadmodule "tls"
- #!endif
- # ----------------- Declaration of Script Flags -----------------------------
- flags
- FLAG_ACC : 1, # the request will be recorded by ACC
- FLAG_FAILUREROUTE : 2, # we are operating from the failure route
- FLAG_NAT : 3, # the UAC is behind a NAT
- FLAG_REPL_ENABLED : 4, # REGISTER replication is enabled if set
- FLAG_TOTAG : 5, # request has a To tag
- FLAG_PSTN_ALLOWED : 6, # the user is allowed to use the PSTN
- FLAG_DONT_RM_CRED : 7, # do not remove the credentials
- FLAG_AUTH_OK : 8, # authentication succeeded
- FLAG_SERWEB_RSVD1 : 9, # bit reserved for use with serweb
- FLAG_SERWEB_RSVD2 : 10, # bit reserved for use with serweb
- FLAG_SESSIONTIMER : 11, # indicates that the UAC supports Session Timer
- FLAG_RR_DONE : 12, # the request got already one RR header
- FLAG_RTP_PROXY : 13, # the RTP proxy is turned on
- FLAG_NAT_REG : 14, # the UAC behind NAT, stored in location record
- FLAG_INIT_DLG : 15, # init INVITE dialog
- FLAG_REVERSE_DIR : 16, # set if request goes callee -> caller direction, requires rr.append_fromtag=1
- FLAG_ACC_MISSED : 17, # the missed call will be recorded by ACC
- FLAG_USRLOC_FWD : 18, # usrloc based forward
- FLAG_NEXT_ROUTE : 19; # there is a route remaining
- avpflags
- dialog_cookie; # attribute will be stored in Route headers
- # ----------------- Module-specific Parameters ------------------------------
- # path to the database
- #
- #DEBCONF-DBURL-START
- modparam("speeddial|auth_db|usrloc|domain|uri_db|gflags|avp_db|db_ops",
- "db_url", "mysql://ser:heslo@localhost/ser")
- #DEBCONF-DBURL-END
- # specify the path to your database for accounting
- #DEBCONF-DBURLACC-START
- modparam("acc_db", "db_url", "mysql://ser:heslo@localhost/ser")
- #DEBCONF-DBURLACC-END
- # -- usrloc --
- # Database access mode: 0 -- memory cached, 1 -- write through,
- # 2 -- delayed write. 1 is generally safer than 2. 2 can help
- # to survive peaks in load. However, it creates delayed peaks that can
- # impair request-processing latency later (usrloc would have to be
- # re-redesigned more lock-free to avoid it).
- #DEBCONF-DBMODE-START
- modparam("usrloc", "db_mode", 1)
- #DEBCONF-DBMODE-END
- # Don't delete expired records from database on a per-contact basis -- that
- # results in bulky DB operations and can lead to synchronization issues
- # in server farm when for a time a server doesn't obtain re-reregistrations
- modparam("usrloc","db_skip_delete",1)
- # -- registrar --
- # Maximum expires time. Forces users to re-register every 10 min.
- modparam("registrar", "max_expires", 600)
- # Minimum expires time. Even if they try, clients cannot register
- # for a shorter time than this.
- modparam("registrar", "min_expires", 240)
- # Identify natted contacts using a flag.
- modparam("registrar", "load_nat_flag", "FLAG_NAT_REG")
- modparam("registrar", "save_nat_flag", "FLAG_NAT_REG")
- # Maximum number of contacts.
- modparam("registrar", "max_contacts", 10)
- # -- auth --
- #modparam("auth_db", "calculate_ha1", yes)
- #modparam("auth_db", "password_column", "password")
- # Minimize replay-attack window.
- modparam("auth", "nonce_expire", 10)
- # Enable/disable extra authentication checks using the following modparams.
- # The values are: 1 -- Request-URI, 2 -- Call-ID, 4 -- From tag,
- # 8 -- source IP. The options are disabled by default.
- # For REGISTER requests we hash the Request-URI, Call-ID, and source IP of the
- # request into the nonce string. This ensures that the generated credentials
- # cannot be used with another registrar, user agent with another source IP
- # address or Call-ID. Note that user agents that change Call-ID with every
- # REGISTER message will not be able to register if you enable this.
- #modparam("auth", "auth_checks_register", 11)
- # For dialog-establishing requests (such as the original INVITE, OPTIONS, etc)
- # we hash the Request-URI and source IP. Hashing Call-ID and From tags takes
- # some extra precaution, because these checks could render some UA unusable.
- #modparam("auth", "auth_checks_no_dlg", 9)
- # For mid-dialog requests, such as re-INVITE, we can hash source IP and
- # Request-URI just like in the previous case. In addition to that we can hash
- # Call-ID and From tag because these are fixed within a dialog and are
- # guaranteed not to change. This settings effectively restrict the usage of
- # generated credentials to a single user agent within a single dialog.
- #modparam("auth", "auth_checks_in_dlg", 15)
- # Deal with clients who can't do qop properly
- modparam("auth", "qop", "")
- #DEBCONF-AUTHSECRET-START
- modparam("auth", "secret", "aqwedrftredswqwddcft")
- #DEBCONF-AUTHSECRET-END
- # -- rr --
- # Add value to lr param to make some broken UAs happy.
- modparam("rr", "enable_full_lr", 1)
- # Limit the length of the AVP cookie to necessary attributes only
- modparam("rr", "cookie_filter", "(account|rproxy|stimer|dialog_id)")
- # You probably do not want that someone can simply read and change
- # the AVP cookie in your Routes, thus should really change this
- # secret value below
- modparam("rr", "cookie_secret", "sgsatewgdbsnmpoiewh")
- # The ftag Route parameter may be used to easily determine if a BYE
- # is coming from caller or callee, but we prefer shorter messages
- # Enable when FLAG_REVERSE_DIR is to be used
- modparam("rr", "append_fromtag", 0)
- # -- gflags --
- # Load global attributes.
- modparam("gflags", "load_global_attrs", 1)
- # -- domain --
- # Load domain attributes.
- modparam("domain", "load_domain_attrs", 1)
- # -- ctl --
- # By default, ctl listens on unixs:/tmp/sip-router_ctl if no other address is
- # specified in modparams; this is also the default for sercmd.
- modparam("ctl", "binrpc", "unixs:/tmp/ser_ctl")
- # Listen on the "standard" fifo for backward compatibility.
- modparam("ctl", "fifo", "fifo:/tmp/ser_fifo")
- # Listen on tcp on localhost.
- modparam("ctl", "binrpc", "tcp:127.0.0.1:2046")
- # -- acc_db --
- # Failed transactions (those with negative responses) should be logged, too.
- modparam("acc_db", "failed_transactions", 1)
- # If you don't want to have accounting entries written into the database,
- # comment the next line out.
- modparam("acc_db", "log_flag", "FLAG_ACC")
- # seems "log_flag" and "log_flag_missed" cannot share the same flag!
- modparam("acc_db", "log_missed_flag", "FLAG_ACC_MISSED")
- # if you would like to customize your CDRs, do it here....
- #modparam("acc_db", "attrs",
- # "$f.sop_billing_category,$f.isPrepaidCustomer,$f.sop_cf_orig_uid")
- # -- tm --
- # Do not restart the resend timer with each reply. (See INBOUND route
- # below.)
- modparam("tm", "restart_fr_on_each_reply", 0)
- # -- xmlrpc --
- #!ifdef WITH_XMLRPC
- # Use a sub-route. This is a lot safer then relying on the request method
- # to distinguish HTTP from SIP
- modparam("xmlrpc", "route", "XMLRPC");
- #!endif
- # -- nathelper --
- # RTP Proxy address
- #DEBCONF-RTTPPROXY-START
- modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:22222")
- #DEBCONF-RTTPPROXY-END
- # TCP keepalives as simple as CRLF
- modparam("nathelper", "natping_crlf", 0)
- # How often to send a NAT ping. Set this to 0 to turn NAT ping off.
- #DEBCONF-NATPING_INTERVAL-START
- modparam("nathelper", "natping_interval", 15)
- #DEBCONF-NATPING_INTERVAL-END
- # Only ping contacts that have the NAT flag set.
- modparam("nathelper", "ping_nated_only", 1)
- # Send an OPTIONS SIP request as NAT ping. If this is not set, a simple
- # 4-byte ping is used.
- modparam("nathelper", "natping_method", "OPTIONS")
- # Temporary statefull natping test (only in future versions)
- #modparam("nathelper", "natping_stateful", 1)
- # -- exec --
- modparam("exec", "time_to_kill", 200);
- modparam("exec", "setvars", 0);
- # -- timer --
- # Register route ON_1MIN_TIMER to be called every minute.
- modparam("timer", "declare_timer",
- "ON_1MIN_TIMER=ON_1MIN_TIMER,60000,slow,enable");
- #!ifdef WITH_TLS
- # -- tls --
- #!ifdef LOCAL_TEST_RUN
- modparam("tls", "config", "./modules/tls/tls.cfg");
- #!else
- modparam("tls", "config", "tls.cfg");
- #!endif
- #!endif
- # -- db_ops --
- modparam("db_ops", "declare_handle", "reload")
- modparam("db_ops", "declare_handle", "gattr_reload")
- # ------------------------- Request Routing Logic --------------------------
- # Main request route.
- #
- # Each request starts here.
- #
- route
- {
- # if you have a PSTN gateway just un-comment the follwoing line and
- # specify the IP address of it to route calls to it.
- #$gw_ip = "1.2.3.4"
- # Alternatively (even better), set it as global persistent parameter
- # using serweb or ser_attrs). If using a PSTN GW, per-subscriber
- # options must ($gw_acl) or may (asserted_id) be set to enable calls
- # to PSTN. If email-like URIs are used, having a URI alias for
- # processing incoming PSTN-to-ip requests may be useful, too.
- # Important: the script is assuming one global pstn-gw for all
- # domains! Failure to allow gw_ip to be a domain-specic attribute
- # would result in security gaps (onsend_route checks only for one
- # gateway).
- # First, do some initial sanity checks.
- route(INIT);
- # Bypass the rest of the script for CANCELs if possible.
- route(CATCH_CANCEL);
- # Check if the request is routed via Route header.
- route(PROCESS_ROUTES);
- # Look up domain IDs
- route(DOMAIN);
- # Answer OPTIONS requests to our system.
- route(OPTIONS_REPLY);
- # Enforce domain policy.
- route(DOMAIN_POLICY);
- # Handle REGISTER requests.
- route(REGISTRAR);
- # From here on we want to know who is calling.
- route(AUTHENTICATION);
- # We are finished with all the precaution work -- let's
- # try to locate the callee. The first route that matches
- # "wins" and relays the request. If none matches, SER will
- # send a 404.
- # Check if we should be outbound proxy for a local user.
- route(OUTBOUND);
- # Redirect in case user dialed a speed dial entry.
- route(SPEEDDIAL);
- # Place various site-specific routes here.
- route(SITE_SPECIFIC);
- # Check if the request is for a local user.
- route(INBOUND);
- # There is SIP user for the called address. Before trying PSTN,
- # you may have to convert the adress, for instance by using
- # ENUM.
- #route(ENUM);
- # Last resort: if none of the previous route has found
- # the recepient, try PSTN.
- route(PSTN);
- # nothing matched
- sl_reply("404", "No route matched");
- }
- # Forward a request to the destination set.
- #
- route[FORWARD]
- {
- # If this is called from the failure route we need to add a new
- # branch.
- if (isflagset(FLAG_FAILUREROUTE)) {
- if (!append_branch()) {
- t_reply("500", "Too many branches");
- drop;
- }
- }
- # If this is an initial INVITE (without a To-tag) we might try
- # another target (call forwarding or voicemail) after receiving
- # an error.
- if (isflagset(FLAG_INIT_DLG)) {
- t_on_failure("FAILURE_ROUTE");
- }
- # Always use the reply route to check for NATed UAS.
- t_on_reply("REPLY_ROUTE");
- # Remove credentials to keep requests shorter
- if (isflagset(FLAG_AUTH_OK) && !isflagset(FLAG_DONT_RM_CRED) ) {
- consume_credentials();
- }
- # Activate the RTP proxy as the second last step because it modifies the
- # body but also sets an dialog AVP cookie.
- route(RTPPROXY);
- # Insert a Record-Route header into all requests.
- # This has to be done as one of the last steps to include all the
- # RR cookies which might have been created during the script run.
- route(RECORD_ROUTE);
- # Send it out now.
- if (!t_relay()) {
- if (isflagset(FLAG_FAILUREROUTE)) {
- # XXX This should be replaced with
- # t_reply_error() similar to sl_reply_error()
- # in order to return the proper failure code.
- # Only, there is no such function yet.
- t_reply("500", "Request cannot be forwarded");
- }
- else {
- sl_reply_error();
- }
- }
- drop;
- }
- # Perform initial checks on an incoming request.
- #
- # Rejects the request if it fails any of the checks.
- #
- route[INIT]
- {
- # Messages with a Max-Forwards header of zero.
- if (!mf_process_maxfwd_header("10")) {
- sl_reply("483","Too Many Hops");
- drop;
- }
- # Set flag for use in the onsend route (because it does not
- # allow to use "select" statements)
- if (@to.tag != "") {
- setflag(FLAG_TOTAG);
- }
- # Check if the UAC is NATed and fix the message accordingly
- route(UAC_NAT_DETECTION);
- # Activate accounting for all initial INVITEs. In-dialog requests
- # are accounted by a RR cookie (see below).
- # It should work also when the call has been already forked at a previous router
- if (method == "INVITE" && !isflagset(FLAG_TOTAG)) {
- $dialog_id = @sys.unique; # make unique dialogid
- setflag(FLAG_ACC);
- setflag(FLAG_ACC_MISSED);
- setflag(FLAG_INIT_DLG);
- } else if (isflagset(FLAG_TOTAG) && @hf_value.route[0].params.ftag != @from.tag) {
- setflag(FLAG_REVERSE_DIR); # callee -> caller
- }
- # if needed then we MUST put after force_rport() which is located in NAT_DETECTION!!!
- # also must be called after FLAG_ACC is set !!!
- # Check t_reply() vs. sl_reply() usage in script
- #if (!t_newtran()) {
- # sl_reply("500", "Internal tm error");
- # drop;
- #}
-
- # Set flag and use it instead of the attribute.
- if ($replicate==1) {
- setflag(FLAG_REPL_ENABLED);
- }
- }
- # Reply OPTIONS requests sent to the proxy itself.
- #
- route[OPTIONS_REPLY]
- {
- # OPTIONS requests without a username in the Request-URI but one
- # of our domains or IPs are addressed to the proxy itself and
- # can be answered statelessly.
- if (method == "OPTIONS" && strempty(@ruri.user) &&
- (uri == myself || $t.did != ""))
- {
- options_reply();
- drop;
- }
- }
- # Check if the sender of the request is behind a NAT device. If so,
- # fix the request so that other devices can talk to the sender nonetheless.
- #
- route[UAC_NAT_DETECTION]
- {
- # Lots of UAs do not include the rport parameter in there Via
- # header, so we put it there regardless.
- force_rport();
- # If a reliable transport was used store the connection internally
- # so that SERs core can re-use the connection later.
- if (proto==TCP || proto == TLS)
- {
- force_tcp_alias();
- }
- # Check if the request contains hints for a NATed UAC. Also, try to
- # rewrite contacts using maddr. Using maddr is a really dubious
- # technique and we better replace such with transport address.
- # Downside: it fails for clients fronted by another server, in
- # which case a valid contact we dislike because of maddr will be
- # substituted inapproprietely (e.g., WM from other domains will
- # fail). If you are worried about that, remove tests for maddr and
- # recompile SER using HONOR_MADDR. Also note that rewriting
- # contacts may possibly lead to client denying subseqent requests
- # to them because they don't recognized fixed contacts as their
- # own. Should you encounter such a case, a possible solution
- # would be to store the original information as a contact parameter
- # and restore it on its way back.
- # In case of UDP we test for
- # - private IPs in Contact
- # - mismatch of transport IP and IP in Via
- # - mismatch of transport port and port in Via
- # in all other cases we skip the port test, because lots of clients
- # do not correctly advertise their emphemeral port number in their Via
- # header in case of reliable transports (although they are not behind
- # a NAT).
- # Warning: if you are dealing with SIP implementations which are
- # running on public IP and do as-symmertic signaling for whatever
- # reason the following check will make their signaling symmetric.
- # If you need to support as-symmertic signaling reduce the following
- # nat_uac_test for UDP to "3" or even "1".
- if ((proto == UDP && nat_uac_test("19")) ||
- (nat_uac_test("3")) ||
- (@hf_value["contact"] != "" && @contact.uri.params.maddr != ""))
- {
- setflag(FLAG_NAT);
- if (method == "REGISTER") {
- # Prepare the Contact so that the registrar module
- # saves the source address and port as well.
- fix_nated_register();
- }
- else {
- # Overwrite the Contact to allow proper in-dialog
- # routing.
- # but do not override if there is already a proxy in the path, we'll route by record-route,
- # RURI responsibility takes to previous proxy
- # TODO: shouldn't we rather limit to methods which are dialog aware (INVITE, UPDATE, SUBSCRIBE, ..)
- if (strempty(@hf_value.record_route) || (@hf_value["contact"]!="" && @contact.uri.params.maddr!="")) {
- fix_nated_contact();
- }
- }
- }
- }
- # Check if the receiver of the request is behind a NAT device. If so,
- # fix the Contact header to allow proper routing of in-dialog requests.
- route[UAS_NAT_DETECTION]
- {
- # Fix the Contact in the reply if it contains a private IP to
- # allow proper routing of in-dialog messages.
- # Do the same if the contact is maddred.
- # But skip 3XX responses, because we do not know the right IP for that,
- # even if they contain private IPs.
- if (status=~"(3[0-9][0-9])") {
- break;
- }
- # prevent contact overwriting when a proxy between ser and UAS.
- # We get it from record-route but it's rather difficult or
- # do it only for UAS which is registered in usrloc database and has no
- # proxy on path.
- # Note: destination forced by $fwd_always_target is not NAT detected and contact left untouched!
- if (isflagset(FLAG_INIT_DLG) && !isflagset(FLAG_USRLOC_FWD)) {
- break;
- }
- # for in-dialog requests we get it easily because it provides loose_route()
- if (!isflagset(FLAG_INIT_DLG) && isflagset(FLAG_NEXT_ROUTE)) {
- break;
- }
- # Prevent that we over-write the Contact with the IP of our proxy when
- # the reply loops through ourself.
- if (src_ip == myself) {
- break;
- }
- # In this case we check only if the Contact URI contains a private
- # IP, because the Via header contains only informations from the UAC.
- # Additionally we check if the port in the Contact URI differs from
- # the port of the transport to catch UAS or ALG which put the public
- # IP address into the Contact header, but "forget" about the port.
- # Warning: if you are dealing with SIP implementations which are
- # running on public IP and do as-symmertic signaling for whatever
- # reason the following check will make their signaling symmetric.
- # If you need to support as-symmertic signaling reduce the following
- # nat_uac_test for UDP to just "1".
- if ( (proto == UDP && nat_uac_test("33")) ||
- (nat_uac_test("1") ||
- (@hf_value["contact"] != "" && @contact.uri.params.maddr != "")))
- {
- # TODO: check if no proxy between UAS&myself
- fix_nated_contact();
- }
- }
- # Activates RTP proxy if necessary.
- #
- route[RTPPROXY]
- {
- if (@cfg_get.rtp_proxy.enabled == "0") {
- # RTP Proxy is disabled
- break;
- } else if (@cfg_get.rtp_proxy.enabled == "detect") {
- if (!isflagset(FLAG_NAT)) {
- # If no NAT is involved we don't have to do here anything.
- break;
- }
- } else if (@cfg_get.rtp_proxy.enabled != "1") {
- # This is not a valid setting
- xlog("L_ERR", "Unknown option for rtp_proxy.enabled: %@cfg_get.rtp_proxy.enabled\n");
- break;
- } # else rtp proxy is permanently enabled
- # If the message terminates a dialog for which the RTP proxy
- # was turned on, turn it off again.
- if ((method == "BYE" && isflagset(FLAG_RTP_PROXY)) ||
- (method == "CANCEL")) {
- unforce_rtp_proxy();
- append_hf("P-RTP-Proxy: Off\r\n");
- break;
- }
- # Turn the RTP proxy on for INVITEs and UPDATEs, if they
- # have a body
- if (((method=="INVITE" || method == "UPDATE") && @msg.body != "")
- && !isflagset(FLAG_RTP_PROXY))
- {
- force_rtp_proxy('r');
- append_hf("P-RTP-Proxy: On\r\n");
- setflag(FLAG_RTP_PROXY);
- $rproxy = 1;
- setavpflag($rproxy, "dialog_cookie");
- }
- }
- # Handling of Route headers
- #
- route[PROCESS_ROUTES]
- {
- # subsequent messages withing a dialog should take the
- # path determined by the Route headers.
- if (loose_route()) {
- if (!defined $dialog_id) {
- $dialog_id = $t.dialog_id; # there is only 1 dialog_id
- }
- if (@rr.next_route != "") {
- setflag("FLAG_NEXT_ROUTE");
- }
- xlog("L_DEBUG", "\n%mb\n\ndialogid -/from/to=%$dialog_id/%$f.dialog_id/%$t.dialog_id");
- if (method == "INVITE" || method == "UPDATE" || method == "ACK" || method == "BYE") {
- if (!defined $dialog_id) {
- sl_reply("400", "Missing cookie");
- drop;
- }
- }
- # Mark routing logic in request.
- append_hf("P-hint: rr-enforced\r\n");
- # If the Route contained the accounting AVP cookie we
- # set the accounting flag for the acc_db module.
- # This is more for demonstration purpose as this could
- # also be solved without RR cookies.
- # Note: this means all in-dialog request will show up in
- # the accounting tables, so prepare your accounting software
- # for this.
- if ($account == "yes") {
- setflag(FLAG_ACC);
- setflag(FLAG_ACC_MISSED);
- }
- # Restore the RTP proxy flag if present
- if ($rproxy == "1") {
- setflag(FLAG_RTP_PROXY);
- }
- # Restore Session Timer flag and headers.
- if ( defined $stimer && ($stimer != "0")) {
- route(SESSION_TIMER);
- }
- # Some broken devices overide the dialog route set with the
- # Record-Route headers from each in-dialog request. So, we
- # better add Record-Route headers again. If we call
- # record_route() after loose_route(), the AVP cookies are
- # restored automatically. Additionally, there is a scenario
- # where Record-Route headers are necessary if an initial
- # SUBSCRIBE is forked.
- #
- # Note that here we forward before authentication checks
- # are executed. Generally, we only authenticate
- # out-of-dialog requests. Some in-dialog requests can't be
- # authenticated at all, see the call-forwarding example in
- # route[DOMAIN].
- route(RECORD_ROUTE);
- route(FORWARD);
- }
- }
- # Add a Record-Route header
- #
- route[RECORD_ROUTE]
- {
- if (!isflagset(FLAG_RR_DONE) && method != "REGISTER") {
- # We record-route all messages to make sure that
- # subsequent messages will go through our proxy. This is
- # particularly good if upstream and downstream entities
- # use different transport protocols.
- # If the ACC flag is set, store this in a Record-Route
- # AVP cookie. This is more for demonstration purposes.
- if (isflagset(FLAG_ACC)) {
- $account = "yes";
- setavpflag($account, "dialog_cookie");
- }
- setavpflag("$f.dialog_id", "dialog_cookie");
- # Insert the RR header.
- record_route();
- # This flag allows to call this route several times
- # without inserting several RR headers.
- setflag(FLAG_RR_DONE);
- }
- }
- # Look up the domains of the caller and the callee.
- #
- route[DOMAIN]
- {
- # Check whether the caller is from a local domain.
- lookup_domain("$fd", "@from.uri.host");
- # Check whether the callee is at a local domain
- lookup_domain("$td", "@ruri.host");
- }
- # Check domain usage policies and reject illegal requests.
- #
- route[DOMAIN_POLICY]
- {
- # If we don't know the domain of the caller nor the domain of the
- # callee, somone tries to use our proxy as a relay. However, we
- # can only apply this check out-of-dialog requests without a To
- # tag. In some cases such as call-forwarding, subsequent requests
- # may not include served domain neither as origination nor
- # destination (a@A calls b@B who forwards to c@C. A BYE by c@C is
- # then From b@B and To a@A. There is no mentioning of c@C despite
- # legitimate behaviour of c@C).
- if (!isflagset(FLAG_TOTAG) && strempty($t.did) && strempty($f.did)) {
- sl_reply("403", "Relaying Forbidden");
- drop;
- }
- }
- # The Registrar
- #
- route[REGISTRAR]
- {
- # Process only REGISTERs here.
- if (method != "REGISTER") {
- break;
- }
- # If this is a replica (sent to the multicast address), trust it to
- # be secure and store it in usrloc
- if (dst_ip==224.0.1.75) {
- if (!isflagset(FLAG_REPL_ENABLED)) {
- # Multicast replication administratively disabled.
- # Ignore.
- drop;
- }
- # Read marker from master
- if (search("^Repl-Marker: nated")) {
- setflag(FLAG_NAT);
- }
- # If the replicating server added its own server id to the
- # request, obtain the value and store it in an attribute.
- # This is used by registrar.
- $server_id = @msg.header["SER-Server-ID"];
- # Assume URI in form of UID@mydomain and store contacts
- # under this UID. Note that this only works if local policy
- # causes UIDs to have form compliant to RFC3261 URI
- # usernames.
- if (@ruri.user!="")
- $tu.uid = @ruri.user;
- if (isflagset(FLAG_NAT)) {
- setflag(FLAG_NAT_REG);
- }
- if (!save_mem_nr("location")) {
- log(1, "Error while saving replicated REGISTER.\n");
- }
- drop;
- }
- else {
- # This is a REGISTER request received from the UA. Remove
- # our internal header fields if they are present. The may
- # have been added maliciously.
- remove_hf("SER-Server-ID");
- remove_hf("Repl-Marker");
- }
- # Check if the REGISTER if for one of our local domains.
- if (strempty($t.did)) {
- sl_reply("403", "Register Forwarding Forbidden");
- drop;
- }
- # The REGISTER target is in the To header, so reload the domain.
- if (!lookup_domain("$td", "@to.uri.host")) {
- sl_reply("404", "Unknown Domain");
- drop;
- }
- # Useful for clients that ignore expires in 200 (OK). This is an
- # attempt to keep them sticking to our value of 600.
- append_to_reply("Expires: 600\r\n");
- append_to_reply("Min-Expires: 240\r\n");
- # We want only authenticated users to be registered.
- if (!www_authenticate("$fd.digest_realm", "credentials")) {
- if ($? == -2) {
- sl_reply("500", "Internal Server Error");
- }
- else if ($? == -3) {
- sl_reply("400", "Bad Request");
- }
- else {
- if ($digest_challenge != "") {
- append_to_reply("%$digest_challenge");
- }
- sl_reply("401", "Unauthorized");
- }
- drop;
- }
- # Check if the authenticated user is the same as the target user.
- if (!lookup_user("$tu.uid", "@to.uri")) {
- sl_reply("404", "Unknown user in To");
- drop;
- }
- # the authentication ID does not match the ID in the To header
- if ($f.uid != $t.uid) {
- sl_reply("403", "Authentication and To-Header mismatch");
- drop;
- }
- # Check if the authenticated user is the same as the request
- # originator. You may uncomment it if you care, which URI is in
- # the From header.
- #if (!lookup_user("$fr.uid", "@from.uri")) {
- # sl_reply("404", "Unknown user in From");
- # drop;
- #}
- #if ($fu.uid != $fr.uid) {
- # sl_reply("403", "Authentication and From-Header mismatch");
- # drop;
- #}
- if (isflagset(FLAG_NAT)) {
- setflag(FLAG_NAT_REG);
- }
- # Everything is fine. Store the binding.
- if (!save_contacts("location")) {
- sl_reply("400", "Invalid REGISTER Request");
- drop;
- }
- # do not delete the following 3 lines, they are used by debconf
- #DEBCONF-REPLICATION1-START
- #
- #DEBCONF-REPLICATION1-END
- if (isflagset(FLAG_REPL_ENABLED)) {
- if (isflagset(FLAG_NAT)) {
- append_hf("Repl-Marker: nated\r\n");
- }
- # Append this server's unique ID to the request
- append_hf_value("SER-Server-ID", "%@sys.server_id");
- # We are multicasting a successful REGISTER to all proxies
- # on the multicast network to replicate the contact
- # addresses to all of them. In case they share the same IP
- # address (VIP) it is important to set the sending IP
- # address to an unshared one (in the future a special mcast
- # module may use unbound sockets for sending and leave
- # the source IP address decision up to kernel routing
- # tables).
- #DEBCONF-REPL_SEND_ADDR-START
- force_send_socket(udp:127.0.0.1);
- #DEBCONF-REPL_SEND_ADDR-END
- # Put the UID in the Request-URI so that it doesn't have to
- # be looked up in the database by all multicast receivers.
- attr2uri("$tu.uid","user");
- forward_udp(224.0.1.75,5060);
- }
- #DEBCONF-REPLICATION2-START
- #
- #DEBCONF-REPLICATION2-END
- drop;
- }
- # Authentication of request originators claiming to belong to one of our
- # domains.
- #
- route[AUTHENTICATION]
- {
- # CANCELs and ACKs cannot be challenged.
- if (method=="CANCEL" || method=="ACK") {
- break;
- }
- # Requests from non-local to local domains should be permitted.
- # Remove this if you want a walled garden.
- if (strempty($f.did)) {
- break;
- }
- # Gateways are usually not able to authenticate for their requests.
- # You have to trust them base on some other information such as the
- # source IP address.
- # WARNING: If at all this is only safe in a local network!
- if (src_ip == $gw_ip) {
- break;
- }
- if (!proxy_authenticate("$fd.digest_realm", "credentials")) {
- if ($? == -2) {
- sl_reply("500", "Internal Server Error");
- }
- else if ($? == -3) {
- sl_reply("400", "Bad Request");
- }
- else {
- if (defined $digest_challenge && $digest_challenge != "") {
- append_to_reply("%$digest_challenge");
- }
- sl_reply("407", "Proxy Authentication Required");
- }
- drop;
- }
- # Check if the UID derived from authentication matches that from
- # the From header.
- if (!lookup_user("$fr.uid", "@from.uri")) {
- sl_reply("403", "Fake Identity");
- drop;
- }
- if ($fu.uid != $fr.uid) {
- sl_reply("403", "Fake Identity");
- drop;
- }
- setflag(FLAG_AUTH_OK);
- # Load the user attributes of the caller.
- load_attrs("$fu", "$f.uid");
- }
- # Process request targeted to non-local domains.
- #
- route[OUTBOUND]
- {
- # If a local user calls to a foreign domain we play outbound
- # proxy for them.
- # Comment this out if you want a walled garden.
- if ($f.did != "" && strempty($t.did)) {
- append_hf("P-hint: outbound\r\n");
- route(FORWARD);
- }
- }
- # Process speeddial addresses.
- #
- route[SPEEDDIAL]
- {
- # If the caller is local and uses two digits only, we redirect the
- # UA to the real target.
- if ($fd.did != "" && uri =~ "sip:[0-9][0-9]@") {
- if (sd_lookup("speed_dial")) {
- sl_reply("302", "Speed Dial Redirect");
- }
- else {
- sl_reply("404", "Speed Dial Not Found");
- }
- drop;
- }
- }
- # Process requests targeted to a local user.
- #
- route[INBOUND]
- {
- # lets see if know the callee
- if (!lookup_user("$tu.uid", "@ruri")) {
- break;
- }
- # Load the attributes of the callee.
- load_attrs("$tu", "$t.uid");
- # You can check if the called URI is in fact an alias like this.
- #if (! $tu.uri_canonical) {
- # # If the alias URI has different attributes, you can load
- # # them into the URI track like this.
- # load_attrs("$tr", "@ruri");
- #}
- # Check for call forwarding of the callee.
- # Note: The forwarding target has to be full routable URI
- # in this example.
- if (defined $tu.fwd_always_target && $tu.fwd_always_target != "") {
- attr2uri("$tu.fwd_always_target");
- # If we are forwarding to ourselves, don't remove
- # credentials. Otherwise the request would be challenged
- # again.
- # Note: This doesn't apply to failure_route which may
- # still be problematic -- credentials are already
- # removed when we forward. Consider using a 3xx.
- lookup_domain("$td", "@ruri.host");
- if (defined $t.did && $t.did != "") {
- setflag(FLAG_DONT_RM_CRED);
- }
- route(FORWARD);
- }
- # Native SIP destinations are handled using the usrloc database.
- if (lookup_contacts("location")) {
- append_hf("P-hint: usrloc applied\r\n");
- # destination is behind NAT
- if (isflagset(FLAG_NAT_REG)) {
- setflag(FLAG_NAT); /* client was behind NAT when made registration */
- }
- # We set the tm module timers according to the prefences
- # of the callee (avoid too long ringing of his phones).
- # Note1: Timer values have to be in ms now!
- # Note2: This makes even more sense if you switch to a
- # voicemail from the FAILURE_ROUTE below.
- if ($t.fr_inv_timer) {
- if ($t.fr_timer) {
- t_set_fr("$t.fr_inv_timer", "$t.fr_timer");
- }
- else {
- t_set_fr("$t.fr_inv_timer");
- }
- }
- # This enables session timer support as long as one side
- # supports it. If you want to have session timmer support
- # only for calls from your PSTN gateway but not between pure
- # VoIP calls you can remove the comment marks from the if
- # clause in the next line and closing bracket below.
- # WARNING: If at all you should trust IP addresses only in
- # your local network!
- #if (src_ip == $gw_ip) {
- route(SESSION_TIMER);
- #}
- route(FORWARD);
- }
- else {
- sl_reply("480", "Temporarily unavailable");
- drop;
- }
- }
- # Process calls for PSTN.
- #
- route[PSTN]
- {
- # Check some conditions first:
- # PSTN is available for our own users only.
- if (strempty($f.did)) {
- break;
- }
- # If the attribute $gw_ip isn't set, there is no PSTN service
- # active.
- if (!defined $gw_ip) {
- break;
- }
- # And finally, the username of the Request-URI must look like
- # a phone number.
- if (!uri =~ "^sips?:\+?[0-9]{3,18}@") {
- break;
- }
- # You may have to convert the number in the Request-URI into a
- # format that is accepted by your gateway here.
- # Check permissions of the caller for initial INVITEs.
- if (isflagset(FLAG_INIT_DLG)) {
- if ($f.gw_acl != "1") {
- sl_reply("403", "PSTN Not Permitted");
- drop;
- }
- }
- # If the attribute $asserted_id is set, we add its contents as a
- # Remote-Party-ID header.
- # Depending on your gateway, you may have to add a
- # P-Asserted-Identity header here instead.
- if (defined $asserted_id) {
- xlset_attr("$rpidheader",
- "<sip:%$asserted_id@%@ruri.host>;screen=yes");
- replace_attr_hf("Remote-Party-ID", "$rpidheader");
- }
- # Enable Session Timer support with the gateway.
- route(SESSION_TIMER);
- # Replace the domain part of the Request-URI with the value from
- # the attribute and send it out.
- attr2uri("$gw_ip", "domain");
- # Set the PSTN_ALLOWED flag. This will be checked on the
- # onsend_route.
- setflag(FLAG_PSTN_ALLOWED);
- route(FORWARD);
- }
- # Try to process CANCEL requests quickly.
- #
- route[CATCH_CANCEL]
- {
- if (method == CANCEL) {
- # t_relay_cancel() will stop processing if a matching
- # INVITE was found.
- xlog("L_DEBUG", "catching cancel dialogid=%$dialog_id\n");
- if (!t_relay_cancel()) {
- # An INVITE was found but some error occurred.
- sl_reply("500", "Internal Server Error");
- drop;
- }
- # Bad luck, no corresponding INVITE was found, we have to
- # continue with the script.
- }
- }
- # Site specific policy.
- #
- route[SITE_SPECIFIC]
- {
- # This is only relevant for requests for one of our domains.
- if (strempty($t.did)) {
- break;
- }
- # Do site specific routing such as peering.
- # For example:
- if (uri=~"^sip:000777") {
- rewritehostport("sems01.iptel.org:5074");
- route(FORWARD);
- }
- }
- # Process Session-Timer.
- #
- route[SESSION_TIMER]
- {
- # We are only interested in session establishment or session
- # refreshing.
- #
- if (method != "INVITE" && method != "UPDATE") {
- break;
- }
- # Let's check if the Session-Expires header is already present.
- if (@hf_value.session_expires != "") {
- # Compare the Session-Expires header value with the
- # configured Min-SE.
- eval_push("x:%@hf_value.session_expires.uri");
- eval_oper("(int)", -1);
- eval_push("x:%@cfg_get.session_timer.min_se");
- eval_oper("(int)", -1);
- eval_oper(">=", -2);
- # Let's check for the Suported header.
- if (hf_value_exists("Supported", "timer")) {
- # The UAC supports Session-Timer, so we
- # only need to take a look at the values
- if (@eval.pop[-1] == "0") {
- # Session interval is lower than the
- # configured Min-SE
- append_to_reply("Min-SE: %@cfg_get.session_timer.min_se\r\n");
- sl_reply("422", "Session Interval Too Small");
- drop;
- }
- # We store the session expires value for the reply
- # route and mark the attribute for inserting as
- # Record-Route cookie.
- $stimer = @hf_value.session_expires.uri;
- setavpflag($stimer, "dialog_cookie");
- # Set the session timer flag that indicates the
- # UAC supports the extension.
- setflag(FLAG_SESSIONTIMER);
- }
- else {
- # Session epxires was already inserted by some other
- # proxy
- if (@eval.pop[-1] == "0") {
- # Session interval is lower than the
- # configured Min-SE. There is no point in
- # sending 422 response, because the UAC
- # does not support the extension, the values
- # can be corrected instead.
- assign_hf_value("Session-Expires",
- "%@cfg_get.session_timer.min_se");
- remove_hf_value("Min-SE");
- append_hf_value("Min-SE",
- "%@cfg_get.session_timer.min_se");
- }
- }
- }
- else {
- # No Session Timer is requested yet, neither by UAC nor by
- # proxy
- if (@cfg_get.session_timer.default != "0") {
- # Add a Session Expires header to see if the UAS
- # supports Session Timer. We do not insert a
- # Required header because then the call might fail.
- append_hf_value("Session-Expires",
- "%@cfg_get.session_timer.default");
- if (@cfg_get.session_timer.min_se != "90") {
- append_hf_value("Min-SE",
- "%@cfg_get.session_timer.min_se");
- }
- # Mark the attribute to be inserted as a
- # Record-Route cookie
- $stimer = @cfg_get.session_timer.default;
- setavpflag($stimer, "dialog_cookie");
- }
- }
- }
- # Route which checks and performs ENUM queries
- # #
- route[ENUM]
- {
- # perform ENUM query only if the RURI contains an E.164
- # number as uer part
- if (uri =~ "sip:\+[0-9]?@") {
- # if the ENUM query was successful send it right
- # away of to the new target, otherwise do nothing
- if (enum_query()) {
- route(FORWARD);
- }
- }
- }
- # Failure route for initial INVITEs.
- #
- failure_route[FAILURE_ROUTE]
- {
- if (isflagset(FLAG_INIT_DLG)) {
- # Mark that we are operating from a failure route.
- setflag(FLAG_FAILUREROUTE);
- if (t_check_status("486|600")) {
- # If we received a busy and a busy target is set, forward
- # it there.
- # Note: Again, the forwarding target has to be a routeable
- # URI. We redirect using 3xx to avoid possible issues with
- # credentials (if we consumed them, they may be missing in
- # a loop, if we don't consume them, messages are bigger and
- # more vulnerable)
- if ($tu.fwd_busy_target != "") {
- attr2uri("$tu.fwd_busy_target");
- #attr_destination("$tu.fwd_busy_target");
- #route(FORWARD);
- t_reply("302", "Redirect On Busy");
- }
- # Alternatively, you could forward the request to
- # SEMS/voicemail here
- }
- else if (t_check_status("408|480")) {
- # If we received no answer and the noanswer target is set,
- # forward it there.
- # Note: See above.
- if ($tu.fwd_noanswer_target != "") {
- attr2uri("$tu.fwd_noanswer_target");
- #attr_destination("$tu.fwd_noanswer_target");
- #route(FORWARD);
- t_reply("302", "Redirect On No Answer");
- }
- }
- } # if (isflagset...
- }
- # Onreply route that fixes NAT in responses.
- #
- onreply_route[REPLY_ROUTE]
- {
- # Check and fix the Contact in the reply to
- # allow proper routing of in-dialog messages.
- route(UAS_NAT_DETECTION);
- # If RTP proxy was activated and this is a 18x or 2xx reply with a
- # body, inform RTP proxy.
- if (isflagset(FLAG_RTP_PROXY)
- && status=~"(18[03])|(2[0-9][0-9])"
- && @msg.body != "")
- {
- force_rtp_proxy('r');
- }
- # Let's check for session timer support.
- if (isflagset(FLAG_SESSIONTIMER) && status =~ "2[0-9][0-9]") {
- # The UAC wanted to have a session timer.
- if (strempty(@hf_value.session_expires)) {
- # But the UAS does not support it, so we will try
- # to convince the UAC to do it.
- append_hf_value("Session-Expires",
- "%$stimer;refresher=uac");
- if (!hf_value_exists("Require", "timer")) {
- include_hf_value("Require", "timer");
- }
- }
- }
- }
- # Do some final checks before a request is sent out.
- onsend_route
- {
- # Bypass check: Eliminate requests to the PSTN gateway if they have
- # not passed ACL checks and are not marked with FLAG_PSTN_ALLOWED
- # but are dialog-initiating requests (no to-tag, no CANCEL, no ACK).
- # This helps to stop policy bypasses (gateway IP uploaded as a
- # forked contact, or a call-forwarding destination, or a DNS name,
- # or a preloaded route, or something else possibly)
- if (defined $g.gw_ip && to_ip==$g.gw_ip && !isflagset(FLAG_PSTN_ALLOWED)
- && !isflagset(FLAG_TOTAG)
- && method != "ACK" && method != "CANCEL")
- {
- log(1, "ALERT: non authorized packet for PSTN, dropping...\n%mb\n");
- # You can't use advanced features from onsend_route.
- # xlog("L_ALERT", "non authorized packet for PSTN, dropping...\n%mb\n");
- drop;
- }
- # RFC 1918 relay protection: Useful if SER is attached to an
- # administrative network using private IP address space and you
- # wish to prevent UACs from relaying their packets there.
- #
- # You will have to comment this out, if you are regularly serving
- # an RFC 1918 address space.
- if (to_ip==10.0.0.0/8 || to_ip==172.16.0.0/12
- || to_ip==192.168.0.0/16)
- {
- log(1, "ALERT: Packet targeted to an RFC1918 address dropped\n");
- drop;
- }
- }
- # Run every minute by the timer module.
- #
- route[ON_1MIN_TIMER] {
- # Cleanup expired location records
- # MySQL version:
- db_query("delete from location where expires<utc_timestamp()");
- # PostgreSQL version:
- #db_query("delete from location where expires<now()");
- # Reload domains if domain table has been changed recently.
- # Note: because global attributes are read-only and we can't
- # easily remember the "last" status, we check for changed
- # timestamp in 2 minute time-interval.
- # MySQL version:
- 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");
- # PostgreSQL version:
- #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");
- if (@db.fetch.reload.count=="1") {
- # Domain reload only available as fifo command.
- exec_msg("sercmd domain.reload");
- }
- db_close("reload");
- # Reload global attributes (they are cached in memory) if the contents of
- # the global_attrs table has been changed recently.
- db_query("select value from global_attrs where name='gattr_timestamp' and type=0 and cast(value as unsigned int) between unix_timestamp(now())-120 and unix_timestamp(now())", "gattr_reload");
- if (@db.fetch.gattr_reload.count=="1") {
- exec_msg("sercmd global.reload");
- }
- db_close("gattr_reload");
- }
- #!ifdef WITH_XMLRPC
- # handle xmlrpcs
- route[XMLRPC]{
- # accept xmlrpc requests only from localhost
- if (src_ip!=127.0.0.1
- #!ifdef XMLRPC_ALLOW_NET1
- && src_ip != XMLRPC_ALLOW_NET1
- #!endif
- #!ifdef XMLRPC_ALLOW_NET2
- && src_ip != XMLRPC_ALLOW_NET2
- #!endif
- #!ifdef XMLRPC_ALLOW_NET3
- && src_ip != XMLRPC_ALLOW_NET3
- #!endif
- ) {
- xmlrpc_reply("400", "xmlrpc not allowed from this address");
- return;
- }
- if (method!="POST" && method!="GET") {
- xmlrpc_reply("400", "unsupported HTTP method");
- return;
- }
- if (msg:len >= 8192) {
- xmlrpc_reply("513", "request too big");
- return;
- }
- #!ifdef XMLRPC_TLS_ONLY
- # allow xmlrpc only on TLS and only if the client certificate is valid
- if (proto!=TLS){
- xmlrpc_reply("400", "xmlrpc allowed only over TLS");
- return;
- }
- if (@tls.peer.verified!=""){
- xmlrpc_reply("400", "Unauthorized");
- return;
- }
- #!endif
- # close connection only for xmlrpclib user agents (there is a bug in
- # xmlrpclib: it waits for EOF before interpreting the response).
- if (search("^User-Agent:.*xmlrpclib"))
- set_reply_close();
- set_reply_no_connect(); # optional
- dispatch_rpc();
- }
|