Skip to content

Commit 2e8af72

Browse files
alexbiehljezen
authored andcommitted
Avoid roundtrip to Text when inspecting x-forwarded-for header
1 parent 08d3b8e commit 2e8af72

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

Network/HTTP/ReverseProxy.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ import Data.Streaming.Network (AppData, readLens)
6363
import qualified Data.Text.Lazy as TL
6464
import qualified Data.Text.Lazy.Encoding as TLE
6565
import qualified Data.Text as T
66-
import qualified Data.Text.Encoding as TE
6766
import Data.Word8 (isSpace, _colon, _cr)
6867
import GHC.Generics (Generic)
6968
import Network.HTTP.Client (BodyReader, brRead)
@@ -362,7 +361,7 @@ fixReqHeaders wps req =
362361
fromSocket = (("X-Real-IP", S8.pack $ showSockAddr $ WAI.remoteHost req):)
363362
fromForwardedFor = do
364363
h <- lookup "x-forwarded-for" (WAI.requestHeaders req)
365-
listToMaybe $ map (TE.encodeUtf8 . T.strip) $ T.splitOn "," $ TE.decodeUtf8 h
364+
listToMaybe $ map S8.strip $ S8.split ',' h
366365
addXRealIP =
367366
case wpsSetIpHeader wps of
368367
SIHFromSocket -> fromSocket

test/main.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,21 @@ main = hspec $
211211
withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do
212212
lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port4
213213
lbs `shouldBe` "127.0.0.1"
214+
it "doesn't fail on invalid utf8 in x-forwarded-for header" $
215+
let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)
216+
httpWithForwardedFor url = liftIO $ do
217+
man <- HC.newManager HC.tlsManagerSettings
218+
oreq <- liftIO $ HC.parseUrlThrow url
219+
let req = oreq { HC.requestHeaders = [("X-Forwarded-For", "\xbf\xf0\x9f\x92\xa1"), ("Connection", "close")] }
220+
HC.responseBody <$> HC.httpLbs req man
221+
waiProxyTo' getDest onError = waiProxyToSettings getDest defaultWaiProxySettings { wpsOnExc = onError, wpsSetIpHeader = SIHFromHeader }
222+
in withMan $ \manager ->
223+
withWApp (\r f -> f $ responseLBS status200 [] $ getRealIp r ) $ \port1 ->
224+
withWApp (waiProxyTo' (const $ return $ WPRProxyDest $ ProxyDest "127.0.0.1" port1) defaultOnExc manager) $ \port2 ->
225+
withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 ->
226+
withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do
227+
lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port4
228+
lbs `shouldBe` "\xbf\xf0\x9f\x92\xa1"
214229
it "performs log action" $
215230
let ioref :: IO (IORef Int)
216231
ioref = newIORef 1

0 commit comments

Comments
 (0)