Maj sock5 proxy

This commit is contained in:
Erèbe 2016-06-20 17:10:48 +02:00
parent e6950ea526
commit a2eac5a595
2 changed files with 80 additions and 19 deletions

View file

@ -1,3 +1,4 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
@ -11,7 +12,14 @@ module Socks5 where
import ClassyPrelude
import Data.Binary
import Data.Binary.Get
import Data.Binary.Put
import qualified Data.ByteString as BC
import qualified Data.ByteString.Char8 as BC8
import Data.Either
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import Network.Socket (HostName, PortNumber)
import Numeric (showHex)
data AuthMethod = NoAuth
| GSSAPI
@ -48,18 +56,18 @@ instance Binary RequestAuth where
putWord8 (fromIntegral version)
putWord8 (fromIntegral $ length methods)
sequence_ (put <$> methods)
-- Check length <= 255
get = do
version <- fromIntegral <$> getWord8
guard (version == 0x05)
nbMethods <- fromIntegral <$> getWord8
guard (version <= 0xFF)
guard (nbMethods > 0 && nbMethods <= 0xFF)
methods <- replicateM nbMethods get
return $ RequestAuth version methods
data Request = Request
{ version :: Int
, command :: Command
@ -70,9 +78,59 @@ data Request = Request
data Command = Connect
| Bind
| UdpAssociate
deriving (Show, Eq)
deriving (Show, Eq, Enum, Bounded)
instance Binary Command where
put = putWord8 . (+1) . fromIntegral . fromEnum
get = do
cmd <- (\val -> fromIntegral val - 1) <$> getWord8
guard $ cmd >= fromEnum (minBound :: Command) && cmd <= fromEnum (maxBound :: Command)
return .toEnum $ cmd
instance Binary Request where
put Request{..} = do
putWord8 (fromIntegral version)
put command
putWord8 0x00 -- RESERVED
putWord8 0x03 -- DOMAINNAME
let host = BC8.pack addr
putWord8 (fromIntegral . length $ host)
traverse_ put host
putWord16be (fromIntegral port)
get = do
version <- fromIntegral <$> getWord8
guard (version == 5)
cmd <- get :: Get Command
_ <- getWord8 -- RESERVED
opCode <- fromIntegral <$> getWord8 -- DOMAINNAME
guard (opCode == 0x03)
length <- fromIntegral <$> getWord8
host <- either (const T.empty) id . E.decodeUtf8' <$> replicateM length getWord8
guard (not $ null host)
port <- fromIntegral <$> getWord16be
return Request
{ version = version
, command = cmd
, addr = unpack host
, port = port
}
toHex :: LByteString -> String
toHex = foldr showHex "" . unpack
data Response = Response
{ version :: Int
, returnCode :: RetCode

View file

@ -16,20 +16,21 @@ cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: Tunnel, Protocols, Utils
build-depends: base
, classy-prelude
, bytestring
, async
, unordered-containers
, network
, streaming-commons
, websockets
, network-conduit-tls
, connection
, hslogger
build-depends: async
, base
, base64-bytestring >= 1.0
, binary >= 0.7
, bytestring
, classy-prelude
, connection
, hslogger
, mtl
, network
, network-conduit-tls
, streaming-commons
, text >= 1.2.2.1
, unordered-containers
, websockets
default-language: Haskell2010
@ -38,11 +39,12 @@ executable wstunnel
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, wstunnel
, cmdargs
, classy-prelude
, bytestring
, classy-prelude
, cmdargs
, hslogger
, text >= 1.2.2.1
, wstunnel
default-language: Haskell2010
@ -51,6 +53,7 @@ test-suite wstunnel-test
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, text >= 1.2.2.1
, wstunnel
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010