├── .gitignore ├── scripts ├── opensips.sysconfig ├── rtpengine.sysconfig ├── rtpengine.service ├── opensips.service ├── create_translations_table.sqlite ├── create_translations_table.mysql ├── restart_script.sh ├── debian8_install.sh └── centos7_install.sh ├── core ├── build.rb ├── opensips.var.rb.sample └── opensips.cfg.erb └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | opensips.var.rb 2 | opensips.cfg 3 | -------------------------------------------------------------------------------- /scripts/opensips.sysconfig: -------------------------------------------------------------------------------- 1 | # Add extra options here 2 | OPTIONS="" 3 | -------------------------------------------------------------------------------- /scripts/rtpengine.sysconfig: -------------------------------------------------------------------------------- 1 | # Add extra options here 2 | OPTIONS="--interface xxx.xxx.xxx.xxx --listen-ng xxx.xxx.xxx.xxx:60000 -m 50000 -M 55000 -E -L 7" 3 | -------------------------------------------------------------------------------- /core/build.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'erb' 3 | require './opensips.var.rb' 4 | 5 | template = ERB.new(File.read('./opensips.cfg.erb'), nil, '-') 6 | 7 | outfile = File.new('opensips.cfg', 'w'); 8 | 9 | outfile.puts template.result($erb_context) 10 | 11 | -------------------------------------------------------------------------------- /scripts/rtpengine.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Kernel based rtp proxy 3 | After=syslog.target 4 | After=network.target 5 | 6 | [Service] 7 | Type=forking 8 | PIDFile=/var/run/rtpengine.pid 9 | EnvironmentFile=-/etc/sysconfig/rtpengine 10 | ExecStart=/usr/local/bin/rtpengine -p /var/run/rtpengine.pid $OPTIONS 11 | 12 | Restart=always 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /scripts/opensips.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=OpenSIPS is a very fast and flexible SIP (RFC3261) server 3 | After=network.target mysqld.service rtpengine.service 4 | 5 | [Service] 6 | Type=forking 7 | User=opensips 8 | Group=opensips 9 | EnvironmentFile=-/etc/sysconfig/opensips 10 | PIDFile=/var/run/opensips/opensips.pid 11 | ExecStart=/usr/sbin/opensips -P /var/run/opensips/opensips.pid -f /etc/opensips/opensips.cfg $OPTIONS 12 | 13 | Restart=always 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | 18 | -------------------------------------------------------------------------------- /scripts/create_translations_table.sqlite: -------------------------------------------------------------------------------- 1 | CREATE TABLE translations ( 2 | id integer AUTO_INCREMENT, 3 | from_username char(64) DEFAULT NULL, 4 | from_domain char(64) DEFAULT NULL, 5 | match_regex char(64) DEFAULT NULL, 6 | tran_strip int(10) DEFAULT NULL, 7 | tran_prefix char(64) DEFAULT NULL, 8 | tran_user char(64) DEFAULT NULL, 9 | tran_domain char(64) DEFAULT NULL, 10 | tran_port int(11) DEFAULT NULL, 11 | tran_add_header char(255) DEFAULT NULL, 12 | tran_priority int(10) NOT NULL DEFAULT '99', 13 | match_user_agent char(64) DEFAULT NULL, 14 | tran_strip_port tinyint(1) DEFAULT NULL); 15 | 16 | -------------------------------------------------------------------------------- /scripts/create_translations_table.mysql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Table structure for table `translations` 3 | -- 4 | DROP TABLE IF EXISTS `translations`; 5 | CREATE TABLE `translations` ( 6 | `id` int(11) NOT NULL AUTO_INCREMENT, 7 | `from_username` char(64) DEFAULT NULL, 8 | `from_domain` char(64) DEFAULT NULL, 9 | `match_regex` char(64) DEFAULT NULL, 10 | `tran_strip` int(10) DEFAULT NULL, 11 | `tran_prefix` char(64) DEFAULT NULL, 12 | `tran_user` char(64) DEFAULT NULL, 13 | `tran_domain` char(64) DEFAULT NULL, 14 | `tran_port` int(11) DEFAULT NULL, 15 | `tran_add_header` char(255) DEFAULT NULL, 16 | `tran_priority` int(10) NOT NULL DEFAULT '99', 17 | UNIQUE KEY `id` (`id`), 18 | KEY `from_username` (`from_username`,`from_domain`,`match_regex`) 19 | ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 20 | -------------------------------------------------------------------------------- /core/opensips.var.rb.sample: -------------------------------------------------------------------------------- 1 | $erb_context = binding 2 | debug_level = '3' 3 | enable_udp = true 4 | enable_tcp = true 5 | enable_tls = true 6 | enable_ws = true 7 | enable_ipv6 = true 8 | 9 | log_facility = 'LOG_LOCAL2' 10 | listen_ip = 'xxx.xxx.xxx.xxx' 11 | listen_ipv6 = 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxxx:xxxx' 12 | listen_port = '5060' 13 | tls_listen_port = '5061' 14 | ws_listen_port = '8080' 15 | db_url = 'sqlite://var/db/opensips/opensips' 16 | 17 | module_path = '/usr/local/lib64/opensips/modules/' 18 | 19 | user = 'opensips' 20 | group = 'opensips' 21 | 22 | use_enum = '0' 23 | 24 | # We set db_url then reference it for all other db_urls 25 | # since they share a common db. You can set them individually. 26 | group_db_url = db_url 27 | alias_db_url = db_url 28 | auth_db_url = db_url 29 | avp_db_url = db_url 30 | dialog_db_url = db_url 31 | usrloc_db_url = db_url 32 | domain_db_url = db_url 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Federated SIP server 2 | ==================== 3 | 4 | The Federated SIP project is a set of scripts designed to run OpenSIPS + rtpengine in a way that will provide federated, open communication with any other SIP server on the internet. 5 | 6 | Federated SIP Features 7 | ---------------------- 8 | 9 | - SIP registrar with multiple domain support, including authenticated and unauthenticated users. 10 | - Complete server side NAT handling for clients behind NAT. 11 | - Federated SIP proxy server that follows RFC3263 for locating SIP servers. 12 | - WebSocket, TCP, TLS, and UDP connectivity on IPV4 or IPV6. 13 | - Media interop between DTLS-SRTP, SRTP and RTP 14 | - Powerful regular expression based outbound translations for dynamic routing. 15 | - Centos and Debian system set up scripts to turn a bare OS install into a full SIP system in a matter of minutes. 16 | 17 | Checkout KwikyKonf: 18 | * [code](https://github.com/etamme/kwickykonf) 19 | * [demo](http://video.uphreak.com/#github) 20 | 21 | Together with Federate-SIP they make a fast and light WebRTC video chat. 22 | -------------------------------------------------------------------------------- /scripts/restart_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # STOP 4 | #-------------------------------------------------------- 5 | PID=$(pidof opensips) 6 | if [ -e $PID ] 7 | then 8 | echo "opensips not running" 9 | else 10 | echo "killing opensips" 11 | for P in $(pidof opensips) 12 | do 13 | kill -9 $P 14 | done 15 | sleep 1 16 | fi 17 | PID=$(pidof rtpengine) 18 | if [ -e $PID ] 19 | then 20 | echo "rtpengine not running" 21 | else 22 | echo "killing rtpengine" 23 | kill -9 $PID 24 | sleep 1 25 | fi 26 | if [ -d "/proc/rtpengine/0" ]; then 27 | echo "removing control table" 28 | echo "del 0" > /proc/rtpengine/control 29 | fi 30 | echo "removing iptables rules" 31 | iptables -D INPUT -p udp -j rtpengine 32 | iptables -D rtpengine -p udp -j RTPENGINE --id 0 33 | iptables -X rtpengine 34 | echo "unloading kernel module" 35 | rmmod xt_RTPENGINE 36 | sleep 1 37 | 38 | # START 39 | #-------------------------------------------------------- 40 | IP=$(ifconfig eth0 | grep 'inet ' | awk '{print $2}') 41 | echo "loading kernel module" 42 | insmod /usr/local/src/rtpengine/kernel-module/xt_RTPENGINE.ko 43 | sleep 1 44 | 45 | echo "creating iptables rules" 46 | iptables -N rtpengine 47 | iptables -I rtpengine -p udp -j RTPENGINE --id 0 48 | iptables -I INPUT -p udp -j rtpengine 49 | sleep 1 50 | 51 | echo "starting rtpengine" 52 | /usr/local/rtpengine/rtpengine -p /var/run/rtpengine.pid --interface $IP --listen-ng $IP:60000 -m 50000 -M 55000 -L 7 --table=0 --log-facility=local3 53 | sleep 1 54 | 55 | echo "starting opensips" 56 | /usr/local/opensips/sbin/opensips 57 | -------------------------------------------------------------------------------- /scripts/debian8_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # get some basic vars for later 4 | DIR=$(pwd) 5 | if [[ $DIR == *scripts ]] 6 | then 7 | echo "going up to project root directory" 8 | cd .. 9 | DIR=$(pwd) 10 | fi 11 | IP=$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}') 12 | NUM=$(( ( RANDOM % 1000 ) + 1 )) 13 | 14 | # get optional domain and user from user input 15 | echo "Enter your domain name, or press enter for a randomly generated subdomain" 16 | read DOMAIN 17 | if [ -z "$DOMAIN" ] 18 | then 19 | DOMAIN="proxy$NUM.uphreak.com" 20 | fi 21 | echo "Enter a user name, or press enter for a randomly generated user" 22 | read USER 23 | if [ -z "$USER" ] 24 | then 25 | USER="user$NUM" 26 | fi 27 | 28 | # update package lists 29 | apt-get update 30 | 31 | # install required dependencies and build tools 32 | apt-get install -y build-essential bison flex pkgconf ruby libpcre3-dev libsqlite3-dev libncurses5-dev sqlite3 libglib2.0-dev libssl-dev libxml2-dev libxmlrpc-core-c3-dev libcurl4-openssl-dev tcpdump 33 | 34 | # add opensips user with no shell 35 | useradd -s /bin/false opensips 36 | 37 | # clone required repos to local directory 38 | cd /usr/local/src 39 | git clone https://github.com/OpenSIPS/opensips.git 40 | git clone https://github.com/sipwise/rtpengine.git 41 | git clone https://github.com/ralight/sqlite3-pcre.git 42 | 43 | # build opensips 44 | cd opensips 45 | cp Makefile.conf.template Makefile.conf 46 | sed -i -e 's/include_modules?=/include_modules?= db_sqlite/g' Makefile.conf 47 | sed -i -e 's/PREFIX=\/usr\/local\//PREFIX=\/usr\/local\/opensips\//g' Makefile.conf 48 | make all && make all install 49 | 50 | # set up our sqlite database 51 | mkdir -p /var/db/opensips 52 | sqlite3 /var/db/opensips/opensips < ./scripts/sqlite/standard-create.sql 53 | sqlite3 /var/db/opensips/opensips < ./scripts/sqlite/dialog-create.sql 54 | sqlite3 /var/db/opensips/opensips < ./scripts/sqlite/domain-create.sql 55 | sqlite3 /var/db/opensips/opensips < ./scripts/sqlite/auth_db-create.sql 56 | sqlite3 /var/db/opensips/opensips < ./scripts/sqlite/usrloc-create.sql 57 | sqlite3 /var/db/opensips/opensips < $DIR/scripts/create_translations_table.sqlite 58 | sqlite3 /var/db/opensips/opensips "insert into translations (from_domain,match_regex,tran_domain,tran_strip) values ('$DOMAIN','^\+18[045678]{2}[0-9]{7}$','tf.arctele.com',1);" 59 | 60 | chown -R opensips:opensips /var/db/opensips 61 | 62 | # set up opensipsctlrc to use our sqlite database 63 | sed -i -e 's/# DBENGINE=MYSQL/DBENGINE=SQLITE/g' /usr/local/opensips/etc/opensips/opensipsctlrc 64 | sed -i -e 's/# DB_PATH="\/usr\/local\/etc\/opensips\/dbtext"/DB_PATH=\/var\/db\/opensips\/opensips/g' /usr/local/opensips/etc/opensips/opensipsctlrc 65 | 66 | # add our ip to our domain table 67 | /usr/local/opensips/sbin/opensipsctl domain add $DOMAIN:5060 68 | /usr/local/opensips/sbin/opensipsctl domain add $DOMAIN 69 | 70 | # build rtpengine daemon 71 | cd /usr/local/src/rtpengine/daemon && make 72 | mkdir /usr/local/rtpengine && cp rtpengine /usr/local/rtpengine/ 73 | 74 | # start rtpengine 75 | /usr/local/rtpengine/rtpengine -p /var/run/rtpengine.pid --interface $IP --listen-ng $IP:60000 -m 50000 -M 55000 -E -L 3 & 76 | 77 | # build sqlite pcre extension 78 | cd /usr/local/src/sqlite3-pcre 79 | make && make install 80 | 81 | # configure federated opensips.var.rb 82 | cd $DIR/core 83 | cp opensips.var.rb.sample opensips.var.rb 84 | 85 | # disable tls and ipv6 86 | sed -i -e 's/enable_tls = true/enable_tls = false/g' opensips.var.rb 87 | sed -i -e 's/enable_ipv6 = true/enable_ipv6 = false/' opensips.var.rb 88 | # set our listening IP address 89 | sed -i -e "s/listen_ip = 'xxx.xxx.xxx.xxx'/listen_ip = '$IP'/g" opensips.var.rb 90 | # set our modules directory 91 | sed -i -e 's#/usr/local/lib64/opensips/modules/#/usr/local/opensips/lib64/opensips/modules/#g' opensips.var.rb 92 | 93 | # build the config 94 | ./build.rb && cp opensips.cfg /usr/local/opensips/etc/opensips/opensips.cfg 95 | 96 | # start opensips 97 | cd /usr/local/opensips && sbin/opensips 98 | 99 | # add a subscriber 100 | sbin/opensipsctl add "$USER@$DOMAIN" "ilikeopensips$NUM" 101 | 102 | # sleep to get nicer output then print info 103 | sleep 5 104 | echo "" 105 | echo "" 106 | echo "" 107 | echo "AOR : $USER@$DOMAIN" 108 | echo "PASSWORD: ilikeopensips$NUM" 109 | echo "PROXY : $IP" 110 | 111 | -------------------------------------------------------------------------------- /scripts/centos7_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # get some basic vars for later 3 | DIR=$(pwd) 4 | if [[ $DIR == *scripts ]] 5 | then 6 | echo "going up to project root directory" 7 | cd .. 8 | DIR=$(pwd) 9 | fi 10 | IP=$(ifconfig eth0 | awk '/inet /{print substr($2,1)}') 11 | NUM=$(( ( RANDOM % 1000 ) + 1 )) 12 | 13 | # get optional domain and user from user input 14 | echo "Enter your domain name, or press enter for a randomly generated subdomain" 15 | read DOMAIN 16 | if [ -z "$DOMAIN" ] 17 | then 18 | DOMAIN="proxy$NUM.uphreak.com" 19 | fi 20 | echo "Enter a user name, or press enter for a randomly generated user" 21 | read USER 22 | if [ -z "$USER" ] 23 | then 24 | USER="user$NUM" 25 | fi 26 | 27 | # add opensips user with no shell 28 | useradd -s /bin/false opensips 29 | 30 | # install required deps and build tools 31 | yum -y install vim-enhanced libcurl-devel ncurses-devel ruby glib2 glib2-devel xmlrpc-c-devel xmlrpc-c sqlite sqlite-devel pcre pcre-devel openssl openssl-devel tcpdump iptables-devel kernel-devel kernel 32 | yum -y group install "Development Tools" 33 | 34 | # clone required repos 35 | cd /usr/local/src 36 | git clone https://github.com/OpenSIPS/opensips.git 37 | git clone https://github.com/sipwise/rtpengine.git 38 | git clone https://github.com/ralight/sqlite3-pcre.git 39 | 40 | # build opensips 41 | cd opensips 42 | cp Makefile.conf.template Makefile.conf 43 | sed -i -e 's/include_modules?=/include_modules?= db_sqlite/g' Makefile.conf 44 | sed -i -e 's/PREFIX=\/usr\/local\//PREFIX=\/usr\/local\/opensips\//g' Makefile.conf 45 | make all && make all install 46 | 47 | # set up our sqlite database 48 | cd scripts/sqlite 49 | mkdir /var/db/opensips && chown opensips:opensips /var/db/opensips 50 | chown -R opensips:opensips /var/db/opensips 51 | sudo -u opensips sqlite3 /var/db/opensips/opensips < standard-create.sql 52 | sudo -u opensips sqlite3 /var/db/opensips/opensips < dialog-create.sql 53 | sudo -u opensips sqlite3 /var/db/opensips/opensips < domain-create.sql 54 | sudo -u opensips sqlite3 /var/db/opensips/opensips < auth_db-create.sql 55 | sudo -u opensips sqlite3 /var/db/opensips/opensips < usrloc-create.sql 56 | sudo -u opensips sqlite3 /var/db/opensips/opensips < $DIR/scripts/create_translations_table.sqlite 57 | sudo -u opensips sqlite3 /var/db/opensips/opensips "insert into translations (from_domain,match_regex,tran_domain, tran_strip) values ('$DOMAIN','^\+18[045678]{2}[0-9]{7}$','tf.arctele.com',1);" 58 | 59 | # set up opensipsctlrc to use our sqlite database 60 | sed -i -e 's/# DBENGINE=MYSQL/DBENGINE=SQLITE/g' /usr/local/opensips/etc/opensips/opensipsctlrc 61 | sed -i -e 's/# DB_PATH="\/usr\/local\/etc\/opensips\/dbtext"/DB_PATH=\/var\/db\/opensips\/opensips/g' /usr/local/opensips/etc/opensips/opensipsctlrc 62 | 63 | # add our ip to our domain table 64 | /usr/local/opensips/sbin/opensipsctl domain add $IP:5060 65 | /usr/local/opensips/sbin/opensipsctl domain add $DOMAIN:5060 66 | /usr/local/opensips/sbin/opensipsctl domain add $DOMAIN 67 | 68 | # build rtpengine daemon 69 | cd /usr/local/src/rtpengine/daemon 70 | git checkout -t origin/mr4.0.1 71 | make 72 | mkdir /usr/local/rtpengine && cp rtpengine /usr/local/rtpengine/ 73 | 74 | # start rtpengine 75 | /usr/local/rtpengine/rtpengine -p /var/run/rtpengine.pid --interface $IP --listen-ng $IP:60000 -m 50000 -M 55000 -E -L 3 & 76 | 77 | # build sqlite pcre extension 78 | cd /usr/local/src/sqlite3-pcre 79 | make && make install 80 | 81 | # configure federated opensips.var.rb 82 | cd $DIR/core 83 | cp opensips.var.rb.sample opensips.var.rb 84 | 85 | # disable tls and ipv6 86 | sed -i -e 's/enable_tls = true/enable_tls = false/g' opensips.var.rb 87 | sed -i -e 's/enable_ipv6 = true/enable_ipv6 = false/g' opensips.var.rb 88 | 89 | # set our listening IP address 90 | sed -i -e "s/listen_ip = 'xxx.xxx.xxx.xxx'/listen_ip = '$IP'/g" opensips.var.rb 91 | 92 | # set our modules directory 93 | sed -i -e 's#/usr/local/lib64/opensips/modules/#/usr/local/opensips/lib64/opensips/modules/#g' opensips.var.rb 94 | 95 | # build the config 96 | ./build.rb && cp opensips.cfg /usr/local/opensips/etc/opensips/opensips.cfg 97 | 98 | # start opensips 99 | cd /usr/local/opensips && sbin/opensips 100 | 101 | # add a subscriber 102 | sbin/opensipsctl add "$USER@$DOMAIN" "ilikeopensips$NUM" 103 | 104 | # sleep to get nicer output, then print info 105 | sleep 5; 106 | echo "" 107 | echo "" 108 | echo "" 109 | echo "AOR : $USER@$DOMAIN" 110 | echo "PASSWORD: ilikeopensips$NUM" 111 | echo "PROXY : $IP" 112 | -------------------------------------------------------------------------------- /core/opensips.cfg.erb: -------------------------------------------------------------------------------- 1 | # process settings 2 | fork=yes 3 | children=2 4 | 5 | # uncomment for debug 6 | # fork=no 7 | # children=1 8 | 9 | # logging and debug settings 10 | debug=<%= debug_level %> 11 | log_stderror=no 12 | log_facility=<%= log_facility %> 13 | 14 | # network settings 15 | <%-if enable_udp-%> 16 | listen=udp:<%= listen_ip %>:<%= listen_port %> 17 | <%-end-%> 18 | <%-if enable_tcp-%> 19 | listen=tcp:<%= listen_ip %>:<%= listen_port %> 20 | <%-end-%> 21 | <%-if enable_tls-%> 22 | listen=tls:<%= listen_ip %>:<%= tls_listen_port %> 23 | <%-end-%> 24 | <%-if enable_ws-%> 25 | listen=ws:<%= listen_ip %>:<%= ws_listen_port %> 26 | <%-end-%> 27 | <%-if enable_ipv6-%> 28 | <%-if enable_udp-%> 29 | listen=udp:[<%= listen_ipv6 %>]:<%= listen_port%> 30 | <%-end-%> 31 | <%-if enable_tcp-%> 32 | listen=tcp:[<%= listen_ipv6 %>]:<%= listen_port%> 33 | <%-end-%> 34 | <%-if enable_tls-%> 35 | listen=tls:[<%= listen_ipv6 %>]:<%= tls_listen_port%> 36 | <%-end-%> 37 | <%-if enable_ws-%> 38 | listen=ws:[<%= listen_ipv6 %>]:<%= ws_listen_port %> 39 | <%-end-%> 40 | 41 | dns_try_ipv6 = 1 42 | <%-end-%> 43 | 44 | tcp_keepalive = 1 45 | tcp_keepcount = 5 46 | tcp_keepidle = 15 47 | tcp_keepinterval = 10 48 | 49 | #set module path 50 | mpath="<%= module_path %>" 51 | 52 | user=<%= user %> 53 | group=<%= group %> 54 | 55 | <%-if enable_udp-%> 56 | loadmodule "proto_udp.so" 57 | <%-end-%> 58 | <%-if enable_tcp-%> 59 | loadmodule "proto_tcp.so" 60 | <%-end-%> 61 | <%-if enable_tls-%> 62 | loadmodule "proto_tls.so" 63 | <%-end-%> 64 | <%-if enable_ws-%> 65 | loadmodule "proto_ws.so" 66 | <%-end-%> 67 | loadmodule "signaling.so" 68 | loadmodule "sl.so" 69 | loadmodule "tm.so" 70 | loadmodule "rr.so" 71 | loadmodule "db_sqlite.so" 72 | loadmodule "dialog.so" 73 | loadmodule "maxfwd.so" 74 | loadmodule "usrloc.so" 75 | loadmodule "registrar.so" 76 | loadmodule "textops.so" 77 | loadmodule "sipmsgops.so" 78 | loadmodule "mi_fifo.so" 79 | loadmodule "uri.so" 80 | loadmodule "auth.so" 81 | loadmodule "auth_db.so" 82 | loadmodule "nathelper.so" 83 | loadmodule "rtpengine.so" 84 | loadmodule "avpops.so" 85 | loadmodule "pike.so" 86 | loadmodule "domain.so" 87 | loadmodule "enum.so" 88 | loadmodule "stun.so" 89 | 90 | # ---- tcp params ---- 91 | modparam("proto_tcp","tcp_async",1) 92 | 93 | # ---- tm params ---- 94 | # enable transactional avps 95 | modparam("tm", "onreply_avp_mode", 1) 96 | 97 | # ---- fifo params ---- 98 | modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") 99 | 100 | # ---- record route params ---- 101 | # append from tag to the RR. This is used to help determine 102 | modparam("rr", "append_fromtag", 1) 103 | 104 | # ---- registrar params ---- 105 | modparam("registrar", "received_avp", "$avp(received)") 106 | modparam("registrar", "attr_avp", "$avp(attr)") 107 | 108 | # ---- nathelper params ---- 109 | modparam("nathelper","natping_interval", 15) 110 | modparam("nathelper", "received_avp", "$avp(received)") 111 | 112 | # ----- db_sqlite params ---- 113 | modparam("db_sqlite", "load_extension", "/usr/lib/sqlite3/pcre.so") 114 | 115 | # ---- dialog params ---- 116 | modparam("dialog", "db_mode", 1) 117 | modparam("dialog", "db_url", "<%= dialog_db_url %>") 118 | 119 | # ---- user location params ---- 120 | modparam("usrloc", "db_mode", 1) 121 | modparam("usrloc", "db_url", "<%= usrloc_db_url %>") 122 | 123 | # when a UAC sends nated register set a branch flag before saving. 124 | # when lookup is called, usrloc will restore the branch flag and let us 125 | # detect a nated "callee" or UAS 126 | modparam("usrloc", "nat_bflag","uas_nat") 127 | # use the domain portion to match users - not just the user portion 128 | modparam("usrloc", "use_domain",1) 129 | 130 | # ---- auth params ---- 131 | modparam("auth_db", "calculate_ha1", 0) 132 | modparam("auth_db", "password_column", "ha1") 133 | modparam("auth_db", "db_url", "<%= auth_db_url %>") 134 | modparam("auth_db", "load_credentials", "") 135 | modparam("auth_db", "use_domain", 1) 136 | 137 | # ---- avpops params ---- 138 | modparam("avpops", "db_url", "<%= avp_db_url %>") 139 | modparam("avpops","use_domain",1) 140 | 141 | # ----- pike params ---- 142 | modparam("pike", "sampling_time_unit", 10) 143 | modparam("pike", "reqs_density_per_unit", 30) 144 | modparam("pike", "remove_latency", 3600) 145 | 146 | # ----- domain params ---- 147 | modparam("domain", "db_url", "<%= domain_db_url %>") 148 | 149 | # ----- stun params ----- 150 | # keeps logs free of parse errors on stun packets 151 | modparam("stun","primary_ip","<%= listen_ip %>") 152 | modparam("stun","primary_port","<%= listen_port %>") 153 | # alternate ip required, using localhost for compatibility 154 | modparam("stun","alternate_ip","127.0.0.1") 155 | modparam("stun","alternate_port","6050") 156 | 157 | # ----- rtpengine params ---- 158 | modparam("rtpengine", "rtpengine_sock", "udp:<%= listen_ip %>:60000") 159 | <%-if enable_tls-%> 160 | # ----- tls params ---- 161 | modparam("proto_tls", "require_cert", "0") 162 | modparam("proto_tls", "verify_cert", "0") 163 | modparam("proto_tls", "tls_method", "SSLv23") 164 | # server side tls only (not making outbound tls connections) 165 | modparam("proto_tls", "certificate", 166 | "/usr/local/etc/opensips/tls/server/server-cert.pem") 167 | modparam("proto_tls", "private_key", 168 | "/usr/local/etc/opensips/tls/server/server-privkey.pem") 169 | modparam("proto_tls", "ca_list", 170 | "/usr/local/etc/opensips/tls/server/server-calist.pem") 171 | <%-end-%> 172 | 173 | # branch flags 174 | # ------------ 175 | # uas_nat - UAS behind nat 176 | # uas_ws - UAS is a websockets client 177 | # upstream_request - Set if the UAC/UAS have reversed from their initial roles 178 | # sdp_offer - Set if we have made an offer, for 183/PRACK offer/answer 179 | 180 | # avps 181 | # ------------ 182 | # uac_nat - transactional avp for detecting UAC behind nat on response 183 | # attr - set before userlocation save, and restored on lookup 184 | 185 | # main routes 186 | # ----------- 187 | # route - general request processing 188 | # route["initial_requests"] - initial request route processing 189 | # route["sequential_requests"] - sequential request route processing 190 | # branch_route["rtpengine"] - processing for rtpengine flags per branch 191 | # onreply_route["reply"] - reply processing for nat and rtpengine flags 192 | # 193 | # helper routes 194 | # ------------- 195 | # route["to_e164"] - special processing for e164 196 | # route["enum_query"] - does enum lookup if enabled 197 | # route["outbound_translations"] - look up and apply translations 198 | # route["to_local_domain"] - user location lookup and processing 199 | # route["challenge_request"] - consolidated digest auth route 200 | 201 | # main request routing logic 202 | route{ 203 | # choose to enable, or disable enum lookups by setting this to 1 or 0 204 | $var(use_enum)=<%= use_enum %>; 205 | 206 | # use variables in the xlog to make log output "standardized" in spacing 207 | $var(prefix)="route : "+ 208 | $(cs{s.width, 6})+": "+$(rm{s.width, 9})+":"; 209 | 210 | # some scanner mitigation 211 | 212 | # check to see if the src ip is flooding us and drop requests accordingly 213 | if ( src_ip != myself && !pike_check_req() ) { exit; } 214 | # check packet for signs that it came from a scanner 215 | if( $ua=~"^sipvicious" || 216 | $ua=~"^freindly-scanner" || 217 | $ua=~"^VaxSip" || 218 | $ua=~"^sipcli" || 219 | $rd=="<%= listen_ip %>") 220 | { 221 | xlog("L_INFO","$var(prefix) ban scanner $si\n"); 222 | exit; 223 | } 224 | 225 | # kill any requests that we do not handle 226 | if (!is_method("UPDATE|PRACK|SUBSCRIBE|NOTIFY|REGISTER|INVITE|ACK|BYE| 227 | CANCEL|REFER|OPTIONS|INFO|MESSAGE")) 228 | { 229 | sl_send_reply("405","Method Not Allowed"); 230 | exit; 231 | } 232 | 233 | # we do not handle any subscriptions locally 234 | if (is_method("SUBSCRIBE") && uri == myself) { 235 | sl_send_reply("405","Method Not Allowed"); 236 | exit; 237 | } 238 | 239 | # kill anything that is looping 240 | if (!mf_process_maxfwd_header("10")) { 241 | sl_send_reply("483","Too Many Hops"); 242 | exit; 243 | } 244 | 245 | # record route all requests b/c it doesn't hurt, and some 246 | # UA are buggy and throw away route sets 247 | if (!is_method("REGISTER")) { 248 | record_route(); 249 | } 250 | 251 | # setup avp for detecting uac behind a nat in the response 252 | $avp(uac_nat)=0; 253 | 254 | # UAC nat detection 255 | # 256 | # See the following url for more options : 257 | # http://www.opensips.org/html/docs/modules/2.1.x/nathelper.html#id294107 258 | # 259 | 260 | # We are also checking to see if a Record-Route header is present. 261 | # We only want to do contact rewriting for user agents that are "local" 262 | # to us, aka immediately adjacent not using other proxy servers. 263 | if ( af == INET && !is_present_hf("Record-Route") && nat_uac_test("35")) { 264 | xlog("L_INFO","$var(prefix) request from uac behind nat\n"); 265 | # append recieved and port to first via so we can route responses back 266 | force_rport(); 267 | # set a transactional avp letting us know that the uac is behind a nat 268 | $avp(uac_nat)=1; 269 | if (is_method("REGISTER")) { 270 | fix_nated_register(); 271 | } else { 272 | fix_nated_contact(); 273 | # this helps us know if the UAS (requested destination) in a 274 | # sequential request is behind a nat 275 | search_append('Contact:.*sip:[^>[:cntrl:]]*', ';nat=yes'); 276 | } 277 | } 278 | 279 | # we will hand off to either initial or sequential request processing blocks 280 | # that will return and continue executing the code after this if/else 281 | 282 | # initial request processing 283 | if (!has_totag()) { 284 | route("initial_requests"); 285 | } 286 | # sequential request processing 287 | else { 288 | if (is_method("CANCEL|BYE")) { 289 | rtpengine_delete(); 290 | } 291 | route("sequential_requests"); 292 | } 293 | 294 | # set our reply route 295 | t_on_reply("reply"); 296 | 297 | # all processing has been completed, t_relay to the next hop 298 | if (!t_relay()) { 299 | sl_reply_error(); 300 | }; 301 | exit; 302 | } 303 | 304 | # process initial requests 305 | route["initial_requests"] { 306 | $var(prefix)="route[initial_requests] : "+ 307 | $(cs{s.width, 6})+": "+$(rm{s.width, 9})+":"; 308 | # log requests, but skip REGISTER and OPTIONS so we dont flood the log 309 | if(!is_method("REGISTER|OPTIONS")){ 310 | xlog("L_INFO","$var(prefix) received initial request to $ru from $fu\n"); 311 | } 312 | # preloaded route checking 313 | if (loose_route() && !is_method("ACK|CANCEL")) { 314 | xlog("L_INFO","$var(prefix) initial request with preloaded routes " 315 | "[$fu/$tu/$ru/$ci] - rejecting\n"); 316 | sl_send_reply("403","Preload Route denied"); 317 | exit; 318 | } 319 | 320 | # we only accept requests to a user, not to a server 321 | if ($rU==NULL && !is_method("REGISTER|OPTIONS")) { 322 | # request with no Username in RURI 323 | sl_send_reply("484","Address Incomplete"); 324 | exit; 325 | } 326 | 327 | # set the route for processing branches 328 | t_on_branch("rtpengine"); 329 | 330 | # Detect if UAC is websockets client and set flag for later processing 331 | if ( proto == WS ) { 332 | setflag(uac_ws); 333 | } 334 | 335 | # registration processing 336 | if (is_method("REGISTER")) { 337 | # initialize the unauthenticated AVP so by default we auth 338 | $avp(unauthenticated)=0; 339 | 340 | # get attributes from the domain (if it is local) 341 | if (is_from_local("$var(attrs)")) { 342 | if($var(attrs)=="noauth") 343 | $avp(unauthenticated)=1; 344 | } else { 345 | xlog("L_INFO","$var(prefix) attempt to register non local domain\n"); 346 | sl_send_reply("603","Decline - unknown domain"); 347 | exit; 348 | } 349 | 350 | # do not challenge domains that are "unauthenticated" 351 | if($avp(unauthenticated)==0){ 352 | if (!www_authorize("", "subscriber")) { 353 | www_challenge("", "0"); 354 | exit; 355 | } 356 | # make sure they are registering a legitimate AOR, 357 | # not just using correct auth credentials 358 | if (!db_check_to()) { 359 | xlog("L_INFO","$var(prefix) attempt to register with bad To header\n"); 360 | sl_send_reply("403","Forbidden auth ID"); 361 | exit; 362 | } 363 | } 364 | # We have authorized a UAC, now if they are behind a NAT, we need to 365 | # set the nat branch flag before we save. This will then be restored 366 | # on a call to lookup, allowing us to detect a NAT'd UAS or "callee" in 367 | # a branch route, or onreply route. In any "main route" the bflag will be 368 | # for the first branch if there is more than one. 369 | if ($avp(uac_nat)==1) { 370 | setbflag(uas_nat); 371 | } 372 | # If the client is using websocket (webrtc) and save the attribute for 373 | # detection later on location lookup 374 | if ( isflagset(uac_ws) ) { 375 | setbflag(uas_ws); 376 | } 377 | 378 | # save the ip version info in a bflag to be restored on lookup() 379 | if ( af == INET ) { 380 | setbflag(uas_ip4); 381 | } else { 382 | setbflag(uas_ip6); 383 | } 384 | 385 | # comment out registration saving to reduce logs 386 | # xlog("L_INFO","$var(prefix) saving registration for $tu\n"); 387 | # save flags: 388 | # p0 - path support 389 | # v - path received parameter support 390 | if (!save("location","p0v")) { 391 | sl_reply_error(); 392 | } 393 | exit; 394 | } 395 | 396 | # CANCEL processing 397 | if (is_method("CANCEL") && t_check_trans()) { 398 | # if this is a CANCEL with an associated transaction 399 | # just let the main route block t_relay 400 | return; 401 | } else if (is_method("CANCEL") && !t_check_trans()) { 402 | # drop CANCEL requests that have no associated transaction 403 | exit; 404 | } 405 | 406 | # create dialog 407 | if (is_method("INVITE")) { 408 | create_dialog(); 409 | setflag(dialog_created); 410 | # check if UAC is ipv6 411 | if( af == INET6 ) { 412 | $dlg_val(uac_ipv) = "IP6"; 413 | } else { 414 | $dlg_val(uac_ipv) = "IP4"; 415 | } 416 | } 417 | xlog("L_INFO","$var(prefix) fU=$fU fd=$fd rU=$rU\n"); 418 | 419 | # Initial request processing for: INVITE, MESSAGE, NOTIFY 420 | if (method=="INVITE" || method=="MESSAGE" || method=="NOTIFY") { 421 | 422 | # translations are standardized on e164 so we check if the request matches 423 | # an e164 pattern and apply any missing prefixes 424 | $var(is_e164) = route("to_e164"); 425 | 426 | # lookup and apply any outbound translations 427 | # 428 | # this is where you would add translations to send e164 requests to a 429 | # carrier, or add aliases for things like extensions 430 | route("outbound_translations"); 431 | 432 | # if this is an e164 user portion, do an enum lookup if use_enum is enabled 433 | if ($var(is_e164)) { 434 | route("enum_query"); 435 | } 436 | 437 | # we have done aliasing, translations, and ENUM lookup 438 | # now check to see what the domain is 439 | if (is_uri_host_local()) { 440 | route("to_local_domain"); 441 | } else { 442 | route("challenge_request"); 443 | 444 | # non local domain, resolve A/AAAA to determine ipv6/ipv4 445 | # NOTE this does not do SRV/NAPTR and is not a "complete" solution 446 | if ( isflagset(dialog_created) ) { 447 | $var(dest) = $rd; 448 | $var(dest_ip) = $(var(dest){ip.resolve}); 449 | if ( $var(dest_ip) =~ "^([0-9]{1,3}\.){3}[0-9]{1,3}$" ) { 450 | xlog("L_INFO","$var(prefix) non-local request to IPV4 destination: " 451 | "$var(dest_ip)\n"); 452 | $dlg_val(uas_ipv)="IP4"; 453 | } else { 454 | xlog("L_INFO","$var(prefix) non-local request to IPV6 destination: " 455 | "$var(dest_ip)\n"); 456 | $dlg_val(uas_ipv)="IP6"; 457 | } 458 | } 459 | } 460 | } 461 | # return to main route block for rtp proxying and t_relay 462 | return; 463 | } 464 | 465 | # process sequential requests 466 | route["sequential_requests"] { 467 | $var(prefix)="route[sequential_requests]: "+ 468 | $(cs{s.width, 6})+": "+$(rm{s.width, 9})+":"; 469 | xlog("L_INFO","$var(prefix) received sequential request\n"); 470 | 471 | # UAS NAT detection 472 | # we append ;nat=yes to the contact when we detect NAT on a UAC. if this 473 | # paramater is present in the RURI of a sequential request, it means that 474 | # that the UAS of this request is behind a NAT, and we should set bflag 1 475 | # to indicate that for the remainder of the transaction 476 | if (subst_uri('/(sip:.*);nat=yes/\1/')) { 477 | xlog("L_INFO","$var(prefix) uas is behind a nat (previously detected)\n"); 478 | setbflag(uas_nat); 479 | } 480 | 481 | # set the route for processing branches 482 | t_on_branch("rtpengine"); 483 | 484 | # sequential requests should take the path built up from record-routing 485 | if (loose_route()) { 486 | xlog("L_INFO","$var(prefix) loose routing\n"); 487 | } else { 488 | if ( is_method("ACK") ) { 489 | if (! t_check_trans() ) { 490 | # ACK without matching transaction 491 | # ignore and discard 492 | exit; 493 | } else { 494 | # ACK to a negative response (wont loose route) 495 | # just let the main route t_relay 496 | xlog("L_INFO","$var(prefix) received ACK to negative response - " 497 | "relaying\n"); 498 | } 499 | } else if ( uri != myself ) { 500 | # some other sequential request that is bogus 501 | xlog("L_INFO","$var(prefix) received bogus sequential request - " 502 | "sending 404\n"); 503 | sl_send_reply("404","Not here"); 504 | exit; 505 | } 506 | } 507 | # set direction flags for uas / uac based processing 508 | resetbflag(upstream_request); 509 | if ( is_direction("upstream") ){ 510 | setbflag(upstream_request); 511 | } 512 | return; 513 | } 514 | 515 | branch_route[rtpengine] { 516 | $var(prefix)="branch[" + $T_branch_idx + "] : "+ 517 | $(cs{s.width, 6})+": "+$(rm{s.width, 9})+":"; 518 | 519 | resetbflag(sdp_offer); 520 | 521 | xlog("L_INFO","$var(prefix) message flags: $mf\n"); 522 | xlog("L_INFO","$var(prefix) branch flags: $bf\n"); 523 | 524 | # handle rtp proxying for both initial and sequential requests 525 | if ( (is_method("INVITE") || 526 | is_method("ACK") || 527 | is_method("PRACK")) && 528 | has_body("application/sdp") ) 529 | { 530 | # store dialog values based on branch flags restored on call to lookup() 531 | if ( isbflagset(uas_ip4) ) { 532 | $dlg_val(uas_ipv)="IP4"; 533 | } 534 | else if ( isbflagset(uas_ip6) ) { 535 | $dlg_val(uas_ipv)="IP6"; 536 | } 537 | 538 | xlog("L_INFO","$var(prefix) uac_ipv=$dlg_val(uac_ipv) " 539 | "uas_ipv=$dlg_val(uas_ipv)\n"); 540 | 541 | # set rtpengine flags based on whether uac or uas are websockets 542 | if (isflagset(uac_ws) && isbflagset(uas_ws)) { 543 | $var(rtpengine_flags) = "ICE=force-relay DTLS=passive"; 544 | xlog("L_INFO","$var(prefix) uac and uas are both websockets\n"); 545 | } else if (isflagset(uac_ws) && !isbflagset(uas_ws)) { 546 | $var(rtpengine_flags) = "RTP/AVP replace-session-connection "+ 547 | "replace-origin ICE=remove"; 548 | xlog("L_INFO","$var(prefix) uac is ws uas is not\n"); 549 | } else if (!isflagset(uac_ws) && isbflagset(uas_ws)) { 550 | $var(rtpengine_flags) = "UDP/TLS/RTP/SAVPF ICE=force"; 551 | xlog("L_INFO","$var(prefix) uas is ws uac is not\n"); 552 | } else if (!isflagset(uac_ws) && !isbflagset(uas_ws)) { 553 | $var(rtpengine_flags) = "RTP/AVP replace-session-connection "+ 554 | "replace-origin ICE=remove"; 555 | xlog("L_INFO","$var(prefix) neither uac or uas are websocket\n"); 556 | } 557 | 558 | # set the ip version address family 559 | if ( isbflagset(upstream_request) ){ 560 | $var(rtpengine_flags)=$var(rtpengine_flags) + 561 | " address-family=" + $dlg_val(uac_ipv); 562 | } else { 563 | $var(rtpengine_flags)=$var(rtpengine_flags) + 564 | " address-family=" + $dlg_val(uas_ipv); 565 | } 566 | 567 | if( is_method("ACK") || is_method("PRACK") ){ 568 | xlog("L_INFO","$var(prefix) rtpengine answer $var(rtpengine_flags)\n"); 569 | rtpengine_answer("$var(rtpengine_flags)"); 570 | } else { 571 | xlog("L_INFO","$var(prefix) rtpengine offer $var(rtpengine_flags)\n"); 572 | rtpengine_offer("$var(rtpengine_flags)"); 573 | setbflag(sdp_offer); 574 | } 575 | } 576 | } 577 | 578 | onreply_route["reply"] { 579 | $var(prefix)="onreply_route : "+ 580 | $(cs{s.width, 6})+": "+$(rs{s.width, 9})+":"; 581 | xlog("L_INFO","$var(prefix) response\n"); 582 | xlog("L_INFO","$var(prefix) message flags: $mf\n"); 583 | xlog("L_INFO","$var(prefix) branch flags: $bf\n"); 584 | 585 | # rtp proxying for responses 586 | if ( has_body("application/sdp") ) { 587 | 588 | # save UAS ipv info for rtpengine flags 589 | if ( !isbflagset(uas_ip4) && !isbflagset(uas_ip6) ) { 590 | if( af == INET6 ) { 591 | $avp(uas_ipv)="IP6"; 592 | } else { 593 | $avp(uas_ipv)="IP4"; 594 | } 595 | } 596 | 597 | # set rtpengine flags based on whether uac or uas are websockets 598 | if (isflagset(uac_ws) && isbflagset(uas_ws)) { 599 | $var(rtpengine_flags) = "ICE=force-relay DTLS=passive"; 600 | xlog("L_INFO","$var(prefix) uac and uas are both websockets\n"); 601 | } else if (isflagset(uac_ws) && !isbflagset(uas_ws)) { 602 | $var(rtpengine_flags) = "UDP/TLS/RTP/SAVPF ICE=force"; 603 | xlog("L_INFO","$var(prefix) uac is ws uas is not\n"); 604 | } else if (!isflagset(uac_ws) && isbflagset(uas_ws)) { 605 | $var(rtpengine_flags) = "RTP/AVP replace-session-connection "+ 606 | "replace-origin ICE=remove"; 607 | xlog("L_INFO","$var(prefix) uas is ws uac is not\n"); 608 | } else if (!isflagset(uac_ws) && !isbflagset(uas_ws)) { 609 | $var(rtpengine_flags) = "RTP/AVP replace-session-connection "+ 610 | "replace-origin ICE=remove"; 611 | xlog("L_INFO","$var(prefix) neither uac or uas are websocket\n"); 612 | } 613 | 614 | # set the ip version address family 615 | if ( isbflagset(upstream_request) ) { 616 | $var(rtpengine_flags)=$var(rtpengine_flags) + 617 | " address-family=" + $dlg_val(uas_ipv); 618 | resetbflag(upstream_request); 619 | } else { 620 | $var(rtpengine_flags)=$var(rtpengine_flags) + 621 | " address-family=" + $dlg_val(uac_ipv); 622 | } 623 | 624 | if ( $rs=="183" && !isbflagset(sdp_offer) ) { 625 | xlog("L_INFO","$var(prefix) rtpengine offer $var(rtpengine_flags)\n"); 626 | rtpengine_offer("$var(rtpengine_flags)"); 627 | } else if ( $rs=="200" || $rs=="183") { 628 | xlog("L_INFO","$var(prefix) rtpengine answer $var(rtpengine_flags)\n"); 629 | rtpengine_answer("$var(rtpengine_flags)"); 630 | } 631 | } 632 | 633 | # fix contact for uas behind nat 634 | if (isbflagset(uas_nat)) { 635 | xlog("L_INFO","$var(prefix) uas behind nat (previously detected), " 636 | "fixing contact\n"); 637 | fix_nated_contact(); 638 | } 639 | else if (nat_uac_test("1")) { 640 | xlog("L_INFO","$var(prefix) uas behind nat, fixing contact\n"); 641 | fix_nated_contact(); 642 | } 643 | } 644 | 645 | # helper routes 646 | 647 | route["to_e164"] { 648 | if($rU =~ "^(\+?1?([2-9][0-9]{2}[2-9][0-9]{2}[0-9]{4}))$") { 649 | # NANP ( +1 NPA NXX XXXX ) 650 | if ($(rU{s.len}) == 10) { 651 | $rU = "+1" + $rU; 652 | } else { 653 | $rU = "+1" + $(rU{s.substr,-10,10}); 654 | } 655 | xlog("L_NOTICE","$var(prefix) NANP e.164 $rU\n"); 656 | return(1); 657 | } else if ($rU =~ "^(\+?[2-9][0-9]{6,14})$") { 658 | # International ( + CC XXXXXXXXXXXXX ) 659 | if ($rU !~ "^\+") { 660 | $rU = "+" + $rU; 661 | } 662 | xlog("L_NOTICE","$var(prefix) international e.164 $rU\n"); 663 | return(2); 664 | } 665 | return(-1); 666 | } 667 | 668 | route["enum_query"] { 669 | # if this is an e.164 number, do an ENUM lookup on it 670 | if($var(use_enum) == 0) 671 | return(-1); 672 | 673 | xlog("L_INFO","$var(prefix) doing enum lookup on e164.arpa and e164.org\n"); 674 | if(enum_query() || enum_query("e164.org.")){ 675 | xlog("L_INFO","$var(prefix) ENUM query set RURI=$ru\n"); 676 | return(1); 677 | } 678 | return(-1); 679 | } 680 | 681 | route["outbound_translations"] { 682 | 683 | $var(log_query)=0; 684 | if($var(log_query)){ 685 | xlog("L_INFO","$var(prefix) select tran_strip, tran_prefix, tran_user, " 686 | "tran_domain, tran_port, tran_add_header,tran_strip_port " 687 | "from translations where (from_username='$fU' or " 688 | "from_username IS NULL) and from_domain='$fd' and " 689 | "(match_user_agent like '$ua%' or match_user_agent IS NULL ) " 690 | "and ('$rU' regexp match_regex or match_regex IS NULL) " 691 | "order by tran_priority limit 1\n"); 692 | } 693 | 694 | # outbound routing translations 695 | if(avp_db_query("select tran_strip, tran_prefix, tran_user, tran_domain, tran_port, tran_add_header,tran_strip_port from translations where (from_username='$fU' or from_username IS NULL) and from_domain='$fd' and (match_user_agent like '$ua%' or match_user_agent IS NULL ) and ('$rU' regexp match_regex or match_regex IS NULL) order by tran_priority limit 1","$avp(tran_strip);$avp(tran_prefix);$avp(tran_user);$avp(tran_domain);$avp(tran_port);$avp(tran_add_header);$avp(tran_strip_port)")) 696 | { 697 | # if there is a full on user part replacement 698 | # we do that, and do no strip/prefix 699 | if($avp(tran_user)!=null) { 700 | $rU=$avp(tran_user); 701 | } else { 702 | # if a translation strip exists, apply it before prefixing 703 | if($avp(tran_strip)!=null) { 704 | $rU = $(rU{s.substr, $(avp(tran_strip){s.int}), 0}); 705 | } 706 | # apply any translation prefix that exists 707 | if($avp(tran_prefix)!=null) { 708 | $rU= $avp(tran_prefix)+$rU; 709 | } 710 | } 711 | 712 | # translation domain is all or nothing, no partial substitution 713 | if($avp(tran_domain)!=null) { 714 | $rd=$avp(tran_domain); 715 | } 716 | 717 | # translation port is all or nothing, no partial substitution 718 | # also we can only strip the port if there is no port translation 719 | if($avp(tran_port)!=null) { 720 | $rp=$avp(tran_port); 721 | } else if($avp(tran_strip_port)!=null) { 722 | $rp=""; 723 | } 724 | 725 | if($avp(tran_add_header)!=null) { 726 | append_hf("$avp(tran_add_header)\r\n"); 727 | } 728 | 729 | xlog("L_INFO","$var(prefix) tran_strip=$avp(tran_strip) " 730 | "tran_prefix=$avp(tran_prefix) tran_user=$avp(tran_user) " 731 | "tran_domain=$avp(tran_domain) tran_port=$avp(tran_port) " 732 | "tran_strip_port=$avp(tran_strip_port) " 733 | "tran_add_header=$avp(tran_add_header)\n"); 734 | xlog("L_INFO","$var(prefix) post translation RURI=$ru\n"); 735 | } 736 | } 737 | 738 | route["to_local_domain"] { 739 | # this is a local domain, do a user location lookup 740 | $var(original_ruri)=$ru; 741 | if (!lookup("location","m") ) { 742 | xlog("L_INFO","$var(prefix) no registration found for $rU - sending 404\n"); 743 | t_newtran(); 744 | t_reply("404", "Not Found"); 745 | exit; 746 | } else { 747 | xlog("L_INFO","$var(prefix) found registration for $var(original_ruri)\n"); 748 | } 749 | } 750 | 751 | route["challenge_request"] { 752 | if($avp(unauthenticated)==0) { 753 | if (!proxy_authorize("", "subscriber")) { 754 | xlog("L_INFO","$var(prefix) challenging request to external domain $rd\n"); 755 | proxy_challenge("", "0"); 756 | exit; 757 | } else { 758 | # caller authorized 759 | xlog("L_INFO","$var(prefix) authorized request\n"); 760 | consume_credentials(); 761 | } 762 | # check to see if the from header is one of our known users 763 | if (!db_check_from()) { 764 | xlog("L_INFO","$var(prefix) unknown user in From header - rejecting\n"); 765 | sl_send_reply("403","Forbidden auth ID"); 766 | exit; 767 | } 768 | } 769 | } 770 | 771 | --------------------------------------------------------------------------------