Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ping rate limit configurable #108

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Network/HTTP2/Client.hs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading