modules/websocket: Updated connection reuse and closing flags for WebSocket handshake.
[sip-router] / modules / websocket / example / kamailio.cfg
1 #!KAMAILIO
2 #
3 # Simple/sample kamailio.cfg for running a proxy/registrar with TLS and
4 # WebSockets support.
5
6 #!substdef "!DBURL!sqlite:///db.sqlite!g"
7 #!substdef "!MY_IP_ADDR!192.168.111.136!g"
8 #!substdef "!MY_WS_PORT!80!g"
9 #!substdef "!MY_WSS_PORT!443!g"
10 #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
11 #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"
12
13 #!define LOCAL_TEST_RUN
14 #!define WITH_TLS
15 #!define WITH_WEBSOCKETS
16
17
18 ####### Global Parameters #########
19
20 fork=yes
21 children=4
22
23 alias="example.com"
24
25 #!ifdef WITH_TLS
26 enable_tls=1
27 #!endif
28
29 listen=MY_IP_ADDR
30 #!ifdef WITH_WEBSOCKETS
31 listen=MY_WS_ADDR
32 #!ifdef WITH_TLS
33 listen=MY_WSS_ADDR
34 #!endif
35 #!endif
36
37 tcp_connection_lifetime=3604
38 tcp_accept_no_cl=yes
39 tcp_rd_buf_size=16384
40
41 syn_branch=0
42
43 #!ifdef LOCAL_TEST_RUN
44 debug=2
45 mpath="modules_k:modules"
46 #!else
47 debug=0
48 mpath="/usr/lib64/kamailio/modules_k/:/usr/lib64/kamailio/modules/"
49 #!endif
50
51 loadmodule "db_sqlite.so"
52 loadmodule "tm.so"
53 loadmodule "sl.so"
54 loadmodule "rr.so"
55 loadmodule "pv.so"
56 loadmodule "maxfwd.so"
57 loadmodule "usrloc.so"
58 loadmodule "registrar.so"
59 loadmodule "textops.so"
60 loadmodule "siputils.so"
61 loadmodule "xlog.so"
62 loadmodule "sanity.so"
63 loadmodule "ctl.so"
64 loadmodule "auth.so"
65 loadmodule "auth_db.so"
66 loadmodule "kex.so"
67 loadmodule "mi_rpc.so"
68 #!ifdef WITH_TLS
69 loadmodule "tls.so"
70 #!endif
71 #!ifdef WITH_WEBSOCKETS
72 loadmodule "xhttp.so"
73 loadmodule "websocket.so"
74 loadmodule "nathelper.so"
75 #!endif
76
77 # ----------------- setting module-specific parameters ---------------
78
79 # ----- tm params -----
80 # auto-discard branches from previous serial forking leg
81 modparam("tm", "failure_reply_mode", 3)
82 # default retransmission timeout: 30sec
83 modparam("tm", "fr_timer", 30000)
84 # default invite retransmission timeout after 1xx: 120sec
85 modparam("tm", "fr_inv_timer", 120000)
86
87 # ----- rr params -----
88 # add value to ;lr param to cope with most of the UAs
89 modparam("rr", "enable_full_lr", 1)
90 # do not append from tag to the RR (no need for this script)
91 modparam("rr", "append_fromtag", 0)
92
93 # ----- registrar params -----
94 modparam("registrar", "method_filtering", 1)
95 modparam("registrar", "max_expires", 3600)
96 modparam("registrar", "gruu_enabled", 0)
97
98 # ----- usrloc params -----
99 modparam("usrloc", "db_url", "DBURL")
100 modparam("usrloc", "db_mode", 0)
101
102 # ----- auth_db params -----
103 modparam("auth_db", "db_url", "DBURL")
104 modparam("auth_db", "calculate_ha1", yes)
105 modparam("auth_db", "password_column", "password")
106 modparam("auth_db", "load_credentials", "")
107
108 #!ifdef WITH_TLS
109 # ----- tls params -----
110 modparam("tls", "tls_method", "SSLv23")
111 modparam("tls", "certificate", "CA/ser1_cert.pem")
112 modparam("tls", "private_key", "CA/privkey.pem")
113 modparam("tls", "ca_list", "CA/calist.pem")
114 #!endif
115
116 #!ifdef WITH_WEBSOCKETS
117 # ----- websocket params -----
118 modparam("websocket", "keepalive_timeout", 30)
119
120 # ----- nathelper params -----
121 modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
122 # Note: leaving NAT pings turned off here as nathelper is _only_ being used for
123 #       WebSocket connections.  NAT pings are not needed as WebSockets have
124 #       their own keep-alives.
125 #!endif
126
127
128 ####### Routing Logic ########
129
130 # Main SIP request routing logic
131 # - processing of any incoming SIP request starts with this route
132 # - note: this is the same as route { ... }
133 request_route {
134
135         # per request initial checks
136         route(REQINIT);
137
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.
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                         t_on_reply("WS_REPLY");
154                 }
155         }
156 #!endif
157
158         # handle requests within SIP dialogs
159         route(WITHINDLG);
160
161         ### only initial requests (no To tag)
162
163         # CANCEL processing
164         if (is_method("CANCEL")) {
165                 if (t_check_trans())
166                         t_relay();
167                 exit;
168         }
169
170         t_check_trans();
171
172         # authentication
173         route(AUTH);
174
175         # record routing for dialog forming requests (in case they are routed)
176         # - remove preloaded route headers
177         remove_hf("Route");
178         if (is_method("INVITE"))
179                 record_route();
180
181         # handle registrations
182         route(REGISTRAR);
183
184         if ($rU==$null) {
185                 # request with no Username in RURI
186                 sl_send_reply("484","Address Incomplete");
187                 exit;
188         }
189
190         # user location service
191         route(LOCATION);
192
193         route(RELAY);
194 }
195
196 route[RELAY] {
197         if (!t_relay()) {
198                 sl_reply_error();
199         }
200         exit;
201 }
202
203 # Per SIP request initial checks
204 route[REQINIT] {
205         if (!mf_process_maxfwd_header("10")) {
206                 sl_send_reply("483","Too Many Hops");
207                 exit;
208         }
209
210         if(!sanity_check("1511", "7")) {
211                 xlog("Malformed SIP message from $si:$sp\n");
212                 exit;
213         }
214 }
215
216 # Handle requests within SIP dialogs
217 route[WITHINDLG] {
218         if (has_totag()) {
219                 # sequential request withing a dialog should
220                 # take the path determined by record-routing
221                 if (loose_route()) {
222 #!ifdef WITH_WEBSOCKETS
223                         if ($du == "") {
224                                 if (!handle_ruri_alias()) {
225                                         xlog("L_ERR", "Bad alias <$ru>\n");
226                                         sl_send_reply("400", "Bad Request");
227                                         exit;
228                                 }
229                         }
230 #!endif
231                         route(RELAY);
232                 } else {
233                         if ( is_method("ACK") ) {
234                                 if ( t_check_trans() ) {
235                                         # no loose-route, but stateful ACK;
236                                         # must be an ACK after a 487
237                                         # or e.g. 404 from upstream server
238                                         t_relay();
239                                         exit;
240                                 } else {
241                                         # ACK without matching transaction...
242                                         # ignore and discard
243                                         exit;
244                                 }
245                         }
246                         sl_send_reply("404","Not here");
247                 }
248                 exit;
249         }
250 }
251
252 # Handle SIP registrations
253 route[REGISTRAR] {
254         if (is_method("REGISTER")) {
255                 if (!save("location"))
256                         sl_reply_error();
257
258                 exit;
259         }
260 }
261
262 # USER location service
263 route[LOCATION] {
264         if (!lookup("location")) {
265                 $var(rc) = $rc;
266                 t_newtran();
267                 switch ($var(rc)) {
268                         case -1:
269                         case -3:
270                                 send_reply("404", "Not Found");
271                                 exit;
272                         case -2:
273                                 send_reply("405", "Method Not Allowed");
274                                 exit;
275                 }
276         }
277 }
278
279 # Authentication route
280 route[AUTH] {
281         if (is_method("REGISTER") || from_uri==myself) {
282                 # authenticate requests
283                 if (!auth_check("$fd", "subscriber", "1")) {
284                         auth_challenge("$fd", "0");
285                         exit;
286                 }
287                 # user authenticated - remove auth header
288                 if(!is_method("REGISTER"))
289                         consume_credentials();
290         }
291         # if caller is not local subscriber, then check if it calls
292         # a local destination, otherwise deny, not an open relay here
293         if (from_uri!=myself && uri!=myself) {
294                 sl_send_reply("403","Not relaying");
295                 exit;
296         }
297 }
298
299 #!ifdef WITH_WEBSOCKETS
300 onreply_route[WS_REPLY] {
301         # Do NAT traversal stuff for replies to a WebSocket connection - even
302         # if it is not behind a NAT!
303         # This won't be needed in the future if Kamailio and the WebSocket
304         # client support outbound.
305         add_contact_alias();
306 }
307
308 event_route[xhttp:request] {
309         set_reply_close();
310         set_reply_no_connect();
311         
312         if ($Rp != MY_WS_PORT && $Rp != MY_WSS_PORT) {
313                 xlog("L_WARN", "HTTP request received on $Rp\n");
314                 xhttp_reply("403", "Forbidden", "", "");
315                 exit;
316         }
317
318         xlog("L_DBG", "HTTP Request Received\n");
319
320         if ($hdr(Upgrade)=~"websocket"
321                         && $hdr(Connection)=~"Upgrade"
322                         && $rm=~"GET") {
323                 xlog("L_DBG", "WebSocket\n");
324                 xlog("L_DBG", " Host: $hdr(Host)\n");
325                 xlog("L_DBG", " Origin: $hdr(Origin)\n");
326
327                 if ($hdr(Host) == $null || !is_myself($hdr(Host))) {
328                         xlog("L_WARN", "Bad host $hdr(Host)\n");
329                         xhttp_reply("403", "Forbidden", "", "");
330                         exit;
331                 }
332
333                 # Optional... validate Origin
334                 # Optional... perform HTTP authentication
335
336                 # ws_handle_handshake() exits (no further configuration file
337                 # processing of the request) when complete.
338                 ws_handle_handshake();
339         }
340
341         xhttp_reply("404", "Not found", "", "");
342 }
343 #!endif