mitm: fix localhost fallback
Kim committed
Mar 25, 2026 at 15:36 UTC
6b99192a6c0de22c03111772b5ee5c15d4fc5bfe
2 files changed
+57
-3
sdk/mitm.go
+17
-3
@@ -108,16 +108,16 @@ func (m *mitmManager) probeTLSPassthrough(ctx context.Context) (MITMProbeReport,
108
report.PublicURL = publicURL
109
report.LeaseID = l.LeaseID()
110
111
- parsedURL, err := url.Parse(publicURL)
111
+ dialAddr, err := m.probeDialAddress(publicURL)
112
if err != nil {
113
- return report, fmt.Errorf("parse public url: %w", err)
113
+ return report, err
114
}
115
116
dialer := &tls.Dialer{
117
NetDialer: &net.Dialer{Timeout: l.api.dialTimeout},
118
Config: m.clientTLSConfig(hostname),
119
}
120
- conn, err := dialer.DialContext(probeCtx, "tcp", utils.EnsurePort(parsedURL.Host))
120
+ conn, err := dialer.DialContext(probeCtx, "tcp", dialAddr)
121
if err != nil {
122
return report, fmt.Errorf("dial mitm probe: %w", err)
123
}
@@ -169,6 +169,20 @@ func (m *mitmManager) probeTLSPassthrough(ctx context.Context) (MITMProbeReport,
169
}
170
}
171
172
+func (m *mitmManager) probeDialAddress(publicURL string) (string, error) {
173
+ parsedURL, err := url.Parse(publicURL)
174
+ if err != nil {
175
+ return "", fmt.Errorf("parse public url: %w", err)
176
+ }
177
+
178
+ dialHost := parsedURL.Host
179
+ l := m.listener
180
+ if l != nil && l.api != nil && l.api.baseURL != nil && utils.IsLocalRelayHost(l.api.baseURL.Hostname()) {
181
+ dialHost = l.api.baseURL.Host
182
+ }
183
+ return utils.EnsurePort(dialHost), nil
184
+}
185
+
186
func (m *mitmManager) clientTLSConfig(hostname string) *tls.Config {
187
probeTLSConf := &tls.Config{
188
ServerName: hostname,
sdk/mitm_test.go
+40
@@ -235,6 +235,46 @@ func TestMITMProbeDetectionBansListener(t *testing.T) {
235
}
236
}
237
238
+func TestMITMProbeDialAddressUsesRelayHostForLocalRelay(t *testing.T) {
239
+ relayURL, err := url.Parse("https://localhost:4017")
240
+ if err != nil {
241
+ t.Fatalf("url.Parse() error = %v", err)
242
+ }
243
+
244
+ listener := &Listener{
245
+ api: &apiClient{baseURL: relayURL},
246
+ }
247
+ listener.mitmManager = newMITMManager(context.Background(), listener)
248
+
249
+ got, err := listener.mitmManager.probeDialAddress("https://bravo-gecko-disco.localhost:4017")
250
+ if err != nil {
251
+ t.Fatalf("probeDialAddress() error = %v", err)
252
+ }
253
+ if got != "localhost:4017" {
254
+ t.Fatalf("probeDialAddress() = %q, want %q", got, "localhost:4017")
255
+ }
256
+}
257
+
258
+func TestMITMProbeDialAddressUsesPublicURLForRemoteRelay(t *testing.T) {
259
+ relayURL, err := url.Parse("https://relay.example")
260
+ if err != nil {
261
+ t.Fatalf("url.Parse() error = %v", err)
262
+ }
263
+
264
+ listener := &Listener{
265
+ api: &apiClient{baseURL: relayURL},
266
+ }
267
+ listener.mitmManager = newMITMManager(context.Background(), listener)
268
+
269
+ got, err := listener.mitmManager.probeDialAddress("https://bravo-gecko-disco.example")
270
+ if err != nil {
271
+ t.Fatalf("probeDialAddress() error = %v", err)
272
+ }
273
+ if got != "bravo-gecko-disco.example:443" {
274
+ t.Fatalf("probeDialAddress() = %q, want %q", got, "bravo-gecko-disco.example:443")
275
+ }
276
+}
277
+
278
func newMITMProbeTLSPair(t *testing.T) (*tls.Conn, *tls.Conn) {
279
t.Helper()
280