diff --git a/configure b/configure
index e10f5134b9..44eb1d4865 100755
--- a/configure
+++ b/configure
@@ -1031,6 +1031,7 @@ enable_backtrace
 enable_symtable
 enable_ipv6
 with_kame
+enable_tcp_fastopen
 enable_getifaddrs
 with_readline
 enable_isc_spnego
@@ -1714,6 +1715,7 @@ Optional Features:
   --enable-symtable       use internal symbol table for backtrace
 			  [all|minimal(default)|none]
   --enable-ipv6           use IPv6 default=autodetect
+  --disable-tcp-fastopen  disable TCP Fast Open support [default=autodetect]
   --enable-getifaddrs     enable the use of getifaddrs() [yes|no].
   --disable-isc-spnego    use SPNEGO from GSSAPI library
   --disable-chroot        disable chroot
@@ -18565,11 +18567,22 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
 #
-# Look for TCP_FASTOPEN
+# Allow forcibly disabling TCP Fast Open support as autodetection might yield
+# confusing results on some systems (e.g. FreeBSD; see set_tcp_fastopen()
+# comment in lib/isc/unix/socket.c).
 #
+
+# Check whether --enable-tcp_fastopen was given.
+if test "${enable_tcp_fastopen+set}" = set; then :
+  enableval=$enable_tcp_fastopen;
+fi
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TCP_FASTOPEN socket option" >&5
 $as_echo_n "checking for TCP_FASTOPEN socket option... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+case "$enable_tcp_fastopen" in
+yes|''|autodetect)
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 #include <sys/types.h>
@@ -18584,15 +18597,23 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   $EGREP "has_tfo" >/dev/null 2>&1; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	ISC_PLATFORM_HAVETFO="#define ISC_PLATFORM_HAVETFO 1"
+		ISC_PLATFORM_HAVETFO="#define ISC_PLATFORM_HAVETFO 1"
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	ISC_PLATFORM_HAVETFO="#undef ISC_PLATFORM_HAVETFO"
+		ISC_PLATFORM_HAVETFO="#undef ISC_PLATFORM_HAVETFO"
 fi
 rm -f conftest*
 
 
+		;;
+	no)
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+		ISC_PLATFORM_HAVETFO="#undef ISC_PLATFORM_HAVETFO"
+		;;
+esac
+
 
 #
 # Check for addrinfo
diff --git a/configure.in b/configure.in
index 7886208d6f..cb8061041b 100644
--- a/configure.in
+++ b/configure.in
@@ -3204,10 +3204,18 @@ AC_TRY_COMPILE([
 AC_SUBST(ISC_PLATFORM_NEEDPORTT)
 
 #
-# Look for TCP_FASTOPEN
+# Allow forcibly disabling TCP Fast Open support as autodetection might yield
+# confusing results on some systems (e.g. FreeBSD; see set_tcp_fastopen()
+# comment in lib/isc/unix/socket.c).
 #
+
+AC_ARG_ENABLE(tcp_fastopen,
+	[  --disable-tcp-fastopen  disable TCP Fast Open support [[default=autodetect]]])
+
 AC_MSG_CHECKING(for TCP_FASTOPEN socket option)
-AC_EGREP_CPP(has_tfo, [
+case "$enable_tcp_fastopen" in
+yes|''|autodetect)
+	AC_EGREP_CPP(has_tfo, [
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/tcp.h>
@@ -3215,10 +3223,17 @@ AC_EGREP_CPP(has_tfo, [
 int has_tfo() { return (0); }
 #endif
 ],
-	[AC_MSG_RESULT(yes)
-	ISC_PLATFORM_HAVETFO="#define ISC_PLATFORM_HAVETFO 1"],
-	[AC_MSG_RESULT(no)
-	ISC_PLATFORM_HAVETFO="#undef ISC_PLATFORM_HAVETFO"])
+		[AC_MSG_RESULT(yes)
+		ISC_PLATFORM_HAVETFO="#define ISC_PLATFORM_HAVETFO 1"],
+		[AC_MSG_RESULT(no)
+		ISC_PLATFORM_HAVETFO="#undef ISC_PLATFORM_HAVETFO"])
+
+		;;
+	no)
+		AC_MSG_RESULT(disabled)
+		ISC_PLATFORM_HAVETFO="#undef ISC_PLATFORM_HAVETFO"
+		;;
+esac
 AC_SUBST(ISC_PLATFORM_HAVETFO)
 
 #
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index d820a6df01..25b2464a22 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -14,6 +14,9 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
 #include <sys/time.h>
 #include <sys/uio.h>
 
@@ -5645,6 +5648,69 @@ isc__socket_filter(isc_socket_t *sock0, const char *filter) {
 #endif
 }
 
+/*
+ * Try enabling TCP Fast Open for a given socket if the OS supports it.
+ */
+static void
+set_tcp_fastopen(isc__socket_t *sock, unsigned int backlog) {
+#if defined(ISC_PLATFORM_HAVETFO) && defined(TCP_FASTOPEN)
+	char strbuf[ISC_STRERRORSIZE];
+
+/*
+ * FreeBSD, as of versions 10.3 and 11.0, defines TCP_FASTOPEN while also
+ * shipping a default kernel without TFO support, so we special-case it by
+ * performing an additional runtime check for TFO support using sysctl to
+ * prevent setsockopt() errors from being logged.
+ */
+#if defined(__FreeBSD__) && defined(HAVE_SYSCTLBYNAME)
+#define SYSCTL_TFO "net.inet.tcp.fastopen.enabled"
+	unsigned int enabled;
+	size_t enabledlen = sizeof(enabled);
+	static isc_boolean_t tfo_notice_logged = ISC_FALSE;
+
+	if (sysctlbyname(SYSCTL_TFO, &enabled, &enabledlen, NULL, 0) < 0) {
+		/*
+		 * This kernel does not support TCP Fast Open.  There is
+		 * nothing more we can do.
+		 */
+		return;
+	} else if (enabled == 0) {
+		/*
+		 * This kernel does support TCP Fast Open, but it is disabled
+		 * by sysctl.  Notify the user, but do not nag.
+		 */
+		if (!tfo_notice_logged) {
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_NOTICE,
+				      "TCP_FASTOPEN support is disabled by "
+				      "sysctl (" SYSCTL_TFO " = 0)");
+			tfo_notice_logged = ISC_TRUE;
+		}
+		return;
+	}
+#endif
+
+#ifdef __APPLE__
+	backlog = 1;
+#else
+	backlog = backlog / 2;
+	if (backlog == 0)
+		backlog = 1;
+#endif
+	if (setsockopt(sock->fd, IPPROTO_TCP, TCP_FASTOPEN,
+		       (void *)&backlog, sizeof(backlog)) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "setsockopt(%d, TCP_FASTOPEN) failed with %s",
+				 sock->fd, strbuf);
+		/* TCP_FASTOPEN is experimental so ignore failures */
+	}
+#else
+	UNUSED(sock);
+	UNUSED(backlog);
+#endif
+}
+
 /*
  * Set up to listen on a given socket.  We do this by creating an internal
  * event that will be dispatched when the socket has read activity.  The
@@ -5681,23 +5747,7 @@ isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) {
 		return (ISC_R_UNEXPECTED);
 	}
 
-#if defined(ISC_PLATFORM_HAVETFO) && defined(TCP_FASTOPEN)
-#ifdef __APPLE__
-	backlog = 1;
-#else
-	backlog = backlog / 2;
-	if (backlog == 0)
-		backlog = 1;
-#endif
-	if (setsockopt(sock->fd, IPPROTO_TCP, TCP_FASTOPEN,
-		       (void *)&backlog, sizeof(backlog)) < 0) {
-		isc__strerror(errno, strbuf, sizeof(strbuf));
-		UNEXPECTED_ERROR(__FILE__, __LINE__,
-				 "setsockopt(%d, TCP_FASTOPEN) failed with %s",
-				 sock->fd, strbuf);
-		/* TCP_FASTOPEN is experimental so ignore failures */
-	}
-#endif
+	set_tcp_fastopen(sock, backlog);
 
 	sock->listener = 1;
 
