packages feed

hprox 0.5.2 → 0.5.3

raw patch · 5 files changed

+57/−28 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Network.HProx: [_hide] :: Config -> Bool
- Network.HProx: Config :: Maybe String -> Int -> [(String, CertFile)] -> Maybe FilePath -> Maybe String -> Maybe String -> Maybe String -> Bool -> ByteString -> String -> LogLevel -> Config
+ Network.HProx: Config :: Maybe String -> Int -> [(String, CertFile)] -> Maybe FilePath -> Maybe String -> Maybe String -> Maybe String -> Bool -> Bool -> ByteString -> String -> LogLevel -> Config

Files

Changelog.md view
@@ -1,3 +1,10 @@+## 0.5.3++- add macos-aarch64 build+- add `--hide` option for probe resistance+- gracefully close stream for HTTP CONNECT+- `gzip` encoding middleware removed+ ## 0.5.2  - add Windows build
README.md view
@@ -1,6 +1,7 @@ ## hprox  [![CircleCI](https://circleci.com/gh/bjin/hprox.svg?style=shield)](https://circleci.com/gh/bjin/hprox)+[![CirrusCI](https://api.cirrus-ci.com/github/bjin/hprox.svg)](https://cirrus-ci.com/github/bjin/hprox) [![Depends](https://img.shields.io/hackage-deps/v/hprox.svg)](https://packdeps.haskellers.com/feed?needle=hprox) [![Release](https://img.shields.io/github/release/bjin/hprox.svg)](https://github.com/bjin/hprox/releases) [![Hackage](https://img.shields.io/hackage/v/hprox.svg)](https://hackage.haskell.org/package/hprox)@@ -76,7 +77,8 @@  * Passwords are currently stored in plain text, please set permission accordingly and   avoid using existing password.-* HTTP/3 currently only works on the first domain as specified by `-s/--tls`.+* HTTP/3 currently only works on the first domain as specified by `-s/--tls`, also SNI+  validation is unavailable as well.  ### License 
hprox.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.1.+-- This file has been generated from package.yaml by hpack version 0.35.2. -- -- see: https://github.com/sol/hpack  name:           hprox-version:        0.5.2+version:        0.5.3 synopsis:       a lightweight HTTP proxy server, and more description:    Please see the README on GitHub at <https://github.com/bjin/hprox#readme> category:       Web
src/Network/HProx.hs view
@@ -68,6 +68,7 @@   , _ws       :: Maybe String   , _rev      :: Maybe String   , _doh      :: Maybe String+  , _hide     :: Bool   , _naive    :: Bool   , _name     :: BS8.ByteString   , _log      :: String@@ -79,7 +80,7 @@  -- | Default value of 'Config', same as running @hprox@ without arguments defaultConfig :: Config-defaultConfig = Config Nothing 3000 [] Nothing Nothing Nothing Nothing False "hprox" "stdout" INFO+defaultConfig = Config Nothing 3000 [] Nothing Nothing Nothing Nothing False False "hprox" "stdout" INFO #ifdef QUIC_ENABLED     Nothing #endif@@ -116,6 +117,7 @@                     <*> ws                     <*> rev                     <*> doh+                    <*> hide                     <*> naive                     <*> name                     <*> logging@@ -165,6 +167,10 @@        <> metavar "dns-server:port"        <> help "enable DNS-over-HTTPS(DoH) support (53 will be used if port is not specified)") +    hide = switch+        ( long "hide"+       <> help "never send 'proxy authentication required' response (however this might break the use of HTTPS proxy in browser)")+     naive = switch         ( long "naive"        <> help "add naiveproxy compatible padding (requires TLS)")@@ -234,8 +240,7 @@                    setLogger warpLogger $                    setOnException exceptionHandler $                    setNoParsePath True $-                   setServerName _name $-                   defaultSettings+                   setServerName _name defaultSettings          exceptionHandler req ex             | _loglevel > DEBUG                                 = return ()@@ -251,7 +256,7 @@             | Just ConnectionClosedByPeer <- fromException ex   = return ()             | otherwise                                         =                 logger DEBUG $ "exception: " <> toLogStr (displayException ex) <>-                    (if (isJust req) then " from: " <> logRequest (fromJust req) else "")+                    (if isJust req then " from: " <> logRequest (fromJust req) else "")          warpLogger req status _             | rawPathInfo req == "/.hprox/health" = return ()@@ -326,12 +331,11 @@             Just . flip elem . filter (isJust . BS8.elemIndex ':') . BS8.lines <$> BS8.readFile f     manager <- newTlsManager -    let pset = ProxySettings pauth (Just _name) (BS8.pack <$> _ws) (BS8.pack <$> _rev) (_naive && isSSL) logger+    let pset = ProxySettings pauth (Just _name) (BS8.pack <$> _ws) (BS8.pack <$> _rev) _hide (_naive && isSSL) logger         proxy = healthCheckProvider $                 (if isSSL then forceSSL pset else id) $                 httpProxy pset manager $-                reverseProxy pset manager $-                fallback+                reverseProxy pset manager fallback      when (isJust _ws) $ logger INFO $ "websocket redirect: " <> toLogStr (fromJust _ws)     when (isJust _rev) $ logger INFO $ "reverse proxy: " <> toLogStr (fromJust _rev)
src/Network/HProx/Impl.hs view
@@ -15,7 +15,7 @@   ) where  import Control.Applicative        ((<|>))-import Control.Concurrent.Async   (concurrently)+import Control.Concurrent.Async   (cancel, wait, waitEither, withAsync) import Control.Exception          (SomeException, try) import Control.Monad              (unless, void, when) import Control.Monad.IO.Class     (liftIO)@@ -35,23 +35,24 @@     wpsUpgradeToRaw) import Network.HTTP.Types         qualified as HT import Network.HTTP.Types.Header  qualified as HT+import System.Timeout             (timeout)  import Data.Conduit import Data.Maybe import Network.Wai-import Network.Wai.Middleware.Gzip import Network.Wai.Middleware.StripHeaders  import Network.HProx.Log import Network.HProx.Util  data ProxySettings = ProxySettings-  { proxyAuth    :: Maybe (BS.ByteString -> Bool)-  , passPrompt   :: Maybe BS.ByteString-  , wsRemote     :: Maybe BS.ByteString-  , revRemote    :: Maybe BS.ByteString-  , naivePadding :: Bool-  , logger       :: Logger+  { proxyAuth     :: Maybe (BS.ByteString -> Bool)+  , passPrompt    :: Maybe BS.ByteString+  , wsRemote      :: Maybe BS.ByteString+  , revRemote     :: Maybe BS.ByteString+  , hideProxyAuth :: Bool+  , naivePadding  :: Bool+  , logger        :: Logger   }  logRequest :: Request -> LogStr@@ -102,12 +103,15 @@ checkAuth ProxySettings{..} req     | isNothing proxyAuth = True     | isNothing authRsp   = False-    | otherwise           = fromJust proxyAuth decodedRsp+    | otherwise           =+        pureLogger logger TRACE (authMsg <> " request (credential: " <> toLogStr decodedRsp <> ") from " <> toLogStr (show (remoteHost req))) authorized   where     authRsp = lookup HT.hProxyAuthorization (requestHeaders req)-     decodedRsp = decodeLenient $ snd $ BS8.spanEnd (/=' ') $ fromJust authRsp +    authorized = fromJust proxyAuth decodedRsp+    authMsg = if authorized then "authorized" else "unauthorized"+ redirectWebsocket :: ProxySettings -> Request -> Bool redirectWebsocket ProxySettings{..} req = wpsUpgradeToRaw defaultWaiProxySettings req && isJust wsRemote @@ -174,20 +178,17 @@                                      ]  httpGetProxy :: ProxySettings -> HC.Manager -> Middleware-httpGetProxy pset@ProxySettings{..} mgr fallback = appWrapper $ waiProxyToSettings (return.proxyResponseFor) settings mgr+httpGetProxy pset@ProxySettings{..} mgr fallback = waiProxyToSettings (return.proxyResponseFor) settings mgr   where     settings = defaultWaiProxySettings { wpsSetIpHeader = SIHNone } -    appWrapper = ifRequest isGetProxy (gzip def)--    isGetProxy req = case proxyResponseFor req of-        WPRModifiedRequest _ _ -> True-        _                      -> False-     proxyResponseFor req         | redirectWebsocket pset req = wsWrapper (ProxyDest wsHost wsPort)         | not isGETProxy             = WPRApplication fallback         | checkAuth pset req         = WPRModifiedRequest nreq (ProxyDest host port)+        | hideProxyAuth              =+            pureLogger logger WARN ("unauthorized request (hidden without response): " <> logRequest req) $+            WPRApplication fallback         | otherwise                  =             pureLogger logger WARN ("unauthorized request: " <> logRequest req) $             WPRResponse (proxyAuthRequiredResponse pset)@@ -224,6 +225,9 @@ httpConnectProxy pset@ProxySettings{..} fallback req respond     | not isConnectProxy = fallback req respond     | checkAuth pset req = respondResponse+    | hideProxyAuth      = do+        logger WARN $ "unauthorized request (hidden without response): " <> logRequest req+        fallback req respond     | otherwise          = do         logger WARN $ "unauthorized request: " <> logRequest req         respond (proxyAuthRequiredResponse pset)@@ -240,6 +244,17 @@     tryAndCatchAll :: IO a -> IO (Either SomeException a)     tryAndCatchAll = try +    runStreams :: Int -> IO () -> IO () -> IO (Either SomeException ())+    runStreams secs left right = tryAndCatchAll $+        withAsync left $ \l -> do+            withAsync right $ \r -> do+                res1 <- waitEither l r+                let unfinished = case res1 of+                        Left _ -> r+                        _      -> l+                res2 <- timeout (secs * 1000000) (wait unfinished)+                when (isNothing res2) $ cancel unfinished+     respondResponse         | HT.httpMajor (httpVersion req) < 2 = respond $ responseRaw (handleConnect True) backup         | not naivePadding                   = respond $ responseStream HT.status200 [] streaming@@ -311,6 +326,7 @@                            | otherwise        = fromServer .| toClient         in do             when http1 $ runConduit $ yieldHttp1Response .| toClient-            void $ tryAndCatchAll $ concurrently+            -- gracefully close the other stream after 5 seconds if one side of stream is closed.+            void $ runStreams 5                 (runConduit clientToServer)                 (runConduit serverToClient)