[PATCH] Add TCP Stealth support to OpenSSH

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 



Hi list,

as revealed earlier this year, secret services are actively scanning the
net for vulnerable services in context of programs like CSEC's LANDMARK
and GCHQ's HACIENDA [0]. We assume that OpenSSH is one of the most
lucrative targets of these programs by using 0-day exploits.

Furthermore, there is a long-running worm on the Internet brute-forcing
access to systems by guessing usernames and passwords, which thanks to
"cloud" computing is virtually impossible to contain. (see, for example,
[1])

TCP Stealth is a IETF draft [2] which has to goal of locking out port
scanners by introducing a symmetric secret which has to be known to both
sides for a connection to succeed. This functionality is mplemented by
patching the respective operating system's kernel - in case of Linux
this is done by the Knock patch [3] which introduces a new setsockopt().

In order to broaden support for TCP Stealth on the user side, we've
created patches for the OpenBSD and Linux versions of OpenSSH which
introduce the -z command line option and a new TCPStealthSecret
configuration option if the running kernel/libc exports the TCP_STEALTH
constant.  (PGP-Signatures of the patch are available at the project
homepage [3].) We would be glad if the maintainers decided to
incorporate our patch into the standard track of OpenSSH.

Best regards,
Julian

---

[0]
http://www.heise.de/ct/artikel/NSA-GCHQ-The-HACIENDA-Program-for-Internet-Colonization-2292681.html
[1]
http://blog.sucuri.net/2013/07/ssh-brute-force-the-10-year-old-attack-that-still-persists.html
[2] http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
[3] https://gnunet.org/knock
diff -Nurp openssh-6.7/readconf.c openssh-6.7-knock/readconf.c
--- openssh-6.7/readconf.c	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/readconf.c	2014-11-10 13:45:50.158522261 +0100
@@ -143,6 +143,9 @@ typedef enum {
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
 	oStreamLocalBindMask, oStreamLocalBindUnlink,
+#ifdef TCP_STEALTH
+	oTCPStealthSecret,
+#endif
 	oIgnoredUnknownOption, oDeprecated, oUnsupported
 } OpCodes;
 
@@ -258,6 +261,9 @@ static struct {
 	{ "streamlocalbindmask", oStreamLocalBindMask },
 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
 	{ "ignoreunknown", oIgnoreUnknown },
+#ifdef TCP_STEALTH
+	{ "tcpstealthsecret", oTCPStealthSecret },
+#endif
 
 	{ NULL, oBadOption }
 };
@@ -1424,6 +1430,23 @@ parse_int:
 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
 		goto parse_flag;
 
+#ifdef TCP_STEALTH
+	case oTCPStealthSecret:
+		charptr = &options->tcp_stealth_secret;
+
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%.200s line %d: Missing argument.",
+			    filename, linenum);
+
+		if (*activep && *charptr == NULL) {
+			*charptr = xmalloc(64 + 1);
+			memset(*charptr, 0x00, 64 + 1);
+			strncpy(*charptr, arg, 64);
+		}
+
+		break;
+#endif
 	case oDeprecated:
 		debug("%s line %d: Deprecated option \"%s\"",
 		    filename, linenum, keyword);
@@ -1600,6 +1623,9 @@ initialize_options(Options * options)
 	options->canonicalize_max_dots = -1;
 	options->canonicalize_fallback_local = -1;
 	options->canonicalize_hostname = -1;
+#ifdef TCP_STEALTH
+	options->tcp_stealth_secret = NULL;
+#endif
 }
 
 /*
diff -Nurp openssh-6.7/readconf.h openssh-6.7-knock/readconf.h
--- openssh-6.7/readconf.h	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/readconf.h	2014-11-10 13:45:50.162522227 +0100
@@ -145,6 +145,9 @@ typedef struct {
 	struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
 
 	char	*ignored_unknown; /* Pattern list of unknown tokens to ignore */
+#ifdef TCP_STEALTH
+	char	*tcp_stealth_secret;
+#endif
 }       Options;
 
 #define SSH_CANONICALISE_NO	0
diff -Nurp openssh-6.7/servconf.c openssh-6.7-knock/servconf.c
--- openssh-6.7/servconf.c	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/servconf.c	2014-11-10 13:45:50.162522227 +0100
@@ -148,6 +148,9 @@ initialize_server_options(ServerOptions
 	options->ip_qos_interactive = -1;
 	options->ip_qos_bulk = -1;
 	options->version_addendum = NULL;
+#ifdef TCP_STEALTH
+	options->tcp_stealth_secret = NULL;
+#endif
 }
 
 void
@@ -333,6 +336,9 @@ typedef enum {
 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
 	sAllowStreamLocalForwarding,
+#ifdef TCP_STEALTH
+	sTCPStealthSecret,
+#endif
 	sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -451,6 +457,9 @@ static struct {
 	{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
 	{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
 	{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
+#ifdef TCP_STEALTH
+	{ "tcpstealthsecret", sTCPStealthSecret },
+#endif
 	{ NULL, sBadOption, 0 }
 };
 
@@ -1615,7 +1624,23 @@ process_server_config_line(ServerOptions
 	case sStreamLocalBindUnlink:
 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
 		goto parse_flag;
+#ifdef TCP_STEALTH
+	case sTCPStealthSecret:
+		charptr = &options->tcp_stealth_secret;
+
+		arg = strdelim(&cp);
+		if (!arg || *arg == '\0')
+			fatal("%s line %d: Missing argument.",
+				filename, linenum);
+
+		if (*activep && *charptr == NULL) {
+			*charptr = xmalloc(64 + 1);
+			memset(*charptr, 0x00, 64 + 1);
+			strncpy(*charptr, arg, 64);
+		}
 
+		break;
+#endif
 	case sDeprecated:
 		logit("%s line %d: Deprecated option %s",
 		    filename, linenum, arg);
diff -Nurp openssh-6.7/servconf.h openssh-6.7-knock/servconf.h
--- openssh-6.7/servconf.h	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/servconf.h	2014-11-10 13:45:50.162522227 +0100
@@ -183,6 +183,10 @@ typedef struct {
 
 	u_int	num_auth_methods;
 	char   *auth_methods[MAX_AUTH_METHODS];
+
+#ifdef TCP_STEALTH
+	char	*tcp_stealth_secret;
+#endif
 }       ServerOptions;
 
 /* Information about the incoming connection as used by Match */
@@ -204,6 +208,12 @@ struct connection_info {
  * NB. an option must appear in servconf.c:copy_set_server_options() or
  * COPY_MATCH_STRING_OPTS here but never both.
  */
+#ifdef TCP_STEALTH
+#define M_CP_STEALTHSCRT(X)	M_CP_STROPT(X);
+#else
+#define M_CP_STEALTHSCRT(X)	
+#endif
+
 #define COPY_MATCH_STRING_OPTS() do { \
 		M_CP_STROPT(banner); \
 		M_CP_STROPT(trusted_user_ca_keys); \
@@ -218,6 +228,7 @@ struct connection_info {
 		M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
 		M_CP_STRARRAYOPT(accept_env, num_accept_env); \
 		M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
+		M_CP_STEALTHSCRT(tcp_stealth_secret); \
 	} while (0)
 
 struct connection_info *get_connection_info(int, int);
diff -Nurp openssh-6.7/ssh.1 openssh-6.7-knock/ssh.1
--- openssh-6.7/ssh.1	2014-07-25 00:57:10.000000000 +0200
+++ openssh-6.7-knock/ssh.1	2014-11-10 13:48:25.061186801 +0100
@@ -63,6 +63,7 @@
 .Op Fl S Ar ctl_path
 .Op Fl W Ar host : Ns Ar port
 .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
+.Op Fl z Ar tcp_stealth_secret
 .Oo Ar user Ns @ Oc Ns Ar hostname
 .Op Ar command
 .Ek
@@ -473,6 +474,7 @@ For full details of the options listed b
 .It StreamLocalBindUnlink
 .It StrictHostKeyChecking
 .It TCPKeepAlive
+.It TCPStealthSecret
 .It Tunnel
 .It TunnelDevice
 .It UsePrivilegedPort
@@ -668,6 +670,21 @@ Send log information using the
 .Xr syslog 3
 system module.
 By default this information is sent to stderr.
+.It Fl z Ar tcp_stealth_secret
+Specifies the shared secret which is needed to connect to a stealth SSH TCP
+server. Any string specified will be truncated to or padded with zeroes to 64
+bytes. This option needs kernel support and is therefore only available if the
+required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
+.Pp
+.Cm IMPORTANT:
+This option should only be used for the purpose of testing as other users could
+easily read out the secret from the command line arguments. The
+.Cm TCPStealthSecret
+configuration option is the preferred way of specifying the TCP Stealth secret.
 .El
 .Pp
 .Nm
diff -Nurp openssh-6.7/ssh.c openssh-6.7-knock/ssh.c
--- openssh-6.7/ssh.c	2014-07-17 09:22:19.000000000 +0200
+++ openssh-6.7-knock/ssh.c	2014-11-10 13:48:25.061186801 +0100
@@ -179,6 +179,14 @@ static int remote_forward_confirms_recei
 extern int muxserver_sock;
 extern u_int muxclient_command;
 
+#ifdef TCP_STEALTH
+#define OPT_STEALTH	"[-z tcp_stealth_secret] "
+#define GETOPT_STEALTH	"z:"
+#else
+#define OPT_STEALTH	""
+#define GETOPT_STEALTH	""
+#endif
+
 /* Prints a help message to the user.  This function never returns. */
 
 static void
@@ -192,7 +200,7 @@ usage(void)
 "           [-O ctl_cmd] [-o option] [-p port]\n"
 "           [-Q cipher | cipher-auth | mac | kex | key]\n"
 "           [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]\n"
-"           [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
+"           [-w local_tun[:remote_tun]] " OPT_STEALTH "[user@]hostname [command]\n"
 	);
 	exit(255);
 }
@@ -478,7 +486,7 @@ main(int ac, char **av)
 
  again:
 	while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
-	    "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
+	    "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy" GETOPT_STEALTH)) != -1) {
 		switch (opt) {
 		case '1':
 			options.protocol = SSH_PROTO_1;
@@ -779,6 +787,12 @@ main(int ac, char **av)
 		case 'F':
 			config = optarg;
 			break;
+#ifdef TCP_STEALTH
+		case 'z':
+			options.tcp_stealth_secret = xcalloc(64 + 1, sizeof(u_int8_t));
+			strncpy(options.tcp_stealth_secret, optarg, 64);
+			break;
+#endif
 		default:
 			usage();
 		}
diff -Nurp openssh-6.7/ssh_config.5 openssh-6.7-knock/ssh_config.5
--- openssh-6.7/ssh_config.5	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/ssh_config.5	2014-11-10 13:48:34.321106975 +0100
@@ -1380,6 +1380,15 @@ This is important in scripts, and many u
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.It Cm TCPStealthSecret
+Specifies the shared secret which is needed to connect to a stealth SSH TCP
+Server. Any string specified will be truncated to or padded with zeroes to 64
+bytes. This option needs kernel support and is therefore only available if the
+required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
 .It Cm Tunnel
 Request
 .Xr tun 4
diff -Nurp openssh-6.7/sshconnect.c openssh-6.7-knock/sshconnect.c
--- openssh-6.7/sshconnect.c	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/sshconnect.c	2014-11-10 13:48:34.321106975 +0100
@@ -269,6 +269,17 @@ ssh_create_socket(int privileged, struct
 	}
 	fcntl(sock, F_SETFD, FD_CLOEXEC);
 
+#ifdef TCP_STEALTH
+	if (options.tcp_stealth_secret) {
+		if (setsockopt(sock, IPPROTO_TCP, TCP_STEALTH,
+			       options.tcp_stealth_secret, 64) == -1) {
+			error("setsockopt TCP_STEALTH: %s", strerror(errno));
+			close(sock);
+			return -1;
+		}
+	}
+#endif
+
 	/* Bind the socket to an alternative local IP address */
 	if (options.bind_address == NULL && !privileged)
 		return sock;
diff -Nurp openssh-6.7/sshd.8 openssh-6.7-knock/sshd.8
--- openssh-6.7/sshd.8	2014-07-04 00:40:43.000000000 +0200
+++ openssh-6.7-knock/sshd.8	2014-11-10 13:48:42.693034803 +0100
@@ -55,6 +55,7 @@
 .Op Fl o Ar option
 .Op Fl p Ar port
 .Op Fl u Ar len
+.Op Fl z Ar tcp_stealth_secret
 .Ek
 .Sh DESCRIPTION
 .Nm
@@ -270,6 +271,24 @@ USER@HOST pattern in
 .Cm AllowUsers
 or
 .Cm DenyUsers .
+.It Fl z Ar tcp_stealth_secret
+Turns this SSH server into a stealth SSH TCP server. This option specifies the
+shared secret which is needed by the clients in order to be able to connect to
+the port the SSH server is listening on.  Any string specified will be truncated
+or padded with zeroes to 64 bytes. This option needs kernel support and is
+therefore only available if the required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
+
+.Cm IMPORTANT:
+This option should only be used for the purpose of
+testing as other users could easily read out the secret from the
+command line arguments. The
+.Cm TCPStealthSecret
+configuration option
+is the preferred way of specifying the TCP Stealth secret.
 .El
 .Sh AUTHENTICATION
 The OpenSSH SSH daemon supports SSH protocols 1 and 2.
diff -Nurp openssh-6.7/sshd.c openssh-6.7-knock/sshd.c
--- openssh-6.7/sshd.c	2014-07-15 17:54:14.000000000 +0200
+++ openssh-6.7-knock/sshd.c	2014-11-10 13:48:42.693034803 +0100
@@ -897,6 +897,14 @@ drop_connection(int startups)
 	return (r < p) ? 1 : 0;
 }
 
+#ifdef TCP_STEALTH
+#define OPT_STEALTH	" [-z tcp_stealth_secret]"
+#define GETOPT_STEALTH	"z:"
+#else
+#define OPT_STEALTH	""
+#define GETOPT_STEALTH	""
+#endif
+
 static void
 usage(void)
 {
@@ -912,7 +920,7 @@ usage(void)
 "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
 "            [-E log_file] [-f config_file] [-g login_grace_time]\n"
 "            [-h host_key_file] [-k key_gen_time] [-o option] [-p port]\n"
-"            [-u len]\n"
+"            [-u len]" OPT_STEALTH "\n"
 	);
 	exit(1);
 }
@@ -1082,6 +1090,14 @@ server_listen(void)
 		if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
 		    &on, sizeof(on)) == -1)
 			error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+#ifdef TCP_STEALTH
+		if (options.tcp_stealth_secret != NULL) {
+			if (setsockopt(listen_sock, IPPROTO_TCP, TCP_STEALTH,
+			    options.tcp_stealth_secret, 64) == -1)
+				error("setsockopt TCP_STEALTH: %s",
+				      strerror(errno));
+		}
+#endif
 
 		debug("Bind to port %s on %s.", strport, ntop);
 
@@ -1355,7 +1371,8 @@ main(int ac, char **av)
 	initialize_server_options(&options);
 
 	/* Parse command-line arguments. */
-	while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeE:iqrtQRT46")) != -1) {
+	while ((opt = getopt(ac, av, "z:f:p:b:k:h:g:u:o:C:" \
+			     "dDeE:iqrtQRT46" GETOPT_STEALTH)) != -1) {
 		switch (opt) {
 		case '4':
 			options.address_family = AF_INET;
@@ -1467,6 +1484,12 @@ main(int ac, char **av)
 				exit(1);
 			free(line);
 			break;
+#ifdef TCP_STEALTH
+		case 'z':
+			options.tcp_stealth_secret = xcalloc(64 + 1, sizeof(u_int8_t));
+			strncpy(options.tcp_stealth_secret, optarg, 64);
+			break;
+#endif
 		case '?':
 		default:
 			usage();
diff -Nurp openssh-6.7/sshd_config.5 openssh-6.7-knock/sshd_config.5
--- openssh-6.7/sshd_config.5	2014-07-28 17:40:08.000000000 +0200
+++ openssh-6.7-knock/sshd_config.5	2014-11-10 13:48:45.657009252 +0100
@@ -1280,6 +1280,18 @@ This avoids infinitely hanging sessions.
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.It Cm TCPStealthSecret
+Turns this SSH server into a stealth SSH TCP server. This configuration option
+specifies the shared secret needed by the clients in order to be able to connect
+to the port the SSH server is listening on. This means that port scanners will
+receive a TCP RST and thus will not recognize this TCP port being open.  Any
+string specified will be truncated or padded with zeroes to 64 bytes. This
+option needs kernel support and is therefore only available if the required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
+
 .It Cm TrustedUserCAKeys
 Specifies a file containing public keys of certificate authorities that are
 trusted to sign user certificates for authentication.
diff -Nurp openssh-6.7p1/readconf.c openssh-6.7p1-knock/readconf.c
--- openssh-6.7p1/readconf.c	2014-07-18 00:11:26.000000000 -0400
+++ openssh-6.7p1-knock/readconf.c	2014-11-07 14:10:00.630189385 -0500
@@ -151,6 +151,9 @@ typedef enum {
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
 	oStreamLocalBindMask, oStreamLocalBindUnlink,
+#ifdef TCP_STEALTH
+	oTCPStealthSecret,
+#endif
 	oIgnoredUnknownOption, oDeprecated, oUnsupported
 } OpCodes;
 
@@ -266,6 +269,9 @@ static struct {
 	{ "streamlocalbindmask", oStreamLocalBindMask },
 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
 	{ "ignoreunknown", oIgnoreUnknown },
+#ifdef TCP_STEALTH
+	{ "tcpstealthsecret", oTCPStealthSecret },
+#endif
 
 	{ NULL, oBadOption }
 };
@@ -1433,6 +1439,23 @@ parse_int:
 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
 		goto parse_flag;
 
+#ifdef TCP_STEALTH
+	case oTCPStealthSecret:
+		charptr = &options->tcp_stealth_secret;
+
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%.200s line %d: Missing argument.",
+			    filename, linenum);
+
+		if (*activep && *charptr == NULL) {
+			*charptr = xmalloc(64 + 1);
+			memset(*charptr, 0x00, 64 + 1);
+			strncpy(*charptr, arg, 64);
+		}
+
+		break;
+#endif
 	case oDeprecated:
 		debug("%s line %d: Deprecated option \"%s\"",
 		    filename, linenum, keyword);
@@ -1609,6 +1632,9 @@ initialize_options(Options * options)
 	options->canonicalize_max_dots = -1;
 	options->canonicalize_fallback_local = -1;
 	options->canonicalize_hostname = -1;
+#ifdef TCP_STEALTH
+	options->tcp_stealth_secret = NULL;
+#endif
 }
 
 /*
diff -Nurp openssh-6.7p1/readconf.h openssh-6.7p1-knock/readconf.h
--- openssh-6.7p1/readconf.h	2014-07-18 00:11:26.000000000 -0400
+++ openssh-6.7p1-knock/readconf.h	2014-11-07 14:07:22.334196351 -0500
@@ -145,6 +145,9 @@ typedef struct {
 	struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
 
 	char	*ignored_unknown; /* Pattern list of unknown tokens to ignore */
+#ifdef TCP_STEALTH
+	char	*tcp_stealth_secret;
+#endif
 }       Options;
 
 #define SSH_CANONICALISE_NO	0
diff -Nurp openssh-6.7p1/servconf.c openssh-6.7p1-knock/servconf.c
--- openssh-6.7p1/servconf.c	2014-07-18 00:11:26.000000000 -0400
+++ openssh-6.7p1-knock/servconf.c	2014-11-07 14:10:14.462188776 -0500
@@ -157,6 +157,9 @@ initialize_server_options(ServerOptions
 	options->ip_qos_interactive = -1;
 	options->ip_qos_bulk = -1;
 	options->version_addendum = NULL;
+#ifdef TCP_STEALTH
+	options->tcp_stealth_secret = NULL;
+#endif
 }
 
 void
@@ -362,6 +365,9 @@ typedef enum {
 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
 	sAllowStreamLocalForwarding,
+#ifdef TCP_STEALTH
+	sTCPStealthSecret,
+#endif
 	sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -492,6 +498,9 @@ static struct {
 	{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
 	{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
 	{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
+#ifdef TCP_STEALTH
+	{ "tcpstealthsecret", sTCPStealthSecret },
+#endif
 	{ NULL, sBadOption, 0 }
 };
 
@@ -1662,7 +1671,23 @@ process_server_config_line(ServerOptions
 	case sStreamLocalBindUnlink:
 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
 		goto parse_flag;
+#ifdef TCP_STEALTH
+	case sTCPStealthSecret:
+		charptr = &options->tcp_stealth_secret;
+
+		arg = strdelim(&cp);
+		if (!arg || *arg == '\0')
+			fatal("%s line %d: Missing argument.",
+				filename, linenum);
+
+		if (*activep && *charptr == NULL) {
+			*charptr = xmalloc(64 + 1);
+			memset(*charptr, 0x00, 64 + 1);
+			strncpy(*charptr, arg, 64);
+		}
 
+		break;
+#endif
 	case sDeprecated:
 		logit("%s line %d: Deprecated option %s",
 		    filename, linenum, arg);
diff -Nurp openssh-6.7p1/servconf.h openssh-6.7p1-knock/servconf.h
--- openssh-6.7p1/servconf.h	2014-07-18 00:11:26.000000000 -0400
+++ openssh-6.7p1-knock/servconf.h	2014-11-07 14:08:16.826193953 -0500
@@ -185,6 +185,10 @@ typedef struct {
 
 	u_int	num_auth_methods;
 	char   *auth_methods[MAX_AUTH_METHODS];
+
+#ifdef TCP_STEALTH
+	char	*tcp_stealth_secret;
+#endif
 }       ServerOptions;
 
 /* Information about the incoming connection as used by Match */
@@ -206,6 +210,12 @@ struct connection_info {
  * NB. an option must appear in servconf.c:copy_set_server_options() or
  * COPY_MATCH_STRING_OPTS here but never both.
  */
+#ifdef TCP_STEALTH
+#define M_CP_STEALTHSCRT(X)	M_CP_STROPT(X);
+#else
+#define M_CP_STEALTHSCRT(X)	
+#endif
+
 #define COPY_MATCH_STRING_OPTS() do { \
 		M_CP_STROPT(banner); \
 		M_CP_STROPT(trusted_user_ca_keys); \
@@ -220,6 +230,7 @@ struct connection_info {
 		M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
 		M_CP_STRARRAYOPT(accept_env, num_accept_env); \
 		M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
+		M_CP_STEALTHSCRT(tcp_stealth_secret); \
 	} while (0)
 
 struct connection_info *get_connection_info(int, int);
diff -Nurp openssh-6.7p1/ssh.0 openssh-6.7p1-knock/ssh.0
--- openssh-6.7p1/ssh.0	2014-10-05 23:39:37.000000000 -0400
+++ openssh-6.7p1-knock/ssh.0	2014-11-05 20:35:44.216514377 -0500
@@ -401,6 +401,20 @@ DESCRIPTION
      -y      Send log information using the syslog(3) system module.  By
              default this information is sent to stderr.
 
+     -z tcp_stealth_secret
+             Specifies the shared secret which is needed to connect to a stealth
+             SSH TCP server. Any string specified will be truncated to or padded
+             with zeroes to 64 bytes. This option needs kernel support and is
+             therefore only available if the required setsockopt() call is
+             available.
+             See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
+             for details.
+
+             IMPORTANT: This option should only be used for the purpose of
+             testing as other users could easily read out the secret from the
+             command line arguments. The TCPStealthSecret configuration option
+             is the preferred way of specifying the TCP Stealth secret.
+
      ssh may additionally obtain configuration data from a per-user
      configuration file and a system-wide configuration file.  The file format
      and configuration options are described in ssh_config(5).
diff -Nurp openssh-6.7p1/ssh.1 openssh-6.7p1-knock/ssh.1
--- openssh-6.7p1/ssh.1	2014-07-29 22:32:28.000000000 -0400
+++ openssh-6.7p1-knock/ssh.1	2014-11-07 13:56:02.022226289 -0500
@@ -63,6 +63,7 @@
 .Op Fl S Ar ctl_path
 .Op Fl W Ar host : Ns Ar port
 .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
+.Op Fl z Ar tcp_stealth_secret
 .Oo Ar user Ns @ Oc Ns Ar hostname
 .Op Ar command
 .Ek
@@ -473,6 +474,7 @@ For full details of the options listed b
 .It StreamLocalBindUnlink
 .It StrictHostKeyChecking
 .It TCPKeepAlive
+.It TCPStealthSecret
 .It Tunnel
 .It TunnelDevice
 .It UsePrivilegedPort
@@ -668,6 +670,21 @@ Send log information using the
 .Xr syslog 3
 system module.
 By default this information is sent to stderr.
+.It Fl z Ar tcp_stealth_secret
+Specifies the shared secret which is needed to connect to a stealth SSH TCP
+server. Any string specified will be truncated to or padded with zeroes to 64
+bytes. This option needs kernel support and is therefore only available if the
+required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
+.Pp
+.Cm IMPORTANT:
+This option should only be used for the purpose of testing as other users could
+easily read out the secret from the command line arguments. The
+.Cm TCPStealthSecret
+configuration option is the preferred way of specifying the TCP Stealth secret.
 .El
 .Pp
 .Nm
diff -Nurp openssh-6.7p1/ssh.c openssh-6.7p1-knock/ssh.c
--- openssh-6.7p1/ssh.c	2014-07-18 01:04:11.000000000 -0400
+++ openssh-6.7p1-knock/ssh.c	2014-11-07 14:06:41.110198165 -0500
@@ -193,6 +193,14 @@ static int remote_forward_confirms_recei
 extern int muxserver_sock;
 extern u_int muxclient_command;
 
+#ifdef TCP_STEALTH
+#define OPT_STEALTH	"[-z tcp_stealth_secret] "
+#define GETOPT_STEALTH	"z:"
+#else
+#define OPT_STEALTH	""
+#define GETOPT_STEALTH	""
+#endif
+
 /* Prints a help message to the user.  This function never returns. */
 
 static void
@@ -206,7 +214,7 @@ usage(void)
 "           [-O ctl_cmd] [-o option] [-p port]\n"
 "           [-Q cipher | cipher-auth | mac | kex | key]\n"
 "           [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]\n"
-"           [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
+"           [-w local_tun[:remote_tun]] " OPT_STEALTH "[user@]hostname [command]\n"
 	);
 	exit(255);
 }
@@ -507,7 +515,7 @@ main(int ac, char **av)
 
  again:
 	while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
-	    "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
+	    "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy" GETOPT_STEALTH)) != -1) {
 		switch (opt) {
 		case '1':
 			options.protocol = SSH_PROTO_1;
@@ -808,6 +816,12 @@ main(int ac, char **av)
 		case 'F':
 			config = optarg;
 			break;
+#ifdef TCP_STEALTH
+		case 'z':
+			options.tcp_stealth_secret = xcalloc(64 + 1, sizeof(u_int8_t));
+			strncpy(options.tcp_stealth_secret, optarg, 64);
+			break;
+#endif
 		default:
 			usage();
 		}
diff -Nurp openssh-6.7p1/ssh_config.0 openssh-6.7p1-knock/ssh_config.0
--- openssh-6.7p1/ssh_config.0	2014-10-05 23:39:38.000000000 -0400
+++ openssh-6.7p1-knock/ssh_config.0	2014-11-05 20:48:17.064514377 -0500
@@ -823,6 +823,15 @@ DESCRIPTION
              To disable TCP keepalive messages, the value should be set to
              ``no''.
 
+     TCPStealthSecret
+             Specifies the shared secret which is needed to connect to a stealth
+             SSH TCP Server. Any string specified will be truncated to or padded
+             with zeroes to 64 bytes. This option needs kernel support and is
+             therefore only available if the required setsockopt() call is
+             available.
+             See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
+             for details.
+
      Tunnel  Request tun(4) device forwarding between the client and the
              server.  The argument must be ``yes'', ``point-to-point'' (layer
              3), ``ethernet'' (layer 2), or ``no''.  Specifying ``yes''
diff -Nurp openssh-6.7p1/ssh_config.5 openssh-6.7p1-knock/ssh_config.5
--- openssh-6.7p1/ssh_config.5	2014-07-18 00:11:26.000000000 -0400
+++ openssh-6.7p1-knock/ssh_config.5	2014-11-07 13:54:30.402230321 -0500
@@ -1380,6 +1380,15 @@ This is important in scripts, and many u
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.It Cm TCPStealthSecret
+Specifies the shared secret which is needed to connect to a stealth SSH TCP
+Server. Any string specified will be truncated to or padded with zeroes to 64
+bytes. This option needs kernel support and is therefore only available if the
+required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
 .It Cm Tunnel
 Request
 .Xr tun 4
diff -Nurp openssh-6.7p1/sshconnect.c openssh-6.7p1-knock/sshconnect.c
--- openssh-6.7p1/sshconnect.c	2014-07-18 00:11:26.000000000 -0400
+++ openssh-6.7p1-knock/sshconnect.c	2014-11-07 14:07:11.342196835 -0500
@@ -279,6 +279,17 @@ ssh_create_socket(int privileged, struct
 	}
 	fcntl(sock, F_SETFD, FD_CLOEXEC);
 
+#ifdef TCP_STEALTH
+	if (options.tcp_stealth_secret) {
+		if (setsockopt(sock, IPPROTO_TCP, TCP_STEALTH,
+			       options.tcp_stealth_secret, 64) == -1) {
+			error("setsockopt TCP_STEALTH: %s", strerror(errno));
+			close(sock);
+			return -1;
+		}
+	}
+#endif
+
 	/* Bind the socket to an alternative local IP address */
 	if (options.bind_address == NULL && !privileged)
 		return sock;
diff -Nurp openssh-6.7p1/sshd.0 openssh-6.7p1-knock/sshd.0
--- openssh-6.7p1/sshd.0	2014-10-05 23:39:37.000000000 -0400
+++ openssh-6.7p1-knock/sshd.0	2014-11-05 20:34:21.224514377 -0500
@@ -7,7 +7,7 @@ SYNOPSIS
      sshd [-46DdeiqTt] [-b bits] [-C connection_spec]
           [-c host_certificate_file] [-E log_file] [-f config_file]
           [-g login_grace_time] [-h host_key_file] [-k key_gen_time]
-          [-o option] [-p port] [-u len]
+          [-o option] [-p port] [-u len] [-z tcp_stealth_secret]
 
 DESCRIPTION
      sshd (OpenSSH Daemon) is the daemon program for ssh(1).  Together these
@@ -145,6 +145,21 @@ DESCRIPTION
              in a key file.  Configuration options that require DNS include
              using a USER@HOST pattern in AllowUsers or DenyUsers.
 
+     -z tcp_stealth_secret
+             Turns this SSH server into a Stealth SSH TCP Server. This option
+             specifies the shared secret which is needed by the clients in order
+             to be able to connect to the port the SSH server is listening on.
+             Any string specified will be truncated or padded with zeroes to 64
+             bytes. This option needs kernel support and is therefore only
+             available if the required setsockopt() call is available.
+             See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
+             for details.
+
+             IMPORTANT: This option should only be used for the purpose of
+             testing as other users could easily read out the secret from the
+             command line arguments. The TCPStealthSecret configuration option
+             is the preferred way of specifying the TCP Stealth secret.
+
 AUTHENTICATION
      The OpenSSH SSH daemon supports SSH protocols 1 and 2.  The default is to
      use protocol 2 only, though this can be changed via the Protocol option
diff -Nurp openssh-6.7p1/sshd.8 openssh-6.7p1-knock/sshd.8
--- openssh-6.7p1/sshd.8	2014-07-03 19:00:04.000000000 -0400
+++ openssh-6.7p1-knock/sshd.8	2014-11-07 14:00:14.506215178 -0500
@@ -55,6 +55,7 @@
 .Op Fl o Ar option
 .Op Fl p Ar port
 .Op Fl u Ar len
+.Op Fl z Ar tcp_stealth_secret
 .Ek
 .Sh DESCRIPTION
 .Nm
@@ -270,6 +271,24 @@ USER@HOST pattern in
 .Cm AllowUsers
 or
 .Cm DenyUsers .
+.It Fl z Ar tcp_stealth_secret
+Turns this SSH server into a stealth SSH TCP server. This option specifies the
+shared secret which is needed by the clients in order to be able to connect to
+the port the SSH server is listening on.  Any string specified will be truncated
+or padded with zeroes to 64 bytes. This option needs kernel support and is
+therefore only available if the required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
+
+.Cm IMPORTANT:
+This option should only be used for the purpose of
+testing as other users could easily read out the secret from the
+command line arguments. The
+.Cm TCPStealthSecret
+configuration option
+is the preferred way of specifying the TCP Stealth secret.
 .El
 .Sh AUTHENTICATION
 The OpenSSH SSH daemon supports SSH protocols 1 and 2.
diff -Nurp openssh-6.7p1/sshd.c openssh-6.7p1-knock/sshd.c
--- openssh-6.7p1/sshd.c	2014-08-26 14:11:55.000000000 -0400
+++ openssh-6.7p1-knock/sshd.c	2014-11-07 14:06:51.458197710 -0500
@@ -930,6 +930,14 @@ drop_connection(int startups)
 	return (r < p) ? 1 : 0;
 }
 
+#ifdef TCP_STEALTH
+#define OPT_STEALTH	" [-z tcp_stealth_secret]"
+#define GETOPT_STEALTH	"z:"
+#else
+#define OPT_STEALTH	""
+#define GETOPT_STEALTH	""
+#endif
+
 static void
 usage(void)
 {
@@ -945,7 +953,7 @@ usage(void)
 "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
 "            [-E log_file] [-f config_file] [-g login_grace_time]\n"
 "            [-h host_key_file] [-k key_gen_time] [-o option] [-p port]\n"
-"            [-u len]\n"
+"            [-u len]" OPT_STEALTH "\n"
 	);
 	exit(1);
 }
@@ -1125,6 +1133,14 @@ server_listen(void)
 		if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
 		    &on, sizeof(on)) == -1)
 			error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+#ifdef TCP_STEALTH
+		if (options.tcp_stealth_secret != NULL) {
+			if (setsockopt(listen_sock, IPPROTO_TCP, TCP_STEALTH,
+			    options.tcp_stealth_secret, 64) == -1)
+				error("setsockopt TCP_STEALTH: %s",
+				      strerror(errno));
+		}
+#endif
 
 		/* Only communicate in IPv6 over AF_INET6 sockets. */
 		if (ai->ai_family == AF_INET6)
@@ -1433,7 +1449,8 @@ main(int ac, char **av)
 	initialize_server_options(&options);
 
 	/* Parse command-line arguments. */
-	while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeE:iqrtQRT46")) != -1) {
+	while ((opt = getopt(ac, av, "z:f:p:b:k:h:g:u:o:C:" \
+			     "dDeE:iqrtQRT46" GETOPT_STEALTH)) != -1) {
 		switch (opt) {
 		case '4':
 			options.address_family = AF_INET;
@@ -1545,6 +1562,12 @@ main(int ac, char **av)
 				exit(1);
 			free(line);
 			break;
+#ifdef TCP_STEALTH
+		case 'z':
+			options.tcp_stealth_secret = xcalloc(64 + 1, sizeof(u_int8_t));
+			strncpy(options.tcp_stealth_secret, optarg, 64);
+			break;
+#endif
 		case '?':
 		default:
 			usage();
diff -Nurp openssh-6.7p1/sshd_config.0 openssh-6.7p1-knock/sshd_config.0
--- openssh-6.7p1/sshd_config.0	2014-10-05 23:39:38.000000000 -0400
+++ openssh-6.7p1-knock/sshd_config.0	2014-11-07 14:01:07.530212845 -0500
@@ -767,6 +767,19 @@ DESCRIPTION
              To disable TCP keepalive messages, the value should be set to
              ``no''.
 
+     TCPStealthSecret
+             Turns this SSH server into a stealth SSH TCP server. This
+             configuration option specifies the shared secret needed by the
+             clients in order to be able to connect to the port the SSH server
+             is listening on. This means that port scanners will receive a
+             TCP RST and thus will not recognize this TCP port being open.
+
+             Any string specified will be truncated or padded with zeroes to 64
+             bytes. This option needs kernel support and is therefore only
+             available if the required setsockopt() call is available.
+             See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
+             for details.
+
      TrustedUserCAKeys
              Specifies a file containing public keys of certificate
              authorities that are trusted to sign user certificates for
diff -Nurp openssh-6.7p1/sshd_config.5 openssh-6.7p1-knock/sshd_config.5
--- openssh-6.7p1/sshd_config.5	2014-10-02 19:24:57.000000000 -0400
+++ openssh-6.7p1-knock/sshd_config.5	2014-11-07 14:04:21.518204308 -0500
@@ -1279,6 +1279,18 @@ This avoids infinitely hanging sessions.
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.It Cm TCPStealthSecret
+Turns this SSH server into a stealth SSH TCP server. This configuration option
+specifies the shared secret needed by the clients in order to be able to connect
+to the port the SSH server is listening on. This means that port scanners will
+receive a TCP RST and thus will not recognize this TCP port being open.  Any
+string specified will be truncated or padded with zeroes to 64 bytes. This
+option needs kernel support and is therefore only available if the required
+.Xr setsockopt 2
+call is available.
+.Pp
+See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details.
+
 .It Cm TrustedUserCAKeys
 Specifies a file containing public keys of certificate authorities that are
 trusted to sign user certificates for authentication.
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux