balena-io / balena-cli

The official balena CLI tool.
Apache License 2.0
453 stars 139 forks source link

balena scan fails to list devices where avahi advertises IPv6 addresses #1350

Open pdcastro opened 5 years ago

pdcastro commented 5 years ago

Quoting from the detailed forum post: https://forums.balena.io/t/cli-scanning-doesnt-support-link-local-addresses/19797/2

After getting the balena-cli setup from source, I could see that the IPv6 results seem to come back and are considered valid up until the cli attempts to "ping" the Docker/balena engine: https://github.com/balena-io/balena-cli/blob/e41ea6fb1af916633281e92a8587e763b183470b/lib/actions/scan.coffee#L79 At this point the IPv6 address is passed in, but it's missing the interface portion (e.g. wlp2s0). For sake of debugging I tried appending %wlp2s0 to the address before that call, making the passed address fe80::9274:272f:812b:2cad%wlp2s0 in this case. I was hopeful, but noticed that the address gets corrupted further down. At some point the address is passed to docker-modem (balena-cli -> docker-toolbox -> dockerode -> docker-modem). Unfortunately, a few different URL manipulation calls in docker-modem (https://github.com/apocas/docker-modem/blob/7bacb95c2ea5290a47a8c79f0c3b5d7c0de0aa2f/lib/modem.js#L104) seems to corrupt the address. I believe this is because url.parse in Node.JS could still be broken (https://github.com/nodejs/node-v0.x-archive/pull/9411). A quick check in the Node REPL seems to confirm this would break:

const url = require("url")
undefined
url.format({protocol: 'http', hostname: 'fe80::9274:272f:812b:2cad%wlp2s0', port: 2375})
'http://[fe80::9274:272f:812b:2cad%wlp2s0]:2375'
url.resolve("http://[fe80::9274:272f:812b:2cad%wlp2s0]:2375", "/")
'http:///'
url.resolve("http://[fe80::9274:272f:812b:2cad]:2375", "/")
'http://[fe80::9274:272f:812b:2cad]:2375/'
url.parse('fe80::9274:272f:812b:2cad%wlp2s0')
Url {
protocol: 'fe80:',
slashes: null,
auth: null,
host: '',
port: null,
hostname: '',
hash: null,
search: null,
query: null,
pathname: '/:9274:272f:812b:2cad%wlp2s0',
path: '/:9274:272f:812b:2cad%wlp2s0',
href: 'fe80:/:9274:272f:812b:2cad%wlp2s0' }
url.parse('http://[fe80::9274:272f:812b:2cad%wlp2s0]:2375')
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: '',
port: null,
hostname: '',
hash: null,
search: null,
query: null,
pathname: '/[fe80::9274:272f:812b:2cad%wlp2s0]:2375',
path: '/[fe80::9274:272f:812b:2cad%wlp2s0]:2375',
href: 'http:///[fe80::9274:272f:812b:2cad%wlp2s0]:2375' }

There might be a good solution here, and I could be missing something obvious :slight_smile: In either case, I decided to see what it would take to get BalenaOS to serve an IPv4 address with Avahi.

As a note, for SSH-ing into the Balena device and as I sanity check I can confirm that both of these commands work:

ssh fe80::9274:272f:812b:2cad%wlp2s0 -p 22222 -l root
nc -vC fe80::2e85:a99b:cc23:706f%wlp2s0 2375
balena-ci commented 5 years ago

[pdcastro] This issue has attached support thread https://jel.ly.fish/#/support-thread~d80e761a-b058-485b-b4e2-ef09f3a4565f

imrehg commented 5 years ago

Not 100% sure if it's the same case, but I had a device here, and balena push uuid.local failed with this error:

EINVAL: connect EINVAL fe80::f8c6:14d1:bbf7:8648:2375 - Local (:::0)

and then repush worked. I guess it's ipv6-related, but not sure if the same underlying issue.

pdcastro commented 4 years ago

Not 100% sure if it's the same case, but I had a device here, and balena push uuid.local failed [...] and then repush worked

This behaviour might also be an instance of https://github.com/balena-io/balena-cli/issues/1518#issuecomment-557136983 (it was reported for Windows, but perhaps it's not limited to Windows).