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

Allow server and web admin APIs to listen on separate port to websocket #44

Closed
banks opened this issue Dec 10, 2015 · 7 comments
Closed
Milestone

Comments

@banks
Copy link
Member

banks commented Dec 10, 2015

Hi

I love the web UI - useful tool. But we certainly couldn't expose it like it is now with just static password in production.

What we could do instead is run our production public instances with it turned off, and then run a separate instance connected to same redis with web on and only expose this over our internal VPN. Or alternatively put it behind our admin proxy that is hooked into our robust user authentication.

But for the second approach to work, we'd need to then make it have no password in config so that users don't need to auth twice (and remember some global made up password).

An alternative I think would be generally useful would be to be able to configure the web interface to be on, to NOT need password, but to listen on a separate port to the public websocket/sockjs server.

That would allow us to run the web UI on same nodes as production but to ensure they are not publically accessible - put them behind our authenticating proxy and/or only expose them over VPN.

While we are at it, I'd like to propose the same for the server API. I realise that the HMAC offers some security for it, but in our case we never want public access so it would be necessary to just lock it down completely.

One option would be disable the server API on the public nodes and have separate instance again only accessible internally but that would require changes. Again it would be neatly solved if you could optionally configure the API to listen on a separate port to the sockjs/websocket endpoint such that we could use same instances but keep access to those totally private at network level rather than rely on HMAC and obscurity.

tl;dr I'm going to end up modifying centrifugo to do either of the following. If you have input on which if any you like the sound of for core project I'll put my effort into that so I can contribute it back.

  1. Use separate centrifugo instance(s) for private stuff
    • allow disabling of server API, leave only websocket/sockjs exposed
    • allow no password for web UI such that it can go behind auth proxy or VPN without annoyance (might be a ticket for the web UI repo - I've not looked at the split of code yet)
  2. Separate ports for private stuff
    • allow optional configuration of separate port(s) for web ui and server API endpoints
    • also allow no password for web UI as above

Thanks for the great project by the way - I started writing something extremely similar for our large scale site after being disappointed at all the open source alternatives I tried, and my design was about as close as can possibly be imagined to the details of centrifugo. I'm very happy you already built it for us :).

@FZambia
Copy link
Member

FZambia commented Dec 10, 2015

Hello!

About Web UI. At moment you can start Centrifugo without UI at all just omitting --web flag. Also if no password set in config file then we can just skip login screen (must be easy to implement).

Could you configure access on location level? For example something like this in Nginx:

location / {
    allow 127.0.0.1;
    deny  all;
}

?

About API. There is option --insecure_api which can disable sign check so you can send unsigned requests with JSON commands in request body. Again - is it possible in your case to just restrict access to API endpoint /api/?

Hope I understood issue correctly.

@banks
Copy link
Member Author

banks commented Dec 10, 2015

Thanks for the reply!

I realise you can disable web but like I said we would need a way to bypass login like you said so we could run it on separate instance.

Could you configure access on location level?
is it possible in your case to just restrict access to API endpoint /api/?

Could do that but in our case we will probably have an AWS ELB right in front of centrifugo doing TCP load balancing so it can't know anything about http request path or routing... Adding whole extra proxy layer just to secure it is possible but it would be much nicer just to not have the api exposed at all (or only on a separate listening port we can control separately).

If you are unsure it's useful to anyone else, I can implement in a fork but it would be great to not be running custom version!

I think my prefered option would be:

  • allow web_secret to be empty (or maybe false to make it explicit) and if it is skip the login
  • add config web_port and api_port which by default are just the same as port
  • if web and/or api have different ports configured, add their handlers to a separate http.ServeMux and serve them with a separate call to ListenAndServe. This allows you to have same instances used for internal API calls and web UI and public websockets, but gives flexibility to lock down access to api/web ports to only internal machines and/or separate proxy with different authentication layer etc.

The simpler option is:

  • allow web_secret to be empty (or maybe false to make it explicit) and if it is skip the login
  • make an option disable_api which just removes the API handler for being registered at all.
  • fix it so that /auth/, /info/ and /action/ APIs are only enabled if web is also enabled...

@FZambia
Copy link
Member

FZambia commented Dec 10, 2015

I think it's better to do as much as possible before forking to custom version. This can happen eventually but at moment all these things seems reasonable.

I think a combination of your points must be done here:

  • if web_password and web_secret are empty then we will skip auth (we can't make it false as config parser expects string). Warning in docs needed here.
  • option to disable http API disable_api - for those who use Nginx.
  • add api_port and web_port options
  • /auth/, /info/ and /action/ APIs should only be enabled if web is enabled (strange that I have not done this before).

I am considering to add some logic into /socket endpoint i.e. use it not just for web interface needs. But it will be another option so now we can just leave it disabled if web disabled.

@banks
Copy link
Member Author

banks commented Dec 10, 2015

Sounds good. If you don't post here I might have a go at this soon but probably not for this week at least so if you want to that will be awesome :)

@FZambia
Copy link
Member

FZambia commented Dec 14, 2015

Started implementing this in separate branch (https://github.com/centrifugal/centrifugo/tree/separate_ports), changed some points above:

  • explicit insecure_web option instead of empty web_password and web_secret.
  • use  admin_port instead of web_port for option name as this port will most probably be used not only by web interface in future.
  • as you don't need disable_api then I think it's better to not add it right now

@banks
Copy link
Member Author

banks commented Dec 15, 2015

Commented on commits - looks awesome thanks. I'll give the branch a try really soon - hopefully next day or two.

@FZambia
Copy link
Member

FZambia commented Dec 21, 2015

Will be released with v1.3.0

@FZambia FZambia closed this as completed Dec 21, 2015
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

2 participants