3

Consider a program server which binds to '*' and listens for incoming connections. I only connect to server from localhost and I do not want external users to be able to connect to it. However, the server program is badly written and does not provide a configuration option or flag to only bind on localhost. Further, it is inconvenient for me to hack the source code of server to fix this.

Hence, I would be looking for a wrapper to run server but make it bind on localhost and not on '*'. (For instance, maybe an LD_PRELOAD-based trick could do the job, like tsocks to force the use on a SOCKS proxy on a third-party program.) Does something like this exist? I am root on the machine, if it helps.

I know that another solution would be to use iptables for that, but these rules do not persist across reboots so they could silently break. Further, they are "global" and could be modified by other users of the server, or confuse them. By contrast, when running the server program as wrapper server, I would be more confident that the setup will not break for some other reason.

a3nm
  • 8,978
  • 5
  • 28
  • 36
  • 1
    Answers to this question : https://superuser.com/questions/241178 look helpful. – p4bl0 Aug 28 '16 at 14:19
  • `iptables` rules can certainly be kept in its configuration and can even automatically save them. – Julie Pelletier Aug 28 '16 at 14:19
  • 1
    I don't suggest using the hack mentioned by p4bl0 since it's overkill considering you'd only need to change a word (or a few) in the actual `server`'s source code to do it properly. – Julie Pelletier Aug 28 '16 at 14:21
  • @JuliePelletier: Thanks for the comments! About modifying the source, I got `server` as a binary distribution, it would be inconvenient to have to install all necessary dependencies to recompile it myself. About persistency of iptable rules, my problem is also that the iptable rules are not "local" to the incriminating program, I would have to remember that `server` is only secure to use on machines where iptables has been suitably configured. I'm currently investigating the namespace-based solution mentioned in p4bl0's comment, which doesn't look so hacky. – a3nm Aug 28 '16 at 14:26
  • 1
    The rule should obviously be applied to the port `server` listens to. – Julie Pelletier Aug 28 '16 at 14:28

1 Answers1

4

Here's how to do it using ip namespaces (requires root privileges, the following should be run as root).

Create a namespace for the server:

ip netns add myserverns

Assign an IP address to the loopback in the namespace and turn it on (source: this post):

ip netns exec myserverns ifconfig lo 127.0.0.1 up

Run server in the namespace (where "serveruser" is the user that should run the server)

ip netns exec myserverns sudo -u serveruser server

Let's assume that the server listens on port 4242. Now, use socat to bind the loopback to the namespace (note the use of bind=127.0.0.1 which is the entire point) (source: this answer):

socat tcp-listen:4242,bind=127.0.0.1,fork,reuseaddr exec:'ip netns exec myserverns socat STDIO tcp-connect\:127.0.0.1\:4242',nofork

This achieves my intended goal: even if server tries to bind to '*' (or to different ports altogether), when we run it in this way, we are sure that it can only be reached on the local machine with port 4242.

a3nm
  • 8,978
  • 5
  • 28
  • 36