diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+0.1.1.10
+--------
+* Add TCP Fast Open capability. It can be turned on by adding a 
+  `"fast_open":true` in `config.json` or specifying a `--fast-open` flag in
+  the command line argument.
+
 0.1.1.0
 -------
 * Use TCP_NOTSENT_LOWAT option to reduce latency
diff --git a/config.json b/config.json
--- a/config.json
+++ b/config.json
@@ -4,6 +4,7 @@
   "local":"localhost",
   "localPort":1090,
   "password":"birthday!",
+  "fast_open":true,
   "method":"aes-256-cfb"
 }
 
diff --git a/moesocks.cabal b/moesocks.cabal
--- a/moesocks.cabal
+++ b/moesocks.cabal
@@ -1,6 +1,6 @@
 name:               moesocks
 category:           Network
-version:            0.1.1.0
+version:            0.1.1.10
 license:            Apache-2.0
 synopsis:           A functional firewall killer
 description:        A socks5 proxy using the client / server architecture.
@@ -58,10 +58,11 @@
                       Network.MoeSocks.Common
                       Network.MoeSocks.Config
                       Network.MoeSocks.Constant
+                      Network.MoeSocks.Encrypt
                       Network.MoeSocks.Helper
+                      Network.MoeSocks.Internal.Socket
                       Network.MoeSocks.Options
                       Network.MoeSocks.TCP
                       Network.MoeSocks.Type
                       Network.MoeSocks.UDP
-                      Network.MoeSocks.Encrypt
 
diff --git a/src/Network/MoeSocks/App.hs b/src/Network/MoeSocks/App.hs
--- a/src/Network/MoeSocks/App.hs
+++ b/src/Network/MoeSocks/App.hs
@@ -56,6 +56,7 @@
               , ("server_port", "remotePort")
               , ("local_address", "local")
               , ("local_port", "localPort")
+              , ("fast_open", "fastOpen")
               ]
 
         in
@@ -201,6 +202,8 @@
           case aAppType of
             TCP_App -> do
               info_ - "LT: " <> aID <> " nyaa!"
+
+              setSocket_TCP_FAST_OPEN _localSocket
               listen _localSocket maxListenQueue
 
               let handleLocal _socket = do
@@ -271,6 +274,8 @@
           setSocketOption _remoteSocket ReuseAddr 1
           bindSocket _remoteSocket _remoteAddr
 
+          setSocket_TCP_FAST_OPEN _remoteSocket
+          
           listen _remoteSocket maxListenQueue
 
           let handleRemote _socket = do
diff --git a/src/Network/MoeSocks/Config.hs b/src/Network/MoeSocks/Config.hs
--- a/src/Network/MoeSocks/Config.hs
+++ b/src/Network/MoeSocks/Config.hs
@@ -19,6 +19,7 @@
   , _throttle = False
   , _throttleSpeed = 8000 -- in Kilobytes
   , _obfuscationFlushBound = 4096
+  , _fastOpen = False
   }
 
 
diff --git a/src/Network/MoeSocks/Encrypt.hs b/src/Network/MoeSocks/Encrypt.hs
--- a/src/Network/MoeSocks/Encrypt.hs
+++ b/src/Network/MoeSocks/Encrypt.hs
@@ -128,7 +128,9 @@
               _encrypt = \case
                   S.Nothing -> E.cipherFinalBS _ctx
                   S.Just _bytes -> do
-                    E.cipherUpdateBS _ctx _bytes
+                    if (_bytes & isn't _Empty)
+                      then E.cipherUpdateBS _ctx _bytes
+                      else pure mempty
 
           pure _encrypt
 
@@ -140,7 +142,9 @@
               _decrypt = \case
                   S.Nothing -> E.cipherFinalBS _ctx
                   S.Just _bytes -> do
-                    E.cipherUpdateBS _ctx _bytes 
+                    if (_bytes & isn't _Empty)
+                      then E.cipherUpdateBS _ctx _bytes 
+                      else pure mempty
           
           pure _decrypt
           
diff --git a/src/Network/MoeSocks/Helper.hs b/src/Network/MoeSocks/Helper.hs
--- a/src/Network/MoeSocks/Helper.hs
+++ b/src/Network/MoeSocks/Helper.hs
@@ -20,6 +20,7 @@
 import Data.Text (Text)
 import Data.Text.Lens
 import Data.Time.Clock
+import Network.MoeSocks.Internal.Socket (sendAllFastOpenTo)
 import Network.Socket hiding (send, recv)
 import Network.Socket.ByteString
 import Prelude hiding (take, (-)) 
@@ -258,6 +259,11 @@
 send_ :: Socket -> ByteString -> IO ()
 send_ = sendAll
 
+
+sendFast_ :: Socket -> ByteString -> SockAddr -> IO ()
+sendFast_ = sendAllFastOpenTo
+
+
 sendAllRandom :: Int -> Socket -> ByteString -> IO ()
 sendAllRandom aFlushBound aSocket aBuffer = do
   _loop aBuffer
@@ -421,6 +427,13 @@
   _consume 0 `onException` _shutdown
   pure ()
 
+
+setSocket_TCP_FAST_OPEN:: Socket -> IO ()
+setSocket_TCP_FAST_OPEN aSocket = 
+  let _TCP_FASTOPEN = 23
+      _TCP_Option = 6
+  in
+  setSocketOption aSocket (CustomSockOpt (_TCP_Option, _TCP_FASTOPEN)) 1 
 
 setSocket_TCP_NOTSENT_LOWAT :: Socket -> IO ()
 setSocket_TCP_NOTSENT_LOWAT aSocket = 
diff --git a/src/Network/MoeSocks/Internal/Socket.hs b/src/Network/MoeSocks/Internal/Socket.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/MoeSocks/Internal/Socket.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Network.MoeSocks.Internal.Socket where
+
+import Control.Monad
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
+import Foreign.C.Types
+import Foreign.Ptr (Ptr)
+import Network.Socket
+import Network.Socket.ByteString
+import Network.Socket.Internal (withSockAddr)
+import qualified Data.ByteString as S
+
+foreign import ccall unsafe "sendto" c_sendto ::
+  CInt -> Ptr a -> CSize -> CInt -> Ptr SockAddr -> CInt -> IO CInt
+
+-- | Send data to the socket.  The recipient can be specified
+-- explicitly, so the socket need not be in a connected state.
+-- Returns the number of bytes sent.  Applications are responsible for
+-- ensuring that all data has been sent.
+sendBufToWithFlag :: Socket            -- (possibly) bound/connected Socket
+          -> Ptr a -> Int  -- Data to send
+          -> SockAddr
+          -> Int
+          -> IO Int            -- Number of Bytes sent
+sendBufToWithFlag 
+  (MkSocket s _family _stype _protocol _status) ptr nbytes addr flags = do
+   withSockAddr addr $ \p_addr sz -> do
+    liftM fromIntegral $
+        c_sendto s ptr (fromIntegral $ nbytes) (fromIntegral flags)
+                          p_addr (fromIntegral sz)
+
+sendToWithFlag :: Socket      -- ^ Socket
+       -> ByteString  -- ^ Data to send
+       -> SockAddr    -- ^ Recipient address
+       -> Int
+       -> IO Int      -- ^ Number of bytes sent
+sendToWithFlag sock xs addr flags =
+    unsafeUseAsCStringLen xs $ \(str, len) -> 
+      sendBufToWithFlag sock str len addr flags
+
+sendAllFastOpenTo :: Socket      -- ^ Socket
+          -> ByteString  -- ^ Data to send
+          -> SockAddr    -- ^ Recipient address
+          -> IO ()
+sendAllFastOpenTo sock xs addr = do
+    let _MSG_FASTOPEN  = 0x20000000  
+    sent <- sendToWithFlag sock xs addr _MSG_FASTOPEN
+    when (sent < S.length xs) $ sendAllTo sock (S.drop sent xs) addr
diff --git a/src/Network/MoeSocks/Options.hs b/src/Network/MoeSocks/Options.hs
--- a/src/Network/MoeSocks/Options.hs
+++ b/src/Network/MoeSocks/Options.hs
@@ -31,6 +31,13 @@
 intParam :: O.Mod O.OptionFields Int -> O.Parser (Maybe Value)
 intParam = optional . fmap toJSON . option auto
 
+bool_To_Maybe :: Bool -> Maybe Bool
+bool_To_Maybe False = Nothing
+bool_To_Maybe True = Just True
+
+boolParam :: O.Mod O.FlagFields Bool -> O.Parser (Maybe Value)
+boolParam = (fmap . fmap) toJSON . fmap bool_To_Maybe . switch
+
 optionParser :: O.Parser MoeOptions
 optionParser = 
   let _c = defaultMoeConfig
@@ -118,6 +125,10 @@
                                         & view (from _Text))
                                     "timeout connection in seconds"
                         
+      _fastOpen = boolParam -
+                        long "fast-open"
+                    <>  help ("use TCP_FASTOPEN, requires Linux 3.7+")
+      
       _obfuscation :: O.Parser Bool 
       _obfuscation = switch -
                           short 'o'
@@ -127,6 +138,7 @@
                                <> "shadowsocks protocol, at the cost of "
                                <> "about 10-20% performance degradation.")
 
+
       _verbosity :: O.Parser Priority 
       _verbosity = flag INFO DEBUG -
                           short 'v'
@@ -226,6 +238,7 @@
         , tag "_method"         _method 
         , tag "_timeout"        _timeout
         , tag "_tcpBufferSize"  _tcpBufferSize
+        , tag "_fastOpen"       _fastOpen
         ]
         & sequenceA
         & fmap catMaybes
diff --git a/src/Network/MoeSocks/TCP.hs b/src/Network/MoeSocks/TCP.hs
--- a/src/Network/MoeSocks/TCP.hs
+++ b/src/Network/MoeSocks/TCP.hs
@@ -17,6 +17,7 @@
 import Network.Socket hiding (send, recv, recvFrom, sendTo)
 import Network.Socket.ByteString (recv)
 import Prelude hiding ((-), take)
+import qualified Data.ByteString as S
 import qualified Data.Strict as S
 
 local_Socks5_RequestHandler :: Env
@@ -88,7 +89,7 @@
     
     logSA "L remote socket" _initSocket - 
       \(_remoteSocket, _remoteAddress) -> do
-      connect _remoteSocket _remoteAddress
+      {-connect _remoteSocket _remoteAddress-}
       setSocketSendFast _remoteSocket
 
       _localPeerAddr <- getPeerName aSocket
@@ -120,14 +121,23 @@
                     then Just - _c ^. throttleSpeed
                     else Nothing
 
-            let sendThread = do
-                  sendBytes _sendChannel _encodeIV
-                  sendBuilderEncrypt _sendChannel _encrypt _header
+            _eHeader <- _encrypt - S.Just - builder_To_ByteString _header
+            _ePartial <- _encrypt - S.Just _partialBytesAfterClientRequest 
+            let _padding = S.length (_eHeader <> _ePartial)
 
-                  when (_partialBytesAfterClientRequest & isn't _Empty) -
-                    sendBytesEncrypt _sendChannel _encrypt 
-                      _partialBytesAfterClientRequest
+            _eInit <- _encrypt . S.Just =<< recv aSocket (4096 + (-_padding))
 
+            let _initBytes = _encodeIV <> _eHeader <> _ePartial <> _eInit
+
+            if _c ^. fastOpen
+              then
+                sendFast_ _remoteSocket _initBytes _remoteAddress
+              else do
+                connect _remoteSocket _remoteAddress
+                send_ _remoteSocket _initBytes
+
+            let sendThread = do
+
                   let _produce = do
                                     produceLoop (info_Id "L --> + Loop")
                                       _timeout
@@ -151,6 +161,7 @@
                     ) -
                     pure ()
 
+            
             let receiveThread = do
                   _decodeIV <- recv _remoteSocket (_cipherBox ^. ivLength)
                   _decrypt <- _cipherBox ^. decryptBuilder - _decodeIV
diff --git a/src/Network/MoeSocks/Type.hs b/src/Network/MoeSocks/Type.hs
--- a/src/Network/MoeSocks/Type.hs
+++ b/src/Network/MoeSocks/Type.hs
@@ -61,6 +61,7 @@
   , _throttle :: Bool
   , _throttleSpeed :: Double
   , _obfuscationFlushBound :: Int -- should be greater then MTU
+  , _fastOpen :: Bool
   }
   deriving (Show, Eq, Generic)
 
