summaryrefslogtreecommitdiff
path: root/doc/s6-tcpserver-access.html
blob: 16b16f9e1d2e4ea0b4186d3814311bd28300b1f5 (plain)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Language" content="en" />
    <title>s6-networking: the s6-tcpserver-access program</title>
    <meta name="Description" content="s6-networking: the s6-tcpserver-access program" />
    <meta name="Keywords" content="s6-networking s6-tcpserver-access tcp access control tcprules tcpwrappers libwrap" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">s6-networking</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> The <tt>s6-tcpserver-access</tt> program </h1>

<p>
<tt>s6-tcpserver-access</tt> is a command-line TCP access
control tool, and additionally performs some fine-tuning on a
TCP socket. It is meant to be run after
<a href="s6-tcpserver.html">s6-tcpserver</a> and before
the application program on the s6-tcpserver command line,
just like tcpwrappers' <tt>tcpd</tt> program.
</p>

<h2> Interface </h2>

<pre>
     s6-tcpserver-access [ -v <em>verbosity</em> ] [ -W | -w ] [ -D | -d ] [ -H | -h ] [ -R | -r ] [ -P | -p ] [ -l <em>localname</em> ] [ -B <em>banner</em> ] [ -t <em>timeout</em> ] [ -i <em>rulesdir</em> | -x <em>rulesfile</em> ] <em>prog...</em>
</pre>

<ul>
 <li> s6-tcpserver-access checks it is run under a UCSPI server tool
such as <a href="s6-tcpserver.html">s6-tcpserver</a>,
 <a href="s6-tcpserver4.html">s6-tcpserver4</a> or
 <a href="s6-tcpserver6.html">s6-tcpserver6</a>, or their
 stripped-down versions
 <a href="s6-tcpserver4d.html">s6-tcpserver4d</a> or
 <a href="s6-tcpserver6d.html">s6-tcpserver6d</a>. </li>
 <li> It checks that the remote end of the connection fits the
accepted criteria defined by the database contained in <em>rulesdir</em>
or <em>rulesfile</em>. If the database tells it to reject the connection,
the program exits 1. </li>
 <li> It sets up a few additional environment variables. </li>
 <li> It executes into <em>prog...</em>,
unless the first matching rule in the rule database
includes instructions to override <em>prog...</em>. </li>
</ul>

<h2> Environment variables </h2>

<p>
s6-tcpserver-access expects to inherit some environment variables from
its parent:
</p>

<ul>
 <li> PROTO: normally TCP, but could be anything else, like SSL. </li>
 <li> ${PROTO}REMOTEIP: the remote address of the socket, i.e. the client's
IP address. This can be IPv4 or (if the underlying skalibs supports it) IPv6. </li>
 <li> ${PROTO}REMOTEPORT: the remote port of the socket. </li>
</ul>

<p>
 Additionally, it exports the following variables before executing into
<em>prog...</em>:
</p>

<ul>
 <li> ${PROTO}LOCALIP: set to the local address of the socket. </li>
 <li> ${PROTO}LOCALPORT: set to the local port of the socket. </li>
 <li> ${PROTO}REMOTEINFO: normally unset, but set to the information
retrieved from ${PROTO}REMOTEIP via the IDENT protocol if the <tt>-r</tt>
option has been given. </li>
 <li> ${PROTO}REMOTEHOST: set to the remote host name obtained from
a DNS lookup. Unset if the <tt>-H</tt> option has been given. </li>
 <li> ${PROTO}LOCALHOST: set to the local host name obtained from a
DNS lookup. If the <tt>-l</tt> option has been given, set to
<em>localname</em> instead. </li>
</ul>

<p>
 Also, the access rules database can instruct s6-tcpserver-access to set
up, or unset, more environment variables, depending on the client address.
</p>

<h2> Options </h2>

<ul>
 <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: be more or less verbose, i.e.
print more or less information to stderr:
  <ul>
   <li> 0: only log error messages. </li>
   <li> 1: only log error and warning messages, and accepted connections.
This is the default. </li>
   <li> 2: also log rejected connections and more warning messages. </li>
   <li> 3: also log detailed warning messages from DNS and IDENT resolution. </li>
  </ul> </li>
 <li> <tt>-W</tt>&nbsp;: non-fatal. If errors happen during DNS or IDENT
resolution, the connection process is not aborted. However, incorrect or
incomplete results might still prevent a legitimate connection from being
authenticated against a DNS name. This is the default. </li>
 <li> <tt>-w</tt>&nbsp;: fatal. Errors during DNS or IDENT resolution will
drop the connection. </li>
 <li> <tt>-D</tt>&nbsp;: disable Nagle's algorithm. Sets the TCP_NODELAY
flag on the network socket. </li>
 <li> <tt>-d</tt>&nbsp;: enable Nagle's algorithm. This is the default. </li>
 <li> <tt>-H</tt>&nbsp;: disable DNS lookups for the ${PROTO}LOCALHOST and
${PROTO}REMOTEHOST environment variables. </li>
 <li> <tt>-h</tt>&nbsp;: enable DNS lookups. This is the default. </li>
 <li> <tt>-R</tt>&nbsp;: disable IDENT lookups for the ${PROTO}REMOTEINFO
environment variable. This is the default. </li>
 <li> <tt>-r</tt>&nbsp;: enable IDENT lookups. This should only be done
for legacy programs that need it. </li>
 <li> <tt>-P</tt>&nbsp;: no paranoid DNS lookups. This is the default. </li>
 <li> <tt>-p</tt>&nbsp;: paranoid. After looking up a name for the remote
host, s6-tcpserver-access will lookup IP addresses for this name, and drop
the connection if none of the results matches the address the connection
is originating from. Note that this still does not replace real
authentication via a cryptographic protocol. </li>
 <li> <tt>-l&nbsp;<em>localname</em></tt>&nbsp;: use <em>localname</em>
as the value for the ${PROTO}LOCALHOST environment variable, instead of
looking it up in the DNS. </li>
 <li> <tt>-B&nbsp;<em>banner</em></tt>&nbsp;: print <em>banner</em> to
the network as soon as the connection is attempted, even before
checking client credentials. The point is to speed up network protocols
that start with a server-side message. </li>
 <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: set a timeout on all the
operations performed by s6-tcpserver-access. If it is not able to do
its job in <em>timeout</em> milliseconds, it will instantly exit 99.
The default is 0, meaning no such timeout. </li>
 <li> <tt>-i&nbsp;<em>rulesdir</em></tt>&nbsp;: check client credentials
against a filesystem-based database in the <em>rulesdir</em> directory. </li>
 <li> <tt>-x&nbsp;<em>rulesfile</em></tt>&nbsp;: check client credentials
against a <a href="https://en.wikipedia.org/wiki/Cdb_(software)">cdb</a>
database in the <em>rulesfile</em> file. <tt>-i</tt> and <tt>-x</tt> are
mutually exclusive. If none of those options is given, no credential checking will be
performed, and a warning will be emitted on every connection if
<em>verbosity</em> is 2 or more. </li>
</ul>

<h2> Access rule checking </h2>

<p>
 s6-tcpserver-access checks its client connection against
a ruleset. This ruleset can be implemented:
</p>

<ul>
 <li> either in the filesystem as an arborescence of directories and files,
if the <tt>-i</tt> option has been given. This option is the most flexible
one: the directory format is simple enough for scripts to understand and
modify it, and the ruleset can be changed dynamically. This is practical,
for instance, for roaming users. </li>
<li> or in a <a href="https://en.wikipedia.org/wiki/Cdb_(software)">CDB
file</a>, if the <tt>-x</tt> option has been given. This option is the most
efficient one if the ruleset is static enough: a lot less system calls are
needed to perform searches in a CDB than in the filesystem. </li>
</ul>

<p>
 The exact format of the ruleset is described on the
<a href="//skarnet.org/software/s6/s6-accessrules-cdb-from-fs.html">s6-accessrules-cdb-from-fs</a> page.
</p>

<p>
s6-tcpserver-access first gets the remote address <em>ip</em> of the
client and converts it to canonical form. Then it checks it with the
<a href="//skarnet.org/software/s6/libs6/accessrules.html#ip4">s6_accessrules_keycheck_ip46()</a>
function. In other words, it tries to match broader and broader network
prefixes of <em>ip</em>, from <tt>ip4/</tt><em>ip</em><tt>_32</tt> to
<tt>ip4/0.0.0.0_0</tt> if <em>ip</em> is v4, or from
<tt>ip6/</tt><em>ip</em><tt>_128</tt> to <tt>ip6/::_0</tt> if <em>ip</em>
is v6. If the result is:
</p>

<ul>
 <li> S6_ACCESSRULES_ERROR: it immediately exits 111. </li>
 <li> S6_ACCESSRULES_DENY: it immediately exits 1. </li>
 <li> S6_ACCESSRULES_ALLOW: it grants access. </li>
 <li> S6_ACCESSRULES_NOTFOUND: more information is needed. </li>
</ul>

<p>
 In the last case, if DNS lookups have been deactivated (<tt>-H</tt>) then access
is denied. But if s6-tcpserver-access is authorized to perform DNS lookups,
then it gets the remote name of the client, <em>remotehost</em>, and
checks it with the
<a href="//skarnet.org/software/s6/libs6/accessrules.html#reversedns">s6_accessrules_keycheck_reversedns()</a>
function. In other words, it tries to match shorter and shorter suffixes
of <em>remotehost</em>, from <tt>reversedns/</tt><em>remotehost</em> to
<tt>reversedns/@</tt>.
This time, the connection is denied is the result is anything else than
S6_ACCESSRULES_ALLOW.
</p>

<p>
 Note that even if the access check succeeds, the connection can still be
denied if paranoid mode has been requested (<tt>-p</tt>) and a forward DNS
query on <em>remotehost</em> does not match <em>ip</em>. 
</p>

<h2> Environment and executable modifications </h2>

<p>
 s6-tcpserver-access interprets non-empty <tt>env</tt> subdirectories
and <tt>exec</tt> files
it finds in the matching rule of the ruleset, as explained
in the <a href="//skarnet.org/software/s6/s6-accessrules-cdb-from-fs.html">s6-accessrules-cdb-from-fs</a>
page.
</p>

<ul>
 <li> An <tt>env</tt> subdirectory is interpreted as if the
<a href="//skarnet.org/software/s6/s6-envdir.html">s6-envdir</a>
command had been called before executing <em>prog</em>: the environment
is modified according to the contents of <tt>env</tt>. </li>
 <li> An <tt>exec</tt> file containing <em>newprog</em> completely
bypasses the rest of s6-tcpserver-access' command line. After
environment modifications, if any, s6-tcpserver-access execs into
<tt><a href="//skarnet.org/software/execline/execlineb.html">execlineb</a> -c <em>newprog</em></tt>. </li>
</ul>

<h2> Notes </h2>

<ul>
 <li> s6-tcpserver-access works with
<a href="s6-tcpserver4d.html">s6-tcpserver4d</a>, handling IPv4 addresses,
as well as
<a href="s6-tcpserver6d.html">s6-tcpserver6d</a>, handling IPv6 addresses.
It will automatically detect the remote address type and match it against the
correct subdatabase. </li>
 <li> s6-tcpserver-access may perform several DNS queries. For efficiency
purposes, it does as many of them as possible in parallel. However, if asked
to do an IDENT query, it does not parallelize it with DNS queries. Take
that into account when estimating a proper <em>timeout</em> value. </li>
</ul>

</body>
</html>