moesocks 0.1.1.20 → 0.1.1.30
raw patch · 14 files changed
+169/−139 lines, 14 filesdep +lens-aeson
Dependencies added: lens-aeson
Files
- CHANGELOG.md +7/−6
- README.md +11/−11
- config.json +1/−1
- moesocks.cabal +2/−1
- src/Main.hs +6/−4
- src/Network/MoeSocks/App.hs +51/−57
- src/Network/MoeSocks/Common.hs +4/−0
- src/Network/MoeSocks/Config.hs +1/−0
- src/Network/MoeSocks/Encrypt.hs +53/−16
- src/Network/MoeSocks/Helper.hs +8/−18
- src/Network/MoeSocks/Internal/Socket.hs +6/−6
- src/Network/MoeSocks/Options.hs +9/−3
- src/Network/MoeSocks/TCP.hs +9/−16
- src/Network/MoeSocks/Type.hs +1/−0
CHANGELOG.md view
@@ -1,14 +1,15 @@+0.1.1.30+--------+* Add more encryption methods from OpenSSL+* Add a `--list-methods` flag to show all supported encryption methods+ 0.1.1.20 ---------* Implement TFO in remote. If your browser and the website your are visiting- both support TFO, you can enjoy TFO all the way through. This could lead to a- huge reduction of latency.+* Implement TFO in remote. 0.1.1.10 ---------* Add TCP Fast Open (TFO) capability. It can be turned on by adding a - `"fast_open":true` field in `config.json` or specifying a `--fast-open` flag- in the command line arguments.+* Add TCP Fast Open (TFO) capability. 0.1.1.0 -------
README.md view
@@ -35,15 +35,15 @@ * Edit `config.json` to fit your setup (at least the `remote` and `password` fields) -* Start a remote node outside the firewall: +* Start a remote node outside a firewall: moesocks --role remote -c config.json -* Start a local node inside the firewall: +* Start a local node inside a firewall: moesocks --role local -c config.json -* Now you have a socks5 proxy running inside the firewall using port +* Now you have a socks5 proxy running inside a firewall using port `localPort`. * Shadowsocks compatible obfuscation can be turned on with the `-o` flag to make@@ -82,13 +82,13 @@ ## [TFO] means faster response in this case -Both local and remote will use TFO when instructed. If your browser and the-website your are visiting both support TFO, you can enjoy TFO all the way-through. This could lead to a huge reduction of latency.+Both local and remote will use TFO when instructed. If the browser in use and+the website to visit both support TFO, you can enjoy TFO all the way through.+This could lead to a huge reduction of latency. ## Enable TFO in your OS runtime. -On Linux 3.7+, you could check the availability of TFO using:+On Linux 3.7+, to check the availability of TFO: cat /proc/sys/net/ipv4/tcp_fastopen @@ -98,13 +98,13 @@ ## Enable TFO in MoeSocks -TFO can be turned on by adding a `"fast_open":true` field in-`config.json` or specifying a `--fast-open` flag in the command line arguments.+TFO can be turned on by adding a `"fastOpen":true` field in `config.json` or+specifying a `--fast-open` flag in the command line arguments. ## Verify -Use `tcpdump` on the `remotePort`, you should see that the first packet `SYN`-will carry the initial data with it. An example command is:+Use `tcpdump` on the `remotePort`, check for that `SYN` should start to carry+payload. An example command is: tcpdump port 8388 -i any -X -v
config.json view
@@ -4,7 +4,7 @@ "local":"localhost", "localPort":1090, "password":"birthday!",- "fast_open":true,+ "fastOpen":true, "method":"aes-256-cfb" }
moesocks.cabal view
@@ -1,6 +1,6 @@ name: moesocks category: Network-version: 0.1.1.20+version: 0.1.1.30 license: Apache-2.0 synopsis: A functional firewall killer description: A socks5 proxy using the client / server architecture.@@ -38,6 +38,7 @@ , hslogger , iproute , lens + , lens-aeson , mtl , network , optparse-applicative
src/Main.hs view
@@ -13,8 +13,10 @@ main :: IO () main = ssl - do _options <- execParser opts- r <- runExceptT - runReaderT moeApp _options- case r of- Left e -> error_ e >> exitFailure- Right _ -> pure ()+ + withGateOptions _options - do+ r <- runExceptT - runReaderT moeApp _options+ case r of+ Left e -> error_ e >> exitFailure+ Right _ -> pure ()
src/Network/MoeSocks/App.hs view
@@ -10,18 +10,18 @@ import Control.Monad.Reader hiding (local) import Control.Monad.Writer hiding (listen) import Data.Aeson hiding (Result)+import Data.Aeson.Lens import Data.ByteString (ByteString)-import Data.ByteString.Lazy (toStrict)+import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Text.Lens-import Data.Text.Strict.Lens (utf8) import Network.MoeSocks.Config import Network.MoeSocks.Constant+import Network.MoeSocks.Encrypt (initCipherBox, safeMethods, unsafeMethods) import Network.MoeSocks.Helper import Network.MoeSocks.TCP import Network.MoeSocks.Type import Network.MoeSocks.UDP-import Network.MoeSocks.Encrypt (initCipherBox) import Network.Socket hiding (send, recv, recvFrom, sendTo) import Network.Socket.ByteString import Prelude hiding ((-), take)@@ -29,101 +29,94 @@ import System.Log.Handler.Simple import System.Log.Logger import qualified Data.HashMap.Strict as H+import qualified Data.Map as Map import qualified Data.Text as T import qualified Data.Text.IO as TIO import qualified System.IO as IO import qualified System.Log.Handler as LogHandler +withGateOptions :: MoeOptions -> IO a -> IO ()+withGateOptions aOption aIO = do+ if aOption ^. listMethods+ then do+ let _br = putStrLn ""++ _br+ putStrLn "Recommended:"+ itraverse_ (\k _ -> putStrLn - "\t\t" <> k ^. _Text) - safeMethods++ _br+ putStrLn "Supported:"+ itraverse_ (\k _ -> putStrLn - "\t\t" <> k ^. _Text) - unsafeMethods++ else+ () <$ aIO+ parseConfig :: MoeOptions -> MoeMonadT MoeConfig parseConfig aOption = do let _maybeFilePath = aOption ^. configFile _v <- case _maybeFilePath of Nothing -> pure - Just - Object mempty- Just _filePath -> do- _data <- io - TIO.readFile - _filePath ^. _Text- pure -- (decodeStrict - review utf8 _data - :: Maybe Value)+ Just _filePath -> fmap (preview _JSON) - + io - TIO.readFile - _filePath ^. _Text let - fromShadowSocksConfig :: [(Text, Value)] -> [(Text, Value)]- fromShadowSocksConfig _configList = - let fixes =++ asList :: ([(Text, Value)] -> [(Text, Value)]) -> Value -> Value+ asList f = over _Object - H.fromList . f . H.toList + + fromShadowSocksConfig :: Text -> Text+ fromShadowSocksConfig x = + let fixes = Map.fromList [ ("server", "remote") , ("server_port", "remotePort") , ("local_address", "local")- , ("local_port", "localPort")- , ("fast_open", "fastOpen") ] in- foldl (flip duplicateKey) _configList fixes-- fromSS :: [(Text, Value)] -> [(Text, Value)]- fromSS = fromShadowSocksConfig-+ fixes ^? ix x & fromMaybe x - let toParsableConfig :: Value -> Value- toParsableConfig (Object _obj) =- Object - - _obj - & H.toList - & fromSS - & over (mapped . _1) (T.cons '_') - & H.fromList- toParsableConfig _ = Null- + toParsableConfig = asList - each . _1 %~ (+ T.cons '_' + . toCamelCase+ . fromShadowSocksConfig+ ) toReadableConfig :: Value -> Value- toReadableConfig (Object _obj) =- Object -- _obj- & H.toList - & over (mapped . _1) T.tail - & H.fromList-- toReadableConfig _ = Null+ toReadableConfig = asList - each . _1 %~ T.tail showConfig :: MoeConfig -> Text- showConfig = view utf8 - . toStrict - . encode + showConfig = review _JSON . toReadableConfig - . toJSON -- + . review _JSON filterEssentialConfig :: Value -> Value- filterEssentialConfig (Object _obj) =- Object -- foldl (flip H.delete) _obj - - [- "_password"- ]+ filterEssentialConfig = over _Object - \_obj ->+ foldl (flip H.delete) _obj - + [+ "_password"+ ] - filterEssentialConfig _ = Null- insertConfig :: Value -> Value -> Value- insertConfig (Object _x) (Object _y) =- Object - _x `H.union` _y- insertConfig _ _ = Null+ insertConfig (Object _from) = over _Object (_from `H.union`)+ insertConfig _ = const Null insertParams :: [(Text, Value)] -> Value -> Value- insertParams xs (Object _x) =- Object - H.fromList xs `H.union` _x- insertParams _ _ = Null+ insertParams _from = over _Object (H.fromList _from `H.union`) + fallbackConfig :: Value -> Value -> Value+ fallbackConfig = flip insertConfig optionalConfig = filterEssentialConfig - toJSON defaultMoeConfig _maybeConfig = _v >>= decode . encode - . flip insertConfig optionalConfig+ . fallbackConfig optionalConfig . insertParams (aOption ^. params) . toParsableConfig @@ -150,6 +143,7 @@ let configStr = showConfig _config ^. _Text :: String io - debug_ - "Using config: " <> configStr pure - _config + & method .~ "camellia-128-cfb8" initLogger :: Priority -> IO ()
src/Network/MoeSocks/Common.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-} module Network.MoeSocks.Common where @@ -23,6 +24,9 @@ showAddressType (IPv6_address xs) = xs ^.. each . to show ^.. folding (concat . L.intersperse ":") ^. from _Text+++makePrisms ''IPRange checkForbidden_IP_List :: AddressType -> [IPRange] -> Bool checkForbidden_IP_List _address@(IPv4_address _) aForbidden_IP_List =
src/Network/MoeSocks/Config.hs view
@@ -34,5 +34,6 @@ , _disableSocks5 = False , _obfuscation = False , _forbidden_IP = ["127.0.0.1", "0.0.0.0", "::1"]+ , _listMethods = False , _params = [] }
src/Network/MoeSocks/Encrypt.hs view
@@ -10,6 +10,8 @@ initCipherBox , identityCipher , ssl+, safeMethods+, unsafeMethods ) where @@ -54,23 +56,58 @@ type MaybeT_IO = ExceptT () IO -methods :: Map Text KeyLength-methods = fromList- [ ("aes-128-cfb" , 16)- , ("aes-192-cfb" , 24)- , ("aes-256-cfb" , 32)- , ("bf-cfb" , 16)- , ("camellia-128-cfb" , 16)- , ("camellia-192-cfb" , 24)- , ("camellia-256-cfb" , 32)- , ("cast5-cfb" , 16)- , ("des-cfb" , 8 )- , ("idea-cfb" , 16)- , ("rc2-cfb" , 16)- , ("rc4" , 16)- , ("seed-cfb" , 16)- ]+type Method = Map Text KeyLength +safeMethods :: Method+safeMethods = fromList - + [ + ("aes-128-cfb" , 16)+ , ("aes-192-cfb" , 24)+ , ("aes-256-cfb" , 32)+ , ("aes-128-ofb" , 16)+ , ("aes-192-ofb" , 24)+ , ("aes-256-ofb" , 32)+ , ("aes-128-ctr" , 16)+ , ("aes-192-ctr" , 24)+ , ("aes-256-ctr" , 32)+ , ("aes-128-cfb8" , 16)+ , ("aes-192-cfb8" , 24)+ , ("aes-256-cfb8" , 32)+ , ("aes-128-cfb1" , 16)+ , ("aes-192-cfb1" , 24)+ , ("aes-256-cfb1" , 32)+ , ("aes-128-gcm" , 16)+ , ("aes-192-gcm" , 24)+ , ("aes-256-gcm" , 32)+ , ("bf-cfb" , 16)+ , ("camellia-128-cfb" , 16)+ , ("camellia-192-cfb" , 24)+ , ("camellia-256-cfb" , 32)+ , ("camellia-128-ofb" , 16)+ , ("camellia-192-ofb" , 24)+ , ("camellia-256-ofb" , 32)+ , ("camellia-128-cfb8" , 16)+ , ("camellia-192-cfb8" , 24)+ , ("camellia-256-cfb8" , 32)+ , ("camellia-128-cfb1" , 16)+ , ("camellia-192-cfb1" , 24)+ , ("camellia-256-cfb1" , 32)+ , ("cast5-cfb" , 16)+ , ("des-cfb" , 8 )+ {-, ("idea-cfb" , 16)-}+ , ("seed-cfb" , 16)+ ]+++unsafeMethods :: Method+unsafeMethods = fromList - + [+ ("rc2-cfb" , 16) -- unsafe+ , ("rc4" , 16) -- unsafe+ ]++methods :: Method+methods = safeMethods <> unsafeMethods hashKey :: ByteString -> KeyLength -> IV_Length -> ByteString hashKey aPassword aKeyLen a_IV_len = loop mempty mempty
src/Network/MoeSocks/Helper.hs view
@@ -14,13 +14,13 @@ import Data.Binary import Data.Binary.Put import Data.ByteString (ByteString)-import Data.IP import Data.Maybe import Data.Monoid import Data.Text (Text)+import qualified Data.Text as T import Data.Text.Lens import Data.Time.Clock-import Network.MoeSocks.Internal.Socket (sendAllFastOpenTo)+import Network.MoeSocks.Internal.Socket (sendAllToFastOpen) import Network.Socket hiding (send, recv) import Network.Socket.ByteString import Prelude hiding (take, (-)) @@ -33,7 +33,6 @@ import qualified Data.ByteString.Builder as B import qualified Data.ByteString.Lazy as LB import qualified Data.Strict as S-{-import Data.List (isPrefixOf)-} -- BEGIN backports@@ -261,7 +260,7 @@ sendFast_ :: Socket -> ByteString -> SockAddr -> IO ()-sendFast_ = sendAllFastOpenTo+sendFast_ = sendAllToFastOpen sendAllRandom :: Int -> Socket -> ByteString -> IO ()@@ -457,18 +456,9 @@ tryIO :: String -> IO a -> IO (Either IOException a) tryIO _ = try -- . logException aID- -maybeIPv4Range :: IPRange -> Maybe (AddrRange IPv4)-maybeIPv4Range (IPv4Range x) = Just x-maybeIPv4Range _ = Nothing -maybeIPv6Range :: IPRange -> Maybe (AddrRange IPv6)-maybeIPv6Range (IPv6Range x) = Just x-maybeIPv6Range _ = Nothing--_IPv4Range :: Prism' IPRange (AddrRange IPv4) -_IPv4Range = prism' IPv4Range maybeIPv4Range--_IPv6Range :: Prism' IPRange (AddrRange IPv6)-_IPv6Range = prism' IPv6Range maybeIPv6Range-+toCamelCase :: Text -> Text+toCamelCase x = x + & T.split (`elem` ['_', '-'])+ & over (_tail . traversed) T.toTitle+ & T.concat
src/Network/MoeSocks/Internal/Socket.hs view
@@ -31,20 +31,20 @@ c_sendto s ptr (fromIntegral $ nbytes) (fromIntegral flags) p_addr (fromIntegral sz) -sendToWithFlag :: Socket -- ^ Socket+sendToWithFlagNoRetry :: Socket -- ^ Socket -> ByteString -- ^ Data to send -> SockAddr -- ^ Recipient address -> Int -> IO Int -- ^ Number of bytes sent-sendToWithFlag sock xs addr flags =+sendToWithFlagNoRetry sock xs addr flags = unsafeUseAsCStringLen xs $ \(str, len) -> sendBufToWithFlagNoRetry sock str len addr flags -sendAllFastOpenTo :: Socket -- ^ Socket+sendAllToFastOpen :: Socket -- ^ Socket -> ByteString -- ^ Data to send -> SockAddr -- ^ Recipient address -> IO ()-sendAllFastOpenTo sock xs addr = do+sendAllToFastOpen 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+ sent <- sendToWithFlagNoRetry sock xs addr _MSG_FASTOPEN+ when (sent < S.length xs) $ sendAll sock (S.drop sent xs)
src/Network/MoeSocks/Options.hs view
@@ -61,6 +61,11 @@ long "disable-socks5" <> help ("Do not start a socks5 server on local. It can be " <> "useful to run moesocks only as a secure tunnel")+ + _listMethods :: O.Parser Bool+ _listMethods = switch -+ long "list-methods"+ <> help "Show supported encryption methods" _tcpBufferSize = intParam - long "tcp-buffer-size"@@ -76,7 +81,7 @@ short 'c' <> long "config" <> metavar "CONFIG"- <> help "Point to the path of the configuration file"+ <> help "Set the path of the configuration file" _remote = textParam - short 's'@@ -123,11 +128,11 @@ <> defaultHelp (_c ^. timeout & show & view (from _Text))- "timeout connection in seconds"+ "Timeout connection in seconds" _fastOpen = boolParam - long "fast-open"- <> help ("use TCP_FASTOPEN, requires Linux 3.7+")+ <> help ("Use TCP_FASTOPEN, requires Linux 3.7+") _obfuscation :: O.Parser Bool _obfuscation = switch -@@ -255,6 +260,7 @@ <*> _disableSocks5 <*> _obfuscation <*> fmap parseForbidden_IP _forbidden_IP+ <*> _listMethods <*> _params opts :: ParserInfo MoeOptions
src/Network/MoeSocks/TCP.hs view
@@ -206,7 +206,7 @@ _decodeIV <- recv aSocket (_cipherBox ^. ivLength) _decrypt <- _cipherBox ^. decryptBuilder - _decodeIV - (_leftOverBytes, _clientRequest) <- parseSocket + (_partialBytesAfterRequest, _clientRequest) <- parseSocket "clientRequest" mempty _decrypt@@ -223,26 +223,19 @@ withCheckedForbidden_IP_List _addr _forbidden_IP - do setSocketSendFast _targetSocket - let _initBytes = _leftOverBytes- let _connectNormal = do- connect _targetSocket _targetAddress- send_ _targetSocket _initBytes+ _remotePeerAddr <- getPeerName aSocket+ let _msg = showRelay _remotePeerAddr _clientRequest + info_ - "RT: " <> _msg+ + let _initBytes = _partialBytesAfterRequest+ if _c ^. fastOpen then sendFast_ _targetSocket _initBytes _targetAddress- {-`onException` -}- {-( do-}- {-error_ - "TCP Fast Open not availabe for: " <> show _targetSocket-}- {-_connectNormal-}- {-)-} else do- _connectNormal- - _remotePeerAddr <- getPeerName aSocket- let _msg = showRelay _remotePeerAddr _clientRequest-- info_ - "RT: " <> _msg+ connect _targetSocket _targetAddress+ send_ _targetSocket _initBytes let handleTarget __targetSocket = do
src/Network/MoeSocks/Type.hs view
@@ -97,6 +97,7 @@ , _disableSocks5 :: Bool , _obfuscation :: Bool , _forbidden_IP :: [IPRange]+ , _listMethods :: Bool , _params :: [(Text, Value)] } deriving (Show, Eq)