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).