packages feed

moesocks 0.1.0.19 → 0.1.0.20

raw patch · 10 files changed

+268/−252 lines, 10 files

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+0.1.0.20+--------+* Rewrite Encrypt module, cache password hash+ 0.1.0.19 -------- * Fix a memory leak
moesocks.cabal view
@@ -1,6 +1,6 @@ name:               moesocks category:           Network-version:            0.1.0.19+version:            0.1.0.20 license:            Apache-2.0 synopsis:           A functional firewall killer description:        A socks5 proxy using the client / server architecture.@@ -54,13 +54,13 @@   other-modules:                               Network.MoeSocks.App                       Network.MoeSocks.BuilderAndParser+                      Network.MoeSocks.Common                       Network.MoeSocks.Config                       Network.MoeSocks.Constant                       Network.MoeSocks.Helper-                      Network.MoeSocks.Internal.ShadowSocks.Encrypt                       Network.MoeSocks.Options-                      Network.MoeSocks.Type-                      Network.MoeSocks.Common                       Network.MoeSocks.TCP+                      Network.MoeSocks.Type                       Network.MoeSocks.UDP+                      Network.MoeSocks.Encrypt 
src/Network/MoeSocks/App.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}  module Network.MoeSocks.App where @@ -20,10 +21,9 @@ import Network.MoeSocks.TCP import Network.MoeSocks.Type import Network.MoeSocks.UDP+import Network.MoeSocks.Encrypt (initBuilder) import Network.Socket hiding (send, recv, recvFrom, sendTo) import Network.Socket.ByteString-import OpenSSL (withOpenSSL)-import OpenSSL.EVP.Cipher (getCipherByName) import Prelude hiding ((-), take) import System.Log.Formatter import System.Log.Handler.Simple@@ -176,15 +176,12 @@   _config <- parseConfig - _options   let _c = _config -  let _method = _config ^. method . _Text--  when (_method /= "none") - do-    _cipher <- io - withOpenSSL - getCipherByName _method+  let _method = _config ^. method -    case _cipher of-      Nothing -> throwError - "Invalid method '" -                              <> _method-      Just _ -> pure ()+  _cipherBox <- (io - initBuilder _method (_config ^. password)) >>= \case+    Nothing -> throwError - "Invalid method '" +                            <> _method ^. _Text+    Just (a, b, c, d) -> pure - CipherBox a b c d    let localAppBuilder :: AppType -> String ->                            (ByteString -> (Socket, SockAddr) -> IO ()) -> @@ -229,7 +226,7 @@    let localSocks5App :: (Socket, SockAddr) -> IO ()       localSocks5App = localAppBuilder TCP_App "socks5" - -                            local_Socks5_RequestHandler _config+                            local_Socks5_RequestHandler _cipherBox _config        showForwarding :: Forward -> String       showForwarding (Forward _localPort _remoteHost _remotePort) =@@ -246,14 +243,16 @@       forward_TCP_App _f _s = do         let _m = showForwarding _f         localAppBuilder TCP_App  ("TCP forwarding " <> _m)-                                (local_TCP_ForwardRequestHandler _config _f) +                                (local_TCP_ForwardRequestHandler _cipherBox +                                _config _f)                                  _s        forward_UDP_App :: Forward -> (Socket, SockAddr) -> IO ()       forward_UDP_App _f _s = do         let _m = showForwarding _f          localAppBuilder UDP_App  ("UDP forwarding " <> _m)-                                (local_UDP_ForwardRequestHandler _config _f) +                                (local_UDP_ForwardRequestHandler _cipherBox+                                _config _f)                                  _s          let remote_TCP_App :: (Socket, SockAddr) -> IO ()@@ -276,7 +275,7 @@                                  forkIO - catchExceptAsyncLog "R thread" -                              logSocket "R remote socket" (pure _newSocket) --                              remote_TCP_RequestHandler _config +                              remote_TCP_RequestHandler _cipherBox _config             forever - handleRemote _remoteSocket @@ -297,7 +296,7 @@                   forkIO - catchExceptAsyncLog "R thread" - -                            remote_UDP_RequestHandler _config _msg _s+                            remote_UDP_RequestHandler _cipherBox _config _msg _s                   
src/Network/MoeSocks/Common.hs view
@@ -4,24 +4,17 @@  import Control.Lens import Control.Monad.Writer hiding (listen)-import Data.ByteString (ByteString) import Data.Text (Text) import Data.Text.Lens-import Data.Text.Strict.Lens (utf8) import Network.MoeSocks.Helper-import Network.MoeSocks.Internal.ShadowSocks.Encrypt as E import Network.MoeSocks.Type import Network.Socket hiding (send, recv, recvFrom, sendTo) import Prelude hiding ((-), take) import qualified Data.List as L-import qualified Data.Strict as S+import qualified Network.MoeSocks.Encrypt as E -plainCipher :: (S.Maybe ByteString) -> IO ByteString+plainCipher :: Cipher plainCipher = E.plainCipher--getCipher :: Text -> Text -> IO (Cipher, Cipher)-getCipher aMethod aPassword =-  getEncDec aMethod (review utf8 aPassword)  showAddressType :: AddressType -> Text showAddressType (IPv4_address xs) = view (from _Text) - 
+ src/Network/MoeSocks/Encrypt.hs view
@@ -0,0 +1,140 @@+-- Heavily inspired by+-- https://github.com/rnons/shadowsocks-haskell/blob/86bd47d474df6800e1f3706b33ae9e8f80696d8f/Shadowsocks/Encrypt.hs+++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}++module Network.MoeSocks.Encrypt where++import Control.Lens+import Control.Monad.Except+import Crypto.Hash.MD5 (hash)+import Data.ByteString (ByteString)+import Data.Map+import Data.Monoid ((<>))+import Data.Text (Text)+import Data.Text.Lens+import Data.Text.Strict.Lens (utf8)+import OpenSSL (withOpenSSL)+import OpenSSL.EVP.Cipher (getCipherByName, CryptoMode(..))+import OpenSSL.Random (randBytes)+import Prelude hiding ((-))+import qualified Data.ByteString as S+import qualified Data.Strict as S+import qualified OpenSSL.EVP.Internal as E++-- BEGIN backports++infixr 0 -+(-) :: (a -> b) -> a -> b+(-) = ($)++-- END backports++type KeyLength = Int+type IV_Length = Int++type Cipher = S.Maybe ByteString -> IO ByteString +type CipherBuilder = ByteString -> IO Cipher+type CipherBox = (Int, IO ByteString, CipherBuilder, CipherBuilder)++type MaybeExceptT = ExceptT () IO++methods :: Map Text (KeyLength, IV_Length)+methods = fromList+    [ ("aes-128-cfb", (16, 16))+    , ("aes-192-cfb", (24, 16))+    , ("aes-256-cfb", (32, 16))+    , ("bf-cfb", (16, 8))+    , ("camellia-128-cfb", (16, 16))+    , ("camellia-192-cfb", (24, 16))+    , ("camellia-256-cfb", (32, 16))+    , ("cast5-cfb", (16, 8))+    , ("des-cfb", (8, 8))+    , ("idea-cfb", (16, 8))+    , ("rc2-cfb", (16, 8))+    , ("rc4", (16, 0))+    , ("seed-cfb", (16, 16))+    ]+++hashKey :: ByteString -> Int -> Int -> ByteString+hashKey aPassword aKeyLen a_IV_len = loop mempty mempty +  where+    _stopLength = aKeyLen + a_IV_len++    loop :: ByteString -> ByteString -> ByteString+    loop _lastHashedBytes _accumHashedBytes+      | S.length _accumHashedBytes >= _stopLength +        = S.take aKeyLen _accumHashedBytes+      | otherwise = let _new = hash - _lastHashedBytes <> aPassword+                    in+                    loop _new - _accumHashedBytes <> _new+++ssl :: IO a -> IO a+ssl = withOpenSSL++eitherToMaybe :: Either a b -> Maybe b+eitherToMaybe (Left _) = Nothing+eitherToMaybe (Right x) = Just x++getMaybe :: Maybe a -> MaybeExceptT a+getMaybe Nothing = throwError ()+getMaybe (Just x) = pure x++mio :: IO (Maybe a) -> MaybeExceptT a+mio = (>>= getMaybe) . io++io :: (MonadIO m) => IO a -> m a+io = liftIO++plainCipher :: Cipher+plainCipher = pure . S.fromMaybe mempty++initBuilder :: Text -> Text -> IO (Maybe CipherBox)+initBuilder aMethod aPassword +  | aMethod == "none" = let constCipher = const - pure plainCipher+                        in+                        pure - Just (0, pure mempty, constCipher, constCipher)++  | otherwise =+      fmap eitherToMaybe - runExceptT - initBuilder' aMethod aPassword++initBuilder' :: Text -> Text -> MaybeExceptT CipherBox+initBuilder' aMethod aPassword = do+  _method <- mio - ssl - getCipherByName - aMethod ^. _Text++  (_keyLength, _IV_Length) <- getMaybe - methods ^? ix aMethod++  let _hashed = hashKey (review utf8 aPassword) _keyLength _IV_Length+      _IV_Maker = io - ssl - randBytes _IV_Length++      _encryptBuilder :: ByteString -> IO Cipher+      _encryptBuilder _iv = do+          _ctx <- io - ssl - E.cipherInitBS _method _hashed _iv Encrypt++          let _encrypt :: Cipher+              _encrypt = \case+                  S.Nothing -> E.cipherFinalBS _ctx+                  S.Just _bytes -> do+                    ssl - E.cipherUpdateBS _ctx _bytes++          pure _encrypt++      _decryptBuilder :: ByteString -> IO Cipher+      _decryptBuilder _iv = do+          _ctx <- io - ssl - E.cipherInitBS _method _hashed _iv Decrypt++          let _decrypt :: Cipher+              _decrypt = \case+                  S.Nothing -> E.cipherFinalBS _ctx+                  S.Just _bytes -> do+                    ssl - E.cipherUpdateBS _ctx _bytes +          +          pure _decrypt+          ++  pure - (_IV_Length, _IV_Maker, _encryptBuilder, _decryptBuilder)+
src/Network/MoeSocks/Helper.hs view
@@ -254,16 +254,19 @@ send_ :: Socket -> ByteString -> IO () send_ = sendAll ++sendBytes :: HQueue -> ByteString -> IO ()+sendBytes _queue = atomically . writeTBQueue _queue . S.Just++sendBytesEncrypt :: HQueue -> HCipher -> ByteString -> IO ()+sendBytesEncrypt _queue _cipher x = sendBytes _queue =<< _cipher (S.Just x)+ sendBuilder :: HQueue -> B.Builder -> IO ()-sendBuilder _queue = -  atomically . writeTBQueue _queue . S.Just . builder_To_ByteString+sendBuilder _queue = sendBytes _queue . builder_To_ByteString -sendBuilderEncrypted ::  HQueue -> -                          HCipher -> -                          B.Builder -> IO ()-sendBuilderEncrypted _queue _encrypt x = -  atomically . writeTBQueue _queue . S.Just =<< -                                      _encrypt (S.Just - builder_To_ByteString x)+sendBuilderEncrypt :: HQueue -> HCipher -> B.Builder -> IO ()+sendBuilderEncrypt _queue _encrypt = +  sendBytesEncrypt _queue _encrypt . builder_To_ByteString  -- | An exception raised when parsing fails. data ParseException = ParseException String
− src/Network/MoeSocks/Internal/ShadowSocks/Encrypt.hs
@@ -1,166 +0,0 @@-{- Original file from the shadowsocks package hosted on Hackage:- - https://hackage.haskell.org/package/shadowsocks- - Copyright: rnons- - Licence: MIT- - Heavily modified here- -}---{- -The MIT License (MIT)--Copyright (c) 2014 rnons--Permission is hereby granted, free of charge, to any person obtaining a copy-of this software and associated documentation files (the "Software"), to deal-in the Software without restriction, including without limitation the rights-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-copies of the Software, and to permit persons to whom the Software is-furnished to do so, subject to the following conditions:--The above copyright notice and this permission notice shall be included in all-copies or substantial portions of the Software.--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-SOFTWARE.--}----{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE LambdaCase #-}--module Network.MoeSocks.Internal.ShadowSocks.Encrypt-  ( getEncDec-  , iv_len-  , plainCipher-  ) where--import           Control.Concurrent.MVar ( newEmptyMVar, isEmptyMVar-                                         , putMVar, readMVar)-import           Crypto.Hash.MD5 (hash)-import           Data.ByteString (ByteString)-import qualified Data.ByteString as S-import qualified Data.HashMap.Strict as HM-import           Data.Maybe (fromJust)-import           Data.Monoid ((<>))-import           OpenSSL (withOpenSSL)-import           OpenSSL.EVP.Cipher (getCipherByName, CryptoMode(..))-import           OpenSSL.EVP.Internal (cipherInitBS, cipherUpdateBS,-                                        cipherFinalBS)-import           OpenSSL.Random (randBytes)-import           Data.Text (Text)-import           Control.Lens-import           Data.Text.Lens-import qualified Data.Strict as S---method_supported :: HM.HashMap Text (Int, Int)-method_supported = HM.fromList-    [ ("aes-128-cfb", (16, 16))-    , ("aes-192-cfb", (24, 16))-    , ("aes-256-cfb", (32, 16))-    , ("bf-cfb", (16, 8))-    , ("camellia-128-cfb", (16, 16))-    , ("camellia-192-cfb", (24, 16))-    , ("camellia-256-cfb", (32, 16))-    , ("cast5-cfb", (16, 8))-    , ("des-cfb", (8, 8))-    , ("idea-cfb", (16, 8))-    , ("rc2-cfb", (16, 8))-    , ("rc4", (16, 0))-    , ("seed-cfb", (16, 16))-    ]--iv_len :: Text -> Int-iv_len method = m1-  where-    (_, m1) = method_supported HM.! method--evpBytesToKey :: ByteString -> Int -> Int -> (ByteString, ByteString)-evpBytesToKey password keyLen ivLen =-    let ms' = S.concat $ ms 0 []-        key = S.take keyLen ms'-        iv  = S.take ivLen $ S.drop keyLen ms'-     in (key, iv)-  where-    ms :: Int -> [ByteString] -> [ByteString]-    ms 0 _ = ms 1 [hash password]-    ms i m-        | S.length (S.concat m) < keyLen + ivLen =-            ms (i+1) (m ++ [hash (last m <> password)])-        | otherwise = m--getSSLEncDec :: Text -> ByteString-             -> IO (S.Maybe ByteString -> IO ByteString-                    , S.Maybe ByteString -> IO ByteString)-getSSLEncDec method password = do-    let (m0, m1) = fromJust $ HM.lookup method method_supported-    random_iv <- withOpenSSL $ randBytes 32-    let cipher_iv = S.take m1 random_iv-    let (key, _) = evpBytesToKey password m0 m1-    cipherCtx <- newEmptyMVar-    decipherCtx <- newEmptyMVar--    cipherMethod <- fmap fromJust $ withOpenSSL $ getCipherByName $ -                                        method ^. _Text-    ctx <- withOpenSSL $ cipherInitBS cipherMethod key cipher_iv Encrypt-    let-        encrypt :: (S.Maybe ByteString) -> IO ByteString-        encrypt = \case-          S.Nothing -> cipherFinalBS ctx-          S.Just buf -> do-            if S.null buf-              then return $! mempty-              else do-                empty <- isEmptyMVar cipherCtx-                if empty-                    then do-                        putMVar cipherCtx $! ()-                        ciphered <- withOpenSSL $ cipherUpdateBS ctx buf-                        return $! cipher_iv <> ciphered-                    else do-                        r <- withOpenSSL $ cipherUpdateBS ctx buf-                        return $! r--        decrypt :: (S.Maybe ByteString) -> IO ByteString-        decrypt = \case-          S.Nothing -> cipherFinalBS ctx-          S.Just buf -> do -            if S.null buf-              then return $! S.empty-              else do-                empty <- isEmptyMVar decipherCtx-                if empty-                    then do-                        let decipher_iv = S.take m1 buf-                        dctx <- withOpenSSL $ -                                cipherInitBS cipherMethod key decipher_iv Decrypt-                        putMVar decipherCtx $! dctx-                        if S.null (S.drop m1 buf)-                            then return ""-                            else do-                                r <- withOpenSSL $-                                        cipherUpdateBS dctx (S.drop m1 buf)-                                return $! r-                    else do-                        dctx <- readMVar decipherCtx-                        r <- withOpenSSL $ cipherUpdateBS dctx buf-                        return $! r--    return (encrypt, decrypt)--plainCipher :: (S.Maybe ByteString -> IO ByteString)-plainCipher = pure . S.fromMaybe mempty--getEncDec :: Text -> ByteString  -          -> IO (S.Maybe ByteString -> IO ByteString-                , S.Maybe ByteString -> IO ByteString)-getEncDec t-  | t == "none" = const $ pure (plainCipher, plainCipher)-  | otherwise = getSSLEncDec t
src/Network/MoeSocks/TCP.hs view
@@ -14,12 +14,16 @@ import Network.MoeSocks.Helper import Network.MoeSocks.Type import Network.Socket hiding (send, recv, recvFrom, sendTo)+import Network.Socket.ByteString (recv) import Prelude hiding ((-), take) import qualified Data.Strict as S -local_Socks5_RequestHandler :: MoeConfig -> ByteString -> (Socket, SockAddr) -                                                                    -> IO ()-local_Socks5_RequestHandler aConfig _ (aSocket,_) = do+local_Socks5_RequestHandler :: CipherBox +                            -> MoeConfig +                            -> ByteString +                            -> (Socket, SockAddr) +                            -> IO ()+local_Socks5_RequestHandler aCipherBox aConfig _ (aSocket,_) = do   (_partialBytesAfterGreeting, _r) <-        parseSocket "clientGreeting" mempty plainCipher         greetingParser aSocket@@ -37,26 +41,34 @@                                 connectionParser                                 aSocket -  local_TCP_RequestHandler aConfig _parsedRequest True aSocket+  local_TCP_RequestHandler aCipherBox aConfig _parsedRequest True aSocket   -local_TCP_ForwardRequestHandler :: MoeConfig -> Forward -> -                                  ByteString -> (Socket, SockAddr) -> IO ()-local_TCP_ForwardRequestHandler aConfig aForwarding _ (aSocket,_) = do+local_TCP_ForwardRequestHandler :: CipherBox +                                -> MoeConfig +                                -> Forward +                                -> ByteString +                                -> (Socket, SockAddr) +                                -> IO ()+local_TCP_ForwardRequestHandler aCipherBox aConfig aForwarding _ (aSocket,_) = do   let _clientRequest = ClientRequest                           TCP_IP_stream_connection                           (Domain_name - aForwarding ^.                              forwardRemoteHost)                           (aForwarding ^. forwardRemotePort)               -  local_TCP_RequestHandler aConfig (mempty, _clientRequest) False aSocket+  local_TCP_RequestHandler aCipherBox aConfig (mempty, _clientRequest) False aSocket   -local_TCP_RequestHandler :: MoeConfig -> (ByteString, ClientRequest) -> -                        Bool -> Socket -> IO ()-local_TCP_RequestHandler aConfig +local_TCP_RequestHandler :: CipherBox +                          -> MoeConfig +                          -> (ByteString, ClientRequest) +                          -> Bool +                          -> Socket +                          -> IO ()+local_TCP_RequestHandler aCipherBox aConfig                          (_partialBytesAfterClientRequest, _clientRequest)                          shouldReplyClient aSocket = do   let @@ -84,11 +96,9 @@     _log - "L T: " <> _msg      let handleLocal __remoteSocket = do-          (_encrypt, _decrypt) <- getCipher-                                    (aConfig ^. method)-                                    (aConfig ^. password)--+          _encodeIV <- aCipherBox ^. generateIV +          _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV+                     let                _header = shadowSocksRequestBuilder _clientRequest           @@ -103,13 +113,12 @@                   else Nothing            let sendThread = do-                sendBuilderEncrypted -                  sendChannel _encrypt _header+                sendBytes sendChannel _encodeIV+                sendBuilderEncrypt sendChannel _encrypt _header                  when (_partialBytesAfterClientRequest & isn't _Empty) --                  atomically . writeTBQueue sendChannel . S.Just =<< -                    _encrypt (S.Just _partialBytesAfterClientRequest)-+                  sendBytesEncrypt sendChannel _encrypt +                    _partialBytesAfterClientRequest                  let _produce = do                                   produceLoop (_logId "L --> + Loop")@@ -133,6 +142,9 @@                   pure ()            let receiveThread = do+                _decodeIV <- recv __remoteSocket (aCipherBox ^. ivLength)+                _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV+                 let _produce = produceLoop (_logId "L <-- + Loop")                                   _timeout                                   _NoThrottle@@ -161,12 +173,11 @@     handleLocal _remoteSocket  -remote_TCP_RequestHandler:: MoeConfig -> Socket -> IO ()-remote_TCP_RequestHandler aConfig aSocket = do-  (_encrypt, _decrypt) <- getCipher-                            (aConfig ^. method)-                            (aConfig ^. password)-  +remote_TCP_RequestHandler :: CipherBox -> MoeConfig -> Socket -> IO ()+remote_TCP_RequestHandler aCipherBox aConfig aSocket = do+  _decodeIV <- recv aSocket (aCipherBox ^. ivLength)+  _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV+   (_leftOverBytes, _clientRequest) <- parseSocket                                            "clientRequest"                                           mempty@@ -229,6 +240,10 @@                   pure ()            let receiveThread = do+                _encodeIV <- aCipherBox ^. generateIV +                _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV+                sendBytes receiveChannel _encodeIV+                 let _produce = do                                   produceLoop (_logId "R <-- + Loop")                                     _timeout
src/Network/MoeSocks/Type.hs view
@@ -99,16 +99,30 @@  makeLenses ''MoeOptions +type Cipher = S.Maybe ByteString -> IO ByteString +type CipherBuilder = ByteString -> IO Cipher++data CipherBox = CipherBox+  {+    _ivLength :: Int+  , _generateIV :: IO ByteString+  , _encryptBuilder :: CipherBuilder+  , _decryptBuilder ::  CipherBuilder+  }++makeLenses '' CipherBox+ data Env = Env   {     _options :: MoeOptions   , _config :: MoeConfig+  , _cipherBox :: CipherBox   }-  deriving (Show, Eq)  makeLenses ''Env -type Cipher = S.Maybe ByteString -> IO ByteString -type Queue = TBQueue (Maybe ByteString)  ++type Queue = TBQueue (Maybe ByteString)  type MoeMonadT = ReaderT MoeOptions (ExceptT String IO)+
src/Network/MoeSocks/UDP.hs view
@@ -8,6 +8,7 @@ import Control.Monad.Writer hiding (listen) import Data.Attoparsec.ByteString import Data.ByteString (ByteString)+import qualified Data.ByteString as S import Network.MoeSocks.BuilderAndParser import Network.MoeSocks.Common import Network.MoeSocks.Helper@@ -36,9 +37,13 @@ processAll f x =    (<>) <$> f (S.Just x) <*> f S.Nothing -local_UDP_ForwardRequestHandler :: MoeConfig -> Forward -> -                                  ByteString -> (Socket,SockAddr) -> IO ()-local_UDP_ForwardRequestHandler aConfig aForwarding aMessage +local_UDP_ForwardRequestHandler :: CipherBox +                                -> MoeConfig +                                -> Forward +                                -> ByteString +                                -> (Socket,SockAddr) +                                -> IO ()+local_UDP_ForwardRequestHandler aCipherBox aConfig aForwarding aMessage                                                      (aSocket, aSockAddr) = do    let _c = aConfig@@ -57,9 +62,8 @@     \(_remoteSocket, _remoteAddr) -> do       connect _remoteSocket _remoteAddr -      (_encrypt, _decrypt) <- getCipher-                                (aConfig ^. method)-                                (aConfig ^. password)+      _encodeIV <- aCipherBox ^. generateIV +      _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV        {-let (_encrypt, _decrypt) = (pure, pure)-} @@ -70,27 +74,34 @@       let _msg = show aSockAddr <> " -> " <> showRequest _clientRequest       _log - "L U: " <> _msg       -      send_ _remoteSocket =<< _encrypt (S.Just _bytes)+      _eMsg <- _encrypt (S.Just _bytes) -      (_r, _) <- recv_ _remoteSocket >>= processAll _decrypt +      send_ _remoteSocket - _encodeIV <> _eMsg++      _response <- recv_ _remoteSocket ++      let (_decodeIV, _responseMsg) = S.splitAt (aCipherBox ^. ivLength) +                                        _response+      _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV+      +      (_r, _) <- processAll _decrypt _responseMsg                                       >>= parseShadowSocksRequest -      {-puts - "L UDP <--: " <> show _r-}       when (_r & isn't _Empty) - do         sendAllTo aSocket _r aSockAddr  -remote_UDP_RequestHandler:: MoeConfig -> ByteString -> (Socket, SockAddr) -                                                                      -> IO ()-remote_UDP_RequestHandler aConfig aMessage (aSocket, aSockAddr) = do-  (_encrypt, _decrypt) <- getCipher-                            (aConfig ^. method)-                            (aConfig ^. password)-  +remote_UDP_RequestHandler :: CipherBox +                          -> MoeConfig +                          -> ByteString +                          -> (Socket, SockAddr) +                          -> IO ()+remote_UDP_RequestHandler aCipherBox _ aMessage (aSocket, aSockAddr) = do+  let (_decodeIV, _eMsg) = S.splitAt (aCipherBox ^. ivLength) +                                       aMessage  -  {-let (_encrypt, _decrypt) = (pure, pure)-}-  -  _msg <- processAll _decrypt aMessage+  _decrypt <- aCipherBox ^. decryptBuilder - _decodeIV+  _msg <- processAll _decrypt _eMsg    (_decryptedMessage, _clientRequest) <- parseShadowSocksRequest _msg   @@ -114,5 +125,8 @@     {-puts - "R UDP <--: " <> show _r-}      when (_r & isn't _Empty) - do+      _encodeIV <- aCipherBox ^. generateIV +      _encrypt <- aCipherBox ^. encryptBuilder - _encodeIV+             _encryptedMessage <- processAll _encrypt _r-      sendAllTo aSocket _encryptedMessage aSockAddr+      sendAllTo aSocket (_encodeIV <> _encryptedMessage) aSockAddr