websocket.cfg 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. #!KAMAILIO
  2. #
  3. # Simple/sample kamailio.cfg for running a proxy/registrar with TLS and
  4. # WebSockets support.
  5. #!substdef "!DBURL!sqlite:///etc/kamailio/db.sqlite!g"
  6. #!substdef "!MY_IP_ADDR!a.b.c.d!g"
  7. #!substdef "!MY_DOMAIN!example.com!g"
  8. #!substdef "!MY_WS_PORT!80!g"
  9. #!substdef "!MY_WSS_PORT!443!g"
  10. #!substdef "!MY_MSRP_PORT!9000!g"
  11. #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
  12. #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"
  13. #!substdef "!MY_MSRP_ADDR!tls:MY_IP_ADDR:MY_MSRP_PORT!g"
  14. #!substdef "!MSRP_MIN_EXPIRES!1800!g"
  15. #!substdef "!MSRP_MAX_EXPIRES!3600!g"
  16. ##!define LOCAL_TEST_RUN
  17. #!define WITH_TLS
  18. #!define WITH_WEBSOCKETS
  19. #!define WITH_MSRP
  20. ####### Global Parameters #########
  21. fork=yes
  22. children=4
  23. #!ifdef WITH_TLS
  24. enable_tls=1
  25. #!endif
  26. listen=MY_IP_ADDR
  27. #!ifdef WITH_WEBSOCKETS
  28. listen=MY_WS_ADDR
  29. #!ifdef WITH_TLS
  30. listen=MY_WSS_ADDR
  31. #!endif
  32. #!endif
  33. #!ifdef WITH_MSRP
  34. listen=MY_MSRP_ADDR
  35. #!endif
  36. tcp_connection_lifetime=3604
  37. tcp_accept_no_cl=yes
  38. tcp_rd_buf_size=16384
  39. #!ifdef LOCAL_TEST_RUN
  40. debug=2
  41. mpath="modules"
  42. #!else
  43. debug=0
  44. mpath="/usr/lib64/kamailio/modules/"
  45. #!endif
  46. loadmodule "db_sqlite.so"
  47. loadmodule "tm.so"
  48. loadmodule "sl.so"
  49. loadmodule "rr.so"
  50. loadmodule "pv.so"
  51. loadmodule "maxfwd.so"
  52. loadmodule "usrloc.so"
  53. loadmodule "registrar.so"
  54. loadmodule "textops.so"
  55. loadmodule "siputils.so"
  56. loadmodule "xlog.so"
  57. loadmodule "sanity.so"
  58. loadmodule "ctl.so"
  59. loadmodule "auth.so"
  60. loadmodule "auth_db.so"
  61. loadmodule "kex.so"
  62. loadmodule "mi_rpc.so"
  63. loadmodule "corex.so"
  64. #!ifdef WITH_TLS
  65. loadmodule "tls.so"
  66. #!endif
  67. #!ifdef WITH_MSRP
  68. loadmodule "msrp.so"
  69. loadmodule "htable.so"
  70. loadmodule "cfgutils.so"
  71. #!endif
  72. #!ifdef WITH_WEBSOCKETS
  73. loadmodule "xhttp.so"
  74. loadmodule "websocket.so"
  75. loadmodule "nathelper.so"
  76. #!endif
  77. # ----------------- setting module-specific parameters ---------------
  78. # ----- tm params -----
  79. # auto-discard branches from previous serial forking leg
  80. modparam("tm", "failure_reply_mode", 3)
  81. # default retransmission timeout: 30sec
  82. modparam("tm", "fr_timer", 30000)
  83. # default invite retransmission timeout after 1xx: 120sec
  84. modparam("tm", "fr_inv_timer", 120000)
  85. # ----- rr params -----
  86. # add value to ;lr param to cope with most of the UAs
  87. modparam("rr", "enable_full_lr", 1)
  88. # do not append from tag to the RR (no need for this script)
  89. modparam("rr", "append_fromtag", 0)
  90. # ----- registrar params -----
  91. modparam("registrar", "method_filtering", 1)
  92. modparam("registrar", "max_expires", 3600)
  93. modparam("registrar", "gruu_enabled", 0)
  94. # ----- usrloc params -----
  95. modparam("usrloc", "db_url", "DBURL")
  96. modparam("usrloc", "db_mode", 0)
  97. # ----- auth params -----
  98. modparam("auth", "nonce_count", 1)
  99. modparam("auth", "qop", "auth")
  100. # ----- auth_db params -----
  101. modparam("auth_db", "db_url", "DBURL")
  102. modparam("auth_db", "calculate_ha1", yes)
  103. modparam("auth_db", "password_column", "password")
  104. modparam("auth_db", "load_credentials", "id")
  105. # ----- corex params -----
  106. modparam("corex", "alias_subdomains", "MY_DOMAIN")
  107. #!ifdef WITH_TLS
  108. # ----- tls params -----
  109. modparam("tls", "tls_method", "SSLv23")
  110. modparam("tls", "certificate", "/etc/pki/CA/ser1_cert.pem")
  111. modparam("tls", "private_key", "/etc/pki/CA/privkey.pem")
  112. modparam("tls", "ca_list", "/etc/pki/CA/calist.pem")
  113. #!endif
  114. #!ifdef WITH_WEBSOCKETS
  115. # ----- nathelper params -----
  116. modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
  117. # Note: leaving NAT pings turned off here as nathelper is _only_ being used for
  118. # WebSocket connections. NAT pings are not needed as WebSockets have
  119. # their own keep-alives.
  120. #!endif
  121. #!ifdef WITH_MSRP
  122. # ----- htable params -----
  123. modparam("htable", "htable", "msrp=>size=8;autoexpire=MSRP_MAX_EXPIRES;")
  124. #!endif
  125. ####### Routing Logic ########
  126. # Main SIP request routing logic
  127. # - processing of any incoming SIP request starts with this route
  128. # - note: this is the same as route { ... }
  129. request_route {
  130. if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
  131. && !(proto == WS || proto == WSS)) || $Rp == MY_MSRP_PORT) {
  132. xlog("L_WARN", "SIP request received on $Rp\n");
  133. sl_send_reply("403", "Forbidden");
  134. exit;
  135. }
  136. # per request initial checks
  137. route(REQINIT);
  138. #!ifdef WITH_WEBSOCKETS
  139. if (nat_uac_test(64)) {
  140. # Do NAT traversal stuff for requests from a WebSocket
  141. # connection - even if it is not behind a NAT!
  142. # This won't be needed in the future if Kamailio and the
  143. # WebSocket client support Outbound and Path.
  144. force_rport();
  145. if (is_method("REGISTER")) {
  146. fix_nated_register();
  147. } else {
  148. if (!add_contact_alias()) {
  149. xlog("L_ERR", "Error aliasing contact <$ct>\n");
  150. sl_send_reply("400", "Bad Request");
  151. exit;
  152. }
  153. }
  154. }
  155. #!endif
  156. # handle requests within SIP dialogs
  157. route(WITHINDLG);
  158. ### only initial requests (no To tag)
  159. # CANCEL processing
  160. if (is_method("CANCEL")) {
  161. if (t_check_trans()) {
  162. t_relay();
  163. }
  164. exit;
  165. }
  166. t_check_trans();
  167. # authentication
  168. route(AUTH);
  169. # record routing for dialog forming requests (in case they are routed)
  170. # - remove preloaded route headers
  171. remove_hf("Route");
  172. if (is_method("INVITE")) {
  173. record_route();
  174. }
  175. # handle registrations
  176. route(REGISTRAR);
  177. if ($rU==$null) {
  178. # request with no Username in RURI
  179. sl_send_reply("484", "Address Incomplete");
  180. exit;
  181. }
  182. # user location service
  183. route(LOCATION);
  184. route(RELAY);
  185. }
  186. route[RELAY] {
  187. if (!t_relay()) {
  188. sl_reply_error();
  189. }
  190. exit;
  191. }
  192. # Per SIP request initial checks
  193. route[REQINIT] {
  194. if (!mf_process_maxfwd_header("10")) {
  195. sl_send_reply("483", "Too Many Hops");
  196. exit;
  197. }
  198. if (!sanity_check("1511", "7")) {
  199. xlog("Malformed SIP message from $si:$sp\n");
  200. exit;
  201. }
  202. if (uri == myself && is_method("OPTIONS") && !(uri=~"sip:.*[@]+.*")) {
  203. options_reply();
  204. exit;
  205. }
  206. }
  207. # Handle requests within SIP dialogs
  208. route[WITHINDLG] {
  209. if (has_totag()) {
  210. # sequential request withing a dialog should
  211. # take the path determined by record-routing
  212. if (loose_route()) {
  213. #!ifdef WITH_WEBSOCKETS
  214. if ($du == "") {
  215. if (!handle_ruri_alias()) {
  216. xlog("L_ERR", "Bad alias <$ru>\n");
  217. sl_send_reply("400", "Bad Request");
  218. exit;
  219. }
  220. }
  221. #!endif
  222. route(RELAY);
  223. } else {
  224. if ( is_method("ACK") ) {
  225. if ( t_check_trans() ) {
  226. # no loose-route, but stateful ACK;
  227. # must be an ACK after a 487
  228. # or e.g. 404 from upstream server
  229. t_relay();
  230. exit;
  231. } else {
  232. # ACK without matching transaction...
  233. # ignore and discard
  234. exit;
  235. }
  236. }
  237. sl_send_reply("404", "Not Found");
  238. }
  239. exit;
  240. }
  241. }
  242. # Handle SIP registrations
  243. route[REGISTRAR] {
  244. if (is_method("REGISTER")) {
  245. if (!save("location")) {
  246. sl_reply_error();
  247. }
  248. exit;
  249. }
  250. }
  251. # USER location service
  252. route[LOCATION] {
  253. if (!is_subscriber("$ru", "subscriber", "1")) {
  254. t_newtran();
  255. send_reply("404", "Not Found");
  256. exit;
  257. }
  258. if (!lookup("location")) {
  259. $var(rc) = $rc;
  260. t_newtran();
  261. switch ($var(rc)) {
  262. case -1:
  263. send_reply("480", "Temporarily Unavailable");
  264. exit;
  265. case -2:
  266. send_reply("405", "Method Not Allowed");
  267. exit;
  268. case -3:
  269. send_reply("500", "Server Internal Error");
  270. exit;
  271. }
  272. }
  273. }
  274. # Authentication route
  275. route[AUTH] {
  276. if (is_method("REGISTER") || from_uri==myself) {
  277. # authenticate requests
  278. if (!auth_check("$fd", "subscriber", "1")) {
  279. auth_challenge("$fd", "0");
  280. exit;
  281. }
  282. # user authenticated - remove auth header
  283. if(!is_method("REGISTER")) {
  284. consume_credentials();
  285. }
  286. }
  287. # if caller is not local subscriber, then check if it calls
  288. # a local destination, otherwise deny, not an open relay here
  289. if (from_uri!=myself && uri!=myself) {
  290. sl_send_reply("403", "Forbidden");
  291. exit;
  292. }
  293. }
  294. #!ifdef WITH_WEBSOCKETS
  295. onreply_route {
  296. if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
  297. && !(proto == WS || proto == WSS)) || $Rp == MY_MSRP_PORT) {
  298. xlog("L_WARN", "SIP response received on $Rp\n");
  299. drop;
  300. }
  301. if (nat_uac_test(64)) {
  302. # Do NAT traversal stuff for replies to a WebSocket connection
  303. # - even if it is not behind a NAT!
  304. # This won't be needed in the future if Kamailio and the
  305. # WebSocket client support Outbound and Path.
  306. add_contact_alias();
  307. }
  308. }
  309. event_route[xhttp:request] {
  310. set_reply_close();
  311. set_reply_no_connect();
  312. if ($Rp != MY_WS_PORT
  313. #!ifdef WITH_TLS
  314. && $Rp != MY_WSS_PORT
  315. #!endif
  316. ) {
  317. xlog("L_WARN", "HTTP request received on $Rp\n");
  318. xhttp_reply("403", "Forbidden", "", "");
  319. exit;
  320. }
  321. xlog("L_DBG", "HTTP Request Received\n");
  322. if ($hdr(Upgrade)=~"websocket"
  323. && $hdr(Connection)=~"Upgrade"
  324. && $rm=~"GET") {
  325. # Validate Host - make sure the client is using the correct
  326. # alias for WebSockets
  327. if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
  328. xlog("L_WARN", "Bad host $hdr(Host)\n");
  329. xhttp_reply("403", "Forbidden", "", "");
  330. exit;
  331. }
  332. # Optional... validate Origin - make sure the client is from an
  333. # authorised website. For example,
  334. #
  335. # if ($hdr(Origin) != "http://communicator.MY_DOMAIN"
  336. # && $hdr(Origin) != "https://communicator.MY_DOMAIN") {
  337. # xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
  338. # xhttp_reply("403", "Forbidden", "", "");
  339. # exit;
  340. # }
  341. # Optional... perform HTTP authentication
  342. # ws_handle_handshake() exits (no further configuration file
  343. # processing of the request) when complete.
  344. if (ws_handle_handshake())
  345. {
  346. # Optional... cache some information about the
  347. # successful connection
  348. exit;
  349. }
  350. }
  351. xhttp_reply("404", "Not Found", "", "");
  352. }
  353. event_route[websocket:closed] {
  354. xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
  355. }
  356. #!endif
  357. #!ifdef WITH_MSRP
  358. event_route[msrp:frame-in] {
  359. msrp_reply_flags("1");
  360. if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
  361. && !(proto == WS || proto == WSS)) && $Rp != MY_MSRP_PORT) {
  362. xlog("L_WARN", "MSRP request received on $Rp\n");
  363. msrp_reply("403", "Action-not-allowed");
  364. exit;
  365. }
  366. if (msrp_is_reply()) {
  367. msrp_relay();
  368. } else if($msrp(method)=="AUTH") {
  369. if($msrp(nexthops)>0) {
  370. msrp_relay();
  371. exit;
  372. }
  373. if (!www_authenticate("MY_DOMAIN", "subscriber",
  374. "$msrp(method)")) {
  375. if (auth_get_www_authenticate("MY_DOMAIN", "1",
  376. "$var(wauth)")) {
  377. msrp_reply("401", "Unauthorized",
  378. "$var(wauth)");
  379. } else {
  380. msrp_reply("500", "Server Error");
  381. }
  382. exit;
  383. }
  384. if ($hdr(Expires) != $null) {
  385. $var(expires) = (int) $hdr(Expires);
  386. if ($var(expires) < MSRP_MIN_EXPIRES) {
  387. msrp_reply("423", "Interval Out-of-Bounds",
  388. "Min-Expires: MSRP_MIN_EXPIRES\r\n");
  389. exit;
  390. } else if ($var(expires) > MSRP_MAX_EXPIRES) {
  391. msrp_reply("423", "Interval Out-of-Bounds",
  392. "Max-Expires: MSRP_MAX_EXPIRES\r\n");
  393. exit;
  394. }
  395. } else {
  396. $var(expires) = MSRP_MAX_EXPIRES;
  397. }
  398. $var(cnt) = $var(cnt) + 1;
  399. pv_printf("$var(sessid)", "s.$(pp).$(var(cnt)).$(RANDOM)");
  400. $sht(msrp=>$var(sessid)::srcaddr) = $msrp(srcaddr);
  401. $sht(msrp=>$var(sessid)::srcsock) = $msrp(srcsock);
  402. $shtex(msrp=>$var(sessid)) = $var(expires) + 5;
  403. # - Use-Path: the MSRP address for server + session id
  404. $var(hdrs) = "Use-Path: msrps://MY_IP_ADDR:MY_MSRP_PORT/"
  405. + $var(sessid) + ";tcp\r\n"
  406. + "Expires: " + $var(expires) + "\r\n";
  407. msrp_reply("200", "OK", "$var(hdrs)");
  408. } else if ($msrp(method)=="SEND" || $msrp(method)=="REPORT") {
  409. if ($msrp(nexthops)>1) {
  410. if ($msrp(method)!="REPORT") {
  411. msrp_reply("200", "OK");
  412. }
  413. msrp_relay();
  414. exit;
  415. }
  416. $var(sessid) = $msrp(sessid);
  417. if ($sht(msrp=>$var(sessid)::srcaddr) == $null) {
  418. # one more hop, but we don't have address in htable
  419. msrp_reply("481", "Session-does-not-exist");
  420. exit;
  421. } else if ($msrp(method)!="REPORT") {
  422. msrp_reply("200", "OK");
  423. }
  424. msrp_relay_flags("1");
  425. msrp_set_dst("$sht(msrp=>$var(sessid)::srcaddr)",
  426. "$sht(msrp=>$var(sessid)::srcsock)");
  427. msrp_relay();
  428. } else {
  429. msrp_reply("501", "Request-method-not-understood");
  430. }
  431. }
  432. #!endif