Skip to content

tcpserver.1

Manvendra Bhangui edited this page Dec 13, 2024 · 10 revisions

NAME

tcpserver - accept incoming TCP IPv4/IPv6, UNIX and TLS/non-TLS connections

SYNOPSIS

tcpserver [ opts ] host / socket [ port ] prog[.so]

DESCRIPTION

opts is a series of getopt-style options. host is one argument. port is one argument. prog [.so] consists of one or more arguments.

tcpserver(1) waits for connections from TCP clients (using AF_INET address family sockets) or UNIX domain socket clients (AF_UNIX address family sockets). If socket starts with '/', tcpserver uses UNIX domain sockets and ignores port argument. For each connection, it runs prog, with descriptor 0 reading from the network and descriptor 1 writing to the network. It also sets up several environment variables. if prog.so is specified, it is expected that prog.so points to a shared object, which gets loaded using dlopen(3) call. Specifying a shared object can significantly improve performance by loading the object only once.

For TCP sockets, the server's address is given by host and port. port may be a name from /etc/services or a number; if it is 0, tcpserver(1) will choose a free TCP port. host may be 0, allowing connections to any local IP address; or a dotted-decimal IP address, allowing connections only to that address; or a host name, allowing connections to the first IP address for that host. Host names are fed through qualification using dns_ip4_qualify (dns_ip6_qualify for ipv6).

For UNIX sockets, the address is given by the path referred by socket argument. tcpserver removes the socket on _exit(2). In case tcpserver is killed or exits abnormally, the socket will be left on the filesystem. Next invocation of tcpserver will result in the 'address already in use' for socket. One can use the -e pidfile option to have a pid file in which case, tcpserver will remove the stale socket if it finds the pid in pidfile is not running.

tcpserver can also do SSL/TLS encryption with remote clients. This requires a SSL certificate to be provided using the -n option. For TLS/SSL sessions, tcpserver -z option sets the environment variable TLS_PROVIDER with details of the TLS connnection. SSL/TLS encryption works for both TCP and UNIX sockets.

tcpserver(1) works differently on Linux and FreeBSD. By default, FreeBSD does not route IPv4 traffic to AF_INET6 sockets. The default behavior intentionally violates RFC2553 for security reasons. IPv4 traffic may be routed with certain per-socket/per-node configuration, however, it is not recommended to do so. Consult ip6(4) for details. Linux, however allows connections to any local IPv4 or IPv6 addresses. So on FreeBSD, to overcome this limitation, tcpserver(1) creates two sockets and binds both IPv4 and IPv6 addresses. It then uses select(2) to carry out operation to accept a connection from the right socket.

tcpserver(1) dumps the list of active connections on stderr when it receives SIGUSR1. tcpserver(1) exits when it receives SIGTERM.

OPTIONS

General options:

-q
Quiet. Do not print error messages.

-Q
(Default.) Print error messages.

-v
Verbose. Print error messages and status messages.

-V
Verbose. Print error messages, status messages and IP connection table.

-e pidfile
Write pid to pidfile and prevent multiple invocation of tcpserver. This is useful when using UNIX sockets where there is possibility of stale sockets being left on the filesystem. This option also removes stale sockets if tcpserver is not found to be running.

Connection options:

-c n
| file

Do not handle more than n simultaneous connections. If there are n simultaneous copies of prog running, defer acceptance of a new connection until one copy finishes. n must be a positive integer. Default: 40. In the second form, file can be a full path to a filename containing an integer specifying n. This file will be reread when tcpserver(1) receives SIGHUP.

-C n
Do not handle more than n simultaneous connections from a particular host/socket. If there are n simultaneous copies of prog running, defer acceptance of a new connection until one copy finishes. n must be a positive integer. Default: 20. This can be also handled by having the environment variable $MAXPERIP compiled in the rules cdb database. The $MAXPERIP environment variables gives tcpserver(1) the ability to have different per host concurrency limit for each and every host that is defined in the rules database.

-x cdb
Follow the rules compiled into cdb by tcprules(1). These rules may specify setting environment variables or rejecting connections from bad sources. You can rerun tcprules(1) to change the rules while tcpserver(1) is running. This option is ignored for UNIX sockets.

-X
With -x cdb, allow connections even if cdb does not exist. Normally tcpserver(1) will drop the connection if cdb does not exist. This option is ignored for UNIX sockets.

-m db.conf
Follow rules specified in the MySQL table tcprules. This table has 4 columns. The column iprules contains an IP address which can include wildcards. eg. 202.144.*.?, 202.144.10-20.1, etc. The column decision can have the value 'D' to deny connections for matching IP addresses. The column env contains a list of comma separated environment variables. e.g HOME=/tmp,SERVER=galaxy. The db.conf file has the following layout

database server ip:database user:database password:database name:table name

with this option, tcpserver(1) will connect to the MySQL server specified by parameters in db.conf file. The connect timeout can be controlled by the environment variable $MYSQL_TIMEOUT.

To enable the -m option, you have to set $MYSQL_LIB variable to point to the mysql shared library. e.g.

  MYSQL_LIB= /usr/lib64/mysql/libmysqlclient.so.21.0.15

You can set $MYSQL_LIB environment variable in /service/name/variables/MYSQL_LIB (here name refers to a service under supervise(8)). You can also set the value in the control file mysql_lib. Environment variable takes precedence over the control file. This option is ignored for UNIX sockets.

-B banner
Write banner to the network immediately after each connection is made. tcpserver(1) writes banner before looking up $TCPREMOTEHOST, before looking up $TCPREMOTEINFO, and before checking cdb. This feature can be used to reduce latency in protocols where the client waits for a greeting from the server.

**-u **uid | **-u **user
One can either pass a positive integer uid or a user in /etc/passwd.

If uid is passed, then switch user ID to uid after preparing to receive connections.

If user is passed, then switch user ID to uid, group ID to gid and supplementary groups associated with the user user after preparing to receive connnection.

**-g **gid | **-g **gid,gid,..
Switch group ID to gid after preparing to receive connections. gid can be a positive integer or group id from /etc/group. It can also be a comma separated list of numerical IDs or groups from /etc/group.

-U
Same as -g GID -u UID. Typically $GID and $UID are set by envuidgid(8).

-1
After preparing to receive connections, print the local port number to standard output. This option is ignored for UNIX sockets.

-4
Fall back to IPv4 sockets. This is necessary for terminally broken systems like OpenBSD which will not let IPv6 sockets connect to V4-mapped IPv6 addresses. Please note that this also applies to DNS lookups, so you will have to use an DNS resolver with an IPv6 address to accept IPv6 connections. Use DNSCACHEIP to set the DNS resolver IP dynamically. This option is ignored for UNIX sockets.

-6
Force IPv6 mode in UCSPI environment variables, even for IPv4 connections. This will set $PROTO to TCP6 and put IPv4-mapped IPv6 addresses in $TCP6LOCALIP and $TCP6REMOTEIP. This option is ignored for UNIX sockets.

-Iinterface
Bind to the network interface interface ("eth0" on Linux, for example). This is only defined and needed for IPv6 link-local addresses. This option is ignored for UNIX sockets.

-b n
Allow a backlog of approximately n TCP SYNs. On some systems, n is silently limited to 5. On systems supporting SYN cookies, the backlog is irrelevant.

-o
Leave IP options alone. If the client is sending packets along an IP source route, send packets back along the same route. This option is ignored for UNIX sockets.

-O
(Default.) Kill IP options. A client can still use source routing to connect and to send data, but packets will be sent back along the default route. This option is ignored for UNIX sockets.

-d
Delay sending data for a fraction of a second whenever the remote host is responding slowly. This is currently the default, but it may not be in the future; if you want it, set it explicitly. This option is ignored for UNIX sockets.

-D
Never delay sending data; enable TCP_NODELAY. This option is ignored for UNIX sockets.

Data-gathering options:

-h
(Default.) Look up the remote host name in DNS to set the environment variable $TCPREMOTEHOST. This option is ignored for UNIX sockets.

-H
Do not look up the remote host name in DNS; remove the environment variable $TCPREMOTEHOST. To avoid loops, you must use this option for servers on TCP port 53. This option is ignored for UNIX sockets.

-p
Paranoid. After looking up the remote host name in DNS, look up the IP addresses in DNS for that host name, and remove the environment variable $TCPREMOTEHOST if none of the addresses match the client's IP address. The environment variable $TCPPARANOID is set if host has a reverse dns but IP does not match $TCPREMOTEIP. This option is ignored for UNIX sockets.

-P
(Default.) Not paranoid.

-l localname
Do not look up the local host name in DNS; use localname for the environment variable $TCPLOCALHOST. A common choice for localname is 0. To avoid loops, you must use this option for servers on TCP port 53. This option is ignored for UNIX sockets.

-r
(Default.) Attempt to obtain $TCPREMOTEINFO from the remote host. (Ignored for UNIX)

-R
Do not attempt to obtain $TCPREMOTEINFO from the remote host. To avoid loops, you must use this option for servers on TCP ports 53 and 113. (Ignored for UNIX)

-t n
Give up on the $TCPREMOTEINFO connection attempt after n seconds. Default: 26. (Ignored for UNIX)

-T n
Terminate connection if no data is received in n seconds. Default: 300.

-S n
Timeout accept for TLS/SSL connection in n seconds. Default: 60.

-s
Use default cert servercert.pem in /etc/indimail/certs. The location of certificate directory can be changed by using -i option or setting $CERTDIR environment variable.

-i certdir
Directory having certificates. Default is /etc/indimail/certs.

-n certfile
Use certfile as the TLS/SSL certificate. If the -n option is not provided, tcpserver will not initiate a TLS/SSL session. certfile can be an empty string to use TLS_CERTFILE environment variable.

-a cafile
Specify cafile as the file containing CA certificates. Sometimes, special CA certificates are needed if an intermediate certificate used by your issuing CA expires. Note that the file given with -a is passed to SSL_CTX_load_verify_locations and thus may contain several CA certificates, which will be used during SSL connection negotiation to close any gap in the certificate chain. If this is not provided, the file /etc/indimail/certs/clientca.pem will be used.

-L crlfile
A list of Certificate Revocation Lists (CRLs). If present it should contain the CRLs of the CAs in cafile and client certs that will be checked for revocation. If this is not provided, the file /etc/indimail/certs/clientcrl.pem will be used.

-f cipher_list
Use ciphers listed in cipher_list. Without this tcpserver uses TLS_CIPHER_LIST environment variable if set (or system configured PROFILE=SYSTEM ciphers for TLSv1.2 and below). For TLSv1.3 the environment variable TLS_CIPHER_SUITE is used instead. See openssl-ciphers(1ossl).

-M tls_method
Use tls_method to set client/server method / protocol. This will be one of SSLv23, SSLv3, TLSv1, TLSv1_1, TLSv1_2, TLSv1_3 values. Without this option, the actual protocol version used will be negotiated to the highest version mutually supported by the client and the server. The supported protocols at this moment are TLSv1.2 and TLSv1.3. Older protocols have been deprecated and removed. It is best not to use this option to let tcpserver chose the highest protocol supported.

-N
Client-initiated renegotiation is disabled by default. This option enables it. This option is ignored for UNIX sockets.

-z
Set TLS_PROVIDER environment variables with details of the TLS/SSL connection. This environment variable will be available for prog[.so] when using TLS/SSL.

IPv4-mapped IPv6 addresses

Setting up tcpserver(1) with simultaneous bindings to IPv4 and IPv6 addresses, the Unix kernel employs the mapping

::ffff:a.b.c.d
for the IPv4 address
a.b.c.d

Setting up tcpserver(1) in IPv4 mode (-4) only or in compatibility mode, IPv4 addresses are considered in their native format without the IPv6 prefix. Thus, usual IPv4 addresses can be entered in rules.cdb even in common IPv4/IPv6 bindings.

DNS RESOLVER SETTINGS

DNSCACHEIP, DNSREWRITEFILE

Use $DNSCACHEIP to set the DNS resolver's IP(s) dynamically irrespectively from the settings in /etc/resolv.conf. The individual IPs are separated by blanks; IPv6 LLU addresses may be appended with the interface name following a '%' sign. If the environment variable $LOCALDOMAIN is populated, this name will be appended to unqualified host names. Additional rewriting of local to public names is facilitated in case the file /etc/dnsrewrite exists and is populated, or alternatively, the environment variable $DNSREWRITEFILE points to a different file. See djbdns(7), qualification(5)

Loading Shared Objects

tcpserver(1) can load shared objects by specifying a shared object on the command line. In such cases tcpserver(1) will execute a function whose name is the basename of the shared object.

A special case can be setup for qmail-smtpd and rblmstpd by specifying the following environment variables

PLUGIN0=/usr/lib/indimail/plugins/qmail_smtpd.so
PLUGIN0_dir=/etc/indimail
PLUGIN0_init=smtp_init
PLUGIN1=/usr/lib/indimail/plugins/rblsmtpd.so

The above causes tcpserver(1) to load qmail_smtpd.so and execute the smtp_init(1) function, after changing directory to /var/indimail, in the parent. smtp_init() loads all qmail-smtpd control files. Here PLUGIN0 is defined as /usr/lib/indimail/plugins/qmail_smtpd.so, which causes the function qmail_smtpd() to be preloaded. This improves the perfomance of the smtp service. In the above example, rblsmtpd.so is loaded without executing any initialization function and without changing directory. On SIGHUP, tcpserver(1) executes the function smtp_init(0). The variable PLUGINn_dir should be used if your function expects to be in a particular directory to function properly. PLUGIN1 causes tcpserver(1) to preload rblsmtpd.so and if prog is /usr/lib/indimail/plugins/rblsmtpd.so, it will simply execute the function rblsmtpd, from the shared library rblsmtpd.so already preloaded in the memory.

The function (basename of the shared objec) is passed argc, argv and envp.

func(int argc, char **argv, char **env)

Here argc is the number of arguments passed to the shared object, argv the arguments and envp is the modified environment variables set by tcpserver(1). See tcp-env(1). If you want your function to inherit all env variables set by tcpserver(1), just do the following in your function

environ = envp;

Now with the above set of variables you just need to have an invocation of tcpserver(1) similar to below, which will cause tcpserver(1) to execute the function rblsmtpd(argc, argv) followed by function qmail_smtpd(argc, arg) for every connection. This is almost equivalent to executing the binary versions rblsmtpd, qmail-smtpd.

tcpserver 127.0.0.1 25 /usr/indimail/lib/plugins/rblsmtpd.so -rdnsbl-1.uceprotect.net \
    /usr/indimail/lib/plugins/qmail_smtpd.so

ENVIRONMENT

TLS_CERTFILE
server ssl certificate. This is used when an empty string is passed as the argument to the -n option. Default is servercert.pem

CLIENTCA
CA certificate. This can be overriden by the -c option. Default is /etc/indimail/certs/clientca.pem

CLIENTCRL
Certificate Revocation Lists. Default is /etc/indimail/certs/clientcrl.pem

TLS_CIPHER_LIST
A set of OpenSSL cipher strings. Multiple ciphers contained in a string should be separated by a colon. This can be overriden by the -f option.

CERTDIR
Directory having servercert.pem. Default is /etc/indimail/certs.

NOTES

A script update_tmprsadh in cron uses the following openssl commands to pre-generate 2048 bites RSA and DH parameters. You can pass --maxbits argument to update_tmprsadh to generate these with higher bits. You can set the environment variable SSL_BITS to make tcpserver choose specific bits for the RSA/DH parameters. These files are generated in /etc/indimail/certs. update_rmprsadh is installed to be run by cron if you have installed indimail from Open Build Service.

cd /etc/indimail/certs
/usr/bin/openssl genrsa  -out    rsa2048.pem 2048
/usr/bin/openssl dhparam -out -2  dh2048.pem 2048

Some ciphersuites may use ephemeral Diffie-Hellman (DH) key exchange. In these cases, the session data is negotiated using the ephemeral/temporary DH key and the key supplied and certified by the certificate chain is only used for signing. Anonymous ciphers (without a permanent server key) also use ephemeral DH keys.

Using ephemeral DH key exchange yields forward secrecy as the connection can only be decrypted when the DH key is known. By generating a temporary DH key inside the server application that is lost when the application is left, it becomes impossible for an attacker to decrypt past sessions, even if they get hold of the normal (certified) key, as this key was only used for signing.

In order to perform a DH key exchange the server must use a DH group (DH parameters) and generate a DH key. The server will always generate a new DH key during the negotiation.

As generating DH parameters is extremely time consuming, an application should not generate the parameters on the fly. DH parameters can be reused, as the actual key is newly generated during the negotiation.

Typically applications should use well known DH parameters that have built-in support in OpenSSL. The macro SSL_set_dh_auto(3ossl) configures OpenSSL to use the default built-in DH parameters for the SSL object. Passing a value of 1 in the onoff parameter switches the feature on, and passing a value of 0 switches it off. The default setting is off.

If "auto" DH parameters are switched on then the parameters will be selected to be consistent with the size of the key associated with the server's certificate. If there is no certificate (e.g. for PSK ciphersuites), then it it will be consistent with the size of the negotiated symmetric cipher key.

Applications may supply their own DH parameters instead of using the built-in values. This approach is discouraged and applications should in preference use the built-in parameter support described above. Applications wishing to supply their own DH parameters should call SSL_set0_tmp_dh_pkey(3ossl) to supply the parameters for SSL. The parameters should be supplied in the dhpkey argument as an EVP_PKEY containg DH parameters. Ownership of the dhpkey value is passed to the SSL_CTX or SSL object as a result of this call, and so the caller should not free it if the function call is succesful..

SEE ALSO

unix(7) tcprules(1), tcprulescheck(1), argv0(1), fixcrio(1), recordio(1), rblsmtpd(1), tcpclient(1), who@(1), date@(1), finger@(1), http@(1), tcpcat(1), mconnect(1), openssl(1) dlopen(3) supervise(8), svscan(8), tcp-environ(5), socket(2) bind(2) listen(2) connect(2) select(2) accept(2) openssl-ciphers(1ossl). http://cr.yp.to/ucspi-tcp.html

Clone this wiki locally