Browse code

examples: added WebSocket edge proxy example using outbound for NAT traversal

Peter Dunkley authored on 24/04/2013 20:07:07
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,293 @@
1
+#!KAMAILIO
2
+#
3
+# Edge proxy configuration with SIP over WebSocket support
4
+#
5
+
6
+#!substdef "!DBURL!sqlite:///etc/kamailio/db.sqlite!g"
7
+#!substdef "!MY_IP_ADDR!a.b.c.d!g"
8
+#!substdef "!MY_DOMAIN!example.com!g"
9
+#!substdef "!MY_WS_PORT!80!g"
10
+#!substdef "!MY_WSS_PORT!443!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
+
14
+#!substdef "!REGISTRAR_IP!e.f.g.h!g"
15
+#!substdef "!REGISTRAR_PORT!5060!g"
16
+#!substdef "!FLOW_TIMER!20!g"
17
+
18
+#!define WITH_TLS
19
+#!define WITH_WEBSOCKETS
20
+
21
+
22
+####### Global Parameters #########
23
+
24
+debug=2
25
+log_stderror=no
26
+log_facility=LOG_LOCAL0
27
+fork=yes
28
+children=4
29
+mpath="/usr/lib64/kamailio/modules/"
30
+force_rport=yes
31
+
32
+#!ifdef WITH_TLS
33
+enable_tls=1
34
+#!endif
35
+
36
+listen=MY_IP_ADDR
37
+#!ifdef WITH_WEBSOCKETS
38
+listen=MY_WS_ADDR
39
+#!ifdef WITH_TLS
40
+listen=MY_WSS_ADDR
41
+#!endif
42
+#!endif
43
+
44
+tcp_connection_lifetime=30 # FLOW_TIMER + 10
45
+tcp_accept_no_cl=yes
46
+tcp_rd_buf_size=16384
47
+
48
+
49
+####### Modules Section ########
50
+
51
+loadmodule "tm.so"
52
+loadmodule "sl.so"
53
+loadmodule "outbound.so"
54
+loadmodule "rr.so"
55
+loadmodule "path.so"
56
+loadmodule "pv.so"
57
+loadmodule "maxfwd.so"
58
+loadmodule "xlog.so"
59
+loadmodule "sanity.so"
60
+loadmodule "ctl.so"
61
+loadmodule "mi_rpc.so"
62
+loadmodule "mi_fifo.so"
63
+loadmodule "textops.so"
64
+loadmodule "siputils.so"
65
+loadmodule "stun.so"
66
+loadmodule "kex.so"
67
+loadmodule "corex.so"
68
+#!ifdef WITH_TLS
69
+loadmodule "tls.so"
70
+#!endif
71
+#!ifdef WITH_WEBSOCKETS
72
+loadmodule "xhttp.so"
73
+loadmodule "websocket.so"
74
+#!endif
75
+
76
+# ----------------- setting module-specific parameters ---------------
77
+
78
+# ----- mi_fifo params -----
79
+modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
80
+
81
+# ----- tm params -----
82
+modparam("tm", "failure_reply_mode", 3)
83
+
84
+# ----- rr params -----
85
+modparam("rr", "append_fromtag", 0)
86
+
87
+# ----- corex params -----
88
+modparam("corex", "alias_subdomains", "MY_DOMAIN")
89
+
90
+#!ifdef WITH_TLS
91
+# ----- tls params -----
92
+modparam("tls", "tls_method", "SSLv23")
93
+modparam("tls", "certificate", "/etc/pki/CA/ser1_cert.pem")
94
+modparam("tls", "private_key", "/etc/pki/CA/privkey.pem")
95
+modparam("tls", "ca_list", "/etc/pki/CA/calist.pem")
96
+#!endif
97
+
98
+#!ifdef WITH_WEBSOCKETS
99
+# ----- websocket params -----
100
+modparam("websocket", "keepalive_timeout", 25) # FLOW_TIMER + 5
101
+#!endif
102
+
103
+
104
+####### Routing Logic ########
105
+
106
+request_route {
107
+	if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
108
+		&& !(proto == WS || proto == WSS)) {
109
+		xlog("L_WARN", "SIP request received on $Rp\n");
110
+		sl_send_reply("403", "Forbidden");
111
+		exit;
112
+	}
113
+
114
+	route(REQINIT);
115
+
116
+	if (is_method("CANCEL")) {
117
+		if (t_check_trans()) {
118
+			route(RELAY);
119
+		}
120
+		exit;
121
+	}
122
+
123
+	route(WITHINDLG);
124
+
125
+	t_check_trans();
126
+
127
+	if (is_method("REGISTER")) {
128
+		remove_hf("Route");
129
+		add_path();
130
+		$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
131
+	} else {
132
+		if (is_method("INVITE|SUBSCRIBE"))
133
+			record_route();
134
+
135
+		if (@via[2] == "") {
136
+			# From client so route to registrar...
137
+
138
+			if ($rU == $null) {
139
+				sl_send_reply("484", "Address Incomplete");
140
+				exit;
141
+			}
142
+			remove_hf("Route");
143
+			$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
144
+		} else {
145
+			# From registrar so route using "Route:" headers...
146
+
147
+			if (!loose_route()) {
148
+				switch($rc) {
149
+				case -2:
150
+					sl_send_reply("403", "Forbidden");
151
+					exit;
152
+				default:
153
+					xlog("L_ERR", "in request_route\n");
154
+					sl_reply_error();
155
+					exit;
156
+				}
157
+			}
158
+
159
+			t_on_failure("FAIL_OUTBOUND");
160
+		}
161
+	}
162
+
163
+	route(RELAY);
164
+}
165
+
166
+route[RELAY] {
167
+	if (!t_relay()) {
168
+		sl_reply_error();
169
+	}
170
+	exit;
171
+}
172
+
173
+route[REQINIT] {
174
+	if (!mf_process_maxfwd_header("10")) {
175
+		sl_send_reply("483","Too Many Hops");
176
+		exit;
177
+	}
178
+
179
+	if(!sanity_check("1511", "7"))
180
+	{
181
+		xlog("Malformed SIP message from $si:$sp\n");
182
+		exit;
183
+	}
184
+}
185
+
186
+route[WITHINDLG] {
187
+	if (has_totag()) {
188
+		if (!loose_route()) {
189
+			switch($rc) {
190
+			case -2:
191
+				sl_send_reply("403", "Forbidden");
192
+				exit;
193
+			default:
194
+				if (is_method("ACK")) {
195
+					if ( t_check_trans() ) {
196
+						route(RELAY);
197
+						exit;
198
+					} else {
199
+						exit;
200
+					}
201
+				}
202
+				sl_send_reply("404","Not Found");
203
+			}
204
+		} else {
205
+			if (is_method("NOTIFY")) {
206
+				record_route();
207
+			}
208
+			route(RELAY);
209
+		}
210
+		exit;
211
+	}
212
+}
213
+
214
+onreply_route {
215
+	if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
216
+		&& !(proto == WS || proto == WSS)) {
217
+		xlog("L_WARN", "SIP response received on $Rp\n");
218
+		drop;
219
+	}
220
+
221
+	if (!t_check_trans()) {
222
+		drop;
223
+	}
224
+
225
+	if ($rm == "REGISTER" && $rs >= 200 && $rs <= 299) {
226
+		remove_hf("Flow-Timer");
227
+		if ($(hdr(Require)[*])=~"outbound")
228
+			insert_hf("Flow-Timer: FLOW_TIMER\r\n", "Call-ID");
229
+	}
230
+}
231
+
232
+failure_route[FAIL_OUTBOUND] {
233
+	if (t_branch_timeout() || !t_branch_replied()) {
234
+		send_reply("430", "Flow Failed");
235
+	}
236
+}
237
+
238
+event_route[xhttp:request] {
239
+	set_reply_close();
240
+	set_reply_no_connect();
241
+
242
+	if ($Rp != MY_WS_PORT
243
+#!ifdef WITH_TLS
244
+		&& $Rp != MY_WSS_PORT
245
+#!endif
246
+	) {
247
+		xlog("L_WARN", "HTTP request received on $Rp\n");
248
+		xhttp_reply("403", "Forbidden", "", "");
249
+		exit;
250
+	}
251
+
252
+	xlog("L_DBG", "HTTP Request Received\n");
253
+
254
+	if ($hdr(Upgrade)=~"websocket"
255
+			&& $hdr(Connection)=~"Upgrade"
256
+			&& $rm=~"GET") {
257
+
258
+		# Validate Host - make sure the client is using the correct
259
+		# alias for WebSockets
260
+		if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
261
+			xlog("L_WARN", "Bad host $hdr(Host)\n");
262
+			xhttp_reply("403", "Forbidden", "", "");
263
+			exit;
264
+		}
265
+
266
+		# Optional... validate Origin - make sure the client is from an
267
+		# authorised website.  For example,
268
+		#
269
+		# if ($hdr(Origin) != "http://communicator.MY_DOMAIN"
270
+		#     && $hdr(Origin) != "https://communicator.MY_DOMAIN") {
271
+		#	xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
272
+		#	xhttp_reply("403", "Forbidden", "", "");
273
+		#	exit;
274
+                # }
275
+
276
+		# Optional... perform HTTP authentication
277
+
278
+		# ws_handle_handshake() exits (no further configuration file
279
+		# processing of the request) when complete.
280
+		if (ws_handle_handshake())
281
+		{
282
+			# Optional... cache some information about the
283
+			# successful connection
284
+			exit;
285
+		}
286
+	}
287
+
288
+	xhttp_reply("404", "Not Found", "", "");
289
+}
290
+
291
+event_route[websocket:closed] {
292
+	xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
293
+}