Skip to content

Commit

Permalink
fix: filter out duplicate dns results
Browse files Browse the repository at this point in the history
  • Loading branch information
nirinchev committed Feb 26, 2025
1 parent 12992e7 commit e3c515e
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 7 deletions.
68 changes: 68 additions & 0 deletions src/rfc-8252-http-server.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { SinonSandbox } from 'sinon';
import sinon from 'sinon';
import { promisify } from 'util';
import { randomBytes } from 'crypto';
import { promises as dns } from 'dns';

// node-fetch@3 is ESM-only...
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
Expand Down Expand Up @@ -485,4 +486,71 @@ describe('RFC8252HTTPServer', function () {
});
});
});

context('with dns duplicates', function () {
const originalDnsLookup = dns.lookup;
let dnsLookupStub: sinon.SinonStub;

this.beforeEach(function () {
dnsLookupStub = sinon.stub();
dns.lookup = dnsLookupStub;
});

this.afterEach(function () {
dns.lookup = originalDnsLookup;
});

it('only filters exact duplicates', async function () {
dnsLookupStub.resolves([
{ address: '127.0.0.1', family: 4 },
{ address: '127.0.0.1', family: 4 },
{ address: '[::1]', family: 6 },
{ address: '[::1]', family: 6 },
]);

const interfaces = await RFC8252HTTPServer['_getAllInterfaces'].call(

Check failure on line 511 in src/rfc-8252-http-server.spec.ts

View workflow job for this annotation

GitHub Actions / Check (ubuntu-latest, 18.x)

Expected 2 arguments, but got 1.
'localhost'
);

expect(interfaces).to.have.lengthOf(2);
expect(interfaces[0].address).to.equal('127.0.0.1');
expect(interfaces[1].address).to.equal('[::1]');
expect(interfaces[0].family).to.equal(4);
expect(interfaces[1].family).to.equal(6);
});

it('keeps same addresses, different family', async function () {
dnsLookupStub.resolves([
{ address: '127.0.0.1', family: 4 },
{ address: '127.0.0.1', family: 6 },
]);

const interfaces = await RFC8252HTTPServer['_getAllInterfaces'].call(

Check failure on line 528 in src/rfc-8252-http-server.spec.ts

View workflow job for this annotation

GitHub Actions / Check (ubuntu-latest, 18.x)

Expected 2 arguments, but got 1.
'localhost'
);

expect(interfaces).to.have.lengthOf(2);
expect(interfaces[0].address).to.equal('127.0.0.1');
expect(interfaces[1].address).to.equal('127.0.0.1');
expect(interfaces[0].family).to.equal(4);
expect(interfaces[1].family).to.equal(6);
});

it('keeps same familes, different address', async function () {
dnsLookupStub.resolves([
{ address: '127.0.0.1', family: 4 },
{ address: '192.168.1.15', family: 4 },
]);

const interfaces = await RFC8252HTTPServer['_getAllInterfaces'].call(

Check failure on line 545 in src/rfc-8252-http-server.spec.ts

View workflow job for this annotation

GitHub Actions / Check (ubuntu-latest, 18.x)

Expected 2 arguments, but got 1.
'localhost'
);

expect(interfaces).to.have.lengthOf(2);
expect(interfaces[0].address).to.equal('127.0.0.1');
expect(interfaces[1].address).to.equal('192.168.1.15');
expect(interfaces[0].family).to.equal(4);
expect(interfaces[1].family).to.equal(4);
});
});
});
30 changes: 23 additions & 7 deletions src/rfc-8252-http-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,25 @@ export class RFC8252HTTPServer {
});
};

private static async _getAllInterfaces(
hostname: string
): Promise<{ address: string; family: number }[]> {
const dnsResults = await dns.lookup(hostname, {
all: true,
hints: ADDRCONFIG,
});

return dnsResults
.filter(
(dns, index, arr) =>
arr.findIndex(
(otherDns) =>
dns.address === otherDns.address && dns.family === otherDns.family
) === index
)
.map(({ address, family }) => ({ address, family }));
}

/**
* Add a redirect from a local URL served on the server to an external URL.
*/
Expand Down Expand Up @@ -368,14 +387,11 @@ export class RFC8252HTTPServer {
// to do what Node.js does by default when only a host is provided,
// namely listening on all interfaces.
let hostname = this.redirectUrl.hostname;
if (hostname.startsWith('[') && hostname.endsWith(']'))
if (hostname.startsWith('[') && hostname.endsWith(']')) {
hostname = hostname.slice(1, -1);
const dnsResults = (
await dns.lookup(hostname, {
all: true,
hints: ADDRCONFIG,
})
).map(({ address, family }) => ({ address, family }));
}

const dnsResults = await RFC8252HTTPServer._getAllInterfaces(hostname);

this.logger.emit('mongodb-oidc-plugin:local-listen-resolved-hostname', {
url: this.redirectUrl.toString(),
Expand Down

0 comments on commit e3c515e

Please sign in to comment.