-
Notifications
You must be signed in to change notification settings - Fork 28.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"localhost" favours IPv6 in node v17, used to favour IPv4 #40537
Comments
If it helps, I happened upon this is tests using Hapi. A Hapi Server listen address defaults to |
It's #39987 -- Node.js now returns IP addresses in the order they are returned from the name resolver/DNS. There's a |
…t request address This is a workaround for nodejs/node#40537
Ah, which is the first "Other notable changes" in the release notes. 🤦 Thanks for the pointer! I'll close this, as it is definitely intended behaviour. A mention of this in some sort of "node v17 migration guide" would likely be helpful to others. |
Node.js 17 switched from resolving host names to IPv4 by default to resolving to the order given by the OS. This was an intended change done in nodejs/node#39987, which nevertheless caused issues in downstream projects, as reported in nodejs/node#40537. scalajs-env-nodejs hit that issue, as the JVM server opened on IPv4 by default (apparently this is what the JVM does), but the client tried to connect via IPv6 with Node.js 17. We fix the issue by forcing the use of IPv4 in the Node.js client, as well as on the JVM server for good measure.
We [recently added some better exception handling](#9) but unfortunately printing the response body isn't working because [`response.text()` is a Promise](https://github.github.io/fetch/#response-body). The message looks like this: `ThriftRequestError: Thrift request failed: HTTP 503 Service Unavailable: [object Promise]` The fix is to use `.then()` to get the body. I have not tested this. I did run `npm run test` and some of the tests pass, but 75 out of 108 thrift-integration tests fail. I'm seeing this error a lot: ``` request to http://localhost:8090/thrift failed, reason: connect ECONNREFUSED ::1:8090 ``` I think it also might have been happening before this change. It looks unrelated. It seems like it's happening because [Hapi listens on 127.0.0.1](https://hapi.dev/api/?v=20.2.2#-serveroptionsaddress) and [Node v17 and higher stopped forcing IPv64addresses to be listed first when resolving domains](nodejs/node#40537 (comment)) so now IPv6 addresses can be returned first. I'll probably post a separate PR for that, but for now I'd prefer not to block this change.
And specify it as "localhost" for the servers that are started by the integration tests. Some of the integration tests were failing for me because: - My laptop is configured with both IPv4 and IPv6 for localhost (and non-localhost, too, but that's not relevant here). - Hapi binds to 0.0.0.0 by default ([API docs](https://hapi.dev/api/?v=20.2.2#-serveroptionsaddress), [code reference](https://github.com/hapijs/hapi/blob/b8ba0adc7c3255995cb56a9a740c4f9750b80e6b/lib/core.js#L339)). - That's an IPv4 address so the server will only accept connections over IPv4 and not IPv6. - Our integration test config specifies `localhost` when creating the clients for connecting to these servers. - `localhost` can resolve to an IPv6 address. - Node before v17 sorted IP addresses from the name resolver so IPv4 addresses were first but Node v17 and newer returns them in the order returned by the resolver ([GitHub comment](nodejs/node#40537 (comment)), [relevant PR](nodejs/node#39987), it's the first "Other Notable Changes" in [the v17.0.0 release notes](https://nodejs.org/en/blog/release/v17.0.0/#other-notable-changes)). Apparently on my laptop an IPv6 address is returned before an IPv4 address. Alternatively I could have changed the test config so clients connect to 127.0.0.1. I like this change because: - It's a good idea to allow users to specify the address to bind to. - Now the test servers will bind to localhost instead of 0.0.0.0 and it's nice to avoid accepting outside connections when possible.
And specify it as "localhost" for the servers that are started by the integration tests. Some of the integration tests were failing for me because: - My laptop is configured with both IPv4 and IPv6 for localhost (and non-localhost, too, but that's not relevant here). - Hapi binds to 0.0.0.0 by default ([API docs](https://hapi.dev/api/?v=20.2.2#-serveroptionsaddress), [code reference](https://github.com/hapijs/hapi/blob/b8ba0adc7c3255995cb56a9a740c4f9750b80e6b/lib/core.js#L339)). - That's an IPv4 address so the server will only accept connections over IPv4 and not IPv6. - Our integration test config specifies `localhost` when creating the clients for connecting to these servers. - `localhost` can resolve to an IPv6 address. - Node before v17 sorted IP addresses from the name resolver so IPv4 addresses were first but Node v17 and newer returns them in the order returned by the resolver ([GitHub comment](nodejs/node#40537 (comment)), [relevant PR](nodejs/node#39987), it's the first "Other Notable Changes" in [the v17.0.0 release notes](https://nodejs.org/en/blog/release/v17.0.0/#other-notable-changes)). Apparently on my laptop an IPv6 address is returned before an IPv4 address. Alternatively I could have changed the test config so clients connect to 127.0.0.1. I like this change because: - It's nice to allow users to specify the address to bind to anyway. - Now the test servers will bind to localhost instead of 0.0.0.0 and it's nice to avoid accepting outside connections when possible.
Node prefers ipv6 from version 17 nodejs/node#40537
I've stumbled upon this issue as well. The issue happened on Windows pc. The fixes mentioned above don't work for me (or not feasible) even using v20. Windows favours IPv6 by default (though I'm not completely sure if it's overall default or it's default for our org) and looks like Node on Windows follows that behaviour. In our situation the following worked:
This command changes precedence rules for dns resolution in a way so IPv4 addresses will have higher precedence. Which means if there are IPv4 and IPv6 address for localhost, it'll pick IPv4. After this change the problem disappeared. |
This resolves an error we were experiencing in the test ``` FetchError: request to http://localhost:6109/list failed, reason: connect ECONNREFUSED ::1:6109 ``` Node.js used to favor IPv4 but that changed in v17 > It's #39987 -- Node.js now returns IP addresses in the order they are returned from the name resolver/DNS. There's a --dns-result-order command line option you can set to control the behaviour -- the difference in Node.js 17 is the default changed. nodejs/node#40537 (comment) Signed-off-by: Phillip Rak <rak.phillip@gmail.com>
This resolves an error we were experiencing in the test ``` FetchError: request to http://localhost:6109/list failed, reason: connect ECONNREFUSED ::1:6109 ``` Node.js used to favor IPv4 but that changed in v17 > It's #39987 -- Node.js now returns IP addresses in the order they are returned from the name resolver/DNS. There's a --dns-result-order command line option you can set to control the behaviour -- the difference in Node.js 17 is the default changed. nodejs/node#40537 (comment) Signed-off-by: Phillip Rak <rak.phillip@gmail.com>
This fixes using broccoli locally with nodejs 18.x. Since node 17.x it favours IPv6 over IPv4: nodejs/node#40537
Here's my workaround (open-source and documented) that I hope that can help you too:
After days of research and trial/error, this is how I got this working:
Related commit introducing this fix: undergroundwires/privacy.sexy@52fadcd |
This commit upgrades Node.js version to v20.x in CI/CD environment. Previously used Node 18.x is moving towards end-of-life, with a planned date of 2025-04-30. In contrast, Node 20.x has been offering long-term support (LTS) since 2023-10-24. This makes Node 20.x a stable and recommended version for production environments. This commit also configures `actions/setup-node` with the `check-latest` flag to always use the latest Node 20.x version, keeping CI/CD setup up-to-date with minimal maintenance. Details: - actions/setup-node#165 - actions/setup-node#160 Using Node 20.x in CI/CD environments provides better compatibility with Electron v29.0 which moves to Node 20.x. Details: - electron/electron#40343 This upgrade improves network connection handling in CI/CD pipelines (where issues occur due to GitHub runners not supporting IPv6). Details: - actions/runner#3138 - actions/runner-images#668 - actions/runner#3213 - actions/runner-images#9540 Node 20.x adopts the Happy Eyeballs algorithm for improved IPv6 connectivity. - nodejs/node#40702 - nodejs/node#41625 - nodejs/node#44731 This mitigates issues like `UND_ERR_CONNECT_TIMEOUT` and localhost DNS resolution in CI/CD environments: Details: - nodejs/node#40537 - actions/runner#3213 - actions/runner-images#9540 Node 20 introduces `setDefaultAutoSelectFamily`, a global function from Node 19.4.0, enabling better IPv4 support, especially in environments with limited or problematic IPv6 support. Details: - nodejs/node#45777 Node 20.x defaults to the new `autoSelectFamily`, improving network connection reliability in GitHub runners lacking full IPv6 support. Details: - nodejs/node#46790
This commit upgrades Node.js version to v20.x in CI/CD environment. Previously used Node 18.x is moving towards end-of-life, with a planned date of 2025-04-30. In contrast, Node 20.x has been offering long-term support (LTS) since 2023-10-24. This makes Node 20.x a stable and recommended version for production environments. This commit also configures `actions/setup-node` with the `check-latest` flag to always use the latest Node 20.x version, keeping CI/CD setup up-to-date with minimal maintenance. Details: - actions/setup-node#165 - actions/setup-node#160 Using Node 20.x in CI/CD environments provides better compatibility with Electron v29.0 which moves to Node 20.x. Details: - electron/electron#40343 This upgrade improves network connection handling in CI/CD pipelines (where issues occur due to GitHub runners not supporting IPv6). Details: - actions/runner#3138 - actions/runner-images#668 - actions/runner#3213 - actions/runner-images#9540 Node 20.x adopts the Happy Eyeballs algorithm for improved IPv6 connectivity. - nodejs/node#40702 - nodejs/node#41625 - nodejs/node#44731 This mitigates issues like `UND_ERR_CONNECT_TIMEOUT` and localhost DNS resolution in CI/CD environments: Details: - nodejs/node#40537 - actions/runner#3213 - actions/runner-images#9540 Node 20 introduces `setDefaultAutoSelectFamily`, a global function from Node 19.4.0, enabling better IPv4 support, especially in environments with limited or problematic IPv6 support. Details: - nodejs/node#45777 Node 20.x defaults to the new `autoSelectFamily`, improving network connection reliability in GitHub runners lacking full IPv6 support. Details: - nodejs/node#46790
in order not to use ipv6. see nodejs/node#40537
Version
v17.0.0
Platform
Darwin pink.local 20.6.0 Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64
Subsystem
No response
What steps will reproduce the bug?
I'm not sure what the underlying mechanism is, but it looks to me like the resolution of "localhost" for
server.listen(PORT, HOST, ...)
and forhttp.request('http://localhost/...', ...)
changed from favouring IPv4 in node v16 and earlier, to favouring IPv6. The result is some possibly confusing breakages when using IPv4 values such as127.0.0.1
and0.0.0.0
. For example, the following script errors with node v17, but succeeds with node v16:Similarly, if we reverse things to listen on
'localhost'
and GET from'http://[::1]:3000/ping'
(IPv6), then it fails on node v16 and passes on node v17.As I said above, I don't know the mechanism for selecting IPv4 or IPv6. I suspect this isn't a "bug", except perhaps a lack of documentation? I don't see any mention of localhost of IPv6 in the changelog. Thanks.
How often does it reproduce? Is there a required condition?
Everytime. While I tested mostly on macOS, I believe I was seeing this in GitHub Action tests running on linux containers.
What is the expected behavior?
No response
What do you see instead?
No response
Additional information
No response
The text was updated successfully, but these errors were encountered: