1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
|
#
# $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
# <sr-users@lists.sip-router.org>.
#
# 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();
}
|