@@ -4,6 +4,7 @@ import { observable, action, computed } from 'mobx';
44import { observer , inject } from "mobx-react" ;
55
66import { styled } from '../../styles' ;
7+ import { isWindows } from '../../util/ui' ;
78import { WarningIcon , Icon } from '../../icons' ;
89
910import { isValidPortConfiguration , ProxyStore } from '../../model/proxy-store' ;
@@ -12,7 +13,8 @@ import {
1213 serverVersion ,
1314 versionSatisfies ,
1415 INITIAL_HTTP2_RANGE ,
15- TLS_PASSTHROUGH_SUPPORTED
16+ TLS_PASSTHROUGH_SUPPORTED ,
17+ KEY_LOG_FILE_SUPPORTED
1618} from '../../services/service-versions' ;
1719
1820import { inputValidation } from '../component-utils' ;
@@ -23,6 +25,7 @@ import {
2325} from '../common/card' ;
2426import { ContentLabel } from '../common/text-content' ;
2527import { Select , TextInput } from '../common/inputs' ;
28+ import { IconButton } from '../common/icon-button' ;
2629import {
2730 SettingsButton ,
2831 SettingsExplanation ,
@@ -85,8 +88,29 @@ const Http2Select = styled(Select)`
8588 padding: 3px;
8689` ;
8790
91+ const TlsKeyLogContainer = styled . div `
92+ margin: 10px 0;
93+ display: flex;
94+ flex-direction: column;
95+ position: relative;
96+ ` ;
97+
98+ const InputClearButton = styled ( IconButton ) `
99+ position: absolute;
100+ top: 1px;
101+ right: 2px;
102+ ` ;
103+
88104const hostnameValidation = inputValidation ( isValidHostname , "Should be a valid hostname" ) ;
89105
106+ const isAbsoluteWindowsPath = ( path : string ) => / ^ ( [ a - z A - Z ] : [ \\ \/ ] | [ \\ \/ ] ) ( (?: [ ^ < > : " \/ \\ | ? * ] + ) [ \\ \/ ] ? ) * $ / . test ( path ) ;
107+ const isAbsolutePosixPath = ( path : string ) => / ^ \/ (?: [ ^ / ] + \/ ? ) * $ / . test ( path ) ;
108+
109+ const pathValidation = inputValidation (
110+ isWindows ? isAbsoluteWindowsPath : isAbsolutePosixPath ,
111+ "Should be a valid absolute file path"
112+ ) ;
113+
90114@inject ( 'proxyStore' )
91115@observer
92116export class ProxySettingsCard extends React . Component <
@@ -160,6 +184,26 @@ export class ProxySettingsCard extends React.Component<
160184 tlsPassthroughConfig . splice ( hostnameIndex , 1 ) ;
161185 }
162186
187+ @observable
188+ tlsKeyFileInput : string = this . props . proxyStore ! . keyLogFilePath || '' ;
189+
190+ @action . bound
191+ setTlsKeyFilePath ( { target } : React . ChangeEvent < HTMLInputElement > ) {
192+ this . tlsKeyFileInput = target . value ;
193+
194+ if ( ! this . tlsKeyFileInput . trim ( ) ) {
195+ this . props . proxyStore ! . keyLogFilePath = undefined ;
196+ } else if ( pathValidation ( target ) ) {
197+ this . props . proxyStore ! . keyLogFilePath = this . tlsKeyFileInput . trim ( ) ;
198+ }
199+ }
200+
201+ @action . bound
202+ clearTlsKeyFilePath ( ) {
203+ this . tlsKeyFileInput = '' ;
204+ this . props . proxyStore ! . keyLogFilePath = undefined ;
205+ }
206+
163207 render ( ) {
164208 const { proxyStore, ...cardProps } = this . props ;
165209 const {
@@ -169,7 +213,10 @@ export class ProxySettingsCard extends React.Component<
169213 http2CurrentlyEnabled,
170214
171215 tlsPassthroughConfig,
172- currentTlsPassthroughConfig
216+ currentTlsPassthroughConfig,
217+
218+ keyLogFilePath,
219+ currentKeyLogFilePath
173220 } = proxyStore ! ;
174221
175222 return < CollapsibleCard { ...cardProps } >
@@ -184,7 +231,8 @@ export class ProxySettingsCard extends React.Component<
184231 visible = {
185232 ( this . isCurrentPortConfigValid && ! this . isCurrentPortInRange ) ||
186233 http2Enabled !== http2CurrentlyEnabled ||
187- ! _ . isEqual ( tlsPassthroughConfig , currentTlsPassthroughConfig )
234+ ! _ . isEqual ( tlsPassthroughConfig , currentTlsPassthroughConfig ) ||
235+ keyLogFilePath !== currentKeyLogFilePath
188236 }
189237 />
190238
@@ -234,7 +282,7 @@ export class ProxySettingsCard extends React.Component<
234282 versionSatisfies ( serverVersion . value , TLS_PASSTHROUGH_SUPPORTED ) && < >
235283 < SettingsSubheading >
236284 TLS Passthrough { ! _ . isEqual ( tlsPassthroughConfig , currentTlsPassthroughConfig ) &&
237- < UnsavedIcon />
285+ < UnsavedIcon title = "Restart app to apply changes" />
238286 }
239287 </ SettingsSubheading >
240288
@@ -259,7 +307,7 @@ export class ProxySettingsCard extends React.Component<
259307 versionSatisfies ( serverVersion . value , INITIAL_HTTP2_RANGE ) && < >
260308 < SettingsSubheading >
261309 HTTP/2 Support { http2Enabled !== http2CurrentlyEnabled &&
262- < UnsavedIcon />
310+ < UnsavedIcon title = "Restart app to apply changes" />
263311 }
264312 </ SettingsSubheading >
265313
@@ -278,6 +326,41 @@ export class ProxySettingsCard extends React.Component<
278326 </ Http2Select >
279327 </ >
280328 }
329+
330+ {
331+ versionSatisfies ( serverVersion . value , KEY_LOG_FILE_SUPPORTED ) && < >
332+ < SettingsSubheading >
333+ TLS Key Log File { keyLogFilePath !== currentKeyLogFilePath &&
334+ < UnsavedIcon title = "Restart app to apply changes" />
335+ }
336+ </ SettingsSubheading >
337+
338+ < TlsKeyLogContainer >
339+ < TextInput
340+ placeholder = {
341+ navigator . platform . startsWith ( 'Win' )
342+ ? 'C:\\tls-keys.log'
343+ : '/tmp/tls-keys.log'
344+ }
345+ value = { this . tlsKeyFileInput }
346+ onChange = { this . setTlsKeyFilePath }
347+ />
348+ { ! ! keyLogFilePath && < >
349+ < InputClearButton
350+ title = "Unset TLS key file"
351+ icon = { [ 'fas' , 'times' ] }
352+ onClick = { this . clearTlsKeyFilePath }
353+ />
354+ </ > }
355+ </ TlsKeyLogContainer >
356+
357+ < SettingsExplanation >
358+ If set, TLS keys for all client & server traffic will be logged to this file ,
359+ allowing inspection of raw TLS packet contents & details in low - level packet
360+ inspection tools like Wireshark .
361+ </ SettingsExplanation >
362+ </ >
363+ }
281364 </ CollapsibleCard >
282365 }
283366
0 commit comments