Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
192 lines (147 sloc) 4.39 KB
<erl>
out(A) ->
{ssi, "TAB.inc", "%%",[{"privbind", "choosen"}]}.
</erl>
<div id="entry">
<h1>Binding to privileged ports</h1>
<p>
A common misfeature found on UN*X operating systems is the
restriction that only root can bind to ports below 1024.
Many a dollar has been wasted on workarounds and -often- the results are
security holes.
</p>
<p>
Both FreeBSD and Solaris have elegant configuration options to
turn this feature off. On FreeBSD:
<div class="box">
<verbatim>
$ sysctl net.inet.ip.portrange.reservedhigh=0
</verbatim>
</div>
the above is best added to your /etc/sysctl.conf
</p>
<p>
Similarly on Solaris we can just configure away this misfeature.
Assuming we want to run Yaws/SSL under a non-root user "erlang" on
ports 80/443.
</p>
<p>
On Solaris we can do that easily by granting the specific right to bind
privileged ports <1024 (and only that) to "erlang" using:
</p>
<div class="box">
<verbatim>
$ /usr/sbin/usermod -K defaultpriv=basic,net_privaddr erlang
</verbatim>
</div>
<p>
And check the we get what we want through:
</p>
<div class="box">
<verbatim>
$ grep erlang /etc/user_attr
erlang::::type=normal;defaultpriv=basic,net_privaddr
</verbatim>
</div>
<p>
On Linux, kernels later than 2.6.24, it's possible to do:
</p>
<div class="box">
<verbatim>
$ setcap 'cap_net_bind_service=+ep' /usr/lib/erlang/erts-5.7.4/bin/beam
</verbatim>
</div>
<p>
The above command grants the capability of binding
privileged ports to beam. Note, you have to grant the priviliges to the
actual exectuable you are using.
<p>
<p>
There are a couple
of other options on Linux. One is to use an auxiliary program
like authbind <em>http://packages.debian.org/stable/authbind</em>
or privbind <em>http://sourceforge.net/projects/privbind/</em>
</p>
<p>
These programs are run by root. Yaws writes its temporary
JIT compiled files in $HOME/.yaws and this doesn't work that
well with authbind/privbind. A non root user will try to
write in /root/.yaws. The solution to this is to set the
environment variable YAWSHOME. Yaws will then consider that to
be HOME rather that $HOME.
</p>
<p>
To start yaws under e.g privbind we can do:
</p>
<div class="box">
<verbatim>
$ sudo YAWSHOME=/tmp/abc privbind -u klacke /home/klacke/bin/yaws \
-c /home/klacke/yaws.conf -i
</verbatim>
</div>
<p>
The above command starts yaws as user <em>klacke</em> and bind
to ports below 1024
</p>
<p>
The authbind program is another option: Here is an example:
</p>
<div class="box">
<verbatim>
touch /etc/authbind/byport/80
touch /etc/authbind/byport/443
chmod 500 /etc/authbind/byport/80
chmod 500 /etc/authbind/byport/443
chown bob /etc/authbind/byport/80
chown bob /etc/authbind/byport/443
YAWSHOME=/home/bob authbind yaws -c /home/bob/yaws.conf -i
</verbatim>
</div>
<p>
Here is a description on how to do this on MacOs X. It's not exactly the same,
since we're still binding to non privileged ports. However,
edit /etc/sysctl and add:
</p>
<pre>
net.inet.ip.forwarding=1
</pre>
<p>
Then with ipfw as the firewall (turn off the gui firewall in system
preferences and manage own rules) use the ipfw rules like these - for
testing on your own box use something like:
</p>
<pre>
ipfw add fwd 127.0.0.1,8080 tcp from any to 127.0.0.1 dst-port 80 in
ipfw add fwd 127.0.0.1,8443 tcp from any to 127.0.0.1 dst-port 443 in
</pre>
<p>
set up yaws to use 8080 and 8443 in yaws.conf and then run as some non
root user. When you browse to http://127.0.0.1 or https://127.0.0.1
you will see your pages that are actually on 8080 and 8443 internally
but will be forwarded via ipfw forwarding.
</p>
<p>
Yet another (more complicated way) for linux users is to hack the kernel.
Here is a patch I did for some version of the 2.6 series kernels .. you get the idea.
</p>
<verbatim>
[root@lax]ipv4 > diff -c af_inet.c*
*** af_inet.c Wed Feb 23 23:31:35 2005
--- af_inet.c~ Thu Feb 17 18:13:13 2005
***************
*** 423,434 ****
snum = ntohs(addr->sin_port);
err = -EACCES;
- #if 0
- /* removed by klacke */
if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
goto out;
- #endif
-
/* We keep a pair of addresses. rcv_saddr is the one
* used by hash lookups, and saddr is used for transmit.
--- 423,430 ----
</verbatim>
<erl>
out(A) -> {ssi, "END2",[],[]}.
</erl>
Something went wrong with that request. Please try again.