netcat-openbsd/compile-without-TLS-support.patch

749 lines
20 KiB
Diff
Raw Normal View History

From: Guilhem Moulin <guilhem@debian.org>
Date: Fri, 09 Jun 2017 13:21:23 +0200
Subject: compile without TLS support
tls.h isn't available in libsd-dev, and -C is already taken for
CRLF line-ending in the Debian-specific patches.
---
Makefile | 2
nc.1 | 63 -----------------------
netcat.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 144 insertions(+), 87 deletions(-)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,6 @@
PROG= nc
SRCS= netcat.c atomicio.c socks.c
-LDADD+= -ltls -lssl -lcrypto
-DPADD+= ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
LIBS= `pkg-config --libs libbsd` -lresolv
OBJS= $(SRCS:.c=.o)
--- a/nc.1
+++ b/nc.1
@@ -33,20 +33,14 @@
.Nd arbitrary TCP and UDP connections and listens
.Sh SYNOPSIS
.Nm nc
-.Op Fl 46cDdFhklNnrStUuvz
-.Op Fl C Ar certfile
-.Op Fl e Ar name
-.Op Fl H Ar hash
+.Op Fl 46DdFhklNnrStUuvz
.Op Fl I Ar length
.Op Fl i Ar interval
-.Op Fl K Ar keyfile
.Op Fl M Ar ttl
.Op Fl m Ar minttl
.Op Fl O Ar length
-.Op Fl o Ar staplefile
.Op Fl P Ar proxy_username
.Op Fl p Ar source_port
-.Op Fl R Ar CAfile
.Op Fl s Ar source
.Op Fl T Ar keyword
.Op Fl V Ar rtable
@@ -101,20 +95,10 @@ to use IPv4 addresses only.
Forces
.Nm
to use IPv6 addresses only.
-.It Fl C Ar certfile
-Specifies the filename from which the public key part of the TLS
-certificate is loaded, in PEM format.
-May only be used with TLS.
-.It Fl c
-If using a TCP socket to connect or listen, use TLS.
-Illegal if not using TCP sockets.
.It Fl D
Enable debugging on the socket.
.It Fl d
Do not attempt to read from stdin.
-.It Fl e Ar name
-Specify the name that must be present in the peer certificate when using TLS.
-Illegal if not using TLS.
.It Fl F
Pass the first connected socket using
.Xr sendmsg 2
@@ -130,11 +114,6 @@ using the
.Xr ssh_config 5
.Cm ProxyUseFdpass
option).
-.It Fl H Ar hash
-Specifies the required hash string of the peer certificate when using TLS.
-The string format required is that used by
-.Xr tls_peer_cert_hash 3 .
-Illegal if not using TLS, and may not be used with -T noverify.
.It Fl h
Prints out
.Nm
@@ -144,10 +123,6 @@ Specifies the size of the TCP receive bu
.It Fl i Ar interval
Specifies a delay time interval between lines of text sent and received.
Also causes a delay time between connections to multiple ports.
-.It Fl K Ar keyfile
-Specifies the filename from which the private key
-is loaded in PEM format.
-May only be used with TLS.
.It Fl k
Forces
.Nm
@@ -188,12 +163,6 @@ Do not do any DNS or service lookups on
hostnames or ports.
.It Fl O Ar length
Specifies the size of the TCP send buffer.
-.It Fl o Ar staplefile
-Specifies the filename from which to load data to be stapled
-during the TLS handshake.
-The file is expected to contain an OCSP response from an OCSP server in
-DER format.
-May only be used with TLS and when a certificate is being used.
.It Fl P Ar proxy_username
Specifies a username to present to a proxy server that requires authentication.
If no username is specified then authentication will not be attempted.
@@ -202,12 +171,6 @@ Proxy authentication is only supported f
Specifies the source port
.Nm
should use, subject to privilege restrictions and availability.
-.It Fl R Ar CAfile
-Specifies the filename from which the root CA bundle for certificate
-verification is loaded, in PEM format.
-Illegal if not using TLS.
-The default is
-.Pa /etc/ssl/cert.pem .
.It Fl r
Specifies that source and/or destination ports should be chosen randomly
instead of sequentially within a range or in the order that the system
@@ -224,24 +187,7 @@ It is an error to use this option in con
.Fl l
option.
.It Fl T Ar keyword
-Change IPv4 TOS value or TLS options.
-For TLS options
-.Ar keyword
-may be one of
-.Ar tlsall ;
-which allows the use of all supported TLS protocols and ciphers,
-.Ar noverify ;
-which disables certificate verification;
-.Ar noname ,
-which disables certificate name checking;
-.Ar clientcert ,
-which requires a client certificate on incoming connections; or
-.Ar muststaple ,
-which requires the peer to provide a valid stapled OCSP response
-with the handshake.
-It is illegal to specify TLS options if not using TLS.
-.Pp
-For IPv4 TOS value
+Change IPv4 TOS value.
.Ar keyword
may be one of
.Ar critical ,
@@ -483,11 +429,6 @@ the source port, with a timeout of 5 sec
.Pp
.Dl $ nc -p 31337 -w 5 host.example.com 42
.Pp
-Open a TCP connection to port 443 of www.google.ca, and negotiate TLS.
-Check for a different name in the certificate for validation.
-.Pp
-.Dl $ nc -v -c -e adsf.au.doubleclick.net www.google.ca 443
-.Pp
Open a UDP connection to port 53 of host.example.com:
.Pp
.Dl $ nc -u host.example.com 53
--- a/netcat.c
+++ b/netcat.c
@@ -99,7 +99,9 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include <tls.h>
+#ifdef TLS
+# include <tls.h>
+#endif
#include <bsd/stdlib.h>
#include <bsd/string.h>
#include "atomicio.h"
@@ -112,13 +114,15 @@
#define POLL_NETIN 2
#define POLL_STDOUT 3
#define BUFSIZE 16384
-#define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
+#ifdef TLS
+# define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
-#define TLS_ALL (1 << 1)
-#define TLS_NOVERIFY (1 << 2)
-#define TLS_NONAME (1 << 3)
-#define TLS_CCERT (1 << 4)
-#define TLS_MUSTSTAPLE (1 << 5)
+# define TLS_ALL (1 << 1)
+# define TLS_NOVERIFY (1 << 2)
+# define TLS_NONAME (1 << 3)
+# define TLS_CCERT (1 << 4)
+# define TLS_MUSTSTAPLE (1 << 5)
+#endif
/* Command Line Options */
int dflag; /* detached, no stdin */
@@ -144,6 +148,7 @@ int Sflag; /* TCP MD5 signature opti
int Tflag = -1; /* IP Type of Service */
int rtableid = -1;
+# if defined(TLS)
int usetls; /* use TLS */
char *Cflag; /* Public cert file */
char *Kflag; /* Private key file */
@@ -153,6 +158,7 @@ int tls_cachanged; /* Using non-defau
int TLSopt; /* TLS options */
char *tls_expectname; /* required name in peer cert */
char *tls_expecthash; /* required hash of peer cert */
+# endif
int timeout = -1;
int family = AF_UNSPEC;
@@ -165,10 +171,16 @@ void atelnet(int, unsigned char *, unsig
void build_ports(char *);
void help(void);
int local_listen(char *, char *, struct addrinfo);
+# if defined(TLS)
void readwrite(int, struct tls *);
+# else
+void readwrite(int);
+# endif
void fdpass(int nfd) __attribute__((noreturn));
int remote_connect(const char *, const char *, struct addrinfo);
+# if defined(TLS)
int timeout_tls(int, struct tls *, int (*)(struct tls *));
+# endif
int timeout_connect(int, const struct sockaddr *, socklen_t);
int socks_connect(const char *, const char *, struct addrinfo,
const char *, const char *, struct addrinfo, int, const char *);
@@ -178,14 +190,23 @@ int unix_connect(char *);
int unix_listen(char *);
void set_common_sockopts(int, int);
int map_tos(char *, int *);
+# if defined(TLS)
int map_tls(char *, int *);
+# endif
void report_connect(const struct sockaddr *, socklen_t, char *);
+# if defined(TLS)
void report_tls(struct tls *tls_ctx, char * host, char *tls_expectname);
+# endif
void usage(int);
+# if defined(TLS)
ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *);
ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *);
void tls_setup_client(struct tls *, int, char *);
struct tls *tls_setup_server(struct tls *, int, char *);
+# else
+ssize_t drainbuf(int, unsigned char *, size_t *);
+ssize_t fillbuf(int, unsigned char *, size_t *);
+# endif
int
main(int argc, char *argv[])
@@ -200,8 +221,10 @@ main(int argc, char *argv[])
const char *errstr;
struct addrinfo proxyhints;
char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
+# if defined(TLS)
struct tls_config *tls_cfg = NULL;
struct tls *tls_ctx = NULL;
+# endif
ret = 1;
socksv = 5;
@@ -212,7 +235,11 @@ main(int argc, char *argv[])
signal(SIGPIPE, SIG_IGN);
while ((ch = getopt(argc, argv,
+# if defined(TLS)
"46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vw:X:x:z")) != -1) {
+# else
+ "46DdFhI:i:klM:m:NnO:P:p:rSs:T:tUuV:vw:X:x:z")) != -1) {
+# endif
switch (ch) {
case '4':
family = AF_INET;
@@ -233,24 +260,30 @@ main(int argc, char *argv[])
else
errx(1, "unsupported proxy protocol");
break;
+# if defined(TLS)
case 'C':
Cflag = optarg;
break;
case 'c':
usetls = 1;
break;
+# endif
case 'd':
dflag = 1;
break;
+# if defined(TLS)
case 'e':
tls_expectname = optarg;
break;
+# endif
case 'F':
Fflag = 1;
break;
+# if defined(TLS)
case 'H':
tls_expecthash = optarg;
break;
+# endif
case 'h':
help();
break;
@@ -259,9 +292,11 @@ main(int argc, char *argv[])
if (errstr)
errx(1, "interval %s: %s", errstr, optarg);
break;
+# if defined(TLS)
case 'K':
Kflag = optarg;
break;
+# endif
case 'k':
kflag = 1;
break;
@@ -290,10 +325,12 @@ main(int argc, char *argv[])
case 'p':
pflag = optarg;
break;
+# if defined(TLS)
case 'R':
tls_cachanged = 1;
Rflag = optarg;
break;
+# endif
case 'r':
rflag = 1;
break;
@@ -348,9 +385,11 @@ main(int argc, char *argv[])
errx(1, "TCP send window %s: %s",
errstr, optarg);
break;
+# if defined(TLS)
case 'o':
oflag = optarg;
break;
+# endif
case 'S':
# if defined(TCP_MD5SIG)
Sflag = 1;
@@ -363,8 +402,10 @@ main(int argc, char *argv[])
errno = 0;
if (map_tos(optarg, &Tflag))
break;
+# if defined(TLS)
if (map_tls(optarg, &TLSopt))
break;
+# endif
if (strlen(optarg) > 1 && optarg[0] == '0' &&
optarg[1] == 'x')
Tflag = (int)strtol(optarg, NULL, 16);
@@ -372,7 +413,11 @@ main(int argc, char *argv[])
Tflag = (int)strtonum(optarg, 0, 255,
&errstr);
if (Tflag < 0 || Tflag > 255 || errstr || errno)
+# if defined(TLS)
errx(1, "illegal tos/tls value %s", optarg);
+# else
+ errx(1, "illegal tos value %s", optarg);
+# endif
break;
default:
usage(1);
@@ -411,12 +456,15 @@ main(int argc, char *argv[])
if (!lflag && kflag)
errx(1, "must use -l with -k");
+# if defined(TLS)
if (uflag && usetls)
errx(1, "cannot use -c and -u");
if ((family == AF_UNIX) && usetls)
errx(1, "cannot use -c and -U");
+# endif
if ((family == AF_UNIX) && Fflag)
errx(1, "cannot use -F and -U");
+# if defined(TLS)
if (Fflag && usetls)
errx(1, "cannot use -c and -F");
if (TLSopt && !usetls)
@@ -433,6 +481,7 @@ main(int argc, char *argv[])
errx(1, "you must specify -c to use -H");
if (tls_expectname && !usetls)
errx(1, "you must specify -c to use -e");
+# endif
/* Get name of temporary socket for unix datagram client */
if ((family == AF_UNIX) && uflag && !lflag) {
@@ -499,6 +548,7 @@ main(int argc, char *argv[])
proxyhints.ai_flags |= AI_NUMERICHOST;
}
+# if defined(TLS)
if (usetls) {
if (Pflag) {
if (pledge("stdio inet dns tty rpath", NULL) == -1)
@@ -544,8 +594,11 @@ main(int argc, char *argv[])
} else if (pledge("stdio inet dns", NULL) == -1)
err(1, "pledge");
}
+# endif
if (lflag) {
+# if defined(TLS)
struct tls *tls_cctx = NULL;
+# endif
int connfd;
ret = 0;
@@ -556,6 +609,7 @@ main(int argc, char *argv[])
s = unix_listen(host);
}
+# if defined(TLS)
if (usetls) {
tls_config_verify_client_optional(tls_cfg);
if ((tls_ctx = tls_server()) == NULL)
@@ -564,6 +618,7 @@ main(int argc, char *argv[])
errx(1, "tls configuration failed (%s)",
tls_error(tls_ctx));
}
+# endif
/* Allow only one connection at a time, but stay alive. */
for (;;) {
if (family != AF_UNIX)
@@ -575,7 +630,11 @@ main(int argc, char *argv[])
* receive datagrams from multiple socket pairs.
*/
if (uflag && kflag)
+# if defined(TLS)
readwrite(s, NULL);
+# else
+ readwrite(s);
+# endif
/*
* For UDP and not -k, we will use recvfrom() initially
* to wait for a caller, then use the regular functions
@@ -600,7 +659,11 @@ main(int argc, char *argv[])
if (vflag)
report_connect((struct sockaddr *)&z, len, NULL);
+# if defined(TLS)
readwrite(s, NULL);
+# else
+ readwrite(s);
+# endif
} else {
len = sizeof(cliaddr);
connfd = accept4(s, (struct sockaddr *)&cliaddr,
@@ -612,6 +675,7 @@ main(int argc, char *argv[])
if (vflag)
report_connect((struct sockaddr *)&cliaddr, len,
family == AF_UNIX ? host : NULL);
+# if defined(TLS)
if ((usetls) &&
(tls_cctx = tls_setup_server(tls_ctx, connfd, host)))
readwrite(connfd, tls_cctx);
@@ -622,6 +686,9 @@ main(int argc, char *argv[])
tls_free(tls_cctx);
tls_cctx = NULL;
}
+# else
+ readwrite(connfd);
+# endif
close(connfd);
}
if (family != AF_UNIX)
@@ -639,7 +706,11 @@ main(int argc, char *argv[])
if ((s = unix_connect(host)) > 0) {
if (!zflag)
+# if defined(TLS)
readwrite(s, NULL);
+# else
+ readwrite(s);
+# endif
close(s);
} else
ret = 1;
@@ -659,6 +730,7 @@ main(int argc, char *argv[])
if (s != -1)
close(s);
+# if defined(TLS)
if (usetls) {
if ((tls_ctx = tls_client()) == NULL)
errx(1, "tls client creation failed");
@@ -666,6 +738,7 @@ main(int argc, char *argv[])
errx(1, "tls configuration failed (%s)",
tls_error(tls_ctx));
}
+# endif
if (xflag)
s = socks_connect(host, portlist[i], hints,
proxy, proxyport, proxyhints, socksv,
@@ -703,6 +776,7 @@ main(int argc, char *argv[])
}
if (Fflag)
fdpass(s);
+# if defined(TLS)
else {
if (usetls)
tls_setup_client(tls_ctx, s, host);
@@ -714,13 +788,19 @@ main(int argc, char *argv[])
tls_ctx = NULL;
}
}
+# else
+ else if (!zflag)
+ readwrite(s);
+# endif
}
}
if (s != -1)
close(s);
+# if defined(TLS)
tls_config_free(tls_cfg);
+# endif
exit(ret);
}
@@ -759,6 +839,7 @@ unix_bind(char *path, int flags)
return (s);
}
+# if defined(TLS)
int
timeout_tls(int s, struct tls *tls_ctx, int (*func)(struct tls *))
{
@@ -840,6 +921,7 @@ tls_setup_server(struct tls *tls_ctx, in
}
return NULL;
}
+# endif
/*
* unix_connect()
@@ -1052,7 +1134,11 @@ local_listen(char *host, char *port, str
* Loop that polls on the network file descriptor and stdin.
*/
void
+# if defined(TLS)
readwrite(int net_fd, struct tls *tls_ctx)
+# else
+readwrite(int net_fd)
+# endif
{
struct pollfd pfd[4];
int stdin_fd = STDIN_FILENO;
@@ -1152,12 +1238,17 @@ readwrite(int net_fd, struct tls *tls_ct
/* try to read from stdin */
if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
+# if defined(TLS)
&stdinbufpos, NULL);
if (ret == TLS_WANT_POLLIN)
pfd[POLL_STDIN].events = POLLIN;
else if (ret == TLS_WANT_POLLOUT)
pfd[POLL_STDIN].events = POLLOUT;
- else if (ret == 0 || ret == -1)
+ else
+# else
+ &stdinbufpos);
+# endif
+ if (ret == 0 || ret == -1)
pfd[POLL_STDIN].fd = -1;
/* read something - poll net out */
if (stdinbufpos > 0)
@@ -1169,12 +1260,17 @@ readwrite(int net_fd, struct tls *tls_ct
/* try to write to network */
if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
+# if defined(TLS)
&stdinbufpos, tls_ctx);
if (ret == TLS_WANT_POLLIN)
pfd[POLL_NETOUT].events = POLLIN;
else if (ret == TLS_WANT_POLLOUT)
pfd[POLL_NETOUT].events = POLLOUT;
- else if (ret == -1)
+ else
+# else
+ &stdinbufpos);
+# endif
+ if (ret == -1)
pfd[POLL_NETOUT].fd = -1;
/* buffer empty - remove self from polling */
if (stdinbufpos == 0)
@@ -1186,12 +1282,17 @@ readwrite(int net_fd, struct tls *tls_ct
/* try to read from network */
if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
+# if defined(TLS)
&netinbufpos, tls_ctx);
if (ret == TLS_WANT_POLLIN)
pfd[POLL_NETIN].events = POLLIN;
else if (ret == TLS_WANT_POLLOUT)
pfd[POLL_NETIN].events = POLLOUT;
- else if (ret == -1)
+ else
+# else
+ &netinbufpos);
+# endif
+ if (ret == -1)
pfd[POLL_NETIN].fd = -1;
/* eof on net in - remove from pfd */
if (ret == 0) {
@@ -1212,12 +1313,17 @@ readwrite(int net_fd, struct tls *tls_ct
/* try to write to stdout */
if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
+# if defined(TLS)
&netinbufpos, NULL);
if (ret == TLS_WANT_POLLIN)
pfd[POLL_STDOUT].events = POLLIN;
else if (ret == TLS_WANT_POLLOUT)
pfd[POLL_STDOUT].events = POLLOUT;
- else if (ret == -1)
+ else
+# else
+ &netinbufpos);
+# endif
+ if (ret == -1)
pfd[POLL_STDOUT].fd = -1;
/* buffer empty - remove self from polling */
if (netinbufpos == 0)
@@ -1241,19 +1347,29 @@ readwrite(int net_fd, struct tls *tls_ct
}
ssize_t
+# if defined(TLS)
drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls)
+# else
+drainbuf(int fd, unsigned char *buf, size_t *bufpos)
+# endif
{
ssize_t n;
ssize_t adjust;
+# if defined(TLS)
if (tls)
n = tls_write(tls, buf, *bufpos);
else {
+# endif
n = write(fd, buf, *bufpos);
/* don't treat EAGAIN, EINTR as error */
if (n == -1 && (errno == EAGAIN || errno == EINTR))
+# if defined(TLS)
n = TLS_WANT_POLLOUT;
}
+# else
+ n = -2;
+# endif
if (n <= 0)
return n;
/* adjust buffer */
@@ -1265,19 +1381,29 @@ drainbuf(int fd, unsigned char *buf, siz
}
ssize_t
+# if defined(TLS)
fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls)
+# else
+fillbuf(int fd, unsigned char *buf, size_t *bufpos)
+# endif
{
size_t num = BUFSIZE - *bufpos;
ssize_t n;
+# if defined(TLS)
if (tls)
n = tls_read(tls, buf + *bufpos, num);
else {
+# endif
n = read(fd, buf + *bufpos, num);
/* don't treat EAGAIN, EINTR as error */
if (n == -1 && (errno == EAGAIN || errno == EINTR))
+# if defined(TLS)
n = TLS_WANT_POLLIN;
}
+# else
+ n = -2;
+# endif
if (n <= 0)
return n;
*bufpos += n;
@@ -1581,6 +1707,7 @@ map_tos(char *s, int *val)
return (0);
}
+# if defined(TLS)
int
map_tls(char *s, int *val)
{
@@ -1662,6 +1789,7 @@ report_tls(struct tls * tls_ctx, char *
}
}
+# endif
void
report_connect(const struct sockaddr *sa, socklen_t salen, char *path)
@@ -1704,17 +1832,12 @@ help(void)
fprintf(stderr, "\tCommand Summary:\n\
\t-4 Use IPv4\n\
\t-6 Use IPv6\n\
- \t-C certfile Public key file\n\
- \t-c Use TLS\n\
\t-D Enable the debug socket option\n\
\t-d Detach from stdin\n\
- \t-e name\t Required name in peer certificate\n\
\t-F Pass socket fd\n\
- \t-H hash\t Hash string of peer certificate\n\
\t-h This help text\n\
\t-I length TCP receive buffer length\n\
\t-i interval Delay interval for lines sent, ports scanned\n\
- \t-K keyfile Private key file\n\
\t-k Keep inbound sockets open for multiple connects\n\
\t-l Listen mode, for inbound connects\n\
\t-M ttl Outgoing TTL / Hop Limit\n\
@@ -1722,14 +1845,12 @@ help(void)
\t-N Shutdown the network socket after EOF on stdin\n\
\t-n Suppress name/port resolutions\n\
\t-O length TCP send buffer length\n\
- \t-o staplefile Staple file\n\
\t-P proxyuser\tUsername for proxy authentication\n\
\t-p port\t Specify local port for remote connects\n\
- \t-R CAfile CA bundle\n\
\t-r Randomize remote ports\n\
\t-S Enable the TCP MD5 signature option\n\
\t-s source Local source address\n\
- \t-T keyword TOS value or TLS options\n\
+ \t-T keyword TOS value\n\
\t-t Answer TELNET negotiation\n\
\t-U Use UNIX domain socket\n\
\t-u UDP mode\n\
@@ -1747,11 +1868,8 @@ void
usage(int ret)
{
fprintf(stderr,
- "usage: nc [-46cDdFhklNnrStUuvz] [-C certfile] [-e name] "
- "[-H hash] [-I length]\n"
- "\t [-i interval] [-K keyfile] [-M ttl] [-m minttl] [-O length]\n"
- "\t [-o staplefile] [-P proxy_username] [-p source_port] "
- "[-R CAfile]\n"
+ "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-M ttl]\n"
+ "\t [-m minttl] [-O length] [-P proxy_username] [-p source_port]\n"
"\t [-s source] [-T keyword] [-V rtable] [-w timeout] "
"[-X proxy_protocol]\n"
"\t [-x proxy_address[:port]] [destination] [port]\n");