summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerebe <>2021-04-07 20:23:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2021-04-07 20:23:00 (GMT)
commit1e2a123535c3d3ffd76177c35bb08cbededc20c4 (patch)
treec42f76a0b5d0fe5a397f2a2c942bb2324545edef
parentdb755a34ce1699427ac93b151fdee515bb9a0124 (diff)
version 0.3.1.0HEAD0.3.1.0master
-rw-r--r--app/Main.hs33
-rw-r--r--src/Tunnel.hs9
-rw-r--r--src/Types.hs15
-rw-r--r--test/Spec.hs12
-rw-r--r--wstunnel.cabal14
5 files changed, 69 insertions, 14 deletions
diff --git a/app/Main.hs b/app/Main.hs
index 28795e5..e687da5 100644
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -31,6 +31,10 @@ data WsTunnel = WsTunnel
, verbose :: Bool
, quiet :: Bool
, pathPrefix :: String
+ , hostHeader :: String
+ , tlsSNI :: String
+ , websocketPingFrequencySec :: Int
+ , wsTunnelCredentials :: String
} deriving (Show, Data, Typeable)
data WsServerInfo = WsServerInfo
@@ -61,10 +65,20 @@ cmdLine = WsTunnel
, pathPrefix = def &= explicit &= name "upgradePathPrefix"
&= help "Use a specific prefix that will show up in the http path in the upgrade request. Useful if you need to route requests server side but don't have vhosts"
&= typ "String" &= groupname "Client options"
+ , wsTunnelCredentials
+ = def &= explicit &= name "upgradeCredentials"
+ &= help "Credentials for the Basic HTTP authorization type sent with the upgrade request."
+ &= typ "USER[:PASS]"
, proxy = def &= explicit &= name "p" &= name "httpProxy"
&= help "If set, will use this proxy to connect to the server" &= typ "USER:PASS@HOST:PORT"
+ , hostHeader = def &= explicit &= name "hostHeader" &= groupname "Client options"
+ &= help "If set, add the custom string as host http header" &= typ "String" &= groupname "Client options"
+ , tlsSNI = def &= explicit &= name "tlsSNI" &= groupname "Client options"
+ &= help "If set, use custom string in the SNI during TLS handshake" &= typ "String" &= groupname "Client options"
, soMark = def &= explicit &= name "soMark"
&= help "(linux only) Mark network packet with SO_MARK sockoption with the specified value. You need to use {root, sudo, capabilities} to run wstunnel when using this option" &= typ "int"
+ , websocketPingFrequencySec = def &= explicit &= name "websocketPingFrequencySec"
+ &= help "do a hearthbeat ping every x seconds to maintain websocket connection" &= typ "int"
, wsTunnelServer = def &= argPos 0 &= typ "ws[s]://wstunnelServer[:port]"
, serverMode = def &= explicit &= name "server"
@@ -168,6 +182,9 @@ main = do
, Main.udpTimeout = if Main.udpTimeout cfg' == 0 then 30 * 10^(6 :: Int)
else if Main.udpTimeout cfg' == -1 then -1
else Main.udpTimeout cfg' * 10^(6:: Int)
+ , Main.websocketPingFrequencySec = if Main.websocketPingFrequencySec cfg' == 0
+ then 30
+ else Main.websocketPingFrequencySec cfg'
}
let serverInfo = parseServerInfo (WsServerInfo False "" 0) (wsTunnelServer cfg)
@@ -220,7 +237,11 @@ runApp cfg serverInfo
, proxySetting = parseProxyInfo (proxy cfg)
, useSocks = False
, upgradePrefix = pathPrefix cfg
+ , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg
, udpTimeout = Main.udpTimeout cfg
+ , tlsSNI = BC.pack $ Main.tlsSNI cfg
+ , hostHeader = BC.pack $ Main.hostHeader cfg
+ , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg
}
toTcpLocalToRemoteTunnelSetting cfg serverInfo (TunnelInfo lHost lPort rHost rPort) =
@@ -236,7 +257,11 @@ runApp cfg serverInfo
, proxySetting = parseProxyInfo (proxy cfg)
, useSocks = False
, upgradePrefix = pathPrefix cfg
+ , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg
, udpTimeout = Main.udpTimeout cfg
+ , tlsSNI = BC.pack $ Main.tlsSNI cfg
+ , hostHeader = BC.pack $ Main.hostHeader cfg
+ , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg
}
toUdpLocalToRemoteTunnelSetting cfg serverInfo (TunnelInfo lHost lPort rHost rPort) =
@@ -252,7 +277,11 @@ runApp cfg serverInfo
, proxySetting = parseProxyInfo (proxy cfg)
, useSocks = False
, upgradePrefix = pathPrefix cfg
+ , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg
, udpTimeout = Main.udpTimeout cfg
+ , tlsSNI = BC.pack $ Main.tlsSNI cfg
+ , hostHeader = BC.pack $ Main.hostHeader cfg
+ , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg
}
toDynamicTunnelSetting cfg serverInfo (TunnelInfo lHost lPort _ _) =
@@ -268,5 +297,9 @@ runApp cfg serverInfo
, proxySetting = parseProxyInfo (proxy cfg)
, useSocks = True
, upgradePrefix = pathPrefix cfg
+ , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg
, udpTimeout = Main.udpTimeout cfg
+ , tlsSNI = BC.pack $ Main.tlsSNI cfg
+ , hostHeader = BC.pack $ Main.hostHeader cfg
+ , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg
}
diff --git a/src/Tunnel.hs b/src/Tunnel.hs
index 5451010..bcb7d11 100644
--- a/src/Tunnel.hs
+++ b/src/Tunnel.hs
@@ -65,7 +65,10 @@ tunnelingClientP cfg@TunnelSettings{..} app conn = onError $ do
debug "Oppening Websocket stream"
stream <- connectionToStream conn
- ret <- WS.runClientWithStream stream serverHost (toPath cfg) WS.defaultConnectionOptions [] run
+ let headers = if not (null upgradeCredentials) then [("Authorization", "Basic " <> B64.encode upgradeCredentials)] else []
+ let hostname = if not (null hostHeader) then (BC.unpack hostHeader) else serverHost
+
+ ret <- WS.runClientWithStream stream hostname (toPath cfg) WS.defaultConnectionOptions headers run
debug "Closing Websocket stream"
return ret
@@ -74,7 +77,7 @@ tunnelingClientP cfg@TunnelSettings{..} app conn = onError $ do
connectionToStream Connection{..} = WS.makeStream read (write . toStrict . fromJust)
onError = flip catch (\(e :: SomeException) -> return . throwError . WebsocketError $ show e)
run cnx = do
- WS.forkPingThread cnx 30
+ WS.forkPingThread cnx websocketPingFrequencySec
app (toConnection cnx)
@@ -98,7 +101,7 @@ tlsClientP TunnelSettings{..} app conn = onError $ do
, NC.settingDisableSession = False
, NC.settingUseServerName = False
}
- connectionParams = NC.ConnectionParams { NC.connectionHostname = serverHost
+ connectionParams = NC.ConnectionParams { NC.connectionHostname = if tlsSNI == mempty then serverHost else BC.unpack tlsSNI
, NC.connectionPort = serverPort
, NC.connectionUseSecure = Just tlsSettings
, NC.connectionUseSocks = Nothing
diff --git a/src/Types.hs b/src/Types.hs
index f3007c7..63da02a 100644
--- a/src/Types.hs
+++ b/src/Types.hs
@@ -13,8 +13,7 @@ import Data.ByteString (hGetSome, hPutStr)
import qualified Data.Streaming.Network as N
import qualified Network.Connection as NC
-import Network.Socket (HostName, PortNumber(..))
-import Network.Socket.Internal (PortNumber(..))
+import Network.Socket (HostName, PortNumber)
import qualified Network.Socket as N hiding (recv, recvFrom,
send, sendTo)
import qualified Network.Socket.ByteString as N
@@ -22,11 +21,14 @@ import qualified Network.Socket.ByteString as N
import qualified Network.WebSockets.Connection as WS
import System.IO.Unsafe (unsafeDupablePerformIO)
-deriving instance Generic PortNumber
-deriving instance Hashable PortNumber
+
+instance Hashable PortNumber where
+ hashWithSalt s p = hashWithSalt s (fromEnum p)
+
deriving instance Generic N.SockAddr
deriving instance Hashable N.SockAddr
+
{-# NOINLINE defaultRecvBufferSize #-}
defaultRecvBufferSize :: Int
defaultRecvBufferSize = unsafeDupablePerformIO $
@@ -75,7 +77,12 @@ data TunnelSettings = TunnelSettings
, useTls :: Bool
, useSocks :: Bool
, upgradePrefix :: String
+ , upgradeCredentials
+ :: ByteString
+ , tlsSNI :: ByteString
+ , hostHeader :: ByteString
, udpTimeout :: Int
+ , websocketPingFrequencySec :: Int
}
instance Show TunnelSettings where
diff --git a/test/Spec.hs b/test/Spec.hs
index dfe32fc..268c012 100644
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -47,6 +47,10 @@ testTCPLocalToRemote useTLS = do
, useSocks = False
, upgradePrefix = "wstunnel"
, udpTimeout = 0
+ , upgradeCredentials = ""
+ , hostHeader = "toto.com"
+ , tlsSNI = "toto.com"
+ , websocketPingFrequencySec = 30
}
let client = runClient tunnelSetting
@@ -104,6 +108,10 @@ testUDPLocalToRemote useTLS = do
, useSocks = False
, upgradePrefix = "wstunnel"
, udpTimeout = -1
+ , upgradeCredentials = ""
+ , hostHeader = "toto.com"
+ , tlsSNI = "toto.com"
+ , websocketPingFrequencySec = 30
}
let client = runClient tunnelSetting
@@ -160,6 +168,10 @@ testSocks5Tunneling useTLS = do
, useSocks = False
, upgradePrefix = "wstunnel"
, udpTimeout = -1
+ , upgradeCredentials = ""
+ , hostHeader = "toto.com"
+ , tlsSNI = "toto.com"
+ , websocketPingFrequencySec = 30
}
let client = runClient tunnelSetting
diff --git a/wstunnel.cabal b/wstunnel.cabal
index 7e9bbc5..c4c05ea 100644
--- a/wstunnel.cabal
+++ b/wstunnel.cabal
@@ -1,13 +1,13 @@
name: wstunnel
-version: 0.3.0.1
-synopsis: Initial project template from stack
+version: 0.3.1.0
+synopsis: Tunneling program over websocket protocol
description: For more information regarding wstunnel, please refer to README.md
homepage: https://github.com/githubuser/wstunnel#readme
license: BSD3
license-file: LICENSE
-author: Author name here
-maintainer: example@example.com
-copyright: 2016 Author name here
+author: Erèbe
+maintainer: github@erebe.eu
+copyright: 2021 Erèbe
category: Web
build-type: Simple
-- extra-source-files:
@@ -26,7 +26,7 @@ library
, connection
, hslogger
, mtl
- , network < 3.0.0.0
+ , network
, network-conduit-tls
, streaming-commons
, text >= 1.2.2.1
@@ -46,7 +46,7 @@ test-suite wstunnel-test
, text >= 1.2.2.1
, classy-prelude
, bytestring
- , network < 3.0.0.0
+ , network
, network-conduit-tls
, streaming-commons
, wstunnel