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

ipv6 client connection fails Error: connect EINVAL #278

Closed
MasterJames opened this issue Apr 13, 2017 · 10 comments
Closed

ipv6 client connection fails Error: connect EINVAL #278

MasterJames opened this issue Apr 13, 2017 · 10 comments

Comments

@MasterJames
Copy link

MasterJames commented Apr 13, 2017

I got the server listening with ipv6 and a percent % with the interface name following For local prefix fe80, but when I go to use Client to connect with wss://[fe80::a00:29?f:fdc2:e0?c]/path
There is no connection with _Error: connect EINVAL_

If I include the Ethernet device name wss://[fe80::a00:380f:fe2f:67fd%enp0s3]/path

Error: You must specify a full WebSocket URL, including hostname. Relative URLs are not supported.
    at WebSocketClient.connect 

while a browser is good with just [i::p:v:6] no devicename and curl wants and likes it with the device name?
Seems like somewhere in the Client connect it's improperly understanding proper acceptable ipv6 addresses?!

Note you can also send a %25 to represent the % sign character and again the same with curl it will understand the url encoded percent sign. I've tried these with it including trying to backslash the percent sign, so not too many more options left I can think of? Maybe I need something other then ipv6 local addresses prefixed with fe80? alas that would be pretty hacking. Another hack might involve DNS.

@MasterJames
Copy link
Author

MasterJames commented Apr 14, 2017

WebSocketClient line 132
this.url = url.parse(requestUrl);

Wrong result...

Url {protocol: "wss:", slashes: true, auth: null, host: "", port: null…}
auth: null
hash: null
host: ""
hostname: ""
href: "wss:///[fe80::a00:380f:fe2f:67fd%enp0s3]/srvlnk"
path: "/[fe80::a00:380f:fe2f:67fd%enp0s3]/srvlnk"
pathname: "/[fe80::a00:380f:fe2f:67fd%enp0s3]/srvlnk"
port: null
protocol: "wss:"
query: null
search: null
slashes: true

{note: the 3rd slash is not there in code, 'cause it's messed up added a path root to href I guess}
Bug confirmed. Please help make this package ipv6 ready anybody?!
Percent Sign Device Name not working in node
nodejs/node-v0.x-archive#9404

After poking around in the url.js I noticed the binding to the dreeded cc file here
https://github.com/nodejs/node/blob/master/src/node_url.cc

I think the best route is to inject a js _parser override into the url prototype like parseIPV6... and that is why cc is not my modus operandi, it's dysfunctional to me there that way.
Maybe somehow(?) injecting a prestripped deviceName into the url.host value, will work as a simple patch.

@ibc
Copy link
Collaborator

ibc commented Apr 14, 2017

Hi, just to be clear:

  • fe80::2e0:4cff:fe68:23ff is a valid IPv6.
  • [fe80::2e0:4cff:fe68:23ff] is a valid IPv6 reference (which means it can be used within a HTTP/WS URI).
  • fe80::2e0:4cff:fe68:23ff%en7 is not a valid IPv6 at all. The % symbol is NOT a valid char within a IPv6.
  • So [fe80::2e0:4cff:fe68:23ff%en7] is not a valid IPv6 reference.

So url.parse() is behaving correctly. As you can see, the behavior of url.parse() is still the same in Node 7.

To summarize:

  • The IPv6 grammar⁄syntax clearly states that %` is not a valid symbol within a IPv6.
  • If you attempt to use an IPv6 with % in Node it will fail (as long as any module calls url.parse() with it), so this is not an issue of Node-WebSocket.
  • WebSocket-Node should not do a specific hack to allow this wrong IPv6.

@MasterJames
Copy link
Author

MasterJames commented Apr 14, 2017

Here is the patch/PR that works for me nothing else would.
See #279
Not sure where the problem really is as you've pointed out thank you for your time.

@ibc
Copy link
Collaborator

ibc commented Apr 14, 2017

Here is the patch/PR that works for me nothing else would. See #279

My point is that such a workaround should not be done within Node-WebSocket. You should not pass any IPv6 with a % symbol and expect that a library binds a local socket on it. Because it's an invalid IPv6.

Not sure where the problem really is as you've pointed out thank you for your time.

The problem is that it's not a valid IPv6. Nothing else.

@MasterJames
Copy link
Author

MasterJames commented Apr 14, 2017

Well it only works that way with the 'Server' it won't bind to it because it's a local range and needs the device name appended with a percent to understand where to route it or something I think? Maybe the specs wrong then? listen requires it if I remove the devicenode with percent from the ip in listen it errors like this...
Error: listen EINVAL fe80::a00

@ibc
Copy link
Collaborator

ibc commented Apr 14, 2017

Then there is a definitive issue with IPv6 and local ranges. The IPv6 BNF grammar does not allow (AFAIK) the % symbol into it. May you point please to any spec/RFC indicating that?

@ibc ibc reopened this Apr 14, 2017
@ibc
Copy link
Collaborator

ibc commented Apr 14, 2017

BTW, in your #279: Instead of that, you may directly pass a URL object to the connect() method.

@MasterJames
Copy link
Author

MasterJames commented Apr 14, 2017

Here is something... also I mention in the PR something about that but that it seems more fool proof and easier, but it's a good point I should explore that.
https://superuser.com/questions/99746/why-is-there-a-percent-sign-in-the-ipv6-address
it points to the so called least difficult they could find here...
https://msdn.microsoft.com/en-us/library/aa917150.aspx
its about routing
every computer is suppose to have a local address https://tools.ietf.org/html/rfc4291#section-2.8
and that needs %devicenames or numbers it's also a loopback I think
see also
Link-local addresses and zone indices
in wiki https://en.wikipedia.org/wiki/IPv6_address

Basically you could have 2 similar local broadcast blocks on different devices connected to the same machine, and with the zone identifier it can properly route it without it it is a local address block too. Also they all must have one as the spec said above and that's the one they get given by default it's in the fe80 block. It seems weird to me too.

@ibc
Copy link
Collaborator

ibc commented Apr 14, 2017

In RFC 3986: Uniform Resource Identifier (URI): Generic Syntax

   A host identified by an IPv6 literal address is represented inside
   the square brackets without a preceding version flag.  The ABNF
   provided here is a translation of the text definition of an IPv6
   literal address provided in [RFC3513].  This syntax does not support
   IPv6 scoped addressing zone identifiers.

So, to be clear, you should NOT include a IPv6 scope ID into a URL.

I understand your issue, but it's not something that should be fixed within Node-WebSocket.

@ibc
Copy link
Collaborator

ibc commented Apr 14, 2017

Said that, it's true that calling bind() with a link-local IPv6 with scope Id does work.

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

No branches or pull requests

3 participants