1 local configmanager = require "core.configmanager"; |
1 local configmanager = require "core.configmanager"; |
2 local show_usage = require "util.prosodyctl".show_usage; |
2 local show_usage = require "util.prosodyctl".show_usage; |
3 local show_warning = require "util.prosodyctl".show_warning; |
3 local show_warning = require "util.prosodyctl".show_warning; |
4 local is_prosody_running = require "util.prosodyctl".isrunning; |
4 local is_prosody_running = require "util.prosodyctl".isrunning; |
|
5 local parse_args = require "util.argparse".parse; |
5 local dependencies = require "util.dependencies"; |
6 local dependencies = require "util.dependencies"; |
6 local socket = require "socket"; |
7 local socket = require "socket"; |
7 local socket_url = require "socket.url"; |
8 local socket_url = require "socket.url"; |
8 local jid_split = require "util.jid".prepped_split; |
9 local jid_split = require "util.jid".prepped_split; |
9 local modulemanager = require "core.modulemanager"; |
10 local modulemanager = require "core.modulemanager"; |
58 end |
59 end |
59 end |
60 end |
60 return false, "Probe endpoint did not return a success status"; |
61 return false, "Probe endpoint did not return a success status"; |
61 end |
62 end |
62 |
63 |
63 local function check_turn_service(turn_service) |
64 local function check_turn_service(turn_service, ping_service) |
64 local stun = require "net.stun"; |
65 local stun = require "net.stun"; |
65 |
66 |
66 -- Create UDP socket for communication with the server |
67 -- Create UDP socket for communication with the server |
67 local sock = assert(require "socket".udp()); |
68 local sock = assert(require "socket".udp()); |
68 sock:setsockname("*", 0); |
69 sock:setsockname("*", 0); |
155 elseif not alloc_response:is_success_resp() then |
156 elseif not alloc_response:is_success_resp() then |
156 result.error = ("Unexpected TURN response: %d (%s)"):format(alloc_response:get_type()); |
157 result.error = ("Unexpected TURN response: %d (%s)"):format(alloc_response:get_type()); |
157 return result; |
158 return result; |
158 end |
159 end |
159 |
160 |
160 -- No errors? Ok! |
161 if not ping_service then |
|
162 -- Success! We won't be running the relay test. |
|
163 return result; |
|
164 end |
|
165 |
|
166 -- Run the relay test - i.e. send a binding request to ping_service |
|
167 -- and receive a response. |
|
168 |
|
169 -- Resolve the IP of the ping service |
|
170 local ping_service_ip, err = socket.dns.toip(ping_service); |
|
171 if not ping_service_ip then |
|
172 result.error = "Unable to resolve external service: "..err; |
|
173 return result; |
|
174 end |
|
175 |
|
176 -- Ask the TURN server to allow packets from the ping service IP |
|
177 local perm_request = stun.new_packet("create-permission"); |
|
178 perm_request:add_xor_peer_address(ping_service_ip); |
|
179 perm_request:add_attribute("username", turn_user); |
|
180 perm_request:add_attribute("realm", realm); |
|
181 perm_request:add_attribute("nonce", nonce); |
|
182 perm_request:add_message_integrity(key); |
|
183 sock:send(perm_request:serialize()); |
|
184 |
|
185 local perm_response, err = receive_packet(); |
|
186 if not perm_response then |
|
187 result.error = "No response from TURN server when requesting peer permission: "..err; |
|
188 return result; |
|
189 elseif perm_response:is_err_resp() then |
|
190 result.error = ("TURN permission request failed: %d (%s)"):format(perm_response:get_error()); |
|
191 return result; |
|
192 elseif not perm_response:is_success_resp() then |
|
193 result.error = ("Unexpected TURN response: %d (%s)"):format(perm_response:get_type()); |
|
194 return result; |
|
195 end |
|
196 |
|
197 -- Ask the TURN server to relay a STUN binding request to the ping server |
|
198 local ping_data = stun.new_packet("binding"):serialize(); |
|
199 |
|
200 local ping_request = stun.new_packet("send", "indication"); |
|
201 ping_request:add_xor_peer_address(ping_service_ip, 3478); |
|
202 ping_request:add_attribute("data", ping_data); |
|
203 ping_request:add_attribute("username", turn_user); |
|
204 ping_request:add_attribute("realm", realm); |
|
205 ping_request:add_attribute("nonce", nonce); |
|
206 ping_request:add_message_integrity(key); |
|
207 sock:send(ping_request:serialize()); |
|
208 |
|
209 local ping_response, err = receive_packet(); |
|
210 if not ping_response then |
|
211 result.error = "No response from ping server ("..ping_service_ip.."): "..err; |
|
212 return result; |
|
213 elseif not ping_response:is_indication() or select(2, ping_response:get_method()) ~= "data" then |
|
214 result.error = ("Unexpected TURN response: %s %s"):format(select(2, ping_response:get_method()), select(2, ping_response:get_type())); |
|
215 return result; |
|
216 end |
|
217 |
|
218 local pong_data = ping_response:get_attribute("data"); |
|
219 if not pong_data then |
|
220 result.error = "No data relayed from remote server"; |
|
221 return; |
|
222 end |
|
223 local pong = stun.new_packet():deserialize(pong_data); |
|
224 |
|
225 result.external_ip_pong = pong:get_xor_mapped_address(); |
|
226 if not result.external_ip_pong then |
|
227 result.error = "Ping server did not return an address"; |
|
228 return result; |
|
229 end |
|
230 |
|
231 -- |
161 |
232 |
162 return result; |
233 return result; |
163 end |
234 end |
164 |
235 |
165 local function skip_bare_jid_hosts(host) |
236 local function skip_bare_jid_hosts(host) |
168 return false; |
239 return false; |
169 end |
240 end |
170 return true; |
241 return true; |
171 end |
242 end |
172 |
243 |
|
244 local check_opts = { |
|
245 short_params = { |
|
246 h = "help", v = "verbose"; |
|
247 }; |
|
248 }; |
|
249 |
173 local function check(arg) |
250 local function check(arg) |
174 if arg[1] == "--help" then |
251 if arg[1] == "help" or arg[1] == "--help" then |
175 show_usage([[check]], [[Perform basic checks on your Prosody installation]]); |
252 show_usage([[check]], [[Perform basic checks on your Prosody installation]]); |
176 return 1; |
253 return 1; |
177 end |
254 end |
178 local what = table.remove(arg, 1); |
255 local what = table.remove(arg, 1); |
|
256 local opts = assert(parse_args(arg, check_opts)); |
179 local array = require "util.array"; |
257 local array = require "util.array"; |
180 local set = require "util.set"; |
258 local set = require "util.set"; |
181 local it = require "util.iterators"; |
259 local it = require "util.iterators"; |
182 local ok = true; |
260 local ok = true; |
183 local function disabled_hosts(host, conf) return host ~= "*" and conf.enabled ~= false; end |
261 local function disabled_hosts(host, conf) return host ~= "*" and conf.enabled ~= false; end |
1149 end |
1227 end |
1150 |
1228 |
1151 for turn_id, turn_service in pairs(turn_services) do |
1229 for turn_id, turn_service in pairs(turn_services) do |
1152 print("Testing "..turn_id.."..."); |
1230 print("Testing "..turn_id.."..."); |
1153 |
1231 |
1154 local result = check_turn_service(turn_service); |
1232 local result = check_turn_service(turn_service, opts.ping); |
1155 if #result.warnings > 0 then |
1233 if #result.warnings > 0 then |
1156 print(("%d warnings:\n\n "):format(#result.warnings)); |
1234 print(("%d warnings:\n\n "):format(#result.warnings)); |
1157 print(table.concat(result.warnings, "\n ")); |
1235 print(table.concat(result.warnings, "\n ")); |
1158 end |
1236 end |
1159 if result.error then |
1237 if result.error then |
1160 print("Error: "..result.error.."\n"); |
1238 print("Error: "..result.error.."\n"); |
1161 ok = false; |
1239 ok = false; |
1162 else |
1240 else |
|
1241 if opts.verbose then |
|
1242 print(("External IP: %s"):format(result.external_ip.address)); |
|
1243 if result.external_ip_pong then |
|
1244 print(("TURN external IP: %s"):format(result.external_ip_pong.address)); |
|
1245 end |
|
1246 end |
1163 print("Success!\n"); |
1247 print("Success!\n"); |
1164 end |
1248 end |
1165 end |
1249 end |
1166 end |
1250 end |
1167 |
1251 |