packages feed

neko-obfs 0.1.0.1 → 0.1.0.2

raw patch · 5 files changed

+104/−48 lines, 5 files

Files

Readme.md view
@@ -15,19 +15,19 @@ Implementation ============== -* `n` is randomly generated for each packet.-* `n` is bounded by a maximum `r`, configurable by the `--randomness` argument.-* To reduce overhead, `n` is set to 0 whenever `m` is greater then a -  threshold `b`, configurable by the `--bound` argument.+* `n` is deduced from a randomly generated `i = n + m` for each packet.+* When a random `i` is less then `m`, payload is split to `p1` and `p2` to satisfy the constrain, where the length of `p1` is equal to `i` and `p1 + p2 = payload`. `p2` will be sent in the next iteration by the same algorithm.+* `i` is bounded by a maximum `r`, configurable by the `--randomnessInBytes` argument.+* To reduce overhead, `n` is set to `0` whenever `m` is greater then `r`.  Usage ===== * local: -        need-obfs --localHost TEXT --localPort INTEGER --remoteHost TEXT --remotePort INTEGER+        neko-obfs --localHost TEXT --localPort INTEGER --remoteHost TEXT --remotePort INTEGER * remote:  -        neko-obfs --remote --remoteHost TEXT --remotePort INTEGER --forwardHost TEXT --forwardPort INTEGER+        neko-obfs --role remote --remoteHost TEXT --remotePort INTEGER --forwardHost TEXT --forwardPort INTEGER * This tunnel should be used inside an encrypted tunnel. * For example: 
neko-obfs.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                neko-obfs-version:             0.1.0.1+version:             0.1.0.2 synopsis:            a TCP tunnel with packet length obfuscation description:         Just another tool that helps accessing the internet license:             Apache-2.0
src/Main.hs view
@@ -4,10 +4,11 @@  import           Helper ((-), log) import           Prelude hiding ((-), log)+import qualified Prelude as Prelude  import           Control.Concurrent.Async (async, waitAnyCatchCancel, waitEitherCancel) import           Control.Lens-import           Control.Monad (replicateM_, join)+import           Control.Monad (replicateM_, join, when) import           Control.Monad.IO.Class (MonadIO(..)) import           Control.Monad.Trans.State.Strict (runStateT) import           Data.Attoparsec.ByteString (parse, maybeResult)@@ -28,29 +29,69 @@ import           Pipes.Safe import           System.Random (randomIO) import           Options.Generic+import System.IO (hSetBuffering, stdin, stdout, BufferMode(LineBuffering))  import           Options (toConfig) import           Parser import           Type  -obfsEncode :: (MonadIO m) => Integer -> Integer -> Pipe ByteString ByteString m a-obfsEncode bound randomness = do+obfsEncode :: (MonadIO m) => Bool -> Integer -> Pipe ByteString ByteString m a+obfsEncode debug randomness = do   for cat - \x -> do     let payloadLen = (fromIntegral - B.length x)+    if (payloadLen >= fromIntegral randomness)+      then do+        let paddingLen = 0+        let chunk =+              view strict - Builder.toLazyByteString -+                Builder.word32BE paddingLen+                <> Builder.byteString+                      (BC.replicate (fromIntegral paddingLen) - '.')+                <> Builder.word32BE payloadLen+                <> Builder.byteString x -    randomLen <--      if (payloadLen > fromIntegral bound)-        then pure 0-        else liftIO - randomIO <&> (`mod` fromIntegral randomness)+        when debug - log - "E: " <> (T.pack - show - B.length chunk)+        yield chunk+      else+        randomLenCheckLoop x+  where+    randomLenCheckLoop payload = do+      let payloadLen = (fromIntegral - B.length payload)+      randomLen <- liftIO - randomIO <&> (`mod` fromIntegral randomness)+      if (payloadLen <= randomLen)+        then+          do+            let paddingLen = randomLen Prelude.- payloadLen+            let chunk =+                  view strict - Builder.toLazyByteString -+                    Builder.word32BE paddingLen+                    <> Builder.byteString+                        (BC.replicate (fromIntegral paddingLen) - '.')+                    <> Builder.word32BE payloadLen+                    <> Builder.byteString payload -    yield - view strict - Builder.toLazyByteString --      Builder.word32BE randomLen-      <> Builder.byteString (BC.replicate (fromIntegral randomLen) - 'a')-      <> Builder.word32BE payloadLen-      <> Builder.byteString x+            when debug - log - "E: " <> (T.pack - show - B.length chunk)+            yield chunk+        else+          do+            let paddingLen = 0+                (now, next) = B.splitAt (fromIntegral randomLen) payload +            let chunk =+                  view strict - Builder.toLazyByteString -+                    Builder.word32BE paddingLen+                    <> Builder.byteString+                        (BC.replicate (fromIntegral paddingLen) - '.')+                    <> Builder.word32BE (fromIntegral - B.length now)+                    <> Builder.byteString now +            when debug - log - "E: " <> (T.pack - show - B.length chunk)+            yield chunk++            randomLenCheckLoop next++ obfsDecode :: (MonadIO m) => Producer ByteString m a -> (ByteString -> m ()) -> m () obfsDecode pull sink = loop pull   where@@ -65,12 +106,15 @@  main :: IO () main = do+  hSetBuffering stdin LineBuffering+  hSetBuffering stdout LineBuffering+   config <- getRecord "a TCP tunnel with packet length obfuscation" <&> toConfig    log - T.pack - show config -  let mtu = 4096-      timeout = fromIntegral - config ^. timeoutInSeconds * 1000000+  let _mtu = fromIntegral - config ^. mtu + (-8) -- 2 word32be+      _timeout = fromIntegral - config ^. timeoutInSeconds * 1000000    let _localHost = config ^. localHost . re packed       _localPort = show - config ^. localPort@@ -78,9 +122,11 @@       _remoteHost = config ^. remoteHost . re packed       _remotePort = show - config ^. remotePort -      _fromSocket = fromSocketTimeout timeout-      _toSocket = toSocketTimeout timeout+      _fromSocket = fromSocketTimeout _timeout+      _toSocket = toSocketTimeout _timeout +      _debug = config ^. debug+   localThread <- pure -     runSafeT . runEffect - serve (Host _localHost) _localPort - \(localSock, localSockAddr) -> do       log - "local accepted: " <> view packed (show localSockAddr)@@ -91,14 +137,14 @@           liftIO - NS.setSocketOption remoteSock NS.NoDelay 1            let-              localPull = _fromSocket localSock mtu+              localPull = _fromSocket localSock _mtu -              remotePull = _fromSocket remoteSock mtu+              remotePull = _fromSocket remoteSock _mtu               remotePush = _toSocket remoteSock             sendThread <- liftIO - async - runEffect - do-            localPull >-> obfsEncode (config ^. bound) (config ^. randomness)+            localPull >-> obfsEncode _debug (config ^. randomnessInBytes)                       >-> remotePush             liftIO - NS.shutdown remoteSock NS.ShutdownSend @@ -123,17 +169,17 @@           liftIO - NS.setSocketOption forwardSock NS.NoDelay 1            let-              remotePull = _fromSocket remoteSock mtu+              remotePull = _fromSocket remoteSock _mtu               remotePush = _toSocket remoteSock -              forwardPull = _fromSocket forwardSock mtu+              forwardPull = _fromSocket forwardSock _mtu            sendThread <- liftIO - async - do             obfsDecode remotePull - send forwardSock             liftIO - NS.shutdown forwardSock NS.ShutdownSend            recvThread <- liftIO - async - runEffect - do-            forwardPull >-> obfsEncode (config ^. bound) (config ^. randomness)+            forwardPull >-> obfsEncode _debug (config ^. randomnessInBytes)                         >-> remotePush             liftIO - NS.shutdown remoteSock NS.ShutdownSend @@ -143,11 +189,12 @@     case config ^. role of-    Local -> do-      _ <- localThread-      pure ()-    Remote -> do-      _ <- remoteThread+    Local -> join localThread+    Remote -> join remoteThread+    Both -> do+      local <- async - join localThread+      remote <- async - join remoteThread+      waitEitherCancel local remote       pure ()    pure ()
src/Options.hs view
@@ -1,6 +1,5 @@--- |- {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}  module Options where @@ -11,16 +10,17 @@  data TunnelOptions = TunnelOptions   {-    localHost :: Maybe Text+    role :: Maybe Text+  , localHost :: Maybe Text   , localPort :: Maybe Integer   , remoteHost :: Text   , remotePort :: Integer   , forwardHost :: Maybe Text   , forwardPort :: Maybe Integer-  , remote :: Bool-  , bound :: Maybe Integer-  , randomness :: Maybe Integer+  , randomnessInBytes :: Maybe Integer   , timeoutInSeconds :: Maybe Integer+  , mtu :: Maybe Integer+  , debug :: Bool   }   deriving (Generic, Show, Eq) @@ -30,6 +30,12 @@ toConfig :: TunnelOptions -> Config toConfig o =   let c = defaultConfig+      _role =+        case role o of+          Just "remote" -> Remote+          Just "local" -> Local+          Just "both" -> Both+          _ -> Local   in   Config     {@@ -39,8 +45,9 @@     , _remotePort = remotePort o     , _forwardHost = fromMaybe (_forwardHost c) (forwardHost o)     , _forwardPort = fromMaybe (_forwardPort c) (forwardPort o)-    , _role = if remote o then Remote else Local-    , _bound = fromMaybe (_bound c) (bound o)-    , _randomness = fromMaybe (_randomness c) (randomness o)+    , _role = _role+    , _randomnessInBytes = fromMaybe (_randomnessInBytes c) (randomnessInBytes o)     , _timeoutInSeconds = fromMaybe (_timeoutInSeconds c) (timeoutInSeconds o)+    , _mtu = fromMaybe (_mtu c) (mtu o)+    , _debug = debug o     }
src/Type.hs view
@@ -7,7 +7,7 @@ import Control.Lens import Data.Text (Text) -data Role = Local | Remote+data Role = Local | Remote | Both   deriving (Show, Eq)  data Config = Config@@ -19,9 +19,10 @@   , _forwardHost :: Text   , _forwardPort :: Integer   , _role :: Role-  , _bound :: Integer-  , _randomness :: Integer+  , _randomnessInBytes :: Integer   , _timeoutInSeconds :: Integer+  , _debug :: Bool+  , _mtu :: Integer   }   deriving (Show, Eq) @@ -37,7 +38,8 @@   , _forwardHost = "127.0.0.1"   , _forwardPort = 1080   , _role = Local-  , _bound = 1024-  , _randomness = 300+  , _randomnessInBytes = 256   , _timeoutInSeconds = 3600+  , _debug = False+  , _mtu = 4096   }