Skip to content

tcpserver.1

Manvendra Bhangui edited this page Feb 8, 2023 · 9 revisions

NAME

tcpserver - accepts incoming TLS/non-TLS TCP IPv4/IPv6 connections

SYNOPSIS

tcpserver [ opts ] host 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. 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.

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).

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.

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.

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. 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.

-X
With -x cdb, allow connections even if cdb does not exist. Normally tcpserver(1) will drop the connection if cdb does not exist.

-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.

-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.

-g gid
Switch group ID to gid after preparing to receive connections. gid must be a positive integer.

-u uid
Switch user ID to uid after preparing to receive connections. uid must be a positive integer.

-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.

-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.

-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.

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

-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.

-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.

-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.

-D
Never delay sending data; enable TCP_NODELAY.

Data-gathering options:

-h
(Default.) Look up the remote host name in DNS to set the environment variable $TCPREMOTEHOST.

-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.

-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

-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.

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

-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.

-t n
Give up on the $TCPREMOTEINFO connection attempt after n seconds. Default: 26.

-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.

-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. The actual protocol version used will be negotiated to the highest version mutually supported by the client and the server. The supported protocols are SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3. Ths option must not be used to avoid version-specific methods since they are now deprecated.

-N
Client-initiated renegotiation is disabled by default. This option enables it.

-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 tcpclient 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

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) select(2) accept(2) http://cr.yp.to/ucspi-tcp.html

Clone this wiki locally