Skip to content

Does HttpClient open two TLS connection instead of just one? #48652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sma opened this issue Mar 23, 2022 · 2 comments
Closed

Does HttpClient open two TLS connection instead of just one? #48652

sma opened this issue Mar 23, 2022 · 2 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-duplicate Closed in favor of an existing report library-io

Comments

@sma
Copy link

sma commented Mar 23, 2022

I think the Dart HttpClient opens two TLS connections to a server and that causes a problem for me.

I'm working with self-signed certificates and have a required client certificate.

Here's a minimal Dart client:

import 'dart:io';

void main() async {
  final key = File('app.key').readAsBytesSync();
  final cert = File('app.cert').readAsBytesSync();
  final sc = SecurityContext(withTrustedRoots: false)
    ..usePrivateKeyBytes(key)
    ..useCertificateChainBytes(cert)
    ..setAlpnProtocols(['http/1.1'], false);
  final client = HttpClient(context: sc);
  client.badCertificateCallback = (cert, host, port) {
    print('do we talk to ${cert.subject} at $host:$port? Yes!');
    return true;
  };
  final request = await client.openUrl('GET', Uri.parse('https://localhost:8443/'));
  request.persistentConnection = false;
  final response = await request.close();
  print(response.statusCode);
  await response.drain();
  client.close();
}

Here's a minimal Node.js server:

const https = require('https');
const fs = require('fs');

const options = {
    enableTrace: true,
    key: fs.readFileSync('server.key'),
    cert: fs.readFileSync('server.cert'),
    requestCert: true,
    rejectUnauthorized: false,
};

const server = https.createServer(options, (req, res) => {
    console.log(req.socket.getPeerCertificate().fingerprint);
    res.writeHead(200);
    res.end('Welcome!\n');
});

server.on('clientError', (err, socket) => {
    console.error(err);
});

server.listen(8443);

I run the server with NODE_DEBUG=tls,https node server.js.

Here's the trace for curl:

TLS 2513: net.Server.on(connection): new TLSSocket
TLS 2513: server _init handle? true
TLS 2513: server initRead handle? true buffered? 0
TLS 2513: server onhandshakestart
TLS 2513: server onhandshakedone
TLS 2513: server _finishInit handle? true alpn http/1.1 servername localhost
TLS 2513: server emit secureConnection
84:E3:E6:E1:B6:59:FF:3E:D5:E9:F8:28:81:46:E3:5C:AB:58:1D:2E

And here's the trace when running the Dart client:

TLS 2527: net.Server.on(connection): new TLSSocket
TLS 2527: server _init handle? true
TLS 2527: server initRead handle? true buffered? 0
TLS 2527: net.Server.on(connection): new TLSSocket
TLS 2527: server _init handle? true
TLS 2527: server initRead handle? true buffered? 0
TLS 2527: server onhandshakestart
Error: socket hang up
    at connResetException (node:internal/errors:692:14)
    at TLSSocket.onSocketClose (node:_tls_wrap:1082:23)
    at TLSSocket.emit (node:events:539:35)
    at node:net:709:12
    at Socket.done (node:_tls_wrap:582:7)
    at Object.onceWrapper (node:events:642:26)
    at Socket.emit (node:events:527:28)
    at TCP.<anonymous> (node:net:709:12) {
  code: 'ECONNRESET'
}
TLS 2527: server onhandshakestart
TLS 2527: server onhandshakedone
TLS 2527: server _finishInit handle? true alpn http/1.1 servername localhost
TLS 2527: server emit secureConnection
84:E3:E6:E1:B6:59:FF:3E:D5:E9:F8:28:81:46:E3:5C:AB:58:1D:2E

Notice the ECONNRESET error and notice how new TLSSocket appears twice.

It looks like Dart is establishing two connections to the server, then retracting on of them.

I think this is a problem, because the "real" server I'm talking to, will stop talking to my client on the first error. The Node.js server is more forgiving. It will eventually respond with "welcome" and talk to Dart.

Here's my Dart version. I'm working on macOS:

$ dart --version
Dart SDK version: 2.17.0-222.0.dev (dev) (Fri Mar 18 12:54:18 2022 -0700) on "macos_x64"
@a-siva
Copy link
Contributor

a-siva commented Mar 23, 2022

Yes, two connections are attempted, please see #41451 and https://dart-review.googlesource.com/c/sdk/+/177560 for details on this.

We have a similar issue filed here #46102

@a-siva a-siva added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io labels Mar 23, 2022
@a-siva a-siva added the closed-duplicate Closed in favor of an existing report label Jun 5, 2023
@a-siva
Copy link
Contributor

a-siva commented Jun 5, 2023

Closing this as a duplicate of #46102

@a-siva a-siva closed this as completed Jun 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-duplicate Closed in favor of an existing report library-io
Projects
None yet
Development

No branches or pull requests

2 participants