senecajs / seneca-transport

Seneca micro-services message transport over TCP and HTTP.
MIT License
63 stars 45 forks source link

Windows issue with client default binding to 0.0.0.0. #37

Closed GlenTiki closed 8 years ago

GlenTiki commented 9 years ago

The discussion over here ran into an issue with a seneca example working on mac vs it working on windows: https://github.com/senecajs/senecajs.org/issues/73

It appears that when no host is specified in the client arg object, it will default to 0.0.0.0, which is fine, but that doesn't work on windows, so a workaround is to specify the host as localhost on windows.

This is probably more of a windows caveat than an issue with the codebase, so we should start to document this, and possibly we can change the default behavior on windows to default the host that a client connects to to localhost instead of 0.0.0.0.

Trello Card

mcdonnelldean commented 9 years ago

@rjrodger @geek I want to signal this because although it's an easy fix I want to understand if there is an impact to changing this value.

geek commented 9 years ago

This is the default that node uses: https://github.com/nodejs/node/blob/master/lib/net.js#L791 and for listeners: https://github.com/nodejs/node/blob/master/lib/net.js#L1167-L1174

mcdonnelldean commented 8 years ago

@geek Given we had a convo with @rjrodger on this, should we change this so that we better support Windows? I'm still unclear if there is an actual reason not to change this.

technicallyjosh commented 8 years ago

I'm actually not sure why you don't default to 127.0.0.1.

Just because the core does it, doesn't always make it the best solution. :)

Seems silly that node.js chose a non-routable meta-address for the default considering you could have 2 subnets running on the same machine (via 2 lan ports) and resolve to the same address...

Given the purposes of senecajs I'd vote to default to 127.0.0.1 if you want to be compatible across the board even if it requires the specification of localhost for a host outside the server it's running on.

127.0.0.1 is always a safe bet since it's just a loopback.

rjrodger commented 8 years ago

@pelger 0.0.0.0 was chosen to make docker container deployment easier - is this still needed, or can we revert to 127.0.0.1 with latest docker? /cc @geek @mcdonnelldean

pelger commented 8 years ago

@mcdonnelldean @thekemkid , not sure why all unassigned is not working for you. All unassigned should work correctly on windows unless there is some funky firewall permissions stuff going on. Before we go changing default settings please try the following: grab netcat for windows (I would use cygwin but native builds are available) open a terminal window and run the following:

nc -l 0.0.0.0 -p

e.g. nc -l 0.0.0.0 -p 10001

In another terminal window run

telnet 100001

You should be able to connect to the port. If you can't give me a ping and lets figure out why not.

The question on the default IP address is more one around usability/security. Choosing 0.0.0.0 means that seneca will bind to all available host ip addresses which MAY be a security risk IF the host is not fire-walled. Choosing 127.0.0.1 means that seneca will only be available on this host. IMO 0.0.0.0 is the correct default because if you are not sitting behind a firewall you've already lost. @rjrodger AFAIK we still need to bind to the bridged IP address in the latest version of docker.

GlenTiki commented 8 years ago

okay, telnet works.

The issue here isn't the listening address, it will listen successfully. Its the address that the client tries to connect to. It won't connect to the default 0.0.0.0, it will just fail. telnet will fail if the specified address to connect to is 0.0.0.0 too.

Basically this script will work as expected when the .client address is set to localhost, but not when it is left out, or when it is set to allhost:

var allhost = "0.0.0.0";
var clienthost = "localhost";

function color() {
  this.add( 'color:red', function(args,done){
    done(null, {hex:'#FF0000'});
  })

  this.add( 'color:blue', function(args,done){
    done(null, {hex:'#0000FF'});
  })
}

var seneca = require('seneca');

seneca()
  .use(color)
  .listen({type:'tcp', host: allhost, port: 5000}) //become a server

setTimeout(function(){
  seneca()
    .client({type:'tcp', port: 5000, host: localhost}) //become a client
    .act('color:red', console.log)
    .act('color:blue', console.log)
}, 3000)

Oh, and this works: telnet localhost 10001

but not this: telnet 0.0.0.0 10001

pelger commented 8 years ago

Yes that is correct. In summary IMO seneca should:

default to 0.0.0.0 server side - i.e. for all listens http/tcp default to 127.0.0.1 client side - i.e. for all outbound connections

agreed? @geek @thekemkid @mcdonnelldean cc @rjrodger