diff --git a/app/Main.hs b/app/Main.hs index 338c0db..2327b9e 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -10,7 +10,6 @@ import Data.CaseInsensitive ( CI ) import qualified Data.CaseInsensitive as CI import qualified Data.ByteString.Char8 as BC import Data.List (head, (!!)) -import Data.Maybe (fromMaybe) import System.Console.CmdArgs import System.Environment (getArgs, withArgs) @@ -34,6 +33,7 @@ data WsTunnel = WsTunnel , pathPrefix :: String , hostHeader :: String , tlsSNI :: String + , tlsVerifyCertificate :: Bool , websocketPingFrequencySec :: Int , wsTunnelCredentials :: String , customHeaders :: [String] @@ -83,6 +83,8 @@ cmdLine = WsTunnel &= 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" + , tlsVerifyCertificate = def &= explicit &= name "tlsVerifyCertificate" &= groupname "Client options" + &= help "Verify tls server certificate. Default to false" , 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" @@ -166,7 +168,7 @@ parseRestrictTo str = let !(!h, !p) = fromMaybe (error "Invalid Parameter restar let (host, port) = BC.spanEnd (/= ':') (BC.pack str) guard (host /= mempty) portNumber <- readMay . BC.unpack $ port :: Maybe Int - return $! (BC.filter (\c -> c /= '[' && c /= ']') (BC.init host), portNumber) + return (BC.filter (\c -> c /= '[' && c /= ']') (BC.init host), portNumber) parseProxyInfo :: String -> Maybe ProxySettings parseProxyInfo str = do @@ -219,8 +221,8 @@ runApp cfg serverInfo -- server mode | serverMode cfg = do putStrLn $ "Starting server with opts " <> tshow serverInfo - key <- if (Main.tlsKey cfg) /= mempty then readFile (Main.tlsKey cfg) else return Credentials.key - certificate <- if (Main.tlsCertificate cfg) /= mempty then readFile (Main.tlsCertificate cfg) else return Credentials.certificate + key <- if Main.tlsKey cfg /= mempty then readFile (Main.tlsKey cfg) else return Credentials.key + certificate <- if Main.tlsCertificate cfg /= mempty then readFile (Main.tlsCertificate cfg) else return Credentials.certificate let tls = if Main.useTls serverInfo then Just (certificate, key) else Nothing runServer tls (Main.host serverInfo, fromIntegral $ Main.port serverInfo) (parseRestrictTo $ restrictTo cfg) @@ -235,7 +237,7 @@ runApp cfg serverInfo -- -D dynamicToRemote tunnels | not . null $ dynamicToRemote cfg = do - let tunnelSetting = toDynamicTunnelSetting cfg serverInfo . parseTunnelInfo $ (dynamicToRemote cfg) ++ ":127.0.0.1:1212" + let tunnelSetting = toDynamicTunnelSetting cfg serverInfo . parseTunnelInfo $ dynamicToRemote cfg ++ ":127.0.0.1:1212" runClient tunnelSetting | otherwise = do @@ -258,6 +260,7 @@ runApp cfg serverInfo , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg , udpTimeout = Main.udpTimeout cfg , tlsSNI = BC.pack $ Main.tlsSNI cfg + , tlsVerifyCertificate = Main.tlsVerifyCertificate cfg , hostHeader = BC.pack $ Main.hostHeader cfg , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg , customHeaders = parseCustomHeader <$> Main.customHeaders cfg @@ -279,6 +282,7 @@ runApp cfg serverInfo , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg , udpTimeout = Main.udpTimeout cfg , tlsSNI = BC.pack $ Main.tlsSNI cfg + , tlsVerifyCertificate = Main.tlsVerifyCertificate cfg , hostHeader = BC.pack $ Main.hostHeader cfg , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg , customHeaders = parseCustomHeader <$> Main.customHeaders cfg @@ -300,6 +304,7 @@ runApp cfg serverInfo , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg , udpTimeout = Main.udpTimeout cfg , tlsSNI = BC.pack $ Main.tlsSNI cfg + , tlsVerifyCertificate = Main.tlsVerifyCertificate cfg , hostHeader = BC.pack $ Main.hostHeader cfg , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg , customHeaders = parseCustomHeader <$> Main.customHeaders cfg @@ -321,6 +326,7 @@ runApp cfg serverInfo , upgradeCredentials = BC.pack $ wsTunnelCredentials cfg , udpTimeout = Main.udpTimeout cfg , tlsSNI = BC.pack $ Main.tlsSNI cfg + , tlsVerifyCertificate = Main.tlsVerifyCertificate cfg , hostHeader = BC.pack $ Main.hostHeader cfg , websocketPingFrequencySec = Main.websocketPingFrequencySec cfg , customHeaders = parseCustomHeader <$> Main.customHeaders cfg diff --git a/src/Tunnel.hs b/src/Tunnel.hs index 6af014e..4e3f455 100644 --- a/src/Tunnel.hs +++ b/src/Tunnel.hs @@ -97,7 +97,7 @@ tlsClientP TunnelSettings{..} app conn = onError $ do where onError = flip catch (\(e :: SomeException) -> return . throwError . TlsError $ show e) - tlsSettings = NC.TLSSettingsSimple { NC.settingDisableCertificateValidation = True + tlsSettings = NC.TLSSettingsSimple { NC.settingDisableCertificateValidation = not tlsVerifyCertificate , NC.settingDisableSession = False , NC.settingUseServerName = False } diff --git a/src/Types.hs b/src/Types.hs index a7f73d0..832a3fd 100644 --- a/src/Types.hs +++ b/src/Types.hs @@ -15,10 +15,7 @@ import Data.CaseInsensitive ( CI ) import qualified Data.Streaming.Network as N import qualified Network.Connection as NC import Network.Socket (HostName, PortNumber) -import qualified Network.Socket as N hiding (recv, recvFrom, - send, sendTo) -import qualified Network.Socket.ByteString as N - +import qualified Network.Socket as N hiding (recv, recvFrom, send, sendTo) import qualified Network.WebSockets.Connection as WS import System.IO.Unsafe (unsafeDupablePerformIO) @@ -78,6 +75,7 @@ data TunnelSettings = TunnelSettings , upgradeCredentials :: ByteString , tlsSNI :: ByteString + , tlsVerifyCertificate :: Bool , hostHeader :: ByteString , udpTimeout :: Int , websocketPingFrequencySec :: Int