Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMPROVE][Federation] Add support for _tcp and protocol DNS entries #17818

Merged
merged 1 commit into from
Jun 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions app/federation/server/lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,20 @@ export function registerWithHub(peerDomain, url, publicKey) {

export function searchHub(peerDomain) {
try {
logger.dns.debug(`searchHub: peerDomain=${ peerDomain }`);

// If there is no DNS entry for that, get from the Hub
const { data: { peer } } = federationRequest('GET', `${ hubUrl }/api/v1/peers?search=${ peerDomain }`);

if (!peer) {
logger.dns.debug(`searchHub: could not find peerDomain=${ peerDomain }`);
throw federationErrors.peerCouldNotBeRegisteredWithHub('dns.registerWithHub');
}

const { url, public_key: publicKey } = peer;

logger.dns.debug(`searchHub: found peerDomain=${ peerDomain } url=${ url }`);

return {
url,
peerDomain,
Expand All @@ -55,13 +60,14 @@ export function search(peerDomain) {
throw federationErrors.disabled('dns.search');
}

logger.dns.debug(`search: ${ peerDomain }`);
logger.dns.debug(`search: peerDomain=${ peerDomain }`);

let srvEntries = [];
let protocol = '';

// Search by HTTPS first
try {
logger.dns.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._https.${ peerDomain }`);
srvEntries = dnsResolveSRV(`_rocketchat._https.${ peerDomain }`);
protocol = 'https';
} catch (err) {
Expand All @@ -71,31 +77,64 @@ export function search(peerDomain) {
// If there is not entry, try with http
if (!srvEntries.length) {
try {
logger.dns.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._http.${ peerDomain }`);
srvEntries = dnsResolveSRV(`_rocketchat._http.${ peerDomain }`);
protocol = 'http';
} catch (err) {
// Ignore errors when looking for DNS entries
}
}

// If there is not entry, try with tcp
if (!srvEntries.length) {
try {
logger.dns.debug(`search: peerDomain=${ peerDomain } srv=_rocketchat._tcp.${ peerDomain }`);
srvEntries = dnsResolveSRV(`_rocketchat._tcp.${ peerDomain }`);
protocol = 'https'; // https is the default

// Then, also try to get the protocol
logger.dns.debug(`search: peerDomain=${ peerDomain } txt=rocketchat-tcp-protocol.${ peerDomain }`);
protocol = dnsResolveTXT(`rocketchat-tcp-protocol.${ peerDomain }`);
protocol = protocol[0].join('');

if (protocol !== 'http' && protocol !== 'https') {
protocol = null;
}
} catch (err) {
// if there is an error while getting the _tcp entry, it means the config is not there
// but if there is an error looking for the `_rocketchat_tcp_protocol` entry, it means we should use https
}
}

const [srvEntry] = srvEntries;

// If there is no entry, throw error
if (!srvEntry) {
if (!srvEntry || !protocol) {
logger.dns.debug(`search: could not find valid SRV entry peerDomain=${ peerDomain } srvEntry=${ JSON.stringify(srvEntry) } protocol=${ protocol }`);
return searchHub(peerDomain);
}

let publicKey = null;

// Get the public key from the TXT record
const publicKeyTxtRecords = dnsResolveTXT(`rocketchat-public-key.${ peerDomain }`);
try {
logger.dns.debug(`search: peerDomain=${ peerDomain } txt=rocketchat-public-key.${ peerDomain }`);
const publicKeyTxtRecords = dnsResolveTXT(`rocketchat-public-key.${ peerDomain }`);

// Join the TXT record, that might be split
const publicKey = publicKeyTxtRecords[0].join('');
// Join the TXT record, that might be split
publicKey = publicKeyTxtRecords[0].join('');
} catch (err) {
// Ignore errors when looking for DNS entries
}

// If there is no entry, throw error
if (!publicKey) {
logger.dns.debug(`search: could not find TXT entry for peerDomain=${ peerDomain } - SRV entry found`);
return searchHub(peerDomain);
}

logger.dns.debug(`search: found peerDomain=${ peerDomain } srvEntry=${ srvEntry.name }:${ srvEntry.port } protocol=${ protocol }`);

return {
url: `${ protocol }://${ srvEntry.name }:${ srvEntry.port }`,
peerDomain,
Expand Down
2 changes: 2 additions & 0 deletions app/federation/server/lib/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export function federationRequestToPeer(method, peerDomain, uri, body, options =
let result;

try {
logger.http.debug(() => `federationRequestToPeer => url=${ baseUrl }${ uri }`);

result = federationRequest(method, `${ baseUrl }${ uri }`, body, options.headers || {}, peerKey);
} catch (err) {
logger.http.error(`${ ignoreErrors ? '[IGNORED] ' : '' }Error ${ err }`);
Expand Down