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
|
<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 program</title>
<meta name="Description" content="s6-networking: the s6-tcpserver program" />
<meta name="Keywords" content="s6-networking s6-tcpserver tcpserver ucspi tcp server super-server ip ipv4 ipv6 TCP/IP" />
<!-- <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</tt> program </h1>
<p>
<tt>s6-tcpserver</tt> is an
<a href="https://cr.yp.to/proto/ucspi.txt">UCSPI tool</a> for
TCP connections, i.e. a super-server. It accepts connections from
clients, and spawns a program to handle each connection.
</p>
<h2> Interface </h2>
<pre>
s6-tcpserver [ -q | -Q | -v ] [ -1 ] [ -c <em>maxconn</em> ] [ -C <em>localmaxconn</em> ] [ -b <em>backlog</em> ] [ -G <em>gidlist</em> ] [ -g <em>gid</em> ] [ -u <em>uid</em> ] [ -U ] <em>ip</em> <em>port</em> <em>prog...</em>
</pre>
<ul>
<li> s6-tcpserver binds to local IP address <em>ip</em> (which can be
IPv4 or IPv6), port <em>port</em>. </li>
<li> It closes its stdin and stdout. </li>
<li> For every TCP connection to this address and port, it spawns a
<em>prog...</em> child with stdin reading from the network socket and
stdout writing to it. </li>
<li> Depending on the verbosity level, it logs what it does to stderr. </li>
<li> It runs until killed by a signal. Depending on the received
signal, it may kill its children before exiting. </li>
</ul>
<h2> Environment variables </h2>
<p>
For each connection, an instance of <em>prog...</em> is spawned with
the following variables set:
</p>
<ul>
<li> PROTO: always set to TCP </li>
<li> TCPLOCALIP: set to the server's address </li>
<li> TCPLOCALPORT: set to the server's port </li>
<li> TCPREMOTEIP: set to the client's address </li>
<li> TCPREMOTEPORT: set to the client's port </li>
<li> TCPCONNNUM: set to the number of connections originating from
the same IP address </li>
</ul>
<h2> Options </h2>
<ul>
<li> <tt>-q</tt> : be quiet. Only print fatal error messages to stderr. </li>
<li> <tt>-Q</tt> : be normally quiet. Print warnings and fatal
error messages to stderr. This is the default. </li>
<li> <tt>-v</tt> : be verbose. Additionally to fatal errors and
warnings, also print status and connection information for every client. </li>
<li> <tt>-1</tt> : write <em>port</em> to stdout, before
closing it, right after binding and listening to the network socket.
If stdout is suitably redirected, this can be used by monitoring
programs to check when the server is ready to accept connections. </li>
<li> <tt>-c <em>maxconn</em></tt> : accept at most
<em>maxconn</em> concurrent connections. Default is 40. It is
impossible to set it higher than 1000. </li>
<li> <tt>-C <em>localmaxconn</em></tt> : accept at most
<em>localmaxconn</em> connections from the same IP address.
Default is 40. It is impossible to set it higher than <em>maxconn</em>. </li>
<li> <tt>-b <em>backlog</em></tt> : set a maximum of
<em>backlog</em> backlog connections on the socket. Extra
connection attempts will rejected by the kernel. </li>
<li> <tt>-G <em>gidlist</em></tt> : change s6-tcpserver's
supplementary group list to <em>gidlist</em> after binding the socket.
This is only valid when run as root. <em>gidlist</em> must be a
comma-separated list of numerical group IDs. </li>
<li> <tt>-g <em>gid</em></tt> : change s6-tcpserver's group id
to <em>gid</em> after binding the socket. This is only valid when run
as root. </li>
<li> <tt>-u <em>uid</em></tt> : change s6-tcpserver's user id
to <em>uid</em> after binding the socket. This is only valid when run
as root. </li>
<li> <tt>-U</tt> : change s6-tcpserver's user id, group id and
supplementary group list
according to the values of the UID, GID and GIDLIST environment variables
after binding the socket. This is only valid when run as root.
This can be used with the
<a href="//skarnet.org/software/s6/s6-envuidgid.html">s6-envuidgid</a>
program to easily script a service that binds to a privileged socket
then drops its privileges to those of a named non-root account. </li>
</ul>
<h2> Signals </h2>
<ul>
<li> SIGTERM: exit. </li>
<li> SIGHUP: send a SIGTERM and a SIGCONT to all children. </li>
<li> SIGQUIT: send a SIGTERM and a SIGCONT to all children, then exit. </li>
<li> SIGABRT: send a SIGKILL to all children, then exit. </li>
</ul>
<h2> Notes </h2>
<ul>
<li> Unlike its ancestor
<a href="https://cr.yp.to/ucspi-tcp/tcpserver.html">tcpserver</a>,
s6-tcpserver performs just the bare minimum: the point is to have a
very small and very fast process to serve connections with the least
possible overhead. Features such as access control and DNS resolution are
provided via the <a href="s6-tcpserver-access.html">s6-tcpserver-access</a>
program. </li>
<li> s6-tcpserver is actually a wrapper that rewrites itself into a
command line running
<ul>
<li> <a href="s6-tcpserver-socketbinder.html">s6-tcpserver-socketbinder</a>,
that binds the socket and listens to it </li>
<li> <a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>,
that drops privileges </li>
<li> <a href="s6-tcpserverd.html">s6-tcpserverd</a>, the long-lived process
that actually accepts the connections. So if you see in your <tt>ps</tt> output
that the name of the process is <tt>s6-tcpserverd</tt>, that's why. </li>
</ul>
<li> s6-tcpserver treats IPv4 and IPv6 separately. If you want to listen on
<em>all</em> the addresses of a machine no matter whether v4 or v6, then you
need to run <em>two</em> s6-tcpserver processes: one on <tt>0.0.0.0</tt> and
and one on <tt>::</tt>. </li>
<li> The option to make s6-tcpserver verbose is <tt>-v</tt>, without an
argument. This is different from the <a href="s6-tcpserverd.html">s6-tcpserverd</a>
interface, where that would be <tt>-v 2</tt>. The difference exists because
s6-tcpserver follows the <a href="https://cr.yp.to/proto/ucspi.txt">UCSPI tool</a>
interface, whereas s6-tcpserverd has no such constraint. </li>
</ul>
</body>
</html>
|