/
privbind.yaws
148 lines (115 loc) · 3.58 KB
/
privbind.yaws
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<erl>
out(A) ->
{ssi, "TAB.inc", "%%",[{"privbind", "choosen"}]}.
</erl>
<div id="entry">
<h1>Binding to priviliged 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>
Linux doesn't have anything like the above. There are a couple
of options on Linux. The best 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 authbind 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>
Yet another option is to is to install fdsrv which is a standalone
program that has the suid bit set, binds priviliged ports and passes
the filedescriptor to yaws. I have made a package out of the jungerl
code that can be easily installed just through the usual cycle of
make && make install The code is at
</p>
<pre>
http://yaws.hyber.org/download/fd_server-2.3.0.tgz
</pre>
<p>
One major drawback with fdsrv is that it doesn't work for SSL. With
the case of SSL, one possible solution is to put ssltunnel in
front of yaws and let yaws bind to 127.0.0.1
</p>
<p>
All in all the fdsrv option is much worse that the authbind option.
</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>