Skip to content

Commit

Permalink
Merge pull request #108 from edsko/edsko/configurable-ping-rate-limit
Browse files Browse the repository at this point in the history
Make ping rate limit configurable
  • Loading branch information
kazu-yamamoto committed Feb 29, 2024
2 parents bb2abca + ac3e68e commit 4478e6e
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 20 deletions.
1 change: 1 addition & 0 deletions Network/HTTP2/Client.hs
Expand Up @@ -66,6 +66,7 @@ module Network.HTTP2.Client (
initialWindowSize,
maxFrameSize,
maxHeaderListSize,
pingRateLimit,

-- * Common configuration
Config (..),
Expand Down
2 changes: 1 addition & 1 deletion Network/HTTP2/Client/Run.hs
Expand Up @@ -52,7 +52,7 @@ data ClientConfig = ClientConfig
-- @userinfo\@@ as part of the authority.
--
-- >>> defaultClientConfig
-- ClientConfig {scheme = "http", authority = "localhost", cacheLimit = 64, connectionWindowSize = 1048576, settings = Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}}
-- ClientConfig {scheme = "http", authority = "localhost", cacheLimit = 64, connectionWindowSize = 1048576, settings = Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing, pingRateLimit = 10}}
defaultClientConfig :: ClientConfig
defaultClientConfig =
ClientConfig
Expand Down
8 changes: 2 additions & 6 deletions Network/HTTP2/H2/Receiver.hs
Expand Up @@ -39,9 +39,6 @@ continuationLimit = 10
headerFragmentLimit :: Int
headerFragmentLimit = 51200 -- 50K

pingRateLimit :: Int
pingRateLimit = 4

settingsRateLimit :: Int
settingsRateLimit = 4

Expand Down Expand Up @@ -328,11 +325,10 @@ control FrameSettings header@FrameHeader{flags, streamId} bs Context{myFirstSett
setframe = CFrames (Just peerAlist) (frames ++ [ack])
writeIORef myFirstSettings True
enqueueControl controlQ setframe
control FramePing FrameHeader{flags, streamId} bs Context{controlQ, pingRate} =
control FramePing FrameHeader{flags, streamId} bs Context{mySettings, controlQ, pingRate} =
unless (testAck flags) $ do
-- Ping Flood - CVE-2019-9512
rate <- getRate pingRate
if rate > pingRateLimit
if rate > pingRateLimit mySettings
then E.throwIO $ ConnectionErrorIsSent EnhanceYourCalm streamId "too many ping"
else do
let frame = pingFrame bs
Expand Down
9 changes: 6 additions & 3 deletions Network/HTTP2/H2/Settings.hs
Expand Up @@ -25,13 +25,15 @@ data Settings = Settings
-- ^ SETTINGS_MAX_FRAME_SIZE
, maxHeaderListSize :: Maybe Int
-- ^ SETTINGS_MAX_HEADER_LIST_SIZE
, pingRateLimit :: Int
-- ^ Maximum number of pings allowed per second (CVE-2019-9512)
}
deriving (Eq, Show)

-- | The default settings.
--
-- >>> baseSettings
-- Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Nothing, initialWindowSize = 65535, maxFrameSize = 16384, maxHeaderListSize = Nothing}
-- Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Nothing, initialWindowSize = 65535, maxFrameSize = 16384, maxHeaderListSize = Nothing, pingRateLimit = 10}
baseSettings :: Settings
baseSettings =
Settings
Expand All @@ -41,12 +43,13 @@ baseSettings =
, initialWindowSize = defaultWindowSize -- 64K (65,535)
, maxFrameSize = defaultPayloadLength -- 2^14 (16,384)
, maxHeaderListSize = Nothing
, pingRateLimit = 10
}

-- | The default settings.
--
-- >>> defaultSettings
-- Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}
-- Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing, pingRateLimit = 10}
defaultSettings :: Settings
defaultSettings =
baseSettings
Expand All @@ -59,7 +62,7 @@ defaultSettings =
-- | Updating settings.
--
-- >>> fromSettingsList defaultSettings [(SettingsEnablePush,0),(SettingsMaxHeaderListSize,200)]
-- Settings {headerTableSize = 4096, enablePush = False, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Just 200}
-- Settings {headerTableSize = 4096, enablePush = False, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Just 200, pingRateLimit = 10}
{- FOURMOLU_DISABLE -}
fromSettingsList :: Settings -> SettingsList -> Settings
fromSettingsList settings kvs = foldl' update settings kvs
Expand Down
2 changes: 1 addition & 1 deletion Network/HTTP2/Server/Run.hs
Expand Up @@ -30,7 +30,7 @@ data ServerConfig = ServerConfig
-- | The default server config.
--
-- >>> defaultServerConfig
-- ServerConfig {numberOfWorkers = 8, connectionWindowSize = 1048576, settings = Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing}}
-- ServerConfig {numberOfWorkers = 8, connectionWindowSize = 1048576, settings = Settings {headerTableSize = 4096, enablePush = True, maxConcurrentStreams = Just 64, initialWindowSize = 262144, maxFrameSize = 16384, maxHeaderListSize = Nothing, pingRateLimit = 10}}
defaultServerConfig :: ServerConfig
defaultServerConfig =
ServerConfig
Expand Down
10 changes: 1 addition & 9 deletions test/HTTP2/ServerSpec.hs
Expand Up @@ -345,15 +345,7 @@ rapidPing C.ClientIO{..} = do
let einfo = EncodeInfo defaultFlags 0 Nothing
opaque64 = "01234567"
bs = encodeFrame einfo $ PingFrame opaque64
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
cioWriteBytes bs
replicateM_ 20 $ cioWriteBytes bs

rapidEmptyHeader :: C.ClientIO -> IO ()
rapidEmptyHeader C.ClientIO{..} = do
Expand Down

0 comments on commit 4478e6e

Please sign in to comment.