Skip to content
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

Unusable IPv6 address printed #4630

Open
codefrau opened this issue Nov 2, 2022 · 8 comments
Open

Unusable IPv6 address printed #4630

codefrau opened this issue Nov 2, 2022 · 8 comments
Assignees

Comments

@codefrau
Copy link

codefrau commented Nov 2, 2022

Bug report

The network IPv6 address printed on my machine is http://[fe80::1]:9684/ but that works neither on the same host nor over the network.

Actual Behavior

This is what is printed on startup:

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:9684/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.0.114:9684/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fe80::1]:9684/

Opening a browser for http://[fe80::1]:9684/ is not working.

That's because fe80:... is a link local address that is not complete without specifying an interface:

> ifconfig | grep fe80::1
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 

but [fe80::1%lo0] is not valid in URLs, and would not work from other machines on the same network anyways.

Expected Behavior

This is what should be printed on my machine:

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:9684/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.0.114:9684/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fdf3:d6d6:1552:47c0:1cbc:d6a:fbe1:7201]:9684/

The last URL (http://[fdf3:d6d6:1552:47c0:1cbc:d6a:fbe1:7201]:9684/) actually works on my local machine, as well as from other machines.

That's because fdf3:... is a "unique local address".

How Do We Reproduce?

On macOS Monterey 12.5.1 and a Mac with wifi run

webpack-dev-server

For context, here's the listing for my wifi interface:

> node -p 'require("os").networkInterfaces()["en0"]'
[
{
    address: 'fe80::104f:825:d43f:9036',
    netmask: 'ffff:ffff:ffff:ffff::',
    family: 'IPv6',
    mac: 'f0:2f:4b:00:eb:9c',
    internal: false,
    cidr: 'fe80::104f:825:d43f:9036/64',
    scopeid: 14
},
{
    address: '192.168.0.114',
    netmask: '255.255.255.0',
    family: 'IPv4',
    mac: 'f0:2f:4b:00:eb:9c',
    internal: false,
    cidr: '192.168.0.114/24'
},
{
    address: 'fdf3:d6d6:1552:47c0:1cbc:d6a:fbe1:7201',
    netmask: 'ffff:ffff:ffff:ffff::',
    family: 'IPv6',
    mac: 'f0:2f:4b:00:eb:9c',
    internal: false,
    cidr: 'fdf3:d6d6:1552:47c0:1cbc:d6a:fbe1:7201/64',
    scopeid: 0
}
]

The simplest fix for my machine would be excluding link-local addresses:

> node -p 'Object.values(require("os").networkInterfaces()).flat().map(each => each.address).filter(addr => !/^fe[89ab]/.test(addr))'
[
'127.0.0.1',
'::1',
'192.168.0.114',
'fdf3:d6d6:1552:47c0:1cbc:d6a:fbe1:7201'
]

Please paste the results of npx webpack-cli info here, and mention other relevant information

System:
  OS: macOS 12.5.1
  CPU: (10) arm64 Apple M1 Max
  Memory: 4.62 GB / 64.00 GB
Binaries:
  Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
  Yarn: 1.22.18 - ~/.nvm/versions/node/v16.14.2/bin/yarn
  npm: 8.5.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
Browsers:
  Chrome: 107.0.5304.87
  Firefox: 105.0.3
  Safari: 15.6.1
  Safari Technology Preview: 16.0
Packages:
  copy-webpack-plugin: ^11.0.0 => 11.0.0 
  html-webpack-plugin: ^5.5.0 => 5.5.0 
  source-map-loader: ^4.0.0 => 4.0.1 
  terser-webpack-plugin: ^5.3.3 => 5.3.6 
  webpack: ^5.74.0 => 5.74.0 
  webpack-cli: ^4.10.0 => 4.10.0 
  webpack-dev-server: ^4.11.1 => 4.11.1 
@alexander-akait
Copy link
Member

Thank for report, feel free to send a PR, code is here https://github.com/webpack/webpack-dev-server/blob/master/lib/Server.js#L326, maybe https://github.com/whitequark/ipaddr.js/blob/master/README.md has function to undestand "working IPs"

@codefrau
Copy link
Author

codefrau commented Nov 4, 2022

I looked into it but the way it's written won't work on my system. It's trying to find the machine's default gateway via the default-gateway package and then print the corresponding IP. But default-gateway uses netstat which on my machine produces this, possibly because I don't actually have an IPv6 route to the internet:

Destination                             Gateway                         Flags           Netif Expire
default                                 fe80::%utun0                    UGcIg           utun0       
default                                 fe80::%utun1                    UGcIg           utun1       
::1                                     ::1                             UHL               lo0       
fd8d:2a9e:520a::/64                     fe80::886:5ba6:74c6:4032%en0    UGc               en0       
fdf3:d6d6:1552:47c0::/64                link#14                         UC                en0       
fdf3:d6d6:1552:47c0:0:fd8d:2a9e:520a    9c:3e:53:10:22:9a               UHLWIi            en0       
fdf3:d6d6:1552:47c0:86:2a4f:1cfe:1d40   ce:91:e4:fb:7a:c9               UHLWI             en0       
fdf3:d6d6:1552:47c0:1cbc:d6a:fbe1:7201  f0:2f:4b:0:eb:9c                UHL               lo0       
fe80::%lo0/64                           fe80::1%lo0                     UcI               lo0       
fe80::1%lo0                             link#1                          UHLI              lo0       
[...more lines...]

So the gateway argument for Server.findIp(gateway) is actually fe80::0%utun0 and the first matching IP is fe80::1. That is what gets printed.

It would be simple to reject link-local addresses:

    const linkLocal = ipaddr.parseCIDR("fe80::/64");
    
    if (linkLocal.match(...)) { ... }

but then no IPv6 address would be printed at all, unless there was a different logic than via the default gateway.

@silverwind
Copy link

silverwind commented Jun 12, 2023

default-gateway returns in your case the first route that matches default destination in the routing table. I think the fact that there are link-local addresses in the table is something macOS-specific, but the module is not really wrong either because those are default gateways after all, but I have no idea if the darwin kernel actually does something useful via those routes.

The fdf3:... adress is a unique-local address that has no default route associated, so will never come out of default-gateway.

Generally I think webpack-dev-server should likely drop the default-gateway dependency and do some parsing/filtering of os.networkInterfaces() data instead, it'll be much faster and such special cases like unique-local addresses could be supported only via that.

@alexander-akait
Copy link
Member

@silverwind Make sense, do you want to send a PR?

@silverwind
Copy link

Not right now, but you can take some inspiration from vite. They completely ignore IPv6, which might be a (lazy) option as well. If IPv6 is supported, it should prefer unique global > unique local.

@vbraun
Copy link

vbraun commented Oct 24, 2023

I'm also getting this error occasionally on Linux (Fedora 38 x86)

The order of preferences should be

  • ipv4 addresses
  • routable ipv6 addresses in descending preferred_lft order (especially with privacy extension it is normal to have lifetimes of ~1h, and it would suck to have the dev server break after a while). Watch out that 0 = infinite lifetime
  • link-local ipv6 fe80:: should be the last resort, or just be ignored. Neither Chrome nor Firefox support it so good luck.

@snitin315
Copy link
Member

I'll fix it

@silverwind
Copy link

silverwind commented Mar 9, 2024

I'd suggest to a least drop the default-gateway dependency. It's a module of mine which I'm not fond of anymore and I will soon deprecate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants