mod_noloris.c revision c41be3600a58bd39a76d1215abcdbbd8e9b1c356
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz/* Licensed to the Apache Software Foundation (ASF) under one or more
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * contributor license agreements. See the NOTICE file distributed with
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * this work for additional information regarding copyright ownership.
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * The ASF licenses this file to You under the Apache License, Version 2.0
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * (the "License"); you may not use this file except in compliance with
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * the License. You may obtain a copy of the License at
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * Unless required by applicable law or agreed to in writing, software
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * distributed under the License is distributed on an "AS IS" BASIS,
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * See the License for the specific language governing permissions and
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * limitations under the License.
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd/* The use of the scoreboard in this module is based on a similar
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * but simpler module, mod_antiloris by Kees Monshouwer, from
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * Note the FIXME that affects both modules.
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * The major difference is that mod_antiloris checks the scoreboard
0066eddda7203f6345b56f77d146a759298dc635gryzor * on every request. This implies a per-request overhead that grows
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * with the scoreboard, and gets very expensive on a big server.
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * On the other hand, this module (mod_noloris) may be slower to
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * react to a DoS attack, and in the case of a very small server
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * it might be too late.
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * Author's untested instinct: mod_antiloris will suit servers with
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * Prefork MPM and low traffic. A server with a threaded MPM
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin * (or possibly a big prefork server with lots of memory) should
bdd978e5ecd8daa2542d4d4e1988c78a622cd7f4nd * raise MaxClients and use mod_noloris.
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantzstatic unsigned int default_max_connections;
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin struct { int child_num; int thread_num; } *sbh = conn->sbh;
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin /* check the IP is not banned */
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn, APLOGNO(02059)
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin "Dropping connection from banned IP %s",
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf /* store this client IP for the monitor to pick up */
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin ap_update_child_status_from_conn(conn->sbh, SERVER_READY, conn);
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirinstatic int noloris_monitor(apr_pool_t *pool, server_rec *s)
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin static int *totals;
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf /* do nothing if disabled */
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin /* skip check if it's not due yet */
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin /* alloc lots of stuff at start, so we don't leak memory per-call */
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin totals = apr_palloc(pool, server_limit*thread_limit);
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf /* Get a per-client count of connections in READ state */
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin for (i = 0; i < server_limit; ++i) {
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin for (j = 0; j < thread_limit; ++j) {
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin n = apr_hash_get(connections, ws->client, APR_HASH_KEY_STRING);
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin if (n == NULL) {
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz apr_hash_set(connections, ws->client, APR_HASH_KEY_STRING, n);
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf /* reset shm before writing to it.
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin * We're only dealing with approx. counts, so we ignore the race condition
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * with our prospective readers
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin /* Now check the hash for clients with too many connections in READ state */
aa0b2780958e9b1467c9d0153a05738e399811a5nd for (hi = apr_hash_first(NULL, connections); hi; hi = apr_hash_next(hi)) {
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin /* if this isn't a trusted proxy, we mark it as bad */
9a367ec3d570bcbaf8923dad66cb3b1532963964trawick if (!apr_hash_get(trusted, ip, APR_HASH_KEY_STRING)) {
9a367ec3d570bcbaf8923dad66cb3b1532963964trawick ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02060)
8951c7d73bfa2ae5a2c8fe5bd27f3e677be02564noirin "noloris: banning %s with %d connections in READ state",
1b390add6886fb1c0acdea82be0ef0920f1158casfstatic int noloris_post(apr_pool_t *pconf, apr_pool_t *ptmp, apr_pool_t *plog,
1b390add6886fb1c0acdea82be0ef0920f1158casf int max_bans = thread_limit * server_limit / default_max_connections;
1b390add6886fb1c0acdea82be0ef0920f1158casf ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(02061)
1b390add6886fb1c0acdea82be0ef0920f1158casf "Failed to create shm segment; mod_noloris disabled");
1b390add6886fb1c0acdea82be0ef0920f1158casfstatic int noloris_pre(apr_pool_t *pconf, apr_pool_t *ptmp, apr_pool_t *plog)
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd /* set up default config stuff here */
if (!err) {
return err;
if (!err) {
return err;
if (!err) {
return err;
{NULL}
NULL,
NULL,
NULL,
NULL,