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

Create connection via file descriptor instead of port #3204

Closed
sholladay opened this issue Jun 14, 2016 · 17 comments
Closed

Create connection via file descriptor instead of port #3204

sholladay opened this issue Jun 14, 2016 · 17 comments
Assignees
Labels
feature New functionality or improvement

Comments

@sholladay
Copy link

sholladay commented Jun 14, 2016

Node's Server#listen() method accepts a fd option and I am wondering if hapi could support something like that.

The reason this would be useful to me is that I want to use substack's tcp-bind and sindresorhus' root-check to drop privileges as soon as possible.

As a simplified example, I wish something like this worked when run with sudo:

const fd = require('tcp-bind')(80);
require('root-check')();

const { Server } = require('hapi'),
const server = new Server();

server.connection({ fd });
server.start((err) => {
    if (err) {
        throw err;
    }

    console.log('Server is ready.');
});

The benefit here is that I can drop privileges as soon as possible, without waiting for the start callback, etc.

@hueniverse
Copy link
Contributor

I'll take a PR where port is an object with { fd }

@thebergamo
Copy link

Just commenting this issue to keep informed about that. If in this half time no ones send the PR I will try to do this request.

@hueniverse
Copy link
Contributor

@thebergamo next time just subscribe to it. No need to waste everyone's time.

@thebergamo
Copy link

sorry!

@kanongil
Copy link
Contributor

Note that you might be able to do this already using { port: /dev/fd/${fd} }

@btmorex
Copy link

btmorex commented Sep 22, 2016

Not that I think this would be a bad change, but you can already do this:

server.connection({autoListen: false});
server.listener.listen(...);
server.start(...);

@sholladay
Copy link
Author

I appreciate the workarounds, everyone.

I have posted a $40 bounty as I don't currently have time to work on it. But this will be very useful, particularly for those who care about security.

@mtharrison
Copy link
Contributor

@sholladay is there a way to get an fd which is bound to a port via the public API? The tcp-bind module seems to dip into process.binding() which is private API.

This addition itself is simple to implement but having to use non-public API for tests might be a deal-breaker.

@sholladay
Copy link
Author

sholladay commented Sep 23, 2016

That does suck. I'm not aware of any other way.

On the other hand, there is a very minimal amount of code that would be necessary in a test. Also, process.binding() has pretty widespread use in the ecosystem and it is unlikely they will break this anytime soon. They specifically discussed it and decided against it, mainly because of ecosystem breakage.

There was even some discussion of exposing this particular use of process.binding(). It seems like they acknowledge that they need to deal with it responsibly.

@mtharrison
Copy link
Contributor

That discussion stills seems very much open to a change in position. Personally, I think until there's a properly documented or accepted way to use it, the workarounds given above are your best option.

Unless @hueniverse disagrees and is happy to use process.binding() in tests?

@sholladay
Copy link
Author

Hmm well fd is a simple number. And Node is at least as responsible for testing that its interface works appropriately with those numbers. I feel like a clever test writer could write a somewhat meaningful test without process.binding().

We can at least assert that fd must be a number. And by defining it as a getter property, we can also assert that it is read by the framework. Probably we could also figure out a way to assert that Node received it correctly (e.g. by listening for error 32 ENOTSOCK).

I'm not saying this is perfect. But it seems like with a bit of work one ought to be able to meet the threshold to get a PR accepted. I mean the important part here IMO is making sure that none of Hapi's internals freak out, not that Node follows its own documentation.

Just trying to be pragmatic here, since I believe that accepting a fd like this will meaningfully move the ball forward in terms of security.

@mtharrison
Copy link
Contributor

mtharrison commented Sep 25, 2016

It's not really about making sure Node follows its own documentation, it's about how to test that the feature works with hapi internals.

For example, you'd ideally want to check that hapi is setting the right address and info values here which are only populated once the listening event is fired. So you'd want your test to actually start the server using the fd value you specify and make sure it propagates through properly.

You would also want to test making a request to that port and making sure it reaches your handler logic.

So we could easily allow specifying an fd and update the validation accordingly but it wouldn't be a thorough test IMO.

@sholladay
Copy link
Author

you'd ideally want to check that hapi is setting the right address

Yeah, that's exactly what I was thinking. I can't think of a way to test that without process.binding(), but maybe a test that doesn't do that could still have some value.

Assuming that is off the table, I guess the question is what would the tests have to do for such a PR to get accepted?

@hueniverse
Copy link
Contributor

If this becomes messy, I am going to reject it. There is a workaround and no one else has asked for this. Whatever anyone proposes has to be so trivial, I don't have to think about it.

@mtharrison
Copy link
Contributor

mtharrison commented Sep 27, 2016

The feature can be trivially added, it just can't be trivially tested, as far as I can tell.

@hueniverse hueniverse self-assigned this Dec 7, 2016
@hueniverse
Copy link
Contributor

Closing for now. If a PR shows up we can reconsider.

@Marsup Marsup added feature New functionality or improvement and removed request labels Sep 20, 2019
@lock
Copy link

lock bot commented Jan 9, 2020

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature New functionality or improvement
Projects
None yet
Development

No branches or pull requests

7 participants