1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-10-05 19:18:01 +08:00
This commit is contained in:
stefanocasazza 2017-06-19 20:24:31 +02:00
parent a66201800c
commit c6a85f2261
44 changed files with 972 additions and 209 deletions

View File

@ -28,7 +28,7 @@ The current version offers the following features :
* Support for aliases/redirection.
* Support for switch the site to a maintenance page only.
* Support for URL traffic based throttling (experimental).
* Support for overriden of error messages by local document (ErrorDocument/40x|500.html).
* Support for overriden of error messages by local document (ex. ErrorDocument/400.html).
* Support for RewriteRule (lighttpd-like) that check for file existence as they do on Apache, some CMS (SilverStripe) require it.
* Support for (apache-like) log [NCSA extended/combined format](http://httpd.apache.org/docs/2.0/mod/mod_log_config.html)
* Support for [JSONRequest](http://json.org/JSONRequest.html).
@ -69,6 +69,7 @@ The current version offers the following features :
* [DNS rebinding](http://en.wikipedia.org/wiki/DNS_rebinding) prevention by RFC1918 filtering and Host header validation.
* selective uri support (DOS regex) for [HTTP Strict Transport Security](https://developer.mozilla.org/en/Security/HTTP_Strict_Transport_Security).
* Immune to [Slow Read DoS attack](http://code.google.com/p/slowhttptest/)
* Provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack.
* [High SSL server quality score](https://www.ssllabs.com/ssltest/analyze.html?d=wifi-aaa2.comune.fi.it)
## Who is Using ULib

36
configure vendored
View File

@ -1050,6 +1050,7 @@ enable_http2
enable_check_time
enable_classic
enable_throttling
enable_evasive
enable_alias
enable_welcome
enable_ACL
@ -1793,6 +1794,7 @@ Optional Features:
--enable-check-time enable server check time between request for parallelization [default=no]
--enable-classic enable server classic model support [default=no]
--enable-throttling enable server bandwidth throttling support [default=no]
--enable-evasive enable server evasive action support [default=no]
--enable-alias enable alias URI support [default=yes]
--enable-welcome enable welcome message support [default=no]
--enable-ACL enable ACL filtering support [default=no]
@ -26478,6 +26480,24 @@ $as_echo "#define U_THROTTLING_SUPPORT 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_throttling" >&5
$as_echo "$enable_throttling" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack" >&5
$as_echo_n "checking if you want to enable to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack... " >&6; }
# Check whether --enable-evasive was given.
if test "${enable_evasive+set}" = set; then :
enableval=$enable_evasive;
fi
if test -z "$enable_evasive"; then
enable_evasive="no"
fi
if test "$enable_evasive" = "yes"; then
$as_echo "#define U_EVASIVE_SUPPORT 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_evasive" >&5
$as_echo "$enable_evasive" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable alias URI support" >&5
$as_echo_n "checking if you want to enable alias URI support... " >&6; }
# Check whether --enable-alias was given.
@ -32849,17 +32869,20 @@ if test "x$ac_cv_crc32_intrinsics" = xyes; then
esac
fi
fi
##########################
if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then
if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then
gcc_lib=`gcc -print-libgcc-file-name`
gcc_dir=`dirname $gcc_lib`
if test -f "$gcc_dir/libstdc++.a"; then
ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib"
else
## if test -f "$gcc_dir/libstdc++.a"; then
## gcc_lib=`gcc -print-libgcc-file-name`
## gcc_dir=`dirname $gcc_lib`
## ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib"
## else
## ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
## fi
ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libgcc" >&5
$as_echo_n "checking whether to use libgcc... " >&6; }
@ -32883,7 +32906,6 @@ fi
fi
fi
##########################
# Check for availablity of "old style" C++ strstream header
for ac_header in strstream.h

View File

@ -2541,17 +2541,20 @@ if test "x$ac_cv_crc32_intrinsics" = xyes; then
esac
fi
fi
##########################
if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then
if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then
gcc_lib=`gcc -print-libgcc-file-name`
gcc_dir=`dirname $gcc_lib`
if test -f "$gcc_dir/libstdc++.a"; then
ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib"
else
## if test -f "$gcc_dir/libstdc++.a"; then
## gcc_lib=`gcc -print-libgcc-file-name`
## gcc_dir=`dirname $gcc_lib`
## ULIB_LIBS="$ULIB_LIBS $gcc_dir/libstdc++.a $gcc_lib"
## else
## ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
## fi
ULIB_LIBS="$ULIB_LIBS -lstdc++ -lgcc"
fi
else
AC_MSG_CHECKING([whether to use libgcc])
AC_ARG_ENABLE(libgcc,
@ -2568,7 +2571,6 @@ if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno; then
)
fi
fi
##########################
# Check for availablity of "old style" C++ strstream header
AC_CHECK_HEADERS([strstream.h])

View File

@ -71,6 +71,17 @@
#
# if PREFORK_CHILD is not defined is as case (>1) with num process the number of CPU in the system
# ----------------------------------------------------------------------------------------------------------------------------------------
# This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
# ----------------------------------------------------------------------------------------------------------------------------------------
# DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
# DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
# DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
# DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
# DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
# DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
# DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
# DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
# ----------------------------------------------------------------------------------------------------------------------------------------
userver {

View File

@ -117,6 +117,17 @@ public:
// 1 - classic, forking after accept client)
// >1 - pool of process serialize plus monitoring process)
// ---------------------------------------------------------------------------------------------------------------------------------------
// This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
// ---------------------------------------------------------------------------------------------------------------------------------------
// DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
// DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
// DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
// DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
// DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
// DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
// DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
// DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
// ---------------------------------------------------------------------------------------------------------------------------------------
# ifdef U_SSL_SOCKET
UServer_Base::bssl = true;

View File

@ -40,6 +40,7 @@ public:
if (subject == U_NOT_FOUND) U_ERROR("cannot find mail header subject on input data");
// ----------------------------------------------------------------------------------------------------------------------------
// scanf mail header Subject: from request
// ----------------------------------------------------------------------------------------------------------------------------
// "Subject: %*[^"]\"%[^"]\", %*[^"]\"%[^"]\", %*[^"]\"%[^"]\""

View File

@ -19,13 +19,13 @@
#define U_PRINT_MEM_USAGE
#ifdef DEBUG
#define U_MAIN_END(value) return value
# define U_MAIN_END(value) return value
# ifdef U_STDCPP_ENABLE
# undef U_PRINT_MEM_USAGE
# define U_PRINT_MEM_USAGE UApplication::printMemUsage();
# endif
#else
#define U_MAIN_END(value) ::exit(value)
# define U_MAIN_END(value) ::exit(value)
#endif
#define U_MAIN \

View File

@ -205,6 +205,9 @@ static inline uint32_t u_findEndHeader1(const char* restrict s, uint32_t n) /* f
U_INTERNAL_TRACE("u_findEndHeader1(%.*s,%u)", U_min(n,128), s, n)
U_INTERNAL_ASSERT_POINTER(s)
U_INTERNAL_ASSERT_MAJOR(n, 0)
if (u_get_unalignedp32(s+n-4) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) return (n-4);
p = memmem(s, n, U_CONSTANT_TO_PARAM(U_CRLF2));

View File

@ -472,22 +472,9 @@ public:
return _insertDataStorage(op);
}
bool insertDataStorage(const UString& _key, int _flag = RDB_INSERT_WITH_PADDING)
bool insertDataStorage(const char* s, uint32_t n, int _flag = RDB_INSERT) // SSL session cache...
{
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%V,%d)", _key.rep, _flag)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(pDataStorage)
pDataStorage->setKeyIdDataSession(_key);
return insertDataStorage(_flag);
}
void insertDataStorage(const char* s, uint32_t n)
{
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%.*S,%u)", n, s, n)
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%.*S,%u,%d)", n, s, n, _flag)
U_CHECK_MEMORY
@ -495,7 +482,14 @@ public:
pDataStorage->setKeyIdDataSession(s, n);
(void) insertDataStorage(RDB_INSERT); // SSL session cache...
return insertDataStorage(_flag);
}
bool insertDataStorage(const UString& _key, int _flag = RDB_INSERT_WITH_PADDING)
{
U_TRACE(0, "URDBObjectHandler<UDataStorage*>::insertDataStorage(%V,%d)", _key.rep, _flag)
return insertDataStorage(U_STRING_TO_PARAM(_key), _flag);
}
UString getKeyID() const { return pDataStorage->keyid; }

View File

@ -145,6 +145,19 @@ typedef struct uhttpinfo {
unsigned char flag[16];
} uhttpinfo;
/**
* GET is used to retrieve a resource on the server.
* HEAD is used to retrieve some information about the document, but don't need the document itself.
* POST says that you are providing some information of your own (i.e., in forms). This may change the state of the server in some way, such as creating a record in a database.
* PUT is used to replace or create a new document on the server.
* DELETE is used to remove a document on the server.
* TRACE is used for protocol debugging purposes.
* OPTIONS is used when the client looks for other methods which can be used on the document.
* CONNECT is used when a client needs to talk to an HTTPS server through a proxy server.
*
* Other HTTP methods that you may see (LINK, UNLINK, and PATCH) are less clearly defined
*/
enum HTTPMethodType {
/* request methods */
HTTP_GET = 0x00000001,

View File

@ -808,6 +808,9 @@
/* enable client response partial write support */
#undef U_CLIENT_RESPONSE_PARTIAL_WRITE_SUPPORT
/* enable server evasive action support */
#undef U_EVASIVE_SUPPORT
/* enable GDB stack dump support */
#undef U_GDB_STACK_DUMP_ENABLE

View File

@ -98,6 +98,7 @@ vClientImage = new client_type[UNotifier::max_connection]; } }
class UHTTP;
class UHTTP2;
class UCommand;
class UEvasive;
class UDayLight;
class UTimeStat;
class USSLSocket;
@ -111,6 +112,7 @@ class UHttpPlugIn;
class UFCGIPlugIn;
class USCGIPlugIn;
class UThrottling;
class USmtpClient;
class UNoCatPlugIn;
class UGeoIPPlugIn;
class UClient_Base;
@ -136,9 +138,9 @@ public:
U_MEMORY_ALLOCATOR
U_MEMORY_DEALLOCATOR
// -----------------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------------
// UServer - configuration parameters
// -----------------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------------
// ENABLE_IPV6 flag indicating the use of ipv6
// SERVER host name or ip address for the listening socket
// PORT port number for the listening socket
@ -189,7 +191,18 @@ public:
// PREFORK_CHILD number of child server processes created at startup ( 0 - serialize, no forking
// 1 - classic, forking after client accept
// >1 - pool of serialized processes plus monitoring process)
// -----------------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------------------------
// This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
// --------------------------------------------------------------------------------------------------------------------------------------
// DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
// DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
// DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
// DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
// DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
// DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
// DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
// DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
// --------------------------------------------------------------------------------------------------------------------------------------
static void run(); // loop waiting for connection
@ -225,9 +238,6 @@ public:
static void setMsgWelcome(const UString& msg);
#endif
#if defined(U_LINUX) && defined(ENABLE_THREAD)
#endif
// -------------------------------------------------------------------
// MANAGE PLUGIN MODULES
// -------------------------------------------------------------------
@ -283,7 +293,7 @@ public:
char buffer4[512];
char buffer5[512];
char buffer6[512];
char buffer7[431];
char buffer7[402];
// ---------------------------------
uint8_t flag_sigterm;
// ---------------------------------
@ -296,12 +306,14 @@ public:
// ---------------------------------
sem_t lock_user1;
sem_t lock_user2;
sem_t lock_evasive;
sem_t lock_throttling;
sem_t lock_rdb_server;
sem_t lock_data_session;
sem_t lock_db_not_found;
char spinlock_user1[1];
char spinlock_user2[1];
char spinlock_evasive[1];
char spinlock_throttling[1];
char spinlock_rdb_server[1];
char spinlock_data_session[1];
@ -353,6 +365,7 @@ public:
#define U_SRV_CNT_PARALLELIZATION UServer_Base::ptr_shared_data->cnt_parallelization
#define U_SRV_LOCK_USER1 &(UServer_Base::ptr_shared_data->lock_user1)
#define U_SRV_LOCK_USER2 &(UServer_Base::ptr_shared_data->lock_user2)
#define U_SRV_LOCK_EVASIVE &(UServer_Base::ptr_shared_data->lock_evasive)
#define U_SRV_LOCK_THROTTLING &(UServer_Base::ptr_shared_data->lock_throttling)
#define U_SRV_LOCK_RDB_SERVER &(UServer_Base::ptr_shared_data->lock_rdb_server)
#define U_SRV_LOCK_SSL_SESSION &(UServer_Base::ptr_shared_data->lock_ssl_session)
@ -360,6 +373,7 @@ public:
#define U_SRV_LOCK_DB_NOT_FOUND &(UServer_Base::ptr_shared_data->lock_db_not_found)
#define U_SRV_SPINLOCK_USER1 UServer_Base::ptr_shared_data->spinlock_user1
#define U_SRV_SPINLOCK_USER2 UServer_Base::ptr_shared_data->spinlock_user2
#define U_SRV_SPINLOCK_EVASIVE UServer_Base::ptr_shared_data->spinlock_evasive
#define U_SRV_SPINLOCK_THROTTLING UServer_Base::ptr_shared_data->spinlock_throttling
#define U_SRV_SPINLOCK_RDB_SERVER UServer_Base::ptr_shared_data->spinlock_rdb_server
#define U_SRV_SPINLOCK_SSL_SESSION UServer_Base::ptr_shared_data->spinlock_ssl_session
@ -633,6 +647,24 @@ protected:
static void initThrottlingServer();
#endif
#ifdef U_EVASIVE_SUPPORT // provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
static bool bwhitelist;
static UString* emailAddress;
static UString* whitelist_IP;
static UEvasive* evasive_rec;
static UString* systemCommand;
static USmtpClient* emailClient;
static UVector<UIPAllow*>* vwhitelist_IP;
static URDBObjectHandler<UDataStorage*>* db_evasive;
static uint32_t blocking_period, page_interval, page_count, site_interval, site_count;
static void initEvasive();
static bool checkHitUriStats();
static bool checkHitSiteStats();
static bool checkHitStats(const char* key, uint32_t key_len, uint32_t interval, uint32_t count);
static bool checkHold(in_addr_t client, const char* client_address, uint32_t client_address_len);
#endif
UServer_Base(UFileConfig* pcfg = U_NULLPTR);
virtual ~UServer_Base();
@ -716,6 +748,7 @@ private:
friend class UHTTP;
friend class UHTTP2;
friend class UEvasive;
friend class UDayLight;
friend class UTimeStat;
friend class USSLSocket;

View File

@ -204,10 +204,40 @@ public:
static bool scanfHeaderRequest(const char* ptr, uint32_t size);
static bool scanfHeaderResponse(const char* ptr, uint32_t size);
static bool readHeaderResponse(USocket* socket, UString& buffer);
static bool isValidRequest( const char* ptr, uint32_t size) __pure;
static bool isValidRequestExt(const char* ptr, uint32_t size) __pure;
static bool readBodyResponse(USocket* socket, UString* buffer, UString& body);
static bool isValidRequest(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequest(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
U_INTERNAL_DUMP("sz = %u UClientImage_Base::size_request = %u", sz, UClientImage_Base::size_request)
if (u_get_unalignedp32(ptr+sz-4) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true);
U_RETURN(false);
}
static bool isValidRequestExt(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequestExt(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
if (sz >= U_CONSTANT_SIZE("GET / HTTP/1.0\r\n\r\n") &&
isValidMethod(ptr) &&
(isValidRequest(ptr, sz) ||
(UClientImage_Base::size_request &&
isValidRequest(ptr, UClientImage_Base::size_request)) ||
memmem(ptr, sz, U_CONSTANT_TO_PARAM(U_CRLF2)) != U_NULLPTR))
{
U_RETURN(true);
}
U_RETURN(false);
}
#ifndef U_HTTP2_DISABLE
static bool copyHeaders(UStringRep* key, void* elem);
static bool upgradeHeaders(UStringRep* key, void* elem)

View File

@ -247,6 +247,17 @@ AC_DEFUN([AC_COMPILATION_OPTIONS],[
fi
AC_MSG_RESULT([$enable_throttling])
AC_MSG_CHECKING(if you want to enable to provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack)
AC_ARG_ENABLE(evasive,
[ --enable-evasive enable server evasive action support [[default=no]]])
if test -z "$enable_evasive"; then
enable_evasive="no"
fi
if test "$enable_evasive" = "yes"; then
AC_DEFINE(U_EVASIVE_SUPPORT, 1, [enable server evasive action support])
fi
AC_MSG_RESULT([$enable_evasive])
AC_MSG_CHECKING(if you want to enable alias URI support)
AC_ARG_ENABLE(alias,
[ --enable-alias enable alias URI support [[default=yes]]])

View File

@ -65,7 +65,7 @@ void UApplication::printMemUsage()
UServer_Base::getStats().rep,
(double)vsz / (1024.0 * 1024.0),
(double)rss / (1024.0 * 1024.0), UNotifier::max_nfd_ready, UServer_Base::max_depth, UServer_Base::nread_again, UServer_Base::nread,
(UServer_Base::nread_again * 100) / UServer_Base::nread, UServer_Base::wakeup_for_nothing, UNotifier::bepollet_threshold);
(UServer_Base::nread_again * 100) / (UServer_Base::nread ? UServer_Base::nread : 1), UServer_Base::wakeup_for_nothing, UNotifier::bepollet_threshold);
ostrstream os(buffer + len, sizeof(buffer) - len);

View File

@ -312,7 +312,6 @@ void ULib::init(const char* mempool, char** argv)
void ULib::end()
{
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
UApplication::printMemUsage();
#endif

View File

@ -58,9 +58,7 @@ bool USmtpClient::_connectServer(const UString& server, unsigned int port, int t
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
// NB: the last argument (0) is necessary...
u_buffer_len = u__snprintf(u_buffer, U_BUFFER_SIZE, U_CONSTANT_TO_PARAM("Sorry, couldn't connect to server '%v:%u'%R"), server.rep, port, 0);
u_buffer_len = u__snprintf(u_buffer,U_BUFFER_SIZE,U_CONSTANT_TO_PARAM("Sorry, couldn't connect to server '%v:%u'%R"),server.rep,port,0); // NB: the last argument (0) is necessary...
}
else
{
@ -91,6 +89,7 @@ bool USmtpClient::_connectServer(UFileConfig& cfg, unsigned int port, int timeou
U_ASSERT_EQUALS(cfg.empty(), false)
// ----------------------------------------------------------------------------------------------------------------------
// USmtpClient - configuration parameters
// ----------------------------------------------------------------------------------------------------------------------
// SMTP_SERVER host name or ip address for server

View File

@ -31,7 +31,7 @@ bool URPCClient_Base::readResponse(USocket* sk, UString& buffer, UString& respon
buffer.size_adjust_force(U_TOKEN_NM);
}
U_INTERNAL_DUMP("buffer = %V response = %V)", buffer.rep, response.rep)
U_INTERNAL_DUMP("buffer = %V response = %V", buffer.rep, response.rep)
if (buffer) U_RETURN(true);

View File

@ -944,6 +944,15 @@ void UClientImage_Base::prepareForRead()
UServer_Base::client_address_len = u__strlen(UServer_Base::client_address, __PRETTY_FUNCTION__);
U_INTERNAL_DUMP("UServer_Base::client_address = %.*S", U_CLIENT_ADDRESS_TO_TRACE)
# ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHold(socket->remoteIPAddress().getInAddr(), U_CLIENT_ADDRESS_TO_PARAM))
{
abortive_close();
return;
}
# endif
}
else
{
@ -959,6 +968,10 @@ void UClientImage_Base::prepareForRead()
UEventFd::fd = socket->iSockDesc;
}
#ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHitSiteStats()) return;
#endif
#ifdef U_THROTTLING_SUPPORT
UServer_Base::initThrottlingClient();
#endif
@ -968,15 +981,17 @@ bool UClientImage_Base::genericRead()
{
U_TRACE_NO_PARAM(0, "UClientImage_Base::genericRead()")
#ifdef DEBUG
#if defined(DEBUG) || defined(U_EVASIVE_SUPPORT)
if (UNLIKELY(socket->iSockDesc == -1))
{
# ifndef U_EVASIVE_SUPPORT
U_WARNING("genericRead(): "
"UEventFd::fd = %d socket->iSockDesc = %d "
"UNotifier::num_connection = %d UNotifier::min_connection = %d "
"UServer_Base::isParallelizationChild() = %b sfd = %d UEventFd::op_mask = %B",
UEventFd::fd, socket->iSockDesc, UNotifier::num_connection, UNotifier::min_connection,
UServer_Base::isParallelizationChild(), sfd, UEventFd::op_mask);
# endif
U_ClientImage_state = U_PLUGIN_HANDLER_ERROR;
@ -986,6 +1001,8 @@ bool UClientImage_Base::genericRead()
U_INTERNAL_ASSERT_EQUALS(socket->iSockDesc, UEventFd::fd)
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
startRequest();
rstart = 0;
@ -1068,8 +1085,6 @@ start:
U_INTERNAL_ASSERT_EQUALS(U_ClientImage_pipeline, false)
U_INTERNAL_ASSERT_EQUALS(U_ClientImage_data_missing, false)
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
if (genericRead() == false)
{
if (U_ClientImage_state == U_PLUGIN_HANDLER_AGAIN &&

View File

@ -29,7 +29,7 @@ static void usp_fork_fortune()
U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT";
// if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT";
U_NEW(Fortune, pfortune, Fortune);
@ -70,6 +70,7 @@ pstmt_fortune->execute();
do {
U_NEW(Fortune, item, Fortune(*pfortune));
pvfortune->push_back(item);
}
while (pstmt_fortune->nextRow());

View File

@ -28,7 +28,7 @@ static void usp_fork_query()
U_NEW(UOrmStatement, pstmt_query, UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION";
// if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION";
U_NEW(World, pworld_query, World);

View File

@ -6,13 +6,10 @@ TechEmpower Web Framework Benchmarks
#include "world.h"
static World* pworld_update;
static UString* pquery;
static UOrmSession* psql_update;
static UOrmStatement* pstmt1;
static UOrmStatement* pstmt2;
#ifndef AS_cpoll_cppsp_DO
static UOrmStatement* pstmt;
static UVector<World*>* pvworld_update;
#endif
static void usp_fork_update()
{
@ -27,20 +24,18 @@ static void usp_fork_update()
return;
}
U_NEW(UOrmStatement, pstmt1, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
U_NEW(UOrmStatement, pstmt2, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
U_NEW(UOrmStatement, pstmt, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF";
// if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF";
U_NEW(World, pworld_update, World);
pstmt1->use( pworld_update->id);
pstmt1->into(pworld_update->randomNumber);
pstmt2->use( pworld_update->randomNumber, pworld_update->id);
pstmt->use( pworld_update->id);
pstmt->into(pworld_update->randomNumber);
U_NEW(UString, pquery, UString(U_CAPACITY));
#ifndef AS_cpoll_cppsp_DO
U_NEW(UVector<World*>, pvworld_update, UVector<World*>(500));
#endif
}
#ifdef DEBUG
@ -50,16 +45,12 @@ static void usp_end_update()
delete psql_update;
if (pstmt1 &&
pstmt2)
if (pstmt)
{
delete pstmt1;
delete pstmt2;
delete pstmt;
delete pquery;
delete pworld_update;
# ifndef AS_cpoll_cppsp_DO
delete pvworld_update;
# endif
}
}
#endif
@ -68,30 +59,56 @@ static void usp_end_update()
Content-Type: application/json
-->
<!--#code
char* ptr;
World* pworld;
char* query = pquery->data();
int i = 0, num_queries = UHTTP::getFormFirstNumericValue(1, 500);
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR('[');
#endif
(void) memcpy(query, "UPDATE World SET randomNumber = v.randomNumber FROM (VALUES",
U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES"));
ptr = query + U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES");
while (true)
{
pworld_update->id = u_get_num_random(10000-1);
pstmt1->execute();
pstmt->execute();
pworld_update->randomNumber = u_get_num_random(10000-1);
pstmt2->execute();
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld_update->id, pworld_update->randomNumber);
#else
World* pworld;
U_NEW(World, pworld, World(*pworld_update));
pvworld_update->push_back(pworld);
if (++i == num_queries) break;
}
pvworld_update->sort();
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR('[');
#endif
i = 0;
while (true)
{
pworld = pvworld_update->at(i);
*ptr++ = '(';
ptr = u_num2str32(pworld->id, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(',',' '));
ptr += 2;
ptr = u_num2str32(pworld->randomNumber, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(')',','));
ptr += 2;
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld->id, pworld->randomNumber);
#endif
if (++i == num_queries) break;
@ -103,8 +120,12 @@ while (true)
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR(']');
#else
USP_OBJ_JSON_stringify(*pvworld_update);
pvworld_update->clear();
#endif
(void) memcpy(ptr-1, ") AS v (id, randomNumber) WHERE World.id = v.id;",
U_CONSTANT_SIZE(") AS v (id, randomNumber) WHERE World.id = v.id;")+1);
*psql_update << query;
pvworld_update->clear();
-->

View File

@ -32,6 +32,13 @@ public:
U_TRACE_REGISTER_OBJECT(5, World, "%u,%u", _id, _randomNumber)
}
World(const World& w) : id(w.id), randomNumber(w.randomNumber)
{
U_TRACE_REGISTER_OBJECT(5, World, "%p", &w)
U_MEMORY_TEST_COPY(w)
}
~World()
{
U_TRACE_UNREGISTER_OBJECT(5, World)
@ -73,6 +80,30 @@ public:
stmt->bindResult(U_ORM_TYPE_HANDLER(randomNumber, unsigned int));
}
// SERVICE
bool operator<(const World& other) const { return cmp_obj(&id, &other.id); }
static int cmp_obj(const void* a, const void* b)
{
U_TRACE(5, "World::cmp_obj(%p,%p)", a, b)
# ifdef U_STDCPP_ENABLE
/**
* The comparison function must follow a strict-weak-ordering
*
* 1) For all x, it is not the case that x < x (irreflexivity)
* 2) For all x, y, if x < y then it is not the case that y < x (asymmetry)
* 3) For all x, y, and z, if x < y and y < z then x < z (transitivity)
* 4) For all x, y, and z, if x is incomparable with y, and y is incomparable with z, then x is incomparable with z (transitivity of incomparability)
*/
return (((const World*)a)->id < (((const World*)b)->id));
# else
return (*(const World**)a)->id < ((*(const World**)b)->id);
# endif
}
#ifdef DEBUG
const char* dump(bool breset) const
{

View File

@ -22,6 +22,10 @@
#include <ulib/utility/services.h>
#include <ulib/net/server/server.h>
#ifdef U_EVASIVE_SUPPORT
# include <ulib/net/client/smtp.h>
#endif
#ifdef _MSWINDOWS_
# include <ws2tcpip.h>
#else
@ -1000,7 +1004,7 @@ public:
uint8_t min_loadavg_remote = 255;
uint32_t min_loadavg_remote_ip = 0;
while ((iBytesTransferred = U_SYSCALL(recvfrom, "%d,%p,%u,%u,%p,%p", fd_sock, datagram, sizeof(datagram), MSG_DONTWAIT, (sockaddr*)&(saddr.psaGeneric), &slDummy)) > 0)
while ((iBytesTransferred = U_SYSCALL(recvfrom,"%d,%p,%u,%u,%p,%p",fd_sock,datagram,sizeof(datagram),MSG_DONTWAIT,(sockaddr*)&(saddr.psaGeneric),&slDummy)) > 0)
{
U_DUMP("Received datagram from (%S:%u) = (%u,%#.*S)",
UIPAddress::toString(saddr.psaIP4Addr.sin_addr.s_addr).rep, ntohs(saddr.psaIP4Addr.sin_port), iBytesTransferred, iBytesTransferred, datagram)
@ -1100,6 +1104,371 @@ private:
ULock* UServer_Base::lock_ocsp_staple;
UThread* UServer_Base::pthread_ocsp;
# endif
/**
* This code provide evasive action in the event of an HTTP DoS or DDoS attack or brute force attack. It is also designed to be a
* detection tool, and can be easily configured to talk to ipchains, firewalls, routers, and etcetera. Detection is performed by
* creating an internal dynamic hash table of IP Addresses and URIs, and denying any single IP address from any of the following:
*
* - Requesting the same page more than a few times per second
* - Making more than 50 concurrent requests per second
* - Making any requests while temporarily blacklisted (on a blocking list)
*
* This method has worked well in both single-server script attacks as well as distributed attacks, but just like other evasive tools,
* is only as useful to the point of bandwidth and processor consumption (e.g. the amount of bandwidth and processor required to
* receive/process/respond to invalid requests), which is why it's a good idea to integrate this with your firewalls and routers.
*
* This code has a built-in cleanup mechanism and scaling capabilities. Because of this, legitimate requests are rarely ever compromised,
* only legitimate attacks. Even a user repeatedly clicking on 'reload' should not be affected unless they do it maliciously,
*
* A web hit request comes in. The following steps take place:
*
* - The IP address of the requestor is looked up on the temporary blacklist.
* - The IP address of the requestor is hashed into a "key". A lookup is performed in the listener's internal hash table to determine if
* the same host has requested more than 50 objects within the past second.
* - The IP address of the requestor and the URI are both hashed into a "key". A lookup is performed in the listener's internal hash table
* to determine if the same host has requested this page more than 3 within the past 1 second.
*
* If any of the above are true, a RESET is sent. This conserves bandwidth and system resources in the event of a DoS attack. Additionally,
* a system command and/or an email notification can also be triggered to block all the originating addresses of a DDoS attack.
*
* Once a single RESET incident occurs, evasive code now blocks the entire IP address for a period of 10 seconds (configurable). If the host
* requests a page within this period, it is forced to wait even longer. Since this is triggered from requesting the same URL multiple times
* per second, this again does not affect legitimate users.
*
* The blacklist can/should be configured to talk to your network's firewalls and/or routers to push the attack out to the front lines, but
* this is not required. This tool is *excellent* at fending off request-based DoS attacks or scripted attacks, and brute force attacks.
* When integrated with firewalls or IP filters, evasive code can stand up to even large attacks. Its features will prevent you from wasting
* bandwidth or having a few thousand CGI scripts running as a result of an attack.
*
* If you do not have an infrastructure capable of fending off any other types of DoS attacks, chances are this tool will only help you to the
* point of your total bandwidth or server capacity for sending RESET's. Without a solid infrastructure and address filtering tool in place, a
* heavy distributed DoS will most likely still take you offline
*/
# ifdef U_EVASIVE_SUPPORT
class U_NO_EXPORT UEvasive : public UDataStorage {
public:
uint32_t timestamp, count;
// COSTRUTTORE
UEvasive()
{
U_TRACE_REGISTER_OBJECT(0, UEvasive, "", 0)
(void) memset(&timestamp, 0, sizeof(uint32_t) * 2);
}
~UEvasive()
{
U_TRACE_UNREGISTER_OBJECT(0, UEvasive)
if (UServer_Base::db_evasive)
{
UServer_Base::db_evasive->close();
delete UServer_Base::db_evasive;
}
}
// define method VIRTUAL of class UDataStorage
virtual char* toBuffer()
{
U_TRACE_NO_PARAM(0, "UEvasive::toBuffer()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_EQUALS(u_buffer_len, 0)
U_MEMCPY(u_buffer, &timestamp, u_buffer_len = sizeof(uint32_t) * 2);
U_INTERNAL_ASSERT_MINOR(u_buffer_len, U_BUFFER_SIZE)
buffer_len = u_buffer_len;
U_RETURN(u_buffer);
}
virtual void fromData(const char* ptr, uint32_t len)
{
U_TRACE(0, "UEvasive::fromData(%.*S,%u)", len, ptr, len)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(ptr)
U_INTERNAL_ASSERT(len >= sizeof(uint32_t) * 2)
U_MEMCPY(&timestamp, ptr, sizeof(uint32_t) * 2);
}
#if defined(DEBUG) && defined(U_STDCPP_ENABLE)
const char* dump(bool breset) const { return ""; }
#endif
private:
U_DISALLOW_COPY_AND_ASSIGN(UEvasive)
};
void UServer_Base::initEvasive()
{
U_TRACE_NO_PARAM(0, "UServer_Base::initEvasive()")
U_INTERNAL_ASSERT_EQUALS(db_evasive, U_NULLPTR)
U_NEW(UEvasive, evasive_rec, UEvasive);
U_NEW(URDBObjectHandler<UDataStorage*>, db_evasive, URDBObjectHandler<UDataStorage*>(U_STRING_FROM_CONSTANT("../db/Evasive"), -1, evasive_rec));
if (isPreForked())
{
U_INTERNAL_ASSERT_POINTER(ptr_shared_data)
U_INTERNAL_ASSERT_DIFFERS(ptr_shared_data, MAP_FAILED)
db_evasive->setShared(U_SRV_LOCK_EVASIVE, U_SRV_SPINLOCK_EVASIVE);
}
bool result = db_evasive->open(1024 * 1024, false, true); // NB: we don't want truncate (we have only the journal)...
U_SRV_LOG("%sdb initialization of Evasive %s: size(%u)", (result ? "" : "WARNING: "), (result ? "success" : "failed"), db_evasive->size());
if (result) db_evasive->reset(); // Initialize the db to contain no entries
else
{
delete db_evasive;
db_evasive = U_NULLPTR;
}
}
bool UServer_Base::checkHold(in_addr_t client, const char* client_address, uint32_t client_address_len)
{
U_TRACE(0, "UServer_Base::checkHold(%u,%.*S,%u)", client, client_address_len, client_address, client_address_len)
U_INTERNAL_ASSERT_POINTER(db_evasive)
if ((bwhitelist = (whitelist_IP && UIPAllow::isAllowed(client, *vwhitelist_IP))) == false) // Check whitelist
{
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
// First see if the IP itself is on "hold"
if (db_evasive->getDataStorage(client_address, client_address_len))
{
U_INTERNAL_DUMP("diff = %u evasive_rec->count = %u", u_now->tv_sec - evasive_rec->timestamp, evasive_rec->count)
if ((u_now->tv_sec - evasive_rec->timestamp) < blocking_period)
{
// Make it wait longer in blacklist land
evasive_rec->timestamp = u_now->tv_sec;
(void) db_evasive->putDataStorage();
U_RETURN(true);
}
}
}
U_RETURN(false);
}
bool UServer_Base::checkHitStats(const char* key, uint32_t key_len, uint32_t interval, uint32_t count)
{
U_TRACE(0, "UServer_Base::checkHitStats(%.*S,%u,%u,%u)", key_len, key, key_len, interval, count)
U_INTERNAL_ASSERT_POINTER(db_evasive)
U_INTERNAL_ASSERT_EQUALS(bwhitelist, false)
if (db_evasive->getDataStorage(key, key_len) == false)
{
evasive_rec->count = 0;
evasive_rec->timestamp = u_now->tv_sec;
}
else
{
// If site/URI is being hit too much, add to "hold" list
uint32_t diff = u_now->tv_sec - evasive_rec->timestamp;
U_INTERNAL_DUMP("diff = %u evasive_rec->count = %u", diff, evasive_rec->count)
if (diff < interval &&
evasive_rec->count >= count)
{
char msg[256];
uint32_t msg_len = (count == site_count
? u__snprintf(msg, sizeof(msg), U_CONSTANT_TO_PARAM("it has requested more than %u objects within the past %u seconds"), site_count, site_interval)
: u__snprintf(msg, sizeof(msg), U_CONSTANT_TO_PARAM("it has requested the same page more than %u within the past %u seconds"), page_count, page_interval));
evasive_rec->count = 0;
evasive_rec->timestamp = u_now->tv_sec;
(void) db_evasive->insertDataStorage(U_CLIENT_ADDRESS_TO_PARAM, RDB_REPLACE);
U_DEBUG("blacklisting address %.*S, possible DoS attack: %.*s", U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
U_SRV_LOG("WARNING: blacklisting address %.*S, possible DoS attack: %.*s", U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
UClientImage_Base::abortive_close();
if (emailAddress ||
systemCommand)
{
// Perform system functions and/or email notification
pid_t pid = UServer_Base::startNewChild();
if (pid > 0) U_RETURN(true); // parent
// child
if (systemCommand)
{
static int fd_stderr;
if (fd_stderr == 0) fd_stderr = UServices::getDevNull("/tmp/dos_system_command.err");
UString cmd(U_CAPACITY);
cmd.snprintf(U_STRING_TO_PARAM(*systemCommand), U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
UString output = UCommand::outputCommand(cmd, U_NULLPTR, -1, fd_stderr);
UServer_Base::logCommandMsgError(cmd.data(), true);
if (UCommand::exit_value) U_WARNING("DOS system command failed: EXIT_VALUE=%d RESPONSE=%V", UCommand::exit_value, output.rep);
}
if (emailAddress)
{
UString server, rcpt;
uint32_t index = emailAddress->find(':');
if (index == U_NOT_FOUND)
{
rcpt = *emailAddress;
server = *UString::str_localhost;
}
else
{
rcpt = emailAddress->substr(index+1);
server = emailAddress->substr(0U, index).copy();
}
if (emailClient->_connectServer(server) == false)
{
if (u_buffer_len)
{
U_WARNING("%.*s", u_buffer_len, u_buffer);
u_buffer_len = 0;
}
}
else
{
UString body(100U);
body.snprintf(U_CONSTANT_TO_PARAM("blacklisting address %.*S, possible DoS attack: %.*s"), U_CLIENT_ADDRESS_TO_TRACE, msg_len, msg);
emailClient->setMessageBody(body);
emailClient->setRecipientAddress(rcpt);
emailClient->setMessageSubject(U_STRING_FROM_CONSTANT("possible DoS attack"));
# ifdef USE_LIBSSL
bool ok = emailClient->sendMessage(true);
# else
bool ok = emailClient->sendMessage(false);
# endif
if (ok == false)
{
emailClient->setStatus();
U_WARNING("DOS email notification to %.*S failed: %.*s", U_STRING_TO_TRACE(*emailAddress), u_buffer_len, u_buffer);
u_buffer_len = 0;
}
}
}
if (pid == 0) UServer_Base::endNewChild();
}
U_RETURN(true);
}
if (diff >= interval) evasive_rec->count = 0; // Reset our hit count list as necessary
evasive_rec->count++;
evasive_rec->timestamp = u_now->tv_sec;
}
(void) db_evasive->putDataStorage();
U_RETURN(false);
}
bool UServer_Base::checkHitSiteStats()
{
U_TRACE_NO_PARAM(0, "UServer_Base::checkHitSiteStats()")
U_INTERNAL_ASSERT_POINTER(db_evasive)
if (bwhitelist == false)
{
char key[32];
U_gettimeofday // NB: optimization if it is enough a time resolution of one second...
if (checkHitStats(key, u__snprintf(key, sizeof(key), U_CONSTANT_TO_PARAM("%.*s_SITE"), U_CLIENT_ADDRESS_TO_TRACE), site_interval, site_count)) U_RETURN(true);
}
U_RETURN(false);
}
bool UServer_Base::checkHitUriStats()
{
U_TRACE_NO_PARAM(0, "UServer_Base::checkHitUriStats()")
U_INTERNAL_ASSERT_POINTER(db_evasive)
if (bwhitelist == false)
{
uint32_t sz = U_http_info.uri_len;
const char* ptr = U_http_info.uri;
# ifdef U_ALIAS
if (*UClientImage_Base::request_uri) // The interpreted pathname of the original requested document (relative to the document root)
{
sz = UClientImage_Base::request_uri->size();
ptr = UClientImage_Base::request_uri->data();
}
# endif
UString key(UServer_Base::client_address_len + sz);
key.snprintf(U_CONSTANT_TO_PARAM("%.*s%.*s"), U_CLIENT_ADDRESS_TO_TRACE, sz, ptr);
if (checkHitStats(U_STRING_TO_PARAM(key), page_interval, page_count)) U_RETURN(true);
}
U_RETURN(false);
}
bool UServer_Base::bwhitelist;
uint32_t UServer_Base::page_count;
uint32_t UServer_Base::site_count;
uint32_t UServer_Base::site_interval;
uint32_t UServer_Base::page_interval;
uint32_t UServer_Base::blocking_period;
UString* UServer_Base::emailAddress;
UString* UServer_Base::whitelist_IP;
UString* UServer_Base::systemCommand;
UEvasive* UServer_Base::evasive_rec;
USmtpClient* UServer_Base::emailClient;
UVector<UIPAllow*>* UServer_Base::vwhitelist_IP;
URDBObjectHandler<UDataStorage*>* UServer_Base::db_evasive;
# endif
#endif
#ifdef U_LINUX
@ -1243,6 +1612,16 @@ UServer_Base::~UServer_Base()
if (throttling_mask) delete throttling_mask;
#endif
#ifdef U_EVASIVE_SUPPORT
if (evasive_rec) delete evasive_rec;
if (vwhitelist_IP)
{
delete whitelist_IP;
delete vwhitelist_IP;
}
#endif
#ifdef U_WELCOME_SUPPORT
if (msg_welcome) delete msg_welcome;
#endif
@ -1528,6 +1907,17 @@ void UServer_Base::loadConfigParam()
// 1 - classic, forking after client accept
// >1 - pool of serialized processes plus monitoring process
// --------------------------------------------------------------------------------------------------------------------------------------
// This directive are for evasive action in the event of an HTTP DoS or DDoS attack or brute force attack
// --------------------------------------------------------------------------------------------------------------------------------------
// DOS_PAGE_COUNT this is the threshhold for the number of requests for the same page (or URI) per page interval
// DOS_PAGE_INTERVAL the interval for the page count threshhold; defaults to 1 second intervals
// DOS_SITE_COUNT this is the threshhold for the total number of requests for any object by the same client per site interval
// DOS_SITE_INTERVAL the interval for the site count threshhold; defaults to 1 second intervals
// DOS_BLOCKING_PERIOD the blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10)
// DOS_WHITE_LIST list of comma separated IP addresses of trusted clients can be whitelisted to insure they are never denied (IPADDR[/MASK])
// DOS_EMAIL_NOTIFY the email address to send a message whenever an IP address becomes blacklisted
// DOS_SYSTEM_COMMAND the system command specified will be executed whenever an IP address becomes blacklisted. Use %v to denote the IP address of the blacklisted IP
// --------------------------------------------------------------------------------------------------------------------------------------
#ifdef USE_LIBSSL
U_INTERNAL_DUMP("bssl = %b", bssl)
@ -1659,14 +2049,13 @@ void UServer_Base::loadConfigParam()
if (x)
{
U_NEW(UString, allow_IP, UString(x));
U_INTERNAL_ASSERT_EQUALS(allow_IP, U_NULLPTR)
U_NEW(UVector<UIPAllow*>, vallow_IP, UVector<UIPAllow*>);
if (UIPAllow::parseMask(*allow_IP, *vallow_IP) == 0)
if (UIPAllow::parseMask(x, *vallow_IP)) U_NEW(UString, allow_IP, UString(x));
else
{
delete allow_IP;
allow_IP = U_NULLPTR;
delete vallow_IP;
vallow_IP = U_NULLPTR;
}
@ -1678,14 +2067,13 @@ void UServer_Base::loadConfigParam()
if (x)
{
U_NEW(UString, allow_IP_prv, UString(x));
U_INTERNAL_ASSERT_EQUALS(allow_IP_prv, U_NULLPTR)
U_NEW(UVector<UIPAllow*>, vallow_IP_prv, UVector<UIPAllow*>);
if (UIPAllow::parseMask(*allow_IP_prv, *vallow_IP_prv) == 0)
if (UIPAllow::parseMask(x, *vallow_IP_prv)) U_NEW(UString, allow_IP_prv, UString(x));
else
{
delete allow_IP_prv;
allow_IP_prv = U_NULLPTR;
delete vallow_IP_prv;
vallow_IP_prv = U_NULLPTR;
}
@ -1694,6 +2082,96 @@ void UServer_Base::loadConfigParam()
enable_rfc1918_filter = cfg->readBoolean(U_CONSTANT_TO_PARAM("ENABLE_RFC1918_FILTER"));
#endif
#ifdef U_EVASIVE_SUPPORT
/**
* This is the threshhold for the number of requests for the same page (or URI) per page interval.
* Once the threshhold for that interval has been exceeded (defaults to 3), the IP address of the client will be added to the blocking list
*/
page_count = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_PAGE_COUNT"), 3);
/**
* The interval for the page count threshhold; defaults to 1 second intervals
*/
page_interval = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_PAGE_INTERVAL"), 1);
/**
* This is the threshhold for the total number of requests for any object by the same client per site interval.
* Once the threshhold for that interval has been exceeded (defaults to 50), the IP address of the client will be added to the blocking list
*/
site_count = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_SITE_COUNT"), 50);
/**
* The interval for the site count threshhold; defaults to 1 second intervals
*/
site_interval = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_SITE_INTERVAL"), 1);
/**
* The blocking period is the amount of time (in seconds) that a client will be blocked for if they are added to the blocking list (defaults to 10).
* During this time, all subsequent requests from the client will result in a abortive close and the timer being reset (e.g. another 10 seconds).
* Since the timer is reset for every subsequent request, it is not necessary to have a long blocking period; in the event of a DoS attack, this
* timer will keep getting reset
*/
blocking_period = cfg->readLong(U_CONSTANT_TO_PARAM("DOS_BLOCKING_PERIOD"), 10);
/**
* IP addresses of trusted clients can be whitelisted to insure they are never denied. The purpose of whitelisting is to protect software, scripts, local
* searchbots, or other automated tools from being denied for requesting large amounts of data from the server. Whitelisting should *not* be used to add
* customer lists or anything of the sort, as this will open the server to abuse. This module is very difficult to trigger without performing some type of
* malicious attack, and for that reason it is more appropriate to allow the module to decide on its own whether or not an individual customer should be blocked
*/
x = cfg->at(U_CONSTANT_TO_PARAM("DOS_WHITE_LIST"));
if (x)
{
U_INTERNAL_ASSERT_EQUALS(whitelist_IP, U_NULLPTR)
U_NEW(UVector<UIPAllow*>, vwhitelist_IP, UVector<UIPAllow*>);
if (UIPAllow::parseMask(x, *vwhitelist_IP)) U_NEW(UString, whitelist_IP, UString(x));
else
{
delete vwhitelist_IP;
vwhitelist_IP = U_NULLPTR;
}
}
/**
* If this value is set, an email will be sent to the address specified whenever an IP address becomes blacklisted
*/
x = cfg->at(U_CONSTANT_TO_PARAM("DOS_EMAIL_NOTIFY"));
if (x)
{
U_INTERNAL_ASSERT_EQUALS(emailClient, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(emailAddress, U_NULLPTR)
U_NEW(UString, emailAddress, UString(x));
U_NEW(USmtpClient, emailClient, USmtpClient(UClientImage_Base::bIPv6));
}
/**
* If this value is set, the system command specified will be executed whenever an IP address becomes blacklisted.
* This is designed to enable system calls to ip filter or other tools. Use %.*s to denote the IP address of the blacklisted IP
*/
x = cfg->at(U_CONSTANT_TO_PARAM("DOS_SYSTEM_COMMAND"));
if (x)
{
U_INTERNAL_ASSERT_EQUALS(systemCommand, U_NULLPTR)
U_NEW(UString, systemCommand, UString(x));
}
#endif
// If you want the webserver to run as a process of a defined user, you can do it.
// For the change of user to work, it's necessary to execute the server with root privileges.
// If it's started by a user that that doesn't have root privileges, this step will be omitted
@ -2546,6 +3024,9 @@ void UServer_Base::init()
UTimer::insert(pstat);
#endif
(void) UFile::_mkdir("../db");
#ifdef U_THROTTLING_SUPPORT
if (db_throttling)
{
@ -2647,6 +3128,10 @@ void UServer_Base::init()
if (throttling_mask) initThrottlingServer();
#endif
#ifdef U_EVASIVE_SUPPORT
initEvasive();
#endif
if (cfg) cfg->clear();
UInterrupt::syscall_restart = false;
@ -3087,6 +3572,26 @@ try_accept:
U_INTERNAL_DUMP("client_address = %.*S", CLIENT_ADDRESS_LEN, CLIENT_ADDRESS)
#ifdef U_EVASIVE_SUPPORT
if (checkHold(CSOCKET->remoteIPAddress().getInAddr(), CLIENT_ADDRESS, CLIENT_ADDRESS_LEN))
{
CSOCKET->abortive_close();
# if defined(ENABLE_THREAD) && !defined(USE_LIBEVENT) && defined(U_SERVER_THREAD_APPROACH_SUPPORT)
if (preforked_num_kids != -1)
# endif
{
U_INTERNAL_ASSERT_DIFFERS(socket_flags & O_NONBLOCK, 0)
# ifndef USE_LIBEVENT
goto try_next;
# endif
}
goto next;
}
#endif
#if defined(_MSWINDOWS_) && !defined(USE_LIBEVENT)
if (CSOCKET->iSockDesc >= FD_SETSIZE)
{

View File

@ -3015,7 +3015,7 @@ loop:
if (nerror == NO_ERROR)
{
U_INTERNAL_ASSERT_MAJOR(pConnection->out_window, 0)
if (pConnection->out_window == 0) goto loop;
U_INTERNAL_DUMP("pStreamOld = %u pStream = %u", pStreamOld, pStream)
@ -3416,8 +3416,6 @@ read_request:
if (sz == 0)
{
// sz = 0 U_http_info.uri_len = 0 U_http2_settings_len = 0 U_ClientImage_close = false
if (U_http2_settings_len)
{
// NB: not OPTION upgrade...

View File

@ -289,6 +289,7 @@ UString UStringExt::dos2unix(const UString& s, bool unix2dos)
if (c == '\n')
{
if (unix2dos) *str++ = '\r';
*str++ = '\n';
continue;

View File

@ -1650,38 +1650,6 @@ __pure bool UHTTP::isValidMethod(const char* ptr)
U_RETURN(false);
}
__pure bool UHTTP::isValidRequest(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequest(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
U_INTERNAL_DUMP("sz = %u UClientImage_Base::size_request = %u", sz, UClientImage_Base::size_request)
if (u_get_unalignedp32(ptr+sz-4) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true);
U_RETURN(false);
}
__pure bool UHTTP::isValidRequestExt(const char* ptr, uint32_t sz)
{
U_TRACE(0, "UHTTP::isValidRequestExt(%.*S,%u)", 30, ptr, sz)
U_INTERNAL_ASSERT_MAJOR(sz, 0)
if (sz >= U_CONSTANT_SIZE("GET / HTTP/1.0\r\n\r\n") &&
isValidMethod(ptr) &&
(isValidRequest(ptr, sz) ||
(UClientImage_Base::size_request &&
isValidRequest(ptr, UClientImage_Base::size_request)) ||
u_findEndHeader1(ptr, sz) != U_NOT_FOUND))
{
U_RETURN(true);
}
U_RETURN(false);
}
bool UHTTP::scanfHeaderRequest(const char* ptr, uint32_t size)
{
U_TRACE(0, "UHTTP::scanfHeaderRequest(%.*S,%u)", size, ptr, size)
@ -1998,6 +1966,7 @@ U_NO_EXPORT bool UHTTP::readHeaderRequest()
{
U_TRACE_NO_PARAM(0, "UHTTP::readHeaderRequest()")
void* p;
uint32_t sz = UClientImage_Base::request->size();
const char* ptr = UClientImage_Base::request->data();
@ -2033,9 +2002,9 @@ U_NO_EXPORT bool UHTTP::readHeaderRequest()
if (u_get_unalignedp32(ptr) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')) U_RETURN(true);
sz = u_findEndHeader1(ptr+2, sz-U_http_info.startHeader-2);
p = memmem(ptr+U_CONSTANT_SIZE(U_CRLF), sz-U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF), U_CONSTANT_TO_PARAM(U_CRLF2));
if (sz != U_NOT_FOUND) sz += U_http_info.startHeader-2;
if (p) sz = U_http_info.startHeader + (const char*)p - ptr;
else
{
# ifdef USE_LIBSSL
@ -2073,6 +2042,7 @@ bool UHTTP::readHeaderResponse(USocket* sk, UString& buffer)
U_INTERNAL_ASSERT_POINTER(sk)
void* p;
const char* ptr;
uint32_t sz = buffer.size();
@ -2147,9 +2117,9 @@ loop: sz = buffer.size();
U_INTERNAL_ASSERT_EQUALS(u_get_unalignedp16(ptr), U_MULTICHAR_CONSTANT16('\r','\n'))
sz = u_findEndHeader1(ptr+U_CONSTANT_SIZE(U_CRLF), sz-U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF));
p = memmem(ptr+U_CONSTANT_SIZE(U_CRLF), sz-U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF), U_CONSTANT_TO_PARAM(U_CRLF2));
if (sz != U_NOT_FOUND) sz += U_http_info.startHeader-U_CONSTANT_SIZE(U_CRLF);
if (p) sz = U_http_info.startHeader + (const char*)p - ptr;
else
{
sz = USocketExt::readWhileNotToken(sk, buffer, U_CONSTANT_TO_PARAM(U_CRLF2), UServer_Base::timeoutMS);
@ -3659,8 +3629,7 @@ bool UHTTP::handlerCache()
const char* ptr1 = ptr+UClientImage_Base::size_request;
if (isValidMethod(ptr1) == false ||
( isValidRequest(ptr1, UClientImage_Base::size_request) == false &&
u_findEndHeader1(ptr1, UClientImage_Base::size_request) == U_NOT_FOUND))
u_findEndHeader1(ptr1, UClientImage_Base::size_request) == U_NOT_FOUND)
{
U_RETURN(false);
}
@ -3986,7 +3955,8 @@ int UHTTP::handlerREAD()
U_INTERNAL_DUMP("UClientImage_Base::size_request = %u U_http_info.clength = %u", UClientImage_Base::size_request, U_http_info.clength)
/* NB: readBodyRequest() depend on UClientImage_Base::request
/**
* NB: readBodyRequest() depend on UClientImage_Base::request
*
* if (UClientImage_Base::size_request < UClientImage_Base::request->size())
* {
@ -4314,6 +4284,10 @@ manage:
UClientImage_Base::isRequestInFileCache()) // => 3)
{
file_in_cache:
# ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHitUriStats()) U_RETURN(U_PLUGIN_HANDLER_ERROR);
# endif
# if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL)
if (isValidation() == false) U_RETURN(U_PLUGIN_HANDLER_FINISHED);
# endif
@ -4435,6 +4409,10 @@ file_exist_and_need_to_be_processed: // NB: if we can't service the content of f
UClientImage_Base::setRequestNeedProcessing();
}
# ifdef U_EVASIVE_SUPPORT
if (UServer_Base::checkHitUriStats()) U_RETURN(U_PLUGIN_HANDLER_ERROR);
# endif
# if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL)
if (isValidation() == false) U_RETURN(U_PLUGIN_HANDLER_FINISHED);
# endif
@ -4442,6 +4420,15 @@ file_exist_and_need_to_be_processed: // NB: if we can't service the content of f
goto end;
}
#ifdef U_EVASIVE_SUPPORT
if (UClientImage_Base::isRequestNotFound() == false && // => 4)
UClientImage_Base::isRequestAlreadyProcessed() == false && // => 5)
UServer_Base::checkHitUriStats())
{
U_RETURN(U_PLUGIN_HANDLER_ERROR);
}
#endif
#if defined(U_HTTP_STRICT_TRANSPORT_SECURITY) || defined(USE_LIBSSL)
if ( UClientImage_Base::isRequestNotFound() == false && // => 4)
(UClientImage_Base::isRequestAlreadyProcessed() || // => 5)

View File

@ -4,7 +4,7 @@ fw_depends mysql ulib
# Travis is broken
if [ "$TRAVIS" != "true" ]; then
MAX_THREADS=$(( 3 * $CPU_COUNT / 2 ))
MAX_THREADS=$CPU_COUNT
else
MAX_THREADS=$(( 2 * $CPU_COUNT ))
fi

View File

@ -29,7 +29,7 @@ static void usp_fork_fortune()
U_NEW(UOrmStatement, pstmt_fortune, UOrmStatement(*psql_fortune, U_CONSTANT_TO_PARAM("SELECT id, message FROM Fortune")));
if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT";
// if (UOrmDriver::isPGSQL()) *psql_fortune << "BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT";
U_NEW(Fortune, pfortune, Fortune);
@ -70,6 +70,7 @@ pstmt_fortune->execute();
do {
U_NEW(Fortune, item, Fortune(*pfortune));
pvfortune->push_back(item);
}
while (pstmt_fortune->nextRow());

View File

@ -28,7 +28,7 @@ static void usp_fork_query()
U_NEW(UOrmStatement, pstmt_query, UOrmStatement(*psql_query, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION";
// if (UOrmDriver::isPGSQL()) *psql_query << "BEGIN TRANSACTION";
U_NEW(World, pworld_query, World);

View File

@ -6,13 +6,10 @@ TechEmpower Web Framework Benchmarks
#include "world.h"
static World* pworld_update;
static UString* pquery;
static UOrmSession* psql_update;
static UOrmStatement* pstmt1;
static UOrmStatement* pstmt2;
#ifndef AS_cpoll_cppsp_DO
static UOrmStatement* pstmt;
static UVector<World*>* pvworld_update;
#endif
static void usp_fork_update()
{
@ -27,20 +24,18 @@ static void usp_fork_update()
return;
}
U_NEW(UOrmStatement, pstmt1, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
U_NEW(UOrmStatement, pstmt2, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("UPDATE World SET randomNumber = ? WHERE id = ?")));
U_NEW(UOrmStatement, pstmt, UOrmStatement(*psql_update, U_CONSTANT_TO_PARAM("SELECT randomNumber FROM World WHERE id = ?")));
if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF";
// if (UOrmDriver::isPGSQL()) *psql_update << "SET synchronous_commit TO OFF";
U_NEW(World, pworld_update, World);
pstmt1->use( pworld_update->id);
pstmt1->into(pworld_update->randomNumber);
pstmt2->use( pworld_update->randomNumber, pworld_update->id);
pstmt->use( pworld_update->id);
pstmt->into(pworld_update->randomNumber);
U_NEW(UString, pquery, UString(U_CAPACITY));
#ifndef AS_cpoll_cppsp_DO
U_NEW(UVector<World*>, pvworld_update, UVector<World*>(500));
#endif
}
#ifdef DEBUG
@ -50,16 +45,12 @@ static void usp_end_update()
delete psql_update;
if (pstmt1 &&
pstmt2)
if (pstmt)
{
delete pstmt1;
delete pstmt2;
delete pstmt;
delete pquery;
delete pworld_update;
# ifndef AS_cpoll_cppsp_DO
delete pvworld_update;
# endif
}
}
#endif
@ -68,30 +59,56 @@ static void usp_end_update()
Content-Type: application/json
-->
<!--#code
char* ptr;
World* pworld;
char* query = pquery->data();
int i = 0, num_queries = UHTTP::getFormFirstNumericValue(1, 500);
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR('[');
#endif
(void) memcpy(query, "UPDATE World SET randomNumber = v.randomNumber FROM (VALUES",
U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES"));
ptr = query + U_CONSTANT_SIZE("UPDATE World SET randomNumber = v.randomNumber FROM (VALUES");
while (true)
{
pworld_update->id = u_get_num_random(10000-1);
pstmt1->execute();
pstmt->execute();
pworld_update->randomNumber = u_get_num_random(10000-1);
pstmt2->execute();
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld_update->id, pworld_update->randomNumber);
#else
World* pworld;
U_NEW(World, pworld, World(*pworld_update));
pvworld_update->push_back(pworld);
if (++i == num_queries) break;
}
pvworld_update->sort();
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR('[');
#endif
i = 0;
while (true)
{
pworld = pvworld_update->at(i);
*ptr++ = '(';
ptr = u_num2str32(pworld->id, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(',',' '));
ptr += 2;
ptr = u_num2str32(pworld->randomNumber, ptr);
u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16(')',','));
ptr += 2;
#ifdef AS_cpoll_cppsp_DO
USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld->id, pworld->randomNumber);
#endif
if (++i == num_queries) break;
@ -103,8 +120,12 @@ while (true)
#ifdef AS_cpoll_cppsp_DO
USP_PUTS_CHAR(']');
#else
USP_OBJ_JSON_stringify(*pvworld_update);
pvworld_update->clear();
#endif
(void) memcpy(ptr-1, ") AS v (id, randomNumber) WHERE World.id = v.id;",
U_CONSTANT_SIZE(") AS v (id, randomNumber) WHERE World.id = v.id;")+1);
*psql_update << query;
pvworld_update->clear();
-->

View File

@ -32,6 +32,13 @@ public:
U_TRACE_REGISTER_OBJECT(5, World, "%u,%u", _id, _randomNumber)
}
World(const World& w) : id(w.id), randomNumber(w.randomNumber)
{
U_TRACE_REGISTER_OBJECT(5, World, "%p", &w)
U_MEMORY_TEST_COPY(w)
}
~World()
{
U_TRACE_UNREGISTER_OBJECT(5, World)
@ -73,6 +80,30 @@ public:
stmt->bindResult(U_ORM_TYPE_HANDLER(randomNumber, unsigned int));
}
// SERVICE
bool operator<(const World& other) const { return cmp_obj(&id, &other.id); }
static int cmp_obj(const void* a, const void* b)
{
U_TRACE(5, "World::cmp_obj(%p,%p)", a, b)
# ifdef U_STDCPP_ENABLE
/**
* The comparison function must follow a strict-weak-ordering
*
* 1) For all x, it is not the case that x < x (irreflexivity)
* 2) For all x, y, if x < y then it is not the case that y < x (asymmetry)
* 3) For all x, y, and z, if x < y and y < z then x < z (transitivity)
* 4) For all x, y, and z, if x is incomparable with y, and y is incomparable with z, then x is incomparable with z (transitivity of incomparability)
*/
return (((const World*)a)->id < (((const World*)b)->id));
# else
return (*(const World**)a)->id < ((*(const World**)b)->id);
# endif
}
#ifdef DEBUG
const char* dump(bool breset) const
{

View File

@ -18,8 +18,8 @@ cat <<EOF >inp/server.cf
userver {
PORT 10001
WELCOME_MSG "generic server ready."
ALLOWED_IP localhost
#ALLOWED_IP localhost,10.30.0.0/16
ALLOWED_IP 127.0.0.1
#ALLOWED_IP 127.0.0.1,10.30.0.0/16
LOG_FILE server.log
LOG_FILE_SZ 1M
PLUGIN echo

View File

@ -1,8 +1,8 @@
userver {
PORT 10001
WELCOME_MSG "generic server ready."
ALLOWED_IP localhost
#ALLOWED_IP localhost,10.30.0.0/16
ALLOWED_IP 127.0.0.1
#ALLOWED_IP 127.0.0.1,10.30.0.0/16
LOG_FILE server.log
LOG_FILE_SZ 1M
PLUGIN echo

View File

@ -100,6 +100,8 @@ done
upload_test $2:8080
kill_server userver_tcp
$SLEEP
pkill userver_tcp 2>/dev/null
}
# function : creat_config
@ -117,6 +119,7 @@ userver {
RUN_AS_USER nobody
#MIN_SIZE_FOR_SENDFILE 2k
REQ_TIMEOUT 30
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE webserver$1.log
LOG_FILE_SZ 1M
LOG_MSG_SIZE -1

View File

@ -30,6 +30,7 @@ cat <<EOF >inp/webserver.cfg
userver {
PORT 8080
RUN_AS_USER apache
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE web_server_multiclient.log
LOG_FILE_SZ 1M
LOG_MSG_SIZE -1

View File

@ -112,6 +112,7 @@ userver {
RUN_AS_USER nobody
REQ_TIMEOUT 30
#MIN_SIZE_FOR_SENDFILE 2k
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE webserver_ssl$1.log
LOG_FILE_SZ 1M
LOG_MSG_SIZE -1

View File

@ -1,14 +1,17 @@
See http://www.debian.org/ for information about Debian GNU/Linux.
Four Debian releases are available on the main site:
Debian 7.11, or wheezy. Access this release through dists/oldstable
Debian 7.11, or wheezy. Access this release through dists/oldoldstable
Debian 7.11 was released Saturday, 4th June 2016.
Debian 8.8, or jessie. Access this release through dists/stable
Debian 8.8, or jessie. Access this release through dists/oldstable
Debian 8.8 was released Saturday, 6th May 2017.
Testing, or stretch. Access this release through dists/testing. The
current tested development snapshot is named stretch. Packages which
Debian 9.0, or stretch. Access this release through dists/stable
Debian 9.0 was released Saturday, 17th June 2017.
Testing, or buster. Access this release through dists/testing. The
current tested development snapshot is named buster. Packages which
have been tested in unstable and passed automated tests propagate to
this release.

View File

@ -2,6 +2,10 @@ SERVER {
PORT 8080
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
DOS_EMAIL_NOTIFY mail.unirel.com:stefano.casazza2@unirel.com
DOS_SYSTEM_COMMAND "sh -c 'echo %.*s: %.*s >> /tmp/dos_blacklist.txt'"
LOG_FILE rdb_server.log
LOG_FILE_SZ 1M

View File

@ -43,14 +43,17 @@ URL: ftp://ftp.at.debian.org/debian/README
See http://www.debian.org/ for information about Debian GNU/Linux.
Four Debian releases are available on the main site:
Debian 7.9, or wheezy. Access this release through dists/oldstable
Debian 7.9 was released Saturday, 5th September 2015.
Debian 7.11, or wheezy. Access this release through dists/oldoldstable
Debian 7.11 was released Saturday, 4th June 2016.
Debian 8.3, or jessie. Access this release through dists/stable
Debian 8.3 was released Saturday, 23rd January 2016.
Debian 8.8, or jessie. Access this release through dists/oldstable
Debian 8.8 was released Saturday, 6th May 2017.
Testing, or stretch. Access this release through dists/testing. The
current tested development snapshot is named stretch. Packages which
Debian 9.0, or stretch. Access this release through dists/stable
Debian 9.0 was released Saturday, 17th June 2017.
Testing, or buster. Access this release through dists/testing. The
current tested development snapshot is named buster. Packages which
have been tested in unstable and passed automated tests propagate to
this release.
@ -105,7 +108,7 @@ the <a href="mailto:webmaster@unirel.com">webmaster</a>.
<address>
<a href="/">www.unirel.com</a><br />
<span>Wed Mar 2 18:45:49 2016<br />
<span>Mon Jun 19 14:01:54 2017<br />
Apache/2.0.49 (Linux/SuSE)</span>
</address>
</body>

View File

@ -1,14 +1,17 @@
See http://www.debian.org/ for information about Debian GNU/Linux.
Four Debian releases are available on the main site:
Debian 7.9, or wheezy. Access this release through dists/oldstable
Debian 7.9 was released Saturday, 5th September 2015.
Debian 7.11, or wheezy. Access this release through dists/oldoldstable
Debian 7.11 was released Saturday, 4th June 2016.
Debian 8.3, or jessie. Access this release through dists/stable
Debian 8.3 was released Saturday, 23rd January 2016.
Debian 8.8, or jessie. Access this release through dists/oldstable
Debian 8.8 was released Saturday, 6th May 2017.
Testing, or stretch. Access this release through dists/testing. The
current tested development snapshot is named stretch. Packages which
Debian 9.0, or stretch. Access this release through dists/stable
Debian 9.0 was released Saturday, 17th June 2017.
Testing, or buster. Access this release through dists/testing. The
current tested development snapshot is named buster. Packages which
have been tested in unstable and passed automated tests propagate to
this release.

View File

@ -61,7 +61,7 @@ U_EXPORT main(int argc, char* argv[], char* env[])
int result;
UString host(argv[1]);
URDBClient<UTCPSocket> x(0);
URDBClient<UTCPSocket> x(U_NULLPTR);
if (x.setHostPort(host, 8080) && x.connect())
{

View File

@ -14,7 +14,7 @@ U_EXPORT main (int argc, char* argv[], char* env[])
U_TRACE(5,"main(%d)",argc)
UFileConfig fcg;
UServerExample server(0);
UServerExample server(U_NULLPTR);
UString plugin_dir(argv[1]), plugin_list(argv[2]);
if (argv[3])