Open port, then lower privs.

Hi, all. "For reasons," I need to set up a telnet-like service -- and, yeah, it needs to be on port 23. In the Unix world, ports < 1024 require root privs to open, but I don't want my server running with root privs for reasons that should be obvious. Using the base Eventmachine example, I'm wondering if someone could show me how to do this? I see that there's a "set_effective_user(username)" method on the object, but I don't see how to use that on the object since instantiating it seems to execute it, and it's too late to do it afterward... no?

Thanks!

-Ken

···

---------------------------------------------------------------------------

require 'eventmachine'

module EchoServer
   def post_init
     puts "-- someone connected to the echo server!"
   end

   def receive_data data
     send_data ">>>you sent: #{data}"
     close_connection if data =~ /quit/i
   end

   def unbind
     puts "-- someone disconnected from the echo server!"
   end
end

EventMachine.run {
   EventMachine.start_server "127.0.0.1", 23, EchoServer # Won't work as non-root user
}

Hi, all. "For reasons," I need to set up a telnet-like service -- and,
yeah, it needs to be on port 23. In the Unix world, ports < 1024 require
root privs to open, but I don't want my server running with root privs for
reasons that should be obvious. Using the base Eventmachine example, I'm
wondering if someone could show me how to do this? I see that there's a
"set_effective_user(username)" method on the object, but I don't see how to
use that on the object since instantiating it seems to execute it, and it's
too late to do it afterward... no?

No, it's not too late :slight_smile:

Background info: setuid - Wikipedia

---------------------------------------------------------------------------

EventMachine.run {
   EventMachine.start_server "127.0.0.1", 23, EchoServer # Won't work
as non-root user
   EventMachine.set_effective_user('hassan') # or 'nobody', or ...
}

That said, sometimes the easiest approach is to just use a proxy or
e.g. iptables to route requests to a privileged port to an app running
on a non-privileged port.

HTH!

···

On Fri, Jun 15, 2018 at 4:44 AM, Ken D'Ambrosio <ken@jots.org> wrote:
--
Hassan Schroeder ------------------------ hassan.schroeder@gmail.com
twitter: @hassan
Consulting Availability : Silicon Valley or remote

Another alternative which might work for your needs is to use POSIX
capabilities. Here are some examples:
https://wiki.apache.org/httpd/NonRootPortBinding

Unfortunately these need to be set on binaries and can't be set on scripts,
so you'll need to set it on the Ruby executable itself, e.g.:

    setcap cap_net_bind_service=+ep /usr/bin/ruby

Beware that if you do this, any Ruby program started by anyone on the
system will be able to bind to any low-numbered port!

···

--
Tony Arcieri