Better Logging
This commit is contained in:
parent
ca70b8b318
commit
79e0afa224
2 changed files with 60 additions and 26 deletions
|
@ -21,7 +21,7 @@ data WsTunnel = WsTunnel
|
||||||
, proxy :: String
|
, proxy :: String
|
||||||
, serverMode :: Bool
|
, serverMode :: Bool
|
||||||
, restrictTo :: String
|
, restrictTo :: String
|
||||||
, _last :: Bool
|
, verbose :: Bool
|
||||||
} deriving (Show, Data, Typeable)
|
} deriving (Show, Data, Typeable)
|
||||||
|
|
||||||
data WsServerInfo = WsServerInfo
|
data WsServerInfo = WsServerInfo
|
||||||
|
@ -53,7 +53,7 @@ cmdLine = WsTunnel
|
||||||
&= help "Start a server that will forward traffic for you" &= groupname "Server options"
|
&= help "Start a server that will forward traffic for you" &= groupname "Server options"
|
||||||
, restrictTo = def &= explicit &= name "r" &= name "restrictTo"
|
, restrictTo = def &= explicit &= name "r" &= name "restrictTo"
|
||||||
&= help "Accept traffic to be forwarded only to this service" &= typ "HOST:PORT"
|
&= help "Accept traffic to be forwarded only to this service" &= typ "HOST:PORT"
|
||||||
, _last = def &= explicit &= name "ツ" &= groupname "Common options"
|
, verbose = def &= groupname "Common options" &= help "Print debug information"
|
||||||
} &= summary ( "Use the websockets protocol to tunnel {TCP,UDP} traffic\n"
|
} &= summary ( "Use the websockets protocol to tunnel {TCP,UDP} traffic\n"
|
||||||
++ "wsTunnelClient <---> wsTunnelServer <---> RemoteHost\n"
|
++ "wsTunnelClient <---> wsTunnelServer <---> RemoteHost\n"
|
||||||
++ "Use secure connection (wss://) to bypass proxies"
|
++ "Use secure connection (wss://) to bypass proxies"
|
||||||
|
@ -106,7 +106,7 @@ main = do
|
||||||
cfg <- if null args then withArgs ["--help"] (cmdArgs cmdLine) else cmdArgs cmdLine
|
cfg <- if null args then withArgs ["--help"] (cmdArgs cmdLine) else cmdArgs cmdLine
|
||||||
|
|
||||||
let serverInfo = parseServerInfo (WsServerInfo False "" 0) (wsTunnelServer cfg)
|
let serverInfo = parseServerInfo (WsServerInfo False "" 0) (wsTunnelServer cfg)
|
||||||
LOG.updateGlobalLogger "wstunnel" (LOG.setLevel LOG.INFO)
|
LOG.updateGlobalLogger "wstunnel" (if verbose cfg then LOG.setLevel LOG.DEBUG else LOG.setLevel LOG.INFO)
|
||||||
|
|
||||||
|
|
||||||
if serverMode cfg
|
if serverMode cfg
|
||||||
|
|
|
@ -116,9 +116,13 @@ connectionToStream Connection{..} = WS.makeStream read (write . toStrict . from
|
||||||
-- Pipes
|
-- Pipes
|
||||||
--
|
--
|
||||||
tunnelingClientP :: TunnelSettings -> (Connection -> IO (Either Error ())) -> (Connection -> IO (Either Error ()))
|
tunnelingClientP :: TunnelSettings -> (Connection -> IO (Either Error ())) -> (Connection -> IO (Either Error ()))
|
||||||
tunnelingClientP info@TunnelSettings{..} app conn = do
|
tunnelingClientP cfg@TunnelSettings{..} app conn = do
|
||||||
|
debug "Oppening Websocket stream"
|
||||||
stream <- connectionToStream conn
|
stream <- connectionToStream conn
|
||||||
onError $ WS.runClientWithStream stream serverHost (toPath info) WS.defaultConnectionOptions [] (app . toConnection)
|
ret <- onError $ WS.runClientWithStream stream serverHost (toPath cfg) WS.defaultConnectionOptions [] (app . toConnection)
|
||||||
|
|
||||||
|
debug "Closing Websocket stream"
|
||||||
|
return ret
|
||||||
|
|
||||||
where
|
where
|
||||||
onError = flip catch (\(e :: SomeException) -> return . Left . WebsocketError $ show e)
|
onError = flip catch (\(e :: SomeException) -> return . Left . WebsocketError $ show e)
|
||||||
|
@ -137,7 +141,9 @@ tlsClientP TunnelSettings{..} app conn = do
|
||||||
, NC.connectionUseSocks = Nothing
|
, NC.connectionUseSocks = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
onError $ do
|
debug "Doing tls Handshake"
|
||||||
|
|
||||||
|
ret <- onError $ do
|
||||||
context <- NC.initConnectionContext
|
context <- NC.initConnectionContext
|
||||||
let socket = fromJust . N.appRawSocket . fromJust $ rawConnection conn
|
let socket = fromJust . N.appRawSocket . fromJust $ rawConnection conn
|
||||||
h <- N.socketToHandle socket ReadWriteMode
|
h <- N.socketToHandle socket ReadWriteMode
|
||||||
|
@ -145,6 +151,9 @@ tlsClientP TunnelSettings{..} app conn = do
|
||||||
connection <- NC.connectFromHandle context h connectionParams
|
connection <- NC.connectFromHandle context h connectionParams
|
||||||
finally (app (toConnection connection)) (hClose h)
|
finally (app (toConnection connection)) (hClose h)
|
||||||
|
|
||||||
|
debug "Closing TLS"
|
||||||
|
return ret
|
||||||
|
|
||||||
where
|
where
|
||||||
onError = flip catch (\(e :: SomeException) -> return . Left . TlsError $ show e)
|
onError = flip catch (\(e :: SomeException) -> return . Left . TlsError $ show e)
|
||||||
|
|
||||||
|
@ -153,22 +162,41 @@ tlsClientP TunnelSettings{..} app conn = do
|
||||||
-- Connectors
|
-- Connectors
|
||||||
--
|
--
|
||||||
tcpConnection :: TunnelSettings -> (Connection -> IO (Either Error ())) -> IO (Either Error ())
|
tcpConnection :: TunnelSettings -> (Connection -> IO (Either Error ())) -> IO (Either Error ())
|
||||||
tcpConnection TunnelSettings{..} app =
|
tcpConnection TunnelSettings{..} app = do
|
||||||
N.runTCPClient (N.clientSettingsTCP (fromIntegral serverPort) (fromString serverHost)) (app . toConnection)
|
debug $ "Oppening tcp connection to " <> fromString serverHost <> ":" <> show (fromIntegral serverPort :: Int)
|
||||||
`catch`
|
|
||||||
(\(e :: SomeException) -> return $ if take 10 (show e) == "user error" then Right () else Left $ TunnelError $ show e)
|
ret <- onError $ N.runTCPClient (N.clientSettingsTCP (fromIntegral serverPort) (fromString serverHost)) $ \conn -> do
|
||||||
|
ret <- app (toConnection conn)
|
||||||
|
either (info . show) (const $ return ()) ret
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
debug $ "Closing tcp connection to " <> fromString serverHost <> ":" <> show (fromIntegral serverPort :: Int)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
where
|
||||||
|
onError = flip catch (\(e :: SomeException) -> return $ if take 10 (show e) == "user error" then Right () else Left $ TunnelError $ show e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
httpProxyConnection :: (HostName, PortNumber) -> TunnelSettings -> (Connection -> IO (Either Error ())) -> IO (Either Error ())
|
httpProxyConnection :: (HostName, PortNumber) -> TunnelSettings -> (Connection -> IO (Either Error ())) -> IO (Either Error ())
|
||||||
httpProxyConnection (host, port) TunnelSettings{..} app =
|
httpProxyConnection (host, port) TunnelSettings{..} app = do
|
||||||
onError $ N.runTCPClient (N.clientSettingsTCP (fromIntegral port) (fromString host)) $ \conn -> do
|
debug $ "Oppening tcp connection to proxy " <> fromString host <> ":" <> show (fromIntegral port :: Int)
|
||||||
|
|
||||||
|
ret <- onError $ N.runTCPClient (N.clientSettingsTCP (fromIntegral port) (fromString host)) $ \conn -> do
|
||||||
_ <- sendConnectRequest conn
|
_ <- sendConnectRequest conn
|
||||||
responseM <- timeout (1000000 * 10) $ readConnectResponse mempty conn
|
responseM <- timeout (1000000 * 10) $ readConnectResponse mempty conn
|
||||||
let response = fromMaybe "No response of the proxy after 10s" responseM
|
let response = fromMaybe "No response of the proxy after 10s" responseM
|
||||||
|
|
||||||
if isAuthorized response
|
if isAuthorized response
|
||||||
then app (toConnection conn)
|
then do ret <- app (toConnection conn)
|
||||||
|
either (info . show) (const $ return ()) ret
|
||||||
|
return ret
|
||||||
else return . Left . ProxyForwardError $ BC.unpack response
|
else return . Left . ProxyForwardError $ BC.unpack response
|
||||||
|
|
||||||
|
debug $ "Closing tcp connection to proxy " <> fromString host <> ":" <> show (fromIntegral port :: Int)
|
||||||
|
return ret
|
||||||
|
|
||||||
where
|
where
|
||||||
sendConnectRequest h = N.appWrite h $ "CONNECT " <> fromString serverHost <> ":" <> fromString (show serverPort) <> " HTTP/1.0\r\n"
|
sendConnectRequest h = N.appWrite h $ "CONNECT " <> fromString serverHost <> ":" <> fromString (show serverPort) <> " HTTP/1.0\r\n"
|
||||||
<> "Host: " <> fromString serverHost <> ":" <> fromString (show serverPort) <> "\r\n\r\n"
|
<> "Host: " <> fromString serverHost <> ":" <> fromString (show serverPort) <> "\r\n\r\n"
|
||||||
|
@ -190,16 +218,19 @@ httpProxyConnection (host, port) TunnelSettings{..} app =
|
||||||
--
|
--
|
||||||
runClient :: TunnelSettings -> IO ()
|
runClient :: TunnelSettings -> IO ()
|
||||||
runClient cfg@TunnelSettings{..} = do
|
runClient cfg@TunnelSettings{..} = do
|
||||||
let withTcp = if isJust proxySetting then httpProxyConnection (fromJust proxySetting) cfg else tcpConnection cfg
|
let withEndPoint = if isJust proxySetting then httpProxyConnection (fromJust proxySetting) cfg else tcpConnection cfg
|
||||||
let doTlsIf tlsNeeded app = if tlsNeeded then tlsClientP cfg app else app
|
let doTlsIf tlsNeeded app = if tlsNeeded then tlsClientP cfg app else app
|
||||||
let tunnelClient = tunnelingClientP cfg
|
let runTunnelClient = tunnelingClientP cfg
|
||||||
let tunnelServer app = withTcp (doTlsIf useTls . tunnelClient $ app)
|
let withTunnel app = withEndPoint (doTlsIf useTls . runTunnelClient $ app)
|
||||||
|
|
||||||
let app localH = do
|
let app localH = do
|
||||||
|
ret <- withTunnel $ \remoteH -> do
|
||||||
info $ "CREATE tunnel :: " <> show cfg
|
info $ "CREATE tunnel :: " <> show cfg
|
||||||
ret <- tunnelServer (`propagateRW` toConnection localH)
|
ret <- remoteH `propagateRW` toConnection localH
|
||||||
handleError ret
|
|
||||||
info $ "CLOSE tunnel :: " <> show cfg
|
info $ "CLOSE tunnel :: " <> show cfg
|
||||||
|
return ret
|
||||||
|
|
||||||
|
handleError ret
|
||||||
|
|
||||||
case protocol of
|
case protocol of
|
||||||
UDP -> runUDPServer (localBind, localPort) app
|
UDP -> runUDPServer (localBind, localPort) app
|
||||||
|
@ -209,13 +240,16 @@ handleError :: Either Error () -> IO ()
|
||||||
handleError (Right ()) = return ()
|
handleError (Right ()) = return ()
|
||||||
handleError (Left err) =
|
handleError (Left err) =
|
||||||
case err of
|
case err of
|
||||||
ProxyConnectionError msg -> info "Cannot connect to the proxy" >> debug msg
|
ProxyConnectionError msg -> info "Cannot connect to the proxy" >> debugPP msg
|
||||||
ProxyForwardError msg -> info "Connection not allowed by the proxy" >> debug msg
|
ProxyForwardError msg -> info "Connection not allowed by the proxy" >> debugPP msg
|
||||||
TunnelError msg -> info "Cannot establish the connection to the server" >> debug msg
|
TunnelError msg -> info "Cannot establish the connection to the server" >> debugPP msg
|
||||||
LocalServerError msg -> info "Cannot create the localServer, port already binded ?" >> debug msg
|
LocalServerError msg -> info "Cannot create the localServer, port already binded ?" >> debugPP msg
|
||||||
WebsocketError msg -> info "Cannot establish websocket connection with the server" >> debug msg
|
WebsocketError msg -> info "Cannot establish websocket connection with the server" >> debugPP msg
|
||||||
TlsError msg -> info "Cannot do tls handshake with the server" >> debug msg
|
TlsError msg -> info "Cannot do tls handshake with the server" >> debugPP msg
|
||||||
Other msg -> debug msg
|
Other msg -> debugPP msg
|
||||||
|
|
||||||
|
where
|
||||||
|
debugPP msg = debug $ "====\n" <> msg <> "\n===="
|
||||||
|
|
||||||
|
|
||||||
propagateRW :: Connection -> Connection -> IO (Either Error ())
|
propagateRW :: Connection -> Connection -> IO (Either Error ())
|
||||||
|
|
Loading…
Reference in a new issue