diff -Nur openssh-6.9p1/readconf.c openssh-6.9p1-knock/readconf.c
--- openssh-6.9p1/readconf.c	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/readconf.c	2015-07-15 14:16:47.607707232 -0300
@@ -156,6 +156,9 @@
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
+#ifdef TCP_STEALTH
+	oTCPStealthSecret,
+#endif
 	oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
 	oIgnoredUnknownOption, oDeprecated, oUnsupported
 } OpCodes;
@@ -276,6 +279,9 @@
 	{ "updatehostkeys", oUpdateHostkeys },
 	{ "hostbasedkeytypes", oHostbasedKeyTypes },
 	{ "ignoreunknown", oIgnoreUnknown },
+#ifdef TCP_STEALTH
+	{ "tcpstealthsecret", oTCPStealthSecret },
+#endif
 
 	{ NULL, oBadOption }
 };
@@ -1496,6 +1502,23 @@
 			*charptr = xstrdup(arg);
 		break;
 
+#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);
@@ -1672,6 +1695,9 @@
 	options->canonicalize_max_dots = -1;
 	options->canonicalize_fallback_local = -1;
 	options->canonicalize_hostname = -1;
+#ifdef TCP_STEALTH
+	options->tcp_stealth_secret = NULL;
+#endif
 	options->revoked_host_keys = NULL;
 	options->fingerprint_hash = -1;
 	options->update_hostkeys = -1;
diff -Nur openssh-6.9p1/readconf.h openssh-6.9p1-knock/readconf.h
--- openssh-6.9p1/readconf.h	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/readconf.h	2015-07-15 14:04:58.425806327 -0300
@@ -153,6 +153,9 @@
 	char	*hostbased_key_types;
 
 	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 -Nur openssh-6.9p1/servconf.c openssh-6.9p1-knock/servconf.c
--- openssh-6.9p1/servconf.c	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/servconf.c	2015-07-15 14:25:04.166739038 -0300
@@ -166,6 +166,9 @@
 	options->ip_qos_interactive = -1;
 	options->ip_qos_bulk = -1;
 	options->version_addendum = NULL;
+#ifdef TCP_STEALTH
+	options->tcp_stealth_secret = NULL;
+#endif
 	options->fingerprint_hash = -1;
 }
 
@@ -412,6 +415,9 @@
 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
 	sAllowStreamLocalForwarding, sFingerprintHash,
+#ifdef TCP_STEALTH
+	sTCPStealthSecret,
+#endif
 	sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -548,6 +554,9 @@
 	{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
 	{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
 	{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
+#ifdef TCP_STEALTH
+	{ "tcpstealthsecret", sTCPStealthSecret },
+#endif
 	{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
 	{ NULL, sBadOption, 0 }
 };
@@ -1826,6 +1835,24 @@
 			options->fingerprint_hash = value;
 		break;
 
+#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 -Nur openssh-6.9p1/servconf.h openssh-6.9p1-knock/servconf.h
--- openssh-6.9p1/servconf.h	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/servconf.h	2015-07-15 14:18:38.255623536 -0300
@@ -193,6 +193,9 @@
 	u_int	num_auth_methods;
 	char   *auth_methods[MAX_AUTH_METHODS];
 
+#ifdef TCP_STEALTH
+	char    *tcp_stealth_secret;
+#endif
 	int	fingerprint_hash;
 }       ServerOptions;
 
@@ -215,6 +218,12 @@
  * 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); \
@@ -233,6 +242,7 @@
 		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 -Nur openssh-6.9p1/ssh.0 openssh-6.9p1-knock/ssh.0
--- openssh-6.9p1/ssh.0	2015-06-30 23:41:10.000000000 -0300
+++ openssh-6.9p1-knock/ssh.0	2015-07-15 14:04:58.429139496 -0300
@@ -408,6 +408,20 @@
      -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 -Nur openssh-6.9p1/ssh.1 openssh-6.9p1-knock/ssh.1
--- openssh-6.9p1/ssh.1	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/ssh.1	2015-07-15 14:04:58.429139496 -0300
@@ -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
@@ -483,6 +484,7 @@
 .It StreamLocalBindUnlink
 .It StrictHostKeyChecking
 .It TCPKeepAlive
+.It TCPStealthSecret
 .It Tunnel
 .It TunnelDevice
 .It UpdateHostKeys
@@ -681,6 +683,21 @@
 .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 -Nur openssh-6.9p1/ssh.c openssh-6.9p1-knock/ssh.c
--- openssh-6.9p1/ssh.c	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/ssh.c	2015-07-15 14:07:18.282271552 -0300
@@ -194,6 +194,14 @@
 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
@@ -207,7 +215,7 @@
 "           [-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);
 }
@@ -595,7 +603,7 @@
 
  again:
 	while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
-	    "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
+	    "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy" GETOPT_STEALTH)) != -1) {
 		switch (opt) {
 		case '1':
 			options.protocol = SSH_PROTO_1;
@@ -906,6 +914,12 @@
 		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 -Nur openssh-6.9p1/ssh_config.0 openssh-6.9p1-knock/ssh_config.0
--- openssh-6.9p1/ssh_config.0	2015-06-30 23:41:12.000000000 -0300
+++ openssh-6.9p1-knock/ssh_config.0	2015-07-15 14:04:58.432472666 -0300
@@ -859,6 +859,15 @@
              To disable TCP keepalive messages, the value should be set to
              M-bM-^@M-^\noM-bM-^@M-^].
 
+     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 M-bM-^@M-^\yesM-bM-^@M-^], M-bM-^@M-^\point-to-pointM-bM-^@M-^] (layer 3),
              M-bM-^@M-^\ethernetM-bM-^@M-^] (layer 2), or M-bM-^@M-^\noM-bM-^@M-^].  Specifying M-bM-^@M-^\yesM-bM-^@M-^] requests the
diff -Nur openssh-6.9p1/ssh_config.5 openssh-6.9p1-knock/ssh_config.5
--- openssh-6.9p1/ssh_config.5	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/ssh_config.5	2015-07-15 14:04:58.432472666 -0300
@@ -1469,6 +1469,15 @@
 .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 -Nur openssh-6.9p1/sshconnect.c openssh-6.9p1-knock/sshconnect.c
--- openssh-6.9p1/sshconnect.c	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/sshconnect.c	2015-07-15 14:04:58.432472666 -0300
@@ -282,6 +282,17 @@
 	}
 	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 -Nur openssh-6.9p1/sshd.0 openssh-6.9p1-knock/sshd.0
--- openssh-6.9p1/sshd.0	2015-06-30 23:41:11.000000000 -0300
+++ openssh-6.9p1-knock/sshd.0	2015-07-15 14:04:58.432472666 -0300
@@ -7,7 +7,7 @@
      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
@@ -144,6 +144,21 @@
              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 -Nur openssh-6.9p1/sshd.8 openssh-6.9p1-knock/sshd.8
--- openssh-6.9p1/sshd.8	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/sshd.8	2015-07-15 14:04:58.432472666 -0300
@@ -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 @@
 .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 -Nur openssh-6.9p1/sshd.c openssh-6.9p1-knock/sshd.c
--- openssh-6.9p1/sshd.c	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/sshd.c	2015-07-15 14:14:17.648384356 -0300
@@ -991,6 +991,14 @@
 	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)
 {
@@ -1006,7 +1014,7 @@
 "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);
 }
@@ -1184,6 +1192,14 @@
 		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)
@@ -1496,7 +1512,8 @@
 
 	/* Parse command-line arguments. */
 	while ((opt = getopt(ac, av,
-	    "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) {
+	    "z:C:E:b:c:f:g:h:k:o:p:u:" \
+	    "46DQRTdeiqrt" GETOPT_STEALTH)) != -1) {
 		switch (opt) {
 		case '4':
 			options.address_family = AF_INET;
@@ -1608,6 +1625,12 @@
 				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 -Nur openssh-6.9p1/sshd_config.0 openssh-6.9p1-knock/sshd_config.0
--- openssh-6.9p1/sshd_config.0	2015-06-30 23:41:12.000000000 -0300
+++ openssh-6.9p1-knock/sshd_config.0	2015-07-15 14:04:58.435805835 -0300
@@ -855,6 +855,19 @@
              To disable TCP keepalive messages, the value should be set to
              M-bM-^@M-^\noM-bM-^@M-^].
 
+     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 -Nur openssh-6.9p1/sshd_config.5 openssh-6.9p1-knock/sshd_config.5
--- openssh-6.9p1/sshd_config.5	2015-06-30 23:35:31.000000000 -0300
+++ openssh-6.9p1-knock/sshd_config.5	2015-07-15 14:04:58.435805835 -0300
@@ -1432,6 +1432,18 @@
 .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, or