Skip to content

Commit c8d8ac0

Browse files
committed
fix(mitm): don’t let dns errors go unhandled
1 parent cf3e6b5 commit c8d8ac0

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

mitm/handlers/RequestSession.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ export default class RequestSession extends TypedEventEmitter<IRequestSessionEve
222222
try {
223223
return await this.dns.lookupIp(host);
224224
} catch (error) {
225-
log.error('DnsLookup.Error', {
225+
log.info('DnsLookup.Error', {
226226
sessionId: this.sessionId,
227227
error,
228228
});

mitm/lib/Dns.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ export class Dns {
5454
}
5555

5656
private async systemLookup(host: string): Promise<IDnsEntry> {
57+
const dnsEntry = createPromise<IDnsEntry>();
58+
Dns.dnsEntries.set(host, dnsEntry);
5759
try {
58-
const dnsEntry = createPromise<IDnsEntry>();
59-
Dns.dnsEntries.set(host, dnsEntry);
6060
const lookupAddresses = await dns.lookup(host.split(':').shift(), {
6161
all: true,
6262
family: 4,
@@ -68,22 +68,20 @@ export class Dns {
6868
})),
6969
};
7070
dnsEntry.resolve(entry);
71-
return entry;
7271
} catch (error) {
73-
Dns.dnsEntries.get(host)?.reject(error);
72+
dnsEntry.reject(error);
7473
Dns.dnsEntries.delete(host);
75-
throw error;
7674
}
75+
return dnsEntry.promise;
7776
}
7877

7978
private async lookupDnsEntry(host: string): Promise<IDnsEntry> {
8079
const existing = Dns.dnsEntries.get(host);
8180
if (existing && !existing.isResolved) return existing.promise;
8281

82+
const dnsEntry = createPromise<IDnsEntry>();
83+
Dns.dnsEntries.set(host, dnsEntry);
8384
try {
84-
const dnsEntry = createPromise<IDnsEntry>();
85-
Dns.dnsEntries.set(host, dnsEntry);
86-
8785
if (!this.socket) {
8886
this.socket = new DnsOverTlsSocket(
8987
this.dnsServer,
@@ -103,12 +101,11 @@ export class Dns {
103101
})),
104102
};
105103
dnsEntry.resolve(entry);
106-
return entry;
107104
} catch (error) {
108-
Dns.dnsEntries.get(host)?.reject(error);
105+
dnsEntry.reject(error);
109106
Dns.dnsEntries.delete(host);
110-
throw error;
111107
}
108+
return dnsEntry.promise;
112109
}
113110

114111
private nextIp(dnsEntry: IDnsEntry): string {

mitm/test/dns.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,30 @@ test('should lookup in the local machine if not found in DoT', async () => {
115115
expect(lookupSpy).toHaveBeenCalledTimes(1);
116116
expect(systemLookupSpy).toHaveBeenCalledTimes(1);
117117
});
118+
119+
test('should properly expose errors if nothing is found', async () => {
120+
const lookupSpy = jest.spyOn(nodeDns, 'lookup').mockClear();
121+
const dotLookup = jest
122+
.spyOn<any, any>(dns, 'lookupDnsEntry')
123+
.mockClear()
124+
.mockImplementationOnce(() => {
125+
throw new Error('Not found');
126+
});
127+
const systemLookupSpy = jest.spyOn<any, any>(dns, 'systemLookup').mockClear();
128+
129+
let unhandledErrorCalled = false;
130+
const handler = () => {
131+
unhandledErrorCalled = true;
132+
};
133+
process.once('unhandledRejection', handler);
134+
135+
await expect(dns.lookupIp('not-real-123423423443433434343-fake-domain.com')).rejects.toThrowError(
136+
'Not found',
137+
);
138+
await new Promise(resolve => setTimeout(resolve, 100));
139+
expect(unhandledErrorCalled).toBe(false);
140+
expect(dotLookup).toHaveBeenCalledTimes(1);
141+
expect(lookupSpy).toHaveBeenCalledTimes(1);
142+
expect(systemLookupSpy).toHaveBeenCalledTimes(1);
143+
process.off('unhandledRejection', handler);
144+
});

0 commit comments

Comments
 (0)