tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

tls: deprecate newSession/resumeSession events - #5774

Closed
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462
Closed

tls: deprecate newSession/resumeSession events#5774
indutny wants to merge 1 commit into
nodejs:masterfrom
indutny:fix/gh-1462

Conversation

@indutny

Copy link
Copy Markdown
Member

Pull Request check-list

Please make sure to review and check all of these items:

  • Does make -j8 test (UNIX) or vcbuild test nosign (Windows) pass with
    this change (including linting)?
  • Is the commit message formatted according to CONTRIBUTING.md?
  • If this change fixes a bug (or a performance problem), is a regression
    test (or a benchmark) included?
  • Is a documentation update included (if this change modifies
    existing APIs, or introduces new ones)?

NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.

Affected core subsystem(s)

tls

Description of change

Deprecate asynchronous newSession/resumeSession events, introduce a
synchronous APIs via newSession/resumeSession option-callback for
tls.createServer.

The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.

See: #1462

Deprecate asynchronous `newSession`/`resumeSession` events, introduce a
synchronous APIs via `newSession`/`resumeSession` option-callback for
`tls.createServer`.
The reason for this transition is rather simple. There is a quite big
amount of code that was added to support this construction, and not that
much users of it. Additionally, that code chunk is running in front of
OpenSSL, so it makes the process of asynchronous session resumption
twice as ineffective.
See: nodejs#1462
@indutny

Copy link
Copy Markdown
MemberAuthor

Next PR will be for removal of this API.

CI: https://ci.nodejs.org/job/node-test-pull-request/1948/

cc @nodejs/crypto
R= @bnoordhuis or @shigeki

@claudiorodriguezclaudiorodriguez added the tls Issues and PRs related to the tls subsystem. label Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

also cc @nodejs/lts , not sure what is our deprecation policy.

@indutnyindutny added c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version. labels Mar 18, 2016
@indutny

Copy link
Copy Markdown
MemberAuthor

cc @tlivings

@bnoordhuis

Copy link
Copy Markdown
Member

I don't think synchronous APIs are a good idea. It makes it impossible to store the session data in a remote service like redis or memcached or a cluster master.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis the sessions are not of a big use anyway, browsers are using TLS tickets, and CLI clients (read other servers) can move to them too. Do you have a use-case for this at IBM?

@bnoordhuis

Copy link
Copy Markdown
Member

Not IBM per se but I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I believe that this use case is very limited and actually helps only on a small percentage of incoming connections.

@tlivings

Copy link
Copy Markdown

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time. If it's used to distribute session on new session, isn't super useful either since it doesn't benefit anyone immediately. Pre-caching sessions in memory is a lot faster and doesn't rely on an async method.

@indutny

Copy link
Copy Markdown
MemberAuthor

@tlivings but it could work with a sync method too?

@tlivings

Copy link
Copy Markdown

Yeah, that's what I am saying. If sessions are pre-cached in memory you only need a sync method.

@bnoordhuis

Copy link
Copy Markdown
Member

Storing sessions in a database or cache like redis doesn't really give any performance benefit of looked up at connect time.

Specious. Do you have numbers to back that up? The extra TCP round-trips in a full TLS handshake aren't free.

@tlivings

Copy link
Copy Markdown

My point is that the time to fetch a session out of redis is slower than to fetch it out of memory. Particularly if you are in a distributed environment where you have to go over the wire to your store.

@bnoordhuis

Copy link
Copy Markdown
Member

Sure, in-process memory is faster than out-of-process memory. That doesn't mean there are no use cases for the latter, though.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis what I'm trying to say is that this use-case doesn't really help that much in presence of TLS sessions tickets which are supported by almost everyone nowadays.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm willing to be convinced by numbers. I researched this subject a few months ago actually and I wasn't really able to come to a conclusion. Keep in mind that many node apps talk to more than just browsers.

FWIW, I'm open to the argument that a session cache is less secure than session tickets, but that's a nuanced topic because it's also perfectly possible to botch the PFS of session tickets.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis some numbers from 2012 by @pquernahttps://journal.paul.querna.org/articles/2012/09/07/adoption-of-tls-extensions . I'm sure adoption is much higher now, but honestly... we are currently carrying a SSL Record parsing just for this purpose. Unless you have numbers to prove that it is very useful - I'm really committed to removing of it.

@bnoordhuis

Copy link
Copy Markdown
Member

I'm not worried about browsers but, as an example, I wasn't able to get session tickets working with python2's ssl module. I didn't dive in too deeply (I stopped at objdump -T _ssl.so | grep tlsext) but I couldn't find anything that suggests it supports it.

@bajtos

Copy link
Copy Markdown
Contributor

I believe @bajtos wrote a module that stores sessions in the cluster master using newSession/resumeSession.

The module is called strong-cluster-tls-store and it uses Node's master<->worker IPC mechanism to synchronize sessions across cluster workers running under the same cluster master process. The usage of the module is described in this blogpost from 2013: https://strongloop.com/strongblog/improve-the-performance-of-the-node-js-https-server/

IIRC, the IPC mechanism used to send messages between Node processes is asynchronous, therefore it cannot be used with a sync version of newSession/resumeSession.

To be honest, I am not following the Node core development closely, I don't know how many people use the native cluster + port sharing capability (as opposed to having each worker listen on an unique port and have Nginx to do both TLS termination and load balancing, for example). Therefore I have no idea whether strong-cluster-tls-store and newSession/resumeSession events are of any use today.

From the point of API consumers, I think it's important to preserve the ability to set newSession and resumeSession after the server was created:

// appvarhttps=require('https');varshareTlsSessions=require('strong-cluster-tls-store');varhttpsOpts={/* configure certificates, etc. */}varserver=https.createServer(httpsOpts,function(req,res){// handle the request});shareTlsSessions(server);server.listen(443);// inside strong-cluster-tls-storemodule.exports=functionshareTlsServer(server){server.newSession=function(){ ... };server.resumeSession=function(){ ... };}

If I am reading the patch correctly, then my example above should work, but it depends on undocumented APIs server.newSession and server.resumeSession. Perhaps these two new properties/methods should be included in the documentation and the API contract?

@indutny

Copy link
Copy Markdown
MemberAuthor

@bajtos perhaps!

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

@bajtos

Copy link
Copy Markdown
Contributor

The question that we are trying to figure out here is how much use does this async session API really provide. The new API is going to be all synchronous, so ruling out async use cases is important to proceed here.

I see. Well, I cannot help you much with that, beyond pointing the single use case which requires async session API that I am aware of - sharing TLS sessions among cluster workers. For what's it worth, because it may not be a use case worth supporting anyways. strong-cluster-tls-store has 85 downloads per months according to npmjs.

I am afraid it's really up to you to make the decision.

One more idea to consider: since the synchronous API has extremely limited use, is it worth to support it at all? Perhaps, instead of changing newSession and resumeSession from async to sync, should we remove it completely?

@tlivings

Copy link
Copy Markdown

We shouldn't remove it, since the point of this change is to maintain support, albeit sync.

The Strongloop example is one way of synchronizing across clusters, but such methods should be able to convert to local population over async, while the outgoing http call looks up from local synchronously. In other words, rather than performing an async call to fetch a session for resume, the expectation would be that some tool/framework would be populating into memory sessions to resume from the shared storage, and therefor not require the complexity of async in node core.

@bnoordhuis

Copy link
Copy Markdown
Member

You mean push-to-workers instead of pull-from-master? That can work but it produces traffic relative to the size of the cluster (O(n) instead of O(1)) and it makes it more likely to get cache misses because the session data hasn't fully propagated yet.

Also, I'm not sure what would happen if there is a cache hit but it's for stale data... I think centralization is easier to reason about in this case.

@indutny

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis I really suggest that the most of the clients will use tickets, unless they are legacy. Even python will use tickets if it will use TLS protocol with openssl.so that supports tickets. In case of tickets - there is no need to pre-distribute them, it is just the ticket key that should be in sync between workers.

Also, from the client-side perspective it works the same way as old SSL sessions, they just decode SSL_SESSION and use it when connecting. No difference at all, hence it will work with many of them, even those that didn't support it at first.

@jasnell

Copy link
Copy Markdown
Member

ping @indutny ... is this something you still want to pursue?

@jasnelljasnell added the stalled Issues and PRs manually marked as stalled and scheduled for automatic closure. label Mar 1, 2017
@indutny

Copy link
Copy Markdown
MemberAuthor

Yes, I want to pursue it, but it stalled.

@jasnell

Copy link
Copy Markdown
Member

@indutny ... I'm going to close this due to lack of forward progress. When you're ready to tackle it again, feel free to reopen or open a new PR :-)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.semver-majorPRs that contain breaking changes and should be released in the next major version.stalledIssues and PRs manually marked as stalled and scheduled for automatic closure.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@indutny@bnoordhuis@tlivings@bajtos@jasnell@claudiorodriguez