-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Dashboard server sometimes only listens on IPv6 loopback address by default instead of both IPv4 and IPv6 #5690
Comments
Hmm, it doesn't seem that ExpressJS is the culprit. When we call |
On further inspection, I don't think the I traced the code through to where it opens up the file descriptor to listen on the port, and the logic is clearly mutually exclusive. I have however confirmed the behaviour of the Personally I regard this as a NodeJS bug. Ideally In the meantime my suggestion is that we implement exactly that functionality in our code as a workaround to this problem. Doing this will have the effect of fixing the issue not only for the |
Also related:
The first issue above suggests alternative workaround that is arguably simpler to implement than the one I proposed in my previous comment: simply setting dns.setDefaultResultOrder("ipv4first") at process start. However to work properly this workaround will need to be set on the calling clients as well. Non-node clients like browsers and That said, I think the more complex workaround that I mentioned above comes with fewer caveats, likely isn't all that complex to implement, and will be more robust overall. |
Looks like changing it to explicitly listen on both protocols will work. Note that I haven't changed the message bus yet (will need to do that as part of this), but for only the dashboard server's Before:
After:
|
Issue
While helping @OnlyOneJMJQ troubleshoot an issue with the truffle dashboard, we encountered a problem where the dashboard's HTTP server was listening only on the IPv6 loopback interface, while his
truffle migrate
command was attempting to connect to the IPv4 interface. This resulted in a mix ofECONNREFUSED
andECONNTIMEOUT
errors from thetruffle migrate
process as it was attempting to connect to the dashboard server process.Steps to Reproduce
dashboard.host
specified in yourtruffle-config.js
truffle dashboard
to spin up the dashboard processtruffle migrate --network dashboard
Note: this very likely only reproduces with Node v17+ (see last paragraph of "underlying cause" discussion below).
Expected Behavior
The
truffle migrate
command should succeed as expected.Actual Results
A mix of
ECONNREFUSED
andECONNTIMEOUT
errors are reported by thetruffle migrate
process, and that process exits with a failure code.Short-term workaround
This issue can be worked around by explicitly setting
dashboard.host
to "127.0.0.1" or "::1" intruffle-config.js
, and ensuring that the value of the dashboard network config (the string, function, or object assigned tonetworks.dashboard
) matches.Underlying cause
Most modern operating systems have two entries for
localhost
in their/etc/hosts
(or in the case of Windows,C:\Windows\system32\drivers\etc\hosts
) files. The first entry usually resolves to the IPv4 loopback address (127.0.0.1
), and the second usually resolves to the IPv6 loopback address (::1
).For some reason when we initialize the dashboard's instance of
http.Server
via express with a hostname value oflocalhost
, it's electing to listen only on the IPv6 loopback interface. To address this, back in node v11.4.0 they added anipv6Only
field to theoptions
object that's passed into thenet.Server.listen
method.What's confusing here is that
ipv6Only
defaults tofalse
, which should trigger "dual stack" support fornet.Server.listen
, and by extension,http.Server.listen
, ashttp.Server.listen
is identical tonet.Server.listen
.However in the dashboard code we don't appear to call
httpServer.listen
directly. Rather, we appear to call thelisten
method of the ExpressJSapp
object.In Node v17.0.0 they switched
dns.lookup
to default toverbatim=true
, which per nodejs/node#39987 (the PR that introduced the change) has the effect of defaulting to IPv6 addresses on name resolution over IPv4 addresses. My strong suspicion is that rather than just passing the unmodifiedhost
string off to the built-inlisten
method, Express is attempting to resolve the hostname and instead providing the resolved IP address. As a result, I strongly suspect that this issue doesn't reproduce prior to node v17.Proposed fix
Either we need to change up the code to avoid calling
expressApp.listen
and instead callhttpServer.listen
ourselves (this can be done by creating thehttp.Server
instance ourselves by callinghttp.createServer({ ... }, this.expressApp!)
), or we need to take extra steps to resolve the IP addresses for the given host and be sure to listen on both protocols.Environment
truffle version
): v5.6.3 (core: 5.6.3)node --version
): v18.12.0The text was updated successfully, but these errors were encountered: