Skip to content

Commit 97d002b

Browse files
committed
Replace TLS event connectHostname/Port & 'hostname' with 'destination'
In most cases, you want event.destination.hostname to get the final target of any given request/tunnel/etc. If you're looking for the SNI hostname for a TLS connection, that's under event.tlsMetadata.sniHostname. The previous 'hostname' field was ambiguous and has been removed.
1 parent 5db2ab5 commit 97d002b

File tree

9 files changed

+31
-44
lines changed

9 files changed

+31
-44
lines changed

src/admin/mockttp-schema.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ export const MockttpSchema = gql`
6464
type TlsPassthroughEvent {
6565
id: String!
6666
67-
upstreamHost: String
68-
upstreamPort: Int!
67+
destination: Destination!
6968
7069
hostname: String
7170
remoteIpAddress: String!
@@ -123,8 +122,7 @@ export const MockttpSchema = gql`
123122
type RawPassthroughEvent {
124123
id: String!
125124
126-
upstreamHost: String!
127-
upstreamPort: Int!
125+
destination: Destination!
128126
129127
remoteIpAddress: String!
130128
remotePort: Int!

src/client/mockttp-admin-request-builder.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,13 @@ export class MockttpAdminRequestBuilder {
384384
tlsPassthroughOpened {
385385
id
386386
387-
${this.schema.asOptionalField('TlsPassthroughEvent', 'upstreamHost')}
388-
upstreamPort
387+
${this.schema.typeHasField('TlsPassthroughEvent', 'destination')
388+
? 'destination { hostname, port }'
389+
: `
390+
upstreamHost
391+
upstreamPort
392+
`
393+
}
389394
390395
hostname
391396
remoteIpAddress
@@ -399,8 +404,13 @@ export class MockttpAdminRequestBuilder {
399404
tlsPassthroughClosed {
400405
id
401406
402-
${this.schema.asOptionalField('TlsPassthroughEvent', 'upstreamHost')}
403-
upstreamPort
407+
${this.schema.typeHasField('TlsPassthroughEvent', 'destination')
408+
? 'destination { hostname, port }'
409+
: `
410+
upstreamHost
411+
upstreamPort
412+
`
413+
}
404414
405415
hostname
406416
remoteIpAddress
@@ -464,8 +474,7 @@ export class MockttpAdminRequestBuilder {
464474
rawPassthroughOpened {
465475
id
466476
467-
upstreamHost
468-
upstreamPort
477+
destination { hostname, port }
469478
470479
remoteIpAddress
471480
remotePort
@@ -477,8 +486,7 @@ export class MockttpAdminRequestBuilder {
477486
rawPassthroughClosed {
478487
id
479488
480-
upstreamHost
481-
upstreamPort
489+
destination { hostname, port }
482490
483491
remoteIpAddress
484492
remotePort

src/server/http-combo-server.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,6 @@ function analyzeAndMaybePassThroughTls(
474474

475475
socket[TlsMetadata] = {
476476
sniHostname,
477-
connectHostname: upstreamDestination?.hostname,
478-
connectPort: upstreamDestination?.port.toString(),
479477
clientAlpn: helloData.alpnProtocols,
480478
ja3Fingerprint: calculateJa3FromFingerprintData(helloData.fingerprintData),
481479
ja4Fingerprint: calculateJa4FromHelloData(helloData)

src/server/mockttp-server.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,6 @@ export class MockttpServer extends AbstractMockttp implements Mockttp {
565565
if (socket instanceof tls.TLSSocket && socket[TlsSetupCompleted]) return;
566566

567567
setImmediate(() => {
568-
// We can get falsey but set hostname values - drop them
569-
if (!request.hostname) delete request.hostname;
570568
if (this.debug) console.warn(`TLS client error: ${JSON.stringify(request)}`);
571569
this.eventEmitter.emit('tls-client-error', request);
572570
});
@@ -1193,8 +1191,7 @@ ${await this.suggestRule(request)}`
11931191
{
11941192
id: uuid(),
11951193
hostname: hostname, // Deprecated, but kept here for backward compat
1196-
upstreamHost: hostname,
1197-
upstreamPort: targetPort
1194+
destination: { hostname, port: targetPort }
11981195
}
11991196
);
12001197

src/types.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,24 @@ export interface Request {
9393
}
9494

9595
export interface TlsConnectionEvent {
96-
/**
97-
* @deprecated - Use `tlsMetadata.sniHostname` or `tlsMetadata.connectHostname` for
98-
* handshake/tunnel details, or `upstreamHost` in passthrough events for the
99-
* upstream host of the passthrough tunnel.
100-
*/
101-
hostname?: string;
102-
10396
remoteIpAddress?: string; // Can be unavailable in some error cases
10497
remotePort?: number; // Can be unavailable in some error cases
10598
tags: string[];
10699
timingEvents: TlsTimingEvents;
100+
destination?: Destination; // Set for tunnelled requests only
107101
tlsMetadata: TlsSocketMetadata;
108102
}
109103

110104
export interface TlsSocketMetadata {
111105
sniHostname?: string;
112-
connectHostname?: string;
113-
connectPort?: string;
114106
clientAlpn?: string[];
115107
ja3Fingerprint?: string;
116108
ja4Fingerprint?: string;
117109
}
118110

119111
export interface TlsPassthroughEvent extends RawPassthroughEvent, TlsConnectionEvent {
120112
// Removes ambiguity of the two parent interface fields
113+
destination: Destination;
121114
remoteIpAddress: string;
122115
remotePort: number;
123116
timingEvents: TlsTimingEvents;
@@ -137,8 +130,7 @@ export interface TlsHandshakeFailure extends TlsConnectionEvent {
137130
export interface RawPassthroughEvent {
138131
id: string;
139132

140-
upstreamHost: string;
141-
upstreamPort: number;
133+
destination: Destination;
142134

143135
/**
144136
* The IP address of the remote client that initiated the connection.

src/util/socket-util.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export function resetOrDestroy(requestOrSocket:
166166

167167
export function buildRawSocketEventData(
168168
socket: net.Socket
169-
): Omit<RawPassthroughEvent, 'id' | 'upstreamHost' | 'upstreamPort'> {
169+
): Omit<RawPassthroughEvent, 'id' | 'destination'> {
170170
const timingInfo = socket[SocketTimingInfo] ||
171171
socket._parent?.[SocketTimingInfo] ||
172172
buildSocketTimingInfo();
@@ -190,7 +190,7 @@ export function buildRawSocketEventData(
190190

191191
export function buildTlsSocketEventData(
192192
socket: net.Socket & Partial<tls.TLSSocket>
193-
): Omit<RawPassthroughEvent, 'id' | 'upstreamHost' | 'upstreamPort'> & TlsConnectionEvent {
193+
): Omit<RawPassthroughEvent, 'id' | 'destination'> & TlsConnectionEvent {
194194
const rawSocketData = buildRawSocketEventData(socket) as Partial<TlsConnectionEvent>;
195195

196196
const timingInfo = socket[SocketTimingInfo] ||
@@ -203,8 +203,6 @@ export function buildTlsSocketEventData(
203203
socket._parent?.[TlsMetadata] ||
204204
{};
205205

206-
rawSocketData.hostname = socket.servername;
207-
208206
return rawSocketData as any;
209207
}
210208

test/integration/subscriptions/raw-passthrough-events.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ nodeOnly(() => {
4848
});
4949

5050
it("should fire for raw sockets that are passed through SOCKS", async () => {
51-
const events: any[] = [];
51+
const events: Array<RawPassthroughEvent> = [];
5252
await server.on('raw-passthrough-opened', (e) => events.push(e));
5353
await server.on('raw-passthrough-closed', (e) => events.push(e));
5454

@@ -62,8 +62,8 @@ nodeOnly(() => {
6262
const [openEvent, closeEvent] = events;
6363
expect(openEvent.id).to.equal(closeEvent.id);
6464

65-
expect(openEvent.upstreamHost).to.equal('localhost');
66-
expect(openEvent.upstreamPort).to.equal(remotePort);
65+
expect(openEvent.destination.hostname).to.equal('localhost');
66+
expect(openEvent.destination.port).to.equal(remotePort);
6767
});
6868

6969
it("should expose sent & received data", async () => {
@@ -144,8 +144,8 @@ nodeOnly(() => {
144144
expect(sentEvent.id).to.equal(openEvent.id);
145145
expect(openEvent.id).to.equal(closeEvent.id);
146146

147-
expect(openEvent.upstreamHost).to.equal('localhost');
148-
expect(openEvent.upstreamPort).to.equal(remotePort);
147+
expect(openEvent.destination.hostname).to.equal('localhost');
148+
expect(openEvent.destination.port).to.equal(remotePort);
149149

150150
expect(receivedEvent.content.toString()).to.equal('123456789');
151151
expect(receivedEvent.direction).to.equal('received');

test/integration/subscriptions/tls-error-events.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ describe("TLS error subscriptions", () => {
9393
'reset', // Node 12+
9494
'cert-rejected' // Chrome
9595
]);
96-
expect(tlsError.hostname).to.equal('localhost');
9796
expect(tlsError.remoteIpAddress).to.be.oneOf([
9897
'::ffff:127.0.0.1', // IPv4 localhost
9998
'::1' // IPv6 localhost
@@ -133,7 +132,6 @@ describe("TLS error subscriptions", () => {
133132
const tlsError = await seenTlsErrorPromise;
134133

135134
expect(tlsError.failureCause).to.be.equal('reset');
136-
expect(tlsError.hostname).to.equal('localhost');
137135
expect(tlsError.remoteIpAddress).to.be.oneOf([
138136
'::ffff:127.0.0.1', // IPv4 localhost
139137
'::1' // IPv6 localhost

test/integration/subscriptions/tls-passthrough-events.spec.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,11 @@ describe("TLS passthrough subscriptions", () => {
4141
const [openEvent, closeEvent] = events;
4242
expect(openEvent.id).to.equal(closeEvent.id);
4343

44-
expect(openEvent.hostname).to.equal('bypass.localhost');
45-
expect(openEvent.upstreamPort).to.equal(443);
44+
expect(openEvent.destination.hostname).to.equal('bypass.localhost');
45+
expect(openEvent.destination.port).to.equal(443);
4646

4747
const { tlsMetadata } = openEvent;
4848
expect(tlsMetadata.sniHostname).to.equal('bypass.localhost');
49-
expect(tlsMetadata.connectHostname).to.equal(undefined);
50-
expect(tlsMetadata.connectPort).to.equal(undefined);
5149
expect(tlsMetadata.clientAlpn).to.deep.equal(isNode
5250
? undefined
5351
: ['h2', 'http/1.1']

0 commit comments

Comments
 (0)