Changeset

5585:3e097acf82de

prosodyctl: Add 'prosodyctl check dns' to make an attempt at verifying the server's DNS records
author Matthew Wild <mwild1@gmail.com>
date Fri, 17 May 2013 13:35:12 +0100 (2013-05-17)
parents 5584:1d841117117c
children 5586:7e1264bf7af8
files prosodyctl
diffstat 1 files changed, 142 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/prosodyctl	Fri May 17 09:01:11 2013 +0100
+++ b/prosodyctl	Fri May 17 13:35:12 2013 +0100
@@ -818,7 +818,148 @@
 				print("    You need to move the following option"..(n>1 and "s" or "")..": "..table.concat(it.to_array(misplaced_options), ", "));
 			end
 		end
-		print("Done.");
+		print("Done.\n");
+	end
+	if not what or what == "dns" then
+		local dns = require "net.dns";
+		local c2s_ports = set.new(config.get("*", "c2s_ports") or {5222});
+		local s2s_ports = set.new(config.get("*", "s2s_ports") or {5269});
+		
+		local c2s_srv_required, s2s_srv_required;
+		if not c2s_ports:contains(5222) then
+			c2s_srv_required = true;
+		end
+		if not s2s_ports:contains(5269) then
+			s2s_srv_required = true;
+		end
+		
+		local problem_hosts = set.new();
+		
+		local external_addresses = set.new();
+		
+		local fqdn = socket.dns.tohostname(socket.dns.gethostname());
+		if fqdn then
+			local res = dns.lookup(fqdn, "A");
+			if res then
+				for _, record in ipairs(res) do
+					external_addresses:add(record.a);
+				end
+			end
+			local res = dns.lookup(fqdn, "AAAA");
+			if res then
+				for _, record in ipairs(res) do
+					external_addresses:add(record.aaaa);
+				end
+			end
+		end
+		
+		if external_addresses:empty() then
+			print("");
+			print("   Failed to determine the external addresses of this server. Checks may be inaccurate.");
+			c2s_srv_required, s2s_srv_required = true, true;
+		end
+		
+		local v6_supported = not not socket.tcp6;
+		
+		for host, host_options in it.filter("*", pairs(config.getconfig())) do
+			local all_targets_ok, some_targets_ok = true, false;
+			
+			local is_component = not not host_options.component_module;
+			print("Checking DNS for "..(is_component and "component" or "host").." "..host.."...");
+			local target_hosts = set.new();
+			if not is_component then
+				local res = dns.lookup("_xmpp-client._tcp."..host..".", "SRV");
+				if res then
+					for _, record in ipairs(res) do
+						target_hosts:add(record.srv.target);
+						if not c2s_ports:contains(record.srv.port) then
+							print("    SRV target "..record.srv.target.." contains unknown client port: "..record.srv.port);
+						end
+					end
+				else
+					if c2s_srv_required then
+						print("    No _xmpp-client SRV record found for "..host..", but it looks like you need one.");
+					else
+						target_hosts:add(host);
+					end
+				end
+			end
+			local res = dns.lookup("_xmpp-server._tcp."..host..".", "SRV");
+			if res then
+				for _, record in ipairs(res) do
+					target_hosts:add(record.srv.target);
+					if not s2s_ports:contains(record.srv.port) then
+						print("    SRV target "..record.srv.target.." contains unknown server port: "..record.srv.port);
+					end
+				end
+			else
+				if s2s_srv_required then
+					print("    No _xmpp-server SRV record found for "..host..", but it looks like you need one.");
+				else
+					target_hosts:add(host);
+				end
+			end
+			if target_hosts:empty() then
+				target_hosts:add(host);
+			end
+			
+			if target_hosts:contains("localhost") then
+				print("    Target 'localhost' cannot be accessed from other servers");
+				target_hosts:remove("localhost");
+			end
+			
+			for host in target_hosts do
+				local host_ok_v4, host_ok_v6;
+				local res = dns.lookup(host, "A");
+				if res then
+					for _, record in ipairs(res) do
+						if external_addresses:contains(record.a) then
+							some_targets_ok = true;
+							host_ok_v4 = true;
+						else
+							print("    "..host.." A record points to unknown address "..record.a);
+							all_targets_ok = false;
+						end
+					end
+				end
+				local res = dns.lookup(host, "AAAA");
+				if res then
+					for _, record in ipairs(res) do
+						if external_addresses:contains(record.aaaa) then
+							some_targets_ok = true;
+							host_ok_v6 = true;
+						else
+							print("    "..host.." AAAA record points to unknown address "..record.aaaa);
+							all_targets_ok = false;
+						end
+					end
+				end
+				
+				if not host_ok_v4 then
+					print("    Host "..host.." does not seem to resolve to this server for IPv4");
+				end
+				if not host_ok_v6 and v6_supported then
+					print("    Host "..host.." does not seem to resolve to this server for IPv6");
+				elseif host_ok_v6 and not v6_supported then
+					print("    Host "..host.." has AAAA records, but your version of LuaSocket does not support IPv6.");
+					print("      Please see http://prosody.im/doc/ipv6 for more information.");
+				end
+			end
+			if not all_targets_ok then
+				print("    "..(some_targets_ok and "Only some" or "No").." targets for "..host.." appear to resolve to this server.");
+				if is_component then
+					print("    DNS records are necessary if you want users on other servers to access this component.");
+				end
+				print("");
+				problem_hosts:add(host);
+			end
+		end
+		if not problem_hosts:empty() then
+			print("");
+			print("For more information about DNS configuration please see http://prosody.im/doc/dns");
+			print("");
+			ok = false;
+		end
 	end
 	if not ok then
 		print("Problems found, see above.");