diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # ChangeLog
 
+## 3.4.7
+
+* Expose `attachConn` to use post-handshake TLS connection.
+  [#1007](https://github.com/yesodweb/wai/pull/1007)
+
 ## 3.4.6
 
 * Preparing for tls v2.1
diff --git a/Network/Wai/Handler/WarpTLS.hs b/Network/Wai/Handler/WarpTLS.hs
--- a/Network/Wai/Handler/WarpTLS.hs
+++ b/Network/Wai/Handler/WarpTLS.hs
@@ -50,6 +50,9 @@
 
     -- * Exception
     WarpTLSException (..),
+
+    -- * Low-level
+    attachConn
 ) where
 
 import Control.Applicative ((<|>))
@@ -357,14 +360,9 @@
         ctx <- TLS.contextNew (backend recvN) params
         TLS.contextHookSetLogging ctx tlsLogging
         TLS.handshake ctx
-        h2 <- (== Just "h2") <$> TLS.getNegotiatedProtocol ctx
-        isH2 <- I.newIORef h2
-        writeBuffer <- createWriteBuffer 16384
-        writeBufferRef <- I.newIORef writeBuffer
-        -- Creating a cache for leftover input data.
-        tls <- getTLSinfo ctx
         mysa <- getSocketName s
-        return (conn ctx writeBufferRef isH2 mysa, tls)
+        attachConn mysa ctx
+    wrappedRecvN recvN n = handleAny (const mempty) $ recvN n
     backend recvN =
         TLS.Backend
             { TLS.backendFlush = return ()
@@ -386,7 +384,20 @@
             )
             throwIO
             $ sendAll sock bs
-    conn ctx writeBufferRef isH2 mysa =
+
+-- | Get "Connection" and "Transport" for a TLS connection that is already did the handshake.
+-- @since 3.4.7
+attachConn :: SockAddr -> TLS.Context -> IO (Connection, Transport)
+attachConn mysa ctx = do
+    h2 <- (== Just "h2") <$> TLS.getNegotiatedProtocol ctx
+    isH2 <- I.newIORef h2
+    writeBuffer <- createWriteBuffer 16384
+    writeBufferRef <- I.newIORef writeBuffer
+    -- Creating a cache for leftover input data.
+    tls <- getTLSinfo ctx
+    return (conn writeBufferRef isH2, tls)
+  where
+    conn writeBufferRef isH2 =
         Connection
             { connSendMany = TLS.sendData ctx . L.fromChunks
             , connSendAll = sendall
@@ -433,10 +444,6 @@
                 (\e -> guard (e == ConnectionClosedByPeer) >> return e)
                 (const (return ()))
                 (TLS.bye ctx)
-
-    wrappedRecvN recvN n = handleAny handler $ recvN n
-    handler :: SomeException -> IO S.ByteString
-    handler _ = return ""
 
 getTLSinfo :: TLS.Context -> IO Transport
 getTLSinfo ctx = do
diff --git a/warp-tls.cabal b/warp-tls.cabal
--- a/warp-tls.cabal
+++ b/warp-tls.cabal
@@ -1,5 +1,5 @@
 Name:                warp-tls
-Version:             3.4.6
+Version:             3.4.7
 Synopsis:            HTTP over TLS support for Warp via the TLS package
 License:             MIT
 License-file:        LICENSE
