IP-blocker
Since v.0.5.1 RESTinio supports ability to check remote address of a new incoming connection and deny or allow this connection for further processing.
By default, RESTinio accepts all incoming connections and tries to read incoming requests from them. But since v.0.5.1 a user can specify an IP-blocker objects and RESTinio will call this object when a new incoming connection accepted. If IP-blocker denies that new connection it will be imediatelly closed. But if IP-blocker allows that connection it will be processed the usual way.
How to specify IP-blocker?
There are three steps those needs to be done to specify own IP-blocker to RESTinio server.
The first step is the creation of class with non-static inspect
method. This class can look like:
class my_ip_blocker {
...
public:
...
restinio::ip_blocker::inspection_result_t
inspect(const restinio::ip_blocker::incoming_info_t & info) noexcept {
if(some_condition(info))
return restinio::ip_blocker::deny();
else
return restinio::ip_blocker::allow();
}
};
Please notice that inspect
gets a single argument of type
restinio::ip_blocker::incoming_info_t
by const reference and returns
restinio::ip_blocker::inspection_result_t
.
It is also important to mention that inspect
is noexcept-method.
The second step is the definition of my_ip_blocker
as a type of
IP-blocker for RESTinio. A typedef with name
ip_blocker_t
should be defined inside the server’s traits:
struct my_traits : public restinio::default_traits_t {
using ip_blocker_t = my_ip_blocker;
};
The third step is the creation an instance of IP-blocker and passing it to the server’s settings:
restinio::run( restinio::on_this_thread<my_traits>()
.port(8080)
.address("localhost")
.ip_blocker(std::make_shared<my_ip_blocker>(...))
.request_handler(...)
... );
The restinio::ip_blocker::incoming_info_t class
An instance of restinio::ip_blocker::incoming_info_t
class passed to
inspect
method contains all available information about the
new connection. This class has the following interface:
class incoming_info_t
{
...
public :
...
//! Get the remote endpoint for the connection.
endpoint_t remote_endpoint() const noexcept;
};
NOTE. Amount of available information can be extended in future versions of RESTinio.
When and where IP-blocker is called?
If a user specifies an IP-blocker object this object will be called by RESTinio’s acceptor. If RESTinio is run on thread pool then calls to IP-blocker object can be performed from different worker thread. It means that IP-blocker should be a thread-safe object if RESTinio is run on thread pool.
It is very important to mention that a call to IP-blocker blocks further work on the accepted connection. It means that IP-blocker should work as fast as possible.
If the default value for ip_blocker_t
is used (e.g.
ip_blocker_t
in server traits has the default value of
restinio::ip_blocker::noop_ip_blocker_t
) then there won’t be any
performance impact because all IP-blocker code will be eliminated by C++
compiler (it’s a consequence of specializations inside RESTinio’s code
for noop_ip_blocker_t
case).
Thread safety of IP-blocker
If RESTinio is run on a thread pool then calls of inspect
can be made
from several threads. Moreover, several calls to inspect
can be
performed at the same time.
It’s a user’s task to make an IP-blocker thread-safe.
Integration of IP-blocker and connection-state-listener
It is possible it integrate functionality of IP-blocker and connection state listener (see Connection state listener) in one object. There is an example that shows how it can be done: ip_blocker).