mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-04 20:05:51 +00:00
@@ -33,11 +33,11 @@
|
|||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/prometheus/Prometheus.hpp"
|
#include "util/prometheus/Prometheus.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
|
||||||
#include "web/IntervalSweepHandler.hpp"
|
|
||||||
#include "web/RPCServerHandler.hpp"
|
#include "web/RPCServerHandler.hpp"
|
||||||
#include "web/Server.hpp"
|
#include "web/Server.hpp"
|
||||||
#include "web/WhitelistHandler.hpp"
|
#include "web/dosguard/DOSGuard.hpp"
|
||||||
|
#include "web/dosguard/IntervalSweepHandler.hpp"
|
||||||
|
#include "web/dosguard/WhitelistHandler.hpp"
|
||||||
|
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
|
||||||
@@ -93,9 +93,9 @@ ClioApplication::run()
|
|||||||
boost::asio::io_context ioc{threads};
|
boost::asio::io_context ioc{threads};
|
||||||
|
|
||||||
// Rate limiter, to prevent abuse
|
// Rate limiter, to prevent abuse
|
||||||
auto whitelistHandler = web::WhitelistHandler{config_};
|
auto whitelistHandler = web::dosguard::WhitelistHandler{config_};
|
||||||
auto dosGuard = web::DOSGuard{config_, whitelistHandler};
|
auto dosGuard = web::dosguard::DOSGuard{config_, whitelistHandler};
|
||||||
auto sweepHandler = web::IntervalSweepHandler{config_, ioc, dosGuard};
|
auto sweepHandler = web::dosguard::IntervalSweepHandler{config_, ioc, dosGuard};
|
||||||
|
|
||||||
// Interface to the database
|
// Interface to the database
|
||||||
auto backend = data::make_Backend(config_);
|
auto backend = data::make_Backend(config_);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "rpc/common/impl/ForwardingProxy.hpp"
|
#include "rpc/common/impl/ForwardingProxy.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "web/Context.hpp"
|
#include "web/Context.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
|
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
@@ -65,7 +65,7 @@ class RPCEngine {
|
|||||||
util::Logger log_{"RPC"};
|
util::Logger log_{"RPC"};
|
||||||
|
|
||||||
std::shared_ptr<BackendInterface> backend_;
|
std::shared_ptr<BackendInterface> backend_;
|
||||||
std::reference_wrapper<web::DOSGuard const> dosGuard_;
|
std::reference_wrapper<web::dosguard::DOSGuardInterface const> dosGuard_;
|
||||||
std::reference_wrapper<WorkQueue> workQueue_;
|
std::reference_wrapper<WorkQueue> workQueue_;
|
||||||
std::reference_wrapper<Counters> counters_;
|
std::reference_wrapper<Counters> counters_;
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
RPCEngine(
|
RPCEngine(
|
||||||
std::shared_ptr<BackendInterface> const& backend,
|
std::shared_ptr<BackendInterface> const& backend,
|
||||||
std::shared_ptr<etl::LoadBalancer> const& balancer,
|
std::shared_ptr<etl::LoadBalancer> const& balancer,
|
||||||
web::DOSGuard const& dosGuard,
|
web::dosguard::DOSGuardInterface const& dosGuard,
|
||||||
WorkQueue& workQueue,
|
WorkQueue& workQueue,
|
||||||
Counters& counters,
|
Counters& counters,
|
||||||
std::shared_ptr<HandlerProvider const> const& handlerProvider
|
std::shared_ptr<HandlerProvider const> const& handlerProvider
|
||||||
@@ -116,7 +116,7 @@ public:
|
|||||||
make_RPCEngine(
|
make_RPCEngine(
|
||||||
std::shared_ptr<BackendInterface> const& backend,
|
std::shared_ptr<BackendInterface> const& backend,
|
||||||
std::shared_ptr<etl::LoadBalancer> const& balancer,
|
std::shared_ptr<etl::LoadBalancer> const& balancer,
|
||||||
web::DOSGuard const& dosGuard,
|
web::dosguard::DOSGuardInterface const& dosGuard,
|
||||||
WorkQueue& workQueue,
|
WorkQueue& workQueue,
|
||||||
Counters& counters,
|
Counters& counters,
|
||||||
std::shared_ptr<HandlerProvider const> const& handlerProvider
|
std::shared_ptr<HandlerProvider const> const& handlerProvider
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
add_library(clio_web)
|
add_library(clio_web)
|
||||||
|
|
||||||
target_sources(
|
target_sources(
|
||||||
clio_web PRIVATE impl/AdminVerificationStrategy.cpp impl/ServerSslContext.cpp IntervalSweepHandler.cpp Resolver.cpp
|
clio_web
|
||||||
Server.cpp
|
PRIVATE Resolver.cpp
|
||||||
|
Server.cpp
|
||||||
|
dosguard/DOSGuard.cpp
|
||||||
|
dosguard/IntervalSweepHandler.cpp
|
||||||
|
dosguard/WhitelistHandler.cpp
|
||||||
|
impl/AdminVerificationStrategy.cpp
|
||||||
|
impl/ServerSslContext.cpp
|
||||||
|
ng/Server.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(clio_web PUBLIC clio_util)
|
target_link_libraries(clio_web PUBLIC clio_util)
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
|
||||||
#include "web/PlainWsSession.hpp"
|
#include "web/PlainWsSession.hpp"
|
||||||
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/impl/HttpBase.hpp"
|
#include "web/impl/HttpBase.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ public:
|
|||||||
std::string const& ip,
|
std::string const& ip,
|
||||||
std::shared_ptr<impl::AdminVerificationStrategy> const& adminVerification,
|
std::shared_ptr<impl::AdminVerificationStrategy> const& adminVerification,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler,
|
std::shared_ptr<HandlerType> const& handler,
|
||||||
boost::beast::flat_buffer buffer
|
boost::beast::flat_buffer buffer
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/impl/WsBase.hpp"
|
#include "web/impl/WsBase.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
boost::asio::ip::tcp::socket&& socket,
|
boost::asio::ip::tcp::socket&& socket,
|
||||||
std::string ip,
|
std::string ip,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler,
|
std::shared_ptr<HandlerType> const& handler,
|
||||||
boost::beast::flat_buffer&& buffer,
|
boost::beast::flat_buffer&& buffer,
|
||||||
bool isAdmin
|
bool isAdmin
|
||||||
@@ -102,7 +102,7 @@ class WsUpgrader : public std::enable_shared_from_this<WsUpgrader<HandlerType>>
|
|||||||
boost::optional<http::request_parser<http::string_body>> parser_;
|
boost::optional<http::request_parser<http::string_body>> parser_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard_;
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
std::string ip_;
|
std::string ip_;
|
||||||
std::shared_ptr<HandlerType> const handler_;
|
std::shared_ptr<HandlerType> const handler_;
|
||||||
@@ -125,7 +125,7 @@ public:
|
|||||||
boost::beast::tcp_stream&& stream,
|
boost::beast::tcp_stream&& stream,
|
||||||
std::string ip,
|
std::string ip,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler,
|
std::shared_ptr<HandlerType> const& handler,
|
||||||
boost::beast::flat_buffer&& buffer,
|
boost::beast::flat_buffer&& buffer,
|
||||||
http::request<http::string_body> request,
|
http::request<http::string_body> request,
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
|
||||||
#include "web/HttpSession.hpp"
|
#include "web/HttpSession.hpp"
|
||||||
#include "web/SslHttpSession.hpp"
|
#include "web/SslHttpSession.hpp"
|
||||||
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/impl/ServerSslContext.hpp"
|
#include "web/impl/ServerSslContext.hpp"
|
||||||
#include "web/interface/Concepts.hpp"
|
#include "web/interface/Concepts.hpp"
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ class Detector : public std::enable_shared_from_this<Detector<PlainSessionType,
|
|||||||
boost::beast::tcp_stream stream_;
|
boost::beast::tcp_stream stream_;
|
||||||
std::optional<std::reference_wrapper<boost::asio::ssl::context>> ctx_;
|
std::optional<std::reference_wrapper<boost::asio::ssl::context>> ctx_;
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
||||||
std::reference_wrapper<web::DOSGuard> const dosGuard_;
|
std::reference_wrapper<dosguard::DOSGuardInterface> const dosGuard_;
|
||||||
std::shared_ptr<HandlerType> const handler_;
|
std::shared_ptr<HandlerType> const handler_;
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::shared_ptr<impl::AdminVerificationStrategy> const adminVerification_;
|
std::shared_ptr<impl::AdminVerificationStrategy> const adminVerification_;
|
||||||
@@ -111,7 +111,7 @@ public:
|
|||||||
tcp::socket&& socket,
|
tcp::socket&& socket,
|
||||||
std::optional<std::reference_wrapper<boost::asio::ssl::context>> ctx,
|
std::optional<std::reference_wrapper<boost::asio::ssl::context>> ctx,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> handler,
|
std::shared_ptr<HandlerType> handler,
|
||||||
std::shared_ptr<impl::AdminVerificationStrategy> adminVerification
|
std::shared_ptr<impl::AdminVerificationStrategy> adminVerification
|
||||||
)
|
)
|
||||||
@@ -213,7 +213,7 @@ class Server : public std::enable_shared_from_this<Server<PlainSessionType, SslS
|
|||||||
std::reference_wrapper<boost::asio::io_context> ioc_;
|
std::reference_wrapper<boost::asio::io_context> ioc_;
|
||||||
std::optional<boost::asio::ssl::context> ctx_;
|
std::optional<boost::asio::ssl::context> ctx_;
|
||||||
util::TagDecoratorFactory tagFactory_;
|
util::TagDecoratorFactory tagFactory_;
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard_;
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||||
std::shared_ptr<HandlerType> handler_;
|
std::shared_ptr<HandlerType> handler_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
std::shared_ptr<impl::AdminVerificationStrategy> adminVerification_;
|
std::shared_ptr<impl::AdminVerificationStrategy> adminVerification_;
|
||||||
@@ -235,7 +235,7 @@ public:
|
|||||||
std::optional<boost::asio::ssl::context> ctx,
|
std::optional<boost::asio::ssl::context> ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
util::TagDecoratorFactory tagFactory,
|
util::TagDecoratorFactory tagFactory,
|
||||||
web::DOSGuard& dosGuard,
|
dosguard::DOSGuardInterface& dosGuard,
|
||||||
std::shared_ptr<HandlerType> handler,
|
std::shared_ptr<HandlerType> handler,
|
||||||
std::optional<std::string> adminPassword
|
std::optional<std::string> adminPassword
|
||||||
)
|
)
|
||||||
@@ -327,7 +327,7 @@ static std::shared_ptr<HttpServer<HandlerType>>
|
|||||||
make_HttpServer(
|
make_HttpServer(
|
||||||
util::Config const& config,
|
util::Config const& config,
|
||||||
boost::asio::io_context& ioc,
|
boost::asio::io_context& ioc,
|
||||||
web::DOSGuard& dosGuard,
|
dosguard::DOSGuardInterface& dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler
|
std::shared_ptr<HandlerType> const& handler
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,9 +20,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
|
||||||
#include "web/SslWsSession.hpp"
|
#include "web/SslWsSession.hpp"
|
||||||
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/impl/HttpBase.hpp"
|
#include "web/impl/HttpBase.hpp"
|
||||||
|
#include "web/interface/Concepts.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
|
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
@@ -78,7 +79,7 @@ public:
|
|||||||
std::shared_ptr<impl::AdminVerificationStrategy> const& adminVerification,
|
std::shared_ptr<impl::AdminVerificationStrategy> const& adminVerification,
|
||||||
boost::asio::ssl::context& ctx,
|
boost::asio::ssl::context& ctx,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler,
|
std::shared_ptr<HandlerType> const& handler,
|
||||||
boost::beast::flat_buffer buffer
|
boost::beast::flat_buffer buffer
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/impl/WsBase.hpp"
|
#include "web/impl/WsBase.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ public:
|
|||||||
boost::beast::ssl_stream<boost::beast::tcp_stream>&& stream,
|
boost::beast::ssl_stream<boost::beast::tcp_stream>&& stream,
|
||||||
std::string ip,
|
std::string ip,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler,
|
std::shared_ptr<HandlerType> const& handler,
|
||||||
boost::beast::flat_buffer&& buffer,
|
boost::beast::flat_buffer&& buffer,
|
||||||
bool isAdmin
|
bool isAdmin
|
||||||
@@ -102,7 +102,7 @@ class SslWsUpgrader : public std::enable_shared_from_this<SslWsUpgrader<HandlerT
|
|||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::string ip_;
|
std::string ip_;
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard_;
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||||
std::shared_ptr<HandlerType> const handler_;
|
std::shared_ptr<HandlerType> const handler_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
bool isAdmin_;
|
bool isAdmin_;
|
||||||
@@ -124,7 +124,7 @@ public:
|
|||||||
boost::beast::ssl_stream<boost::beast::tcp_stream> stream,
|
boost::beast::ssl_stream<boost::beast::tcp_stream> stream,
|
||||||
std::string ip,
|
std::string ip,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> handler,
|
std::shared_ptr<HandlerType> handler,
|
||||||
boost::beast::flat_buffer&& buffer,
|
boost::beast::flat_buffer&& buffer,
|
||||||
http::request<http::string_body> request,
|
http::request<http::string_body> request,
|
||||||
|
|||||||
148
src/web/dosguard/DOSGuard.cpp
Normal file
148
src/web/dosguard/DOSGuard.cpp
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "web/dosguard/DOSGuard.hpp"
|
||||||
|
|
||||||
|
#include "util/Assert.hpp"
|
||||||
|
#include "util/config/Config.hpp"
|
||||||
|
#include "util/log/Logger.hpp"
|
||||||
|
#include "web/dosguard/WhitelistHandlerInterface.hpp"
|
||||||
|
|
||||||
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace web::dosguard {
|
||||||
|
|
||||||
|
DOSGuard::DOSGuard(util::Config const& config, WhitelistHandlerInterface const& whitelistHandler)
|
||||||
|
: whitelistHandler_{std::cref(whitelistHandler)}
|
||||||
|
, maxFetches_{config.valueOr("dos_guard.max_fetches", DEFAULT_MAX_FETCHES)}
|
||||||
|
, maxConnCount_{config.valueOr("dos_guard.max_connections", DEFAULT_MAX_CONNECTIONS)}
|
||||||
|
, maxRequestCount_{config.valueOr("dos_guard.max_requests", DEFAULT_MAX_REQUESTS)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
DOSGuard::isWhiteListed(std::string_view const ip) const noexcept
|
||||||
|
{
|
||||||
|
return whitelistHandler_.get().isWhiteListed(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
DOSGuard::isOk(std::string const& ip) const noexcept
|
||||||
|
{
|
||||||
|
if (whitelistHandler_.get().isWhiteListed(ip))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock const lck(mtx_);
|
||||||
|
if (ipState_.find(ip) != ipState_.end()) {
|
||||||
|
auto [transferedByte, requests] = ipState_.at(ip);
|
||||||
|
if (transferedByte > maxFetches_ || requests > maxRequestCount_) {
|
||||||
|
LOG(log_.warn()) << "Dosguard: Client surpassed the rate limit. ip = " << ip
|
||||||
|
<< " Transfered Byte: " << transferedByte << "; Requests: " << requests;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto it = ipConnCount_.find(ip);
|
||||||
|
if (it != ipConnCount_.end()) {
|
||||||
|
if (it->second > maxConnCount_) {
|
||||||
|
LOG(log_.warn()) << "Dosguard: Client surpassed the rate limit. ip = " << ip
|
||||||
|
<< " Concurrent connection: " << it->second;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DOSGuard::increment(std::string const& ip) noexcept
|
||||||
|
{
|
||||||
|
if (whitelistHandler_.get().isWhiteListed(ip))
|
||||||
|
return;
|
||||||
|
std::scoped_lock const lck{mtx_};
|
||||||
|
ipConnCount_[ip]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DOSGuard::decrement(std::string const& ip) noexcept
|
||||||
|
{
|
||||||
|
if (whitelistHandler_.get().isWhiteListed(ip))
|
||||||
|
return;
|
||||||
|
std::scoped_lock const lck{mtx_};
|
||||||
|
ASSERT(ipConnCount_[ip] > 0, "Connection count for ip {} can't be 0", ip);
|
||||||
|
ipConnCount_[ip]--;
|
||||||
|
if (ipConnCount_[ip] == 0)
|
||||||
|
ipConnCount_.erase(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] bool
|
||||||
|
DOSGuard::add(std::string const& ip, uint32_t numObjects) noexcept
|
||||||
|
{
|
||||||
|
if (whitelistHandler_.get().isWhiteListed(ip))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock const lck(mtx_);
|
||||||
|
ipState_[ip].transferedByte += numObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isOk(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] bool
|
||||||
|
DOSGuard::request(std::string const& ip) noexcept
|
||||||
|
{
|
||||||
|
if (whitelistHandler_.get().isWhiteListed(ip))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock const lck(mtx_);
|
||||||
|
ipState_[ip].requestsCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isOk(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DOSGuard::clear() noexcept
|
||||||
|
{
|
||||||
|
std::scoped_lock const lck(mtx_);
|
||||||
|
ipState_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::unordered_set<std::string>
|
||||||
|
DOSGuard::getWhitelist(util::Config const& config)
|
||||||
|
{
|
||||||
|
using T = std::unordered_set<std::string> const;
|
||||||
|
auto whitelist = config.arrayOr("dos_guard.whitelist", {});
|
||||||
|
auto const transform = [](auto const& elem) { return elem.template value<std::string>(); };
|
||||||
|
return T{
|
||||||
|
boost::transform_iterator(std::begin(whitelist), transform),
|
||||||
|
boost::transform_iterator(std::end(whitelist), transform)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace web::dosguard
|
||||||
@@ -19,11 +19,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/Assert.hpp"
|
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "web/IntervalSweepHandler.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/WhitelistHandler.hpp"
|
#include "web/dosguard/WhitelistHandlerInterface.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/iterator/transform_iterator.hpp>
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
@@ -31,48 +30,32 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iterator>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace web {
|
namespace web::dosguard {
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The interface of a denial of service guard.
|
|
||||||
*/
|
|
||||||
class BaseDOSGuard {
|
|
||||||
public:
|
|
||||||
virtual ~BaseDOSGuard() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clears implementation-defined counters.
|
|
||||||
*/
|
|
||||||
virtual void
|
|
||||||
clear() noexcept = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A simple denial of service guard used for rate limiting.
|
* @brief A simple denial of service guard used for rate limiting.
|
||||||
*
|
*
|
||||||
* @tparam WhitelistHandlerType The type of the whitelist handler
|
* @tparam WhitelistHandlerType The type of the whitelist handler
|
||||||
*/
|
*/
|
||||||
template <typename WhitelistHandlerType>
|
class DOSGuard : public DOSGuardInterface {
|
||||||
class BasicDOSGuard : public BaseDOSGuard {
|
|
||||||
/**
|
/**
|
||||||
* @brief Accumulated state per IP, state will be reset accordingly
|
* @brief Accumulated state per IP, state will be reset accordingly
|
||||||
*/
|
*/
|
||||||
struct ClientState {
|
struct ClientState {
|
||||||
std::uint32_t transferedByte = 0; /**< Accumulated transfered byte */
|
std::uint32_t transferedByte = 0; /**< Accumulated transferred byte */
|
||||||
std::uint32_t requestsCount = 0; /**< Accumulated served requests count */
|
std::uint32_t requestsCount = 0; /**< Accumulated served requests count */
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable std::mutex mtx_;
|
mutable std::mutex mtx_;
|
||||||
std::unordered_map<std::string, ClientState> ipState_;
|
std::unordered_map<std::string, ClientState> ipState_;
|
||||||
std::unordered_map<std::string, std::uint32_t> ipConnCount_;
|
std::unordered_map<std::string, std::uint32_t> ipConnCount_;
|
||||||
std::reference_wrapper<WhitelistHandlerType const> whitelistHandler_;
|
std::reference_wrapper<WhitelistHandlerInterface const> whitelistHandler_;
|
||||||
|
|
||||||
std::uint32_t const maxFetches_;
|
std::uint32_t const maxFetches_;
|
||||||
std::uint32_t const maxConnCount_;
|
std::uint32_t const maxConnCount_;
|
||||||
@@ -90,13 +73,7 @@ public:
|
|||||||
* @param config Clio config
|
* @param config Clio config
|
||||||
* @param whitelistHandler Whitelist handler that checks whitelist for IP addresses
|
* @param whitelistHandler Whitelist handler that checks whitelist for IP addresses
|
||||||
*/
|
*/
|
||||||
BasicDOSGuard(util::Config const& config, WhitelistHandlerType const& whitelistHandler)
|
DOSGuard(util::Config const& config, WhitelistHandlerInterface const& whitelistHandler);
|
||||||
: whitelistHandler_{std::cref(whitelistHandler)}
|
|
||||||
, maxFetches_{config.valueOr("dos_guard.max_fetches", DEFAULT_MAX_FETCHES)}
|
|
||||||
, maxConnCount_{config.valueOr("dos_guard.max_connections", DEFAULT_MAX_CONNECTIONS)}
|
|
||||||
, maxRequestCount_{config.valueOr("dos_guard.max_requests", DEFAULT_MAX_REQUESTS)}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check whether an ip address is in the whitelist or not.
|
* @brief Check whether an ip address is in the whitelist or not.
|
||||||
@@ -106,10 +83,7 @@ public:
|
|||||||
* @return false
|
* @return false
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
isWhiteListed(std::string_view const ip) const noexcept
|
isWhiteListed(std::string_view const ip) const noexcept override;
|
||||||
{
|
|
||||||
return whitelistHandler_.get().isWhiteListed(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check whether an ip address is currently rate limited or not.
|
* @brief Check whether an ip address is currently rate limited or not.
|
||||||
@@ -119,32 +93,7 @@ public:
|
|||||||
* @return false If rate limited and the request should not be processed
|
* @return false If rate limited and the request should not be processed
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
isOk(std::string const& ip) const noexcept
|
isOk(std::string const& ip) const noexcept override;
|
||||||
{
|
|
||||||
if (whitelistHandler_.get().isWhiteListed(ip))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::scoped_lock const lck(mtx_);
|
|
||||||
if (ipState_.find(ip) != ipState_.end()) {
|
|
||||||
auto [transferedByte, requests] = ipState_.at(ip);
|
|
||||||
if (transferedByte > maxFetches_ || requests > maxRequestCount_) {
|
|
||||||
LOG(log_.warn()) << "Dosguard: Client surpassed the rate limit. ip = " << ip
|
|
||||||
<< " Transfered Byte: " << transferedByte << "; Requests: " << requests;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto it = ipConnCount_.find(ip);
|
|
||||||
if (it != ipConnCount_.end()) {
|
|
||||||
if (it->second > maxConnCount_) {
|
|
||||||
LOG(log_.warn()) << "Dosguard: Client surpassed the rate limit. ip = " << ip
|
|
||||||
<< " Concurrent connection: " << it->second;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Increment connection count for the given ip address.
|
* @brief Increment connection count for the given ip address.
|
||||||
@@ -152,13 +101,7 @@ public:
|
|||||||
* @param ip
|
* @param ip
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
increment(std::string const& ip) noexcept
|
increment(std::string const& ip) noexcept override;
|
||||||
{
|
|
||||||
if (whitelistHandler_.get().isWhiteListed(ip))
|
|
||||||
return;
|
|
||||||
std::scoped_lock const lck{mtx_};
|
|
||||||
ipConnCount_[ip]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decrement connection count for the given ip address.
|
* @brief Decrement connection count for the given ip address.
|
||||||
@@ -166,16 +109,7 @@ public:
|
|||||||
* @param ip
|
* @param ip
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
decrement(std::string const& ip) noexcept
|
decrement(std::string const& ip) noexcept override;
|
||||||
{
|
|
||||||
if (whitelistHandler_.get().isWhiteListed(ip))
|
|
||||||
return;
|
|
||||||
std::scoped_lock const lck{mtx_};
|
|
||||||
ASSERT(ipConnCount_[ip] > 0, "Connection count for ip {} can't be 0", ip);
|
|
||||||
ipConnCount_[ip]--;
|
|
||||||
if (ipConnCount_[ip] == 0)
|
|
||||||
ipConnCount_.erase(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds numObjects of usage for the given ip address.
|
* @brief Adds numObjects of usage for the given ip address.
|
||||||
@@ -190,18 +124,7 @@ public:
|
|||||||
* @return false
|
* @return false
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]] bool
|
[[maybe_unused]] bool
|
||||||
add(std::string const& ip, uint32_t numObjects) noexcept
|
add(std::string const& ip, uint32_t numObjects) noexcept override;
|
||||||
{
|
|
||||||
if (whitelistHandler_.get().isWhiteListed(ip))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::scoped_lock const lck(mtx_);
|
|
||||||
ipState_[ip].transferedByte += numObjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isOk(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds one request for the given ip address.
|
* @brief Adds one request for the given ip address.
|
||||||
@@ -215,46 +138,17 @@ public:
|
|||||||
* @return false
|
* @return false
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]] bool
|
[[maybe_unused]] bool
|
||||||
request(std::string const& ip) noexcept
|
request(std::string const& ip) noexcept override;
|
||||||
{
|
|
||||||
if (whitelistHandler_.get().isWhiteListed(ip))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::scoped_lock const lck(mtx_);
|
|
||||||
ipState_[ip].requestsCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isOk(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Instantly clears all fetch counters added by @see add(std::string const&, uint32_t).
|
* @brief Instantly clears all fetch counters added by @see add(std::string const&, uint32_t).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clear() noexcept override
|
clear() noexcept override;
|
||||||
{
|
|
||||||
std::scoped_lock const lck(mtx_);
|
|
||||||
ipState_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] std::unordered_set<std::string>
|
[[nodiscard]] static std::unordered_set<std::string>
|
||||||
getWhitelist(util::Config const& config) const
|
getWhitelist(util::Config const& config);
|
||||||
{
|
|
||||||
using T = std::unordered_set<std::string> const;
|
|
||||||
auto whitelist = config.arrayOr("dos_guard.whitelist", {});
|
|
||||||
auto const transform = [](auto const& elem) { return elem.template value<std::string>(); };
|
|
||||||
return T{
|
|
||||||
boost::transform_iterator(std::begin(whitelist), transform),
|
|
||||||
boost::transform_iterator(std::end(whitelist), transform)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
} // namespace web::dosguard
|
||||||
* @brief A simple denial of service guard used for rate limiting.
|
|
||||||
*/
|
|
||||||
using DOSGuard = BasicDOSGuard<web::WhitelistHandler>;
|
|
||||||
|
|
||||||
} // namespace web
|
|
||||||
110
src/web/dosguard/DOSGuardInterface.hpp
Normal file
110
src/web/dosguard/DOSGuardInterface.hpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
namespace web::dosguard {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The interface of a denial of service guard.
|
||||||
|
*/
|
||||||
|
class BaseDOSGuard {
|
||||||
|
public:
|
||||||
|
virtual ~BaseDOSGuard() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears implementation-defined counters.
|
||||||
|
*/
|
||||||
|
virtual void
|
||||||
|
clear() noexcept = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The interface of a denial of service guard.
|
||||||
|
*/
|
||||||
|
class DOSGuardInterface : public BaseDOSGuard {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Check whether an ip address is in the whitelist or not.
|
||||||
|
*
|
||||||
|
* @param ip The ip address to check
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual bool
|
||||||
|
isWhiteListed(std::string_view const ip) const noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether an ip address is currently rate limited or not.
|
||||||
|
*
|
||||||
|
* @param ip The ip address to check
|
||||||
|
* @return true If not rate limited
|
||||||
|
* @return false If rate limited and the request should not be processed
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual bool
|
||||||
|
isOk(std::string const& ip) const noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Increment connection count for the given ip address.
|
||||||
|
*
|
||||||
|
* @param ip
|
||||||
|
*/
|
||||||
|
virtual void
|
||||||
|
increment(std::string const& ip) noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decrement connection count for the given ip address.
|
||||||
|
*
|
||||||
|
* @param ip
|
||||||
|
*/
|
||||||
|
virtual void
|
||||||
|
decrement(std::string const& ip) noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds numObjects of usage for the given ip address.
|
||||||
|
*
|
||||||
|
* If the total sums up to a value equal or larger than maxFetches_
|
||||||
|
* the operation is no longer allowed and false is returned; true is
|
||||||
|
* returned otherwise.
|
||||||
|
*
|
||||||
|
* @param ip
|
||||||
|
* @param numObjects
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
[[maybe_unused]] virtual bool
|
||||||
|
add(std::string const& ip, uint32_t numObjects) noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds one request for the given ip address.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param ip
|
||||||
|
* @return If the total sums up to a value equal or larger than maxRequestCount_
|
||||||
|
* the operation is no longer allowed and false is returned; true is
|
||||||
|
* returned otherwise.
|
||||||
|
*/
|
||||||
|
[[maybe_unused]] virtual bool
|
||||||
|
request(std::string const& ip) noexcept = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace web::dosguard
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include "web/IntervalSweepHandler.hpp"
|
#include "web/dosguard/IntervalSweepHandler.hpp"
|
||||||
|
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
|
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/system/detail/error_code.hpp>
|
#include <boost/system/detail/error_code.hpp>
|
||||||
@@ -29,12 +29,12 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace web {
|
namespace web::dosguard {
|
||||||
|
|
||||||
IntervalSweepHandler::IntervalSweepHandler(
|
IntervalSweepHandler::IntervalSweepHandler(
|
||||||
util::Config const& config,
|
util::Config const& config,
|
||||||
boost::asio::io_context& ctx,
|
boost::asio::io_context& ctx,
|
||||||
web::BaseDOSGuard& dosGuard
|
BaseDOSGuard& dosGuard
|
||||||
)
|
)
|
||||||
: repeat_{std::ref(ctx)}
|
: repeat_{std::ref(ctx)}
|
||||||
{
|
{
|
||||||
@@ -44,4 +44,4 @@ IntervalSweepHandler::IntervalSweepHandler(
|
|||||||
repeat_.start(sweepInterval, [&dosGuard] { dosGuard.clear(); });
|
repeat_.start(sweepInterval, [&dosGuard] { dosGuard.clear(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace web
|
} // namespace web::dosguard
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
|
||||||
namespace web {
|
namespace web::dosguard {
|
||||||
|
|
||||||
class BaseDOSGuard;
|
class BaseDOSGuard;
|
||||||
|
|
||||||
@@ -42,7 +42,11 @@ public:
|
|||||||
* @param ctx The boost::asio::io_context to use
|
* @param ctx The boost::asio::io_context to use
|
||||||
* @param dosGuard The DOS guard to use
|
* @param dosGuard The DOS guard to use
|
||||||
*/
|
*/
|
||||||
IntervalSweepHandler(util::Config const& config, boost::asio::io_context& ctx, web::BaseDOSGuard& dosGuard);
|
IntervalSweepHandler(
|
||||||
|
util::Config const& config,
|
||||||
|
boost::asio::io_context& ctx,
|
||||||
|
web::dosguard::BaseDOSGuard& dosGuard
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace web
|
} // namespace web::dosguard
|
||||||
118
src/web/dosguard/WhitelistHandler.cpp
Normal file
118
src/web/dosguard/WhitelistHandler.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "web/dosguard/WhitelistHandler.hpp"
|
||||||
|
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/ip/address.hpp>
|
||||||
|
#include <boost/asio/ip/network_v4.hpp>
|
||||||
|
#include <boost/asio/ip/network_v6.hpp>
|
||||||
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <regex>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace web::dosguard {
|
||||||
|
|
||||||
|
void
|
||||||
|
Whitelist::add(std::string_view net)
|
||||||
|
{
|
||||||
|
using namespace boost::asio;
|
||||||
|
|
||||||
|
if (not isMask(net)) {
|
||||||
|
ips_.push_back(ip::make_address(net));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isV4(net)) {
|
||||||
|
subnetsV4_.push_back(ip::make_network_v4(net));
|
||||||
|
} else if (isV6(net)) {
|
||||||
|
subnetsV6_.push_back(ip::make_network_v6(net));
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error(fmt::format("malformed network: {}", net.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Whitelist::isWhiteListed(std::string_view ip) const
|
||||||
|
{
|
||||||
|
using namespace boost::asio;
|
||||||
|
|
||||||
|
auto const addr = ip::make_address(ip);
|
||||||
|
if (std::find(std::begin(ips_), std::end(ips_), addr) != std::end(ips_))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (addr.is_v4()) {
|
||||||
|
return std::find_if(
|
||||||
|
std::begin(subnetsV4_), std::end(subnetsV4_), std::bind_front(&isInV4Subnet, std::cref(addr))
|
||||||
|
) != std::end(subnetsV4_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr.is_v6()) {
|
||||||
|
return std::find_if(
|
||||||
|
std::begin(subnetsV6_), std::end(subnetsV6_), std::bind_front(&isInV6Subnet, std::cref(addr))
|
||||||
|
) != std::end(subnetsV6_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Whitelist::isInV4Subnet(boost::asio::ip::address const& addr, boost::asio::ip::network_v4 const& subnet)
|
||||||
|
{
|
||||||
|
auto const range = subnet.hosts();
|
||||||
|
return range.find(addr.to_v4()) != range.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Whitelist::isInV6Subnet(boost::asio::ip::address const& addr, boost::asio::ip::network_v6 const& subnet)
|
||||||
|
{
|
||||||
|
auto const range = subnet.hosts();
|
||||||
|
return range.find(addr.to_v6()) != range.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Whitelist::isV4(std::string_view net)
|
||||||
|
{
|
||||||
|
static std::regex const ipv4CidrRegex(R"(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}$)");
|
||||||
|
return std::regex_match(std::string(net), ipv4CidrRegex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Whitelist::isV6(std::string_view net)
|
||||||
|
{
|
||||||
|
static std::regex const ipv6CidrRegex(R"(^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}/\d{1,3}$)");
|
||||||
|
return std::regex_match(std::string(net), ipv6CidrRegex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Whitelist::isMask(std::string_view net)
|
||||||
|
{
|
||||||
|
return net.find('/') != std::string_view::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace web::dosguard
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "web/Resolver.hpp"
|
#include "web/Resolver.hpp"
|
||||||
|
#include "web/dosguard/WhitelistHandlerInterface.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/asio/ip/address.hpp>
|
#include <boost/asio/ip/address.hpp>
|
||||||
@@ -30,16 +31,14 @@
|
|||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace web {
|
namespace web::dosguard {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A whitelist to remove rate limits of certain IP addresses.
|
* @brief A whitelist to remove rate limits of certain IP addresses.
|
||||||
@@ -57,23 +56,7 @@ public:
|
|||||||
* @throws std::runtime::error when the network address is not valid
|
* @throws std::runtime::error when the network address is not valid
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
add(std::string_view net)
|
add(std::string_view net);
|
||||||
{
|
|
||||||
using namespace boost::asio;
|
|
||||||
|
|
||||||
if (not isMask(net)) {
|
|
||||||
ips_.push_back(ip::make_address(net));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isV4(net)) {
|
|
||||||
subnetsV4_.push_back(ip::make_network_v4(net));
|
|
||||||
} else if (isV6(net)) {
|
|
||||||
subnetsV6_.push_back(ip::make_network_v6(net));
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error(fmt::format("malformed network: {}", net.data()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks to see if ip address is whitelisted.
|
* @brief Checks to see if ip address is whitelisted.
|
||||||
@@ -83,69 +66,29 @@ public:
|
|||||||
* @return true if the given IP is whitelisted; false otherwise
|
* @return true if the given IP is whitelisted; false otherwise
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
isWhiteListed(std::string_view ip) const
|
isWhiteListed(std::string_view ip) const;
|
||||||
{
|
|
||||||
using namespace boost::asio;
|
|
||||||
|
|
||||||
auto const addr = ip::make_address(ip);
|
|
||||||
if (std::find(std::begin(ips_), std::end(ips_), addr) != std::end(ips_))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (addr.is_v4()) {
|
|
||||||
return std::find_if(
|
|
||||||
std::begin(subnetsV4_), std::end(subnetsV4_), std::bind_front(&isInV4Subnet, std::cref(addr))
|
|
||||||
) != std::end(subnetsV4_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr.is_v6()) {
|
|
||||||
return std::find_if(
|
|
||||||
std::begin(subnetsV6_), std::end(subnetsV6_), std::bind_front(&isInV6Subnet, std::cref(addr))
|
|
||||||
) != std::end(subnetsV6_);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool
|
static bool
|
||||||
isInV4Subnet(boost::asio::ip::address const& addr, boost::asio::ip::network_v4 const& subnet)
|
isInV4Subnet(boost::asio::ip::address const& addr, boost::asio::ip::network_v4 const& subnet);
|
||||||
{
|
|
||||||
auto const range = subnet.hosts();
|
|
||||||
return range.find(addr.to_v4()) != range.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
isInV6Subnet(boost::asio::ip::address const& addr, boost::asio::ip::network_v6 const& subnet)
|
isInV6Subnet(boost::asio::ip::address const& addr, boost::asio::ip::network_v6 const& subnet);
|
||||||
{
|
|
||||||
auto const range = subnet.hosts();
|
|
||||||
return range.find(addr.to_v6()) != range.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
isV4(std::string_view net)
|
isV4(std::string_view net);
|
||||||
{
|
|
||||||
static std::regex const ipv4CidrRegex(R"(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}$)");
|
|
||||||
return std::regex_match(std::string(net), ipv4CidrRegex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
isV6(std::string_view net)
|
isV6(std::string_view net);
|
||||||
{
|
|
||||||
static std::regex const ipv6CidrRegex(R"(^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}/\d{1,3}$)");
|
|
||||||
return std::regex_match(std::string(net), ipv6CidrRegex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
isMask(std::string_view net)
|
isMask(std::string_view net);
|
||||||
{
|
|
||||||
return net.find('/') != std::string_view::npos;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A simple handler to add/check elements in a whitelist.
|
* @brief A simple handler to add/check elements in a whitelist.
|
||||||
*/
|
*/
|
||||||
class WhitelistHandler {
|
class WhitelistHandler : public WhitelistHandlerInterface {
|
||||||
Whitelist whitelist_;
|
Whitelist whitelist_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -170,7 +113,7 @@ public:
|
|||||||
* @return true if the given IP is whitelisted; false otherwise
|
* @return true if the given IP is whitelisted; false otherwise
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
isWhiteListed(std::string_view ip) const
|
isWhiteListed(std::string_view ip) const override
|
||||||
{
|
{
|
||||||
return whitelist_.isWhiteListed(ip);
|
return whitelist_.isWhiteListed(ip);
|
||||||
}
|
}
|
||||||
@@ -200,4 +143,4 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace web
|
} // namespace web::dosguard
|
||||||
44
src/web/dosguard/WhitelistHandlerInterface.hpp
Normal file
44
src/web/dosguard/WhitelistHandlerInterface.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of clio: https://github.com/XRPLF/clio
|
||||||
|
Copyright (c) 2024, the clio developers.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace web::dosguard {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface for a whitelist handler
|
||||||
|
*/
|
||||||
|
class WhitelistHandlerInterface {
|
||||||
|
public:
|
||||||
|
/** @brief Virtual destructor */
|
||||||
|
virtual ~WhitelistHandlerInterface() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks to see if the given IP is whitelisted
|
||||||
|
*
|
||||||
|
* @param ip The IP to check
|
||||||
|
* @return true if the given IP is whitelisted; false otherwise
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual bool
|
||||||
|
isWhiteListed(std::string_view ip) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace web::dosguard
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "util/build/Build.hpp"
|
#include "util/build/Build.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "util/prometheus/Http.hpp"
|
#include "util/prometheus/Http.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/impl/AdminVerificationStrategy.hpp"
|
#include "web/impl/AdminVerificationStrategy.hpp"
|
||||||
#include "web/interface/Concepts.hpp"
|
#include "web/interface/Concepts.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
@@ -114,7 +114,7 @@ class HttpBase : public ConnectionBase {
|
|||||||
protected:
|
protected:
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard_;
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||||
std::shared_ptr<HandlerType> const handler_;
|
std::shared_ptr<HandlerType> const handler_;
|
||||||
util::Logger log_{"WebServer"};
|
util::Logger log_{"WebServer"};
|
||||||
util::Logger perfLog_{"Performance"};
|
util::Logger perfLog_{"Performance"};
|
||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
std::string const& ip,
|
std::string const& ip,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::shared_ptr<AdminVerificationStrategy> adminVerification,
|
std::shared_ptr<AdminVerificationStrategy> adminVerification,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> handler,
|
std::shared_ptr<HandlerType> handler,
|
||||||
boost::beast::flat_buffer buffer
|
boost::beast::flat_buffer buffer
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Types.hpp"
|
||||||
#include "util/Taggable.hpp"
|
#include "util/Taggable.hpp"
|
||||||
#include "util/log/Logger.hpp"
|
#include "util/log/Logger.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/interface/Concepts.hpp"
|
#include "web/interface/Concepts.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ class WsBase : public ConnectionBase, public std::enable_shared_from_this<WsBase
|
|||||||
using std::enable_shared_from_this<WsBase<Derived, HandlerType>>::shared_from_this;
|
using std::enable_shared_from_this<WsBase<Derived, HandlerType>>::shared_from_this;
|
||||||
|
|
||||||
boost::beast::flat_buffer buffer_;
|
boost::beast::flat_buffer buffer_;
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard_;
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||||
bool sending_ = false;
|
bool sending_ = false;
|
||||||
std::queue<std::shared_ptr<std::string>> messages_;
|
std::queue<std::shared_ptr<std::string>> messages_;
|
||||||
std::shared_ptr<HandlerType> const handler_;
|
std::shared_ptr<HandlerType> const handler_;
|
||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
explicit WsBase(
|
explicit WsBase(
|
||||||
std::string ip,
|
std::string ip,
|
||||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||||
std::reference_wrapper<web::DOSGuard> dosGuard,
|
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||||
std::shared_ptr<HandlerType> const& handler,
|
std::shared_ptr<HandlerType> const& handler,
|
||||||
boost::beast::flat_buffer&& buffer
|
boost::beast::flat_buffer&& buffer
|
||||||
)
|
)
|
||||||
|
|||||||
0
src/web/ng/Server.cpp
Normal file
0
src/web/ng/Server.cpp
Normal file
0
src/web/ng/Server.hpp
Normal file
0
src/web/ng/Server.hpp
Normal file
@@ -23,7 +23,6 @@
|
|||||||
#include "rpc/common/Specs.hpp"
|
#include "rpc/common/Specs.hpp"
|
||||||
#include "rpc/common/Types.hpp"
|
#include "rpc/common/Types.hpp"
|
||||||
#include "rpc/common/Validators.hpp"
|
#include "rpc/common/Validators.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
|
||||||
|
|
||||||
#include <boost/json/conversion.hpp>
|
#include <boost/json/conversion.hpp>
|
||||||
#include <boost/json/value.hpp>
|
#include <boost/json/value.hpp>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ target_sources(
|
|||||||
data/cassandra/ExecutionStrategyTests.cpp
|
data/cassandra/ExecutionStrategyTests.cpp
|
||||||
data/cassandra/RetryPolicyTests.cpp
|
data/cassandra/RetryPolicyTests.cpp
|
||||||
data/cassandra/SettingsProviderTests.cpp
|
data/cassandra/SettingsProviderTests.cpp
|
||||||
DOSGuardTests.cpp
|
|
||||||
# ETL
|
# ETL
|
||||||
etl/AmendmentBlockHandlerTests.cpp
|
etl/AmendmentBlockHandlerTests.cpp
|
||||||
etl/CacheLoaderSettingsTests.cpp
|
etl/CacheLoaderSettingsTests.cpp
|
||||||
@@ -127,11 +126,12 @@ target_sources(
|
|||||||
util/TxUtilTests.cpp
|
util/TxUtilTests.cpp
|
||||||
# Webserver
|
# Webserver
|
||||||
web/AdminVerificationTests.cpp
|
web/AdminVerificationTests.cpp
|
||||||
|
web/dosguard/DOSGuardTests.cpp
|
||||||
|
web/dosguard/IntervalSweepHandlerTests.cpp
|
||||||
|
web/dosguard/WhitelistHandlerTests.cpp
|
||||||
web/impl/ServerSslContextTests.cpp
|
web/impl/ServerSslContextTests.cpp
|
||||||
web/RPCServerHandlerTests.cpp
|
web/RPCServerHandlerTests.cpp
|
||||||
web/ServerTests.cpp
|
web/ServerTests.cpp
|
||||||
web/IntervalSweepHandlerTests.cpp
|
|
||||||
web/WhitelistHandlerTests.cpp
|
|
||||||
# New Config
|
# New Config
|
||||||
util/newconfig/ArrayViewTests.cpp
|
util/newconfig/ArrayViewTests.cpp
|
||||||
util/newconfig/ObjectViewTests.cpp
|
util/newconfig/ObjectViewTests.cpp
|
||||||
|
|||||||
@@ -24,10 +24,11 @@
|
|||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "util/prometheus/Label.hpp"
|
#include "util/prometheus/Label.hpp"
|
||||||
#include "util/prometheus/Prometheus.hpp"
|
#include "util/prometheus/Prometheus.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
|
||||||
#include "web/IntervalSweepHandler.hpp"
|
|
||||||
#include "web/Server.hpp"
|
#include "web/Server.hpp"
|
||||||
#include "web/WhitelistHandler.hpp"
|
#include "web/dosguard/DOSGuard.hpp"
|
||||||
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
|
#include "web/dosguard/IntervalSweepHandler.hpp"
|
||||||
|
#include "web/dosguard/WhitelistHandler.hpp"
|
||||||
#include "web/impl/AdminVerificationStrategy.hpp"
|
#include "web/impl/AdminVerificationStrategy.hpp"
|
||||||
#include "web/interface/ConnectionBase.hpp"
|
#include "web/interface/ConnectionBase.hpp"
|
||||||
|
|
||||||
@@ -127,14 +128,14 @@ struct WebServerTest : NoLoggerFixture {
|
|||||||
boost::asio::io_context ctxSync;
|
boost::asio::io_context ctxSync;
|
||||||
std::string const port = std::to_string(tests::util::generateFreePort());
|
std::string const port = std::to_string(tests::util::generateFreePort());
|
||||||
Config cfg{generateJSONWithDynamicPort(port)};
|
Config cfg{generateJSONWithDynamicPort(port)};
|
||||||
WhitelistHandler whitelistHandler{cfg};
|
dosguard::WhitelistHandler whitelistHandler{cfg};
|
||||||
DOSGuard dosGuard{cfg, whitelistHandler};
|
dosguard::DOSGuard dosGuard{cfg, whitelistHandler};
|
||||||
IntervalSweepHandler sweepHandler{cfg, ctxSync, dosGuard};
|
dosguard::IntervalSweepHandler sweepHandler{cfg, ctxSync, dosGuard};
|
||||||
|
|
||||||
Config cfgOverload{generateJSONDataOverload(port)};
|
Config cfgOverload{generateJSONDataOverload(port)};
|
||||||
WhitelistHandler whitelistHandlerOverload{cfgOverload};
|
dosguard::WhitelistHandler whitelistHandlerOverload{cfgOverload};
|
||||||
DOSGuard dosGuardOverload{cfgOverload, whitelistHandlerOverload};
|
dosguard::DOSGuard dosGuardOverload{cfgOverload, whitelistHandlerOverload};
|
||||||
IntervalSweepHandler sweepHandlerOverload{cfgOverload, ctxSync, dosGuardOverload};
|
dosguard::IntervalSweepHandler sweepHandlerOverload{cfgOverload, ctxSync, dosGuardOverload};
|
||||||
// this ctx is for http server
|
// this ctx is for http server
|
||||||
boost::asio::io_context ctx;
|
boost::asio::io_context ctx;
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ std::shared_ptr<web::HttpServer<Executor>>
|
|||||||
makeServerSync(
|
makeServerSync(
|
||||||
util::Config const& config,
|
util::Config const& config,
|
||||||
boost::asio::io_context& ioc,
|
boost::asio::io_context& ioc,
|
||||||
web::DOSGuard& dosGuard,
|
web::dosguard::DOSGuardInterface& dosGuard,
|
||||||
std::shared_ptr<Executor> const& handler
|
std::shared_ptr<Executor> const& handler
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
|
|
||||||
#include "util/LoggerFixtures.hpp"
|
#include "util/LoggerFixtures.hpp"
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuard.hpp"
|
||||||
|
#include "web/dosguard/WhitelistHandlerInterface.hpp"
|
||||||
|
|
||||||
#include <boost/json/parse.hpp>
|
#include <boost/json/parse.hpp>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
@@ -30,11 +31,11 @@
|
|||||||
using namespace testing;
|
using namespace testing;
|
||||||
using namespace util;
|
using namespace util;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace web;
|
using namespace web::dosguard;
|
||||||
namespace json = boost::json;
|
namespace json = boost::json;
|
||||||
|
|
||||||
namespace {
|
struct DOSGuardTest : NoLoggerFixture {
|
||||||
constexpr auto JSONData = R"JSON(
|
static constexpr auto JSONData = R"JSON(
|
||||||
{
|
{
|
||||||
"dos_guard": {
|
"dos_guard": {
|
||||||
"max_fetches": 100,
|
"max_fetches": 100,
|
||||||
@@ -47,20 +48,15 @@ constexpr auto JSONData = R"JSON(
|
|||||||
}
|
}
|
||||||
)JSON";
|
)JSON";
|
||||||
|
|
||||||
constexpr auto IP = "127.0.0.2";
|
static constexpr auto IP = "127.0.0.2";
|
||||||
|
|
||||||
struct MockWhitelistHandler {
|
struct MockWhitelistHandler : WhitelistHandlerInterface {
|
||||||
MOCK_METHOD(bool, isWhiteListed, (std::string_view ip), (const));
|
MOCK_METHOD(bool, isWhiteListed, (std::string_view ip), (const));
|
||||||
};
|
};
|
||||||
|
|
||||||
using MockWhitelistHandlerType = NiceMock<MockWhitelistHandler>;
|
|
||||||
}; // namespace
|
|
||||||
|
|
||||||
class DOSGuardTest : public NoLoggerFixture {
|
|
||||||
protected:
|
|
||||||
Config cfg{json::parse(JSONData)};
|
Config cfg{json::parse(JSONData)};
|
||||||
MockWhitelistHandlerType whitelistHandler;
|
NiceMock<MockWhitelistHandler> whitelistHandler;
|
||||||
BasicDOSGuard<MockWhitelistHandlerType> guard{cfg, whitelistHandler};
|
DOSGuard guard{cfg, whitelistHandler};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(DOSGuardTest, Whitelisting)
|
TEST_F(DOSGuardTest, Whitelisting)
|
||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include "util/AsioContextTestFixture.hpp"
|
#include "util/AsioContextTestFixture.hpp"
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "web/DOSGuard.hpp"
|
#include "web/dosguard/DOSGuardInterface.hpp"
|
||||||
#include "web/IntervalSweepHandler.hpp"
|
#include "web/dosguard/IntervalSweepHandler.hpp"
|
||||||
|
|
||||||
#include <boost/json/parse.hpp>
|
#include <boost/json/parse.hpp>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
using namespace web;
|
using namespace web::dosguard;
|
||||||
|
|
||||||
struct IntervalSweepHandlerTest : SyncAsioContextTest {
|
struct IntervalSweepHandlerTest : SyncAsioContextTest {
|
||||||
protected:
|
protected:
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
#include "util/LoggerFixtures.hpp"
|
#include "util/LoggerFixtures.hpp"
|
||||||
#include "util/config/Config.hpp"
|
#include "util/config/Config.hpp"
|
||||||
#include "web/WhitelistHandler.hpp"
|
#include "web/dosguard/WhitelistHandler.hpp"
|
||||||
|
|
||||||
#include <boost/json/parse.hpp>
|
#include <boost/json/parse.hpp>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace util;
|
using namespace util;
|
||||||
using namespace web;
|
using namespace web::dosguard;
|
||||||
|
|
||||||
struct WhitelistHandlerTest : NoLoggerFixture {};
|
struct WhitelistHandlerTest : NoLoggerFixture {};
|
||||||
|
|
||||||
Reference in New Issue
Block a user