I have written a patch to portmap that reads a config file
(/etc/portmap.conf by default) and binds to the specified interfaces
only, if the file exists and contains directives that match any
existing interfaces.
I have uploaded the patch and a source tarball to my ISP's server:
http://home.online.no/~enrio/portmap...FC2.src.tar.gz
http://home.online.no/~enrio/portmap...ict-bind.patch
The first file is the source tarball the was used by the Fedora Core
build, with all the Fedora patches applied, but without my patch. The
second file i my patch.
However, this raises a number of questions, and maybe you have more
questions that I have not thought of.
First a rationale for doing a change at all:
The version of portmap I have (Fedora Core 2) uses libwrap.so to
determine which connections it should accept. (See man 5 hosts_access.
This invention uses the same configuration files as tcp-wrapper, but
the wrapper code is run inside portmap each time there is a new
connection.) However, the code appears to do quite a bit of processing
of the incoming data before it calls the wrapper library to determine
if the request should be denied. In particular, the rpc decoding of
parameters is performed. This exposes the program to buffer overrun
attacks and whatsnot.
It is possible that the rpc code has been very thoughroughly reviewed
and audited, but I do not have any notice about it, and I guess many
others do not have it aeither. We would rather know the portmapper
does not listen on the wrong interfaces at all. Of course I have a
firewall in place, but by Murphy's law, it can fail, become
misconfigured, etc. The libwrap/hosts.{allow,deny} configuration makes
a second line of defence, but I still feel it is better to simply
check netstat -a | grep '\*:' or something similar, and verify that
nothing is listening to any ports other than the few I have had the
time and expertise to configure tightly.
Second: Is this the right way of doing it?
I have seen a couple of postings on the net advertising pathches that
allows one to specify an interface address on the command line.
Such solutions cover the majority of the small cases where there is a
local network and one linux box has a dsl connection to the world.
However, a more generic solution is required to cover the general
case, where there can be any number of interfaces.
In larger sites the configuration changes much more often than in a
home lan. The configuration is also more complex, and it is much
harder to remember all the small dependencies. If we place the
interfaces (or their IP addresses) on the command line of the daemons
in the boot scripts, it leads to a proliferation of places that have
to be updated when the configuration changes. To mitigate this, one
can write scripts that update such bits from a central configuration
database. I believe there ar a number of commercial tools that do just
that.
Such tools are generally quite expensive, and their maintainers
probably have a hard time catching up with all the software changes
they have to support. We should give some thought to what is the best
design for the case of portmap, minimising the burden both for the
maintainers of such tools and for all the others that cannot afford
the tools.
I have written my patch so that the administrator can specify
something like
# portmpa config file
bind eth0:0 192.168.0.0/24 127.0.0.0/8 some.host
another.host/255.240.0.0
and portmapper will retrieve the list of running interfaces from the
kernel, and check each of them against the list in the config file,
and connect to those interfaces that match an item in the config file.
The next question is, should this code be in portmap? Or should it
rather be moved to the rpc library? Should the same config file affect
all servers using rpc (including the kernel for NFS)? If so, should
the file have a language that allows different directives to apply to
different services?
What about network interfaces that come up after portmap has started?
Should portmap query the kernel regularly about any new interfcaes and
check them against the file?
I have no idea what will happen if someone tries to compile my patch
for another architecture. Is there someone out there with access to
other architectures that is willing to look into the issue? Also, I do
not have the required knowledge to make my patch IPV6-ready. The
portmap code I have contains some ifdef IPV6 directives, but I do not
know if it actually works.
To get the kernel interface information, the patch uses an ioctl,
SIOCGIFCONF.
It returns an array of struct ifreq, but there is no way for the
kernel to specify the size of each structure. Without IPV6 support,
the structure contains a struct sockaddr, but that structure is too
small to hold an IPV6 address. I tried to browse the kernel code for
another interface, no luck yet. Any tips?
I would rather have something portable, but quite likely that does not
exist yet.