Removed cookie checking -- deprecated.
Added better NULL input handling. Altered the logging levels for blocklist matches and module initialisation.
This commit is contained in:
parent
0ba358639f
commit
5ce554fc48
|
@ -19,9 +19,8 @@ Installation
|
||||||
LoadModule blockinator_module modules/libmodblockinator.so
|
LoadModule blockinator_module modules/libmodblockinator.so
|
||||||
|
|
||||||
2. Configure mod_blockinator by adding the following lines in the appropriate location(s):
|
2. Configure mod_blockinator by adding the following lines in the appropriate location(s):
|
||||||
1. Define where Blockinator is installed and where the blocklist DB can be found:
|
1. Define where the blocklist DB can be found:
|
||||||
<IfModule blockinator_module>
|
<IfModule blockinator_module>
|
||||||
BlockinatorHome /path/to/blockinator
|
|
||||||
BlockinatorBlocklistDB /path/to/blocklist.db
|
BlockinatorBlocklistDB /path/to/blocklist.db
|
||||||
</IfModule>
|
</IfModule>
|
||||||
2. Create a mod_rewrite rule to block requests, if matched:
|
2. Create a mod_rewrite rule to block requests, if matched:
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "http_config.h"
|
#include "http_config.h"
|
||||||
#include "http_log.h"
|
#include "http_log.h"
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
module AP_MODULE_DECLARE_DATA blockinator_module;
|
module AP_MODULE_DECLARE_DATA blockinator_module;
|
||||||
|
|
||||||
|
@ -27,7 +26,6 @@ module AP_MODULE_DECLARE_DATA blockinator_module;
|
||||||
*/
|
*/
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *basepath;
|
|
||||||
const char *db;
|
const char *db;
|
||||||
} blockinator_cfg_t;
|
} blockinator_cfg_t;
|
||||||
|
|
||||||
|
@ -42,16 +40,6 @@ static void *create_blockinator_config(apr_pool_t *p, server_rec *s)
|
||||||
return mod_config;
|
return mod_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Function to set the configuration item, 'basepath'
|
|
||||||
*/
|
|
||||||
static const char *blockinator_set_config_basepath(cmd_parms *parms, void *mconfig, const char *arg)
|
|
||||||
{
|
|
||||||
blockinator_cfg_t *cfg = ap_get_module_config(parms->server->module_config, &blockinator_module);
|
|
||||||
cfg->basepath = (char *)arg;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to set the configuration item, 'db'
|
* Function to set the configuration item, 'db'
|
||||||
*/
|
*/
|
||||||
|
@ -67,33 +55,40 @@ static const char *blockinator_set_config_db(cmd_parms *parms, void *mconfig, co
|
||||||
*/
|
*/
|
||||||
static int mod_blockinator_method_handler(request_rec *r)
|
static int mod_blockinator_method_handler(request_rec *r)
|
||||||
{
|
{
|
||||||
const char *remote_ip, *forwarded_ip, *useragent, *cookie;
|
const char *remote_ip, *forwarded_ip, *useragent;
|
||||||
char *statement;
|
char *statement;
|
||||||
char *sqlite3_error;
|
char *sqlite3_error;
|
||||||
sqlite3_stmt *sqlite3_statement;
|
sqlite3_stmt *sqlite3_statement;
|
||||||
|
int sqlite3_rc;
|
||||||
|
|
||||||
/* Capture the relevant information from the inbound request */
|
/* Capture the relevant information from the inbound request */
|
||||||
remote_ip = r->connection->remote_ip;
|
remote_ip = r->connection->remote_ip;
|
||||||
forwarded_ip = apr_table_get(r->headers_in, "X-Forwarded-For");
|
forwarded_ip = apr_table_get(r->headers_in, "X-Forwarded-For");
|
||||||
useragent = apr_table_get(r->headers_in, "User-Agent");
|
useragent = apr_table_get(r->headers_in, "User-Agent");
|
||||||
cookie = apr_table_get(r->headers_in, "Cookie");
|
|
||||||
|
if (forwarded_ip == NULL) {
|
||||||
|
forwarded_ip = "(null)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useragent == NULL) {
|
||||||
|
useragent = "(null)";
|
||||||
|
}
|
||||||
|
|
||||||
/* Build the SQL statement */
|
/* Build the SQL statement */
|
||||||
statement = sqlite3_mprintf("SELECT * FROM blocklist WHERE remote_ip = '%q' AND (forwarded_ip = 'ANY' OR forwarded_ip = '%q') AND (useragent = 'ANY' OR useragent = '%q') AND (cookie = 'ANY' OR instr('%q', cookie))", remote_ip, forwarded_ip, useragent, cookie);
|
statement = sqlite3_mprintf("SELECT * FROM blocklist WHERE remote_ip = '%q' AND (forwarded_ip = 'ANY' OR forwarded_ip = '%q') AND (useragent = 'ANY' OR useragent = '%q')", remote_ip, forwarded_ip, useragent);
|
||||||
|
|
||||||
/* Prepare the statement */
|
/* Prepare the statement */
|
||||||
if (sqlite3_prepare_v2(db, statement, BUFSIZ, &sqlite3_statement, NULL) != SQLITE_OK) {
|
sqlite3_rc = sqlite3_prepare_v2(db, statement, BUFSIZ, &sqlite3_statement, NULL);
|
||||||
|
if (sqlite3_rc != SQLITE_OK) {
|
||||||
/* SQLite error. Allow. */
|
/* SQLite error. Allow. */
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "SQLite error (%s). Allow traffic from %s by default.", sqlite3_error, remote_ip);
|
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "SQLite error (%s). Allow traffic from %s by default.", sqlite3_errmsg(db), remote_ip);
|
||||||
sqlite3_free(sqlite3_error);
|
|
||||||
|
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for any results. */
|
/* Check for any results. */
|
||||||
if (sqlite3_step(sqlite3_statement) == SQLITE_ROW) {
|
if (sqlite3_step(sqlite3_statement) == SQLITE_ROW) {
|
||||||
/* SQLite results. Time to block. */
|
/* SQLite results. Time to block. */
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "Blocklist match. (Forwarded_IP: %s, User-Agent: %s, Cookie: %s)", forwarded_ip, useragent, cookie);
|
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "Blocklist match. (Forwarded_IP: %s, User-Agent: %s)", forwarded_ip, useragent);
|
||||||
apr_table_set(r->headers_in, "X-Block", "1");
|
apr_table_set(r->headers_in, "X-Block", "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,31 +107,16 @@ static int mod_blockinator_method_handler(request_rec *r)
|
||||||
static void mod_blockinator_init_handler(apr_pool_t *p, server_rec *s)
|
static void mod_blockinator_init_handler(apr_pool_t *p, server_rec *s)
|
||||||
{
|
{
|
||||||
char *sqlite3_error;
|
char *sqlite3_error;
|
||||||
char sqlite3_instr_extension[BUFSIZ];
|
|
||||||
|
|
||||||
/* Read config from module */
|
/* Read config from module */
|
||||||
blockinator_cfg_t *cfg = ap_get_module_config(s->module_config, &blockinator_module);
|
blockinator_cfg_t *cfg = ap_get_module_config(s->module_config, &blockinator_module);
|
||||||
|
|
||||||
/* Build the full path to the SQLite instr() extension */
|
|
||||||
sprintf(sqlite3_instr_extension, "%s/sqlite_instr/instr.sqlext", cfg->basepath);
|
|
||||||
|
|
||||||
/* Open the SQLite DB */
|
/* Open the SQLite DB */
|
||||||
|
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Opening mod_blockinator blocklist DB: %s.", cfg->db);
|
||||||
if (sqlite3_open_v2(cfg->db, &db, SQLITE_OPEN_READONLY, "unix-none")) {
|
if (sqlite3_open_v2(cfg->db, &db, SQLITE_OPEN_READONLY, "unix-none")) {
|
||||||
/* Error. */
|
/* Error. */
|
||||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_blockinator: SQLite error (%s). Could not open database.", sqlite3_errmsg(db));
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_blockinator: SQLite error (%s). Could not open database.", sqlite3_errmsg(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the EDSA SQLite extension for instr() */
|
|
||||||
if ((sqlite3_enable_load_extension(db, 1) != SQLITE_OK) ||
|
|
||||||
(sqlite3_load_extension(db, sqlite3_instr_extension, 0, &sqlite3_error) != SQLITE_OK)
|
|
||||||
) {
|
|
||||||
/* FAIL */
|
|
||||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_blockinator: SQLite error (%s). Failed to load the instr() extension.", sqlite3_error);
|
|
||||||
sqlite3_free(sqlite3_error);
|
|
||||||
} else {
|
|
||||||
/* SQLite module successfully loaded. */
|
|
||||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "mod_blockinator: SQLite loaded the instr() extension successfully.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -155,13 +135,6 @@ static void register_hooks(apr_pool_t *p)
|
||||||
* Apache configuration directives
|
* Apache configuration directives
|
||||||
*/
|
*/
|
||||||
static const command_rec mod_blockinator_directives[] = {
|
static const command_rec mod_blockinator_directives[] = {
|
||||||
AP_INIT_TAKE1(
|
|
||||||
"BlockinatorHome",
|
|
||||||
blockinator_set_config_basepath,
|
|
||||||
NULL,
|
|
||||||
RSRC_CONF,
|
|
||||||
"BlockinatorHome (filepath). The base directory of Blockinator."
|
|
||||||
),
|
|
||||||
AP_INIT_TAKE1(
|
AP_INIT_TAKE1(
|
||||||
"BlockinatorBlocklistDB",
|
"BlockinatorBlocklistDB",
|
||||||
blockinator_set_config_db,
|
blockinator_set_config_db,
|
||||||
|
|
|
@ -23,6 +23,8 @@ class SQLiteBlockList(blocklist.BlockList):
|
||||||
cur.execute("DELETE FROM blocklist")
|
cur.execute("DELETE FROM blocklist")
|
||||||
|
|
||||||
for key,item in self.data.iteritems():
|
for key,item in self.data.iteritems():
|
||||||
|
if item["useragent"] == 'NULL':
|
||||||
|
item["useragent"] = '(null)'
|
||||||
cur.execute("INSERT INTO blocklist VALUES ('%s', '%s', '%s', '%s')" % (item["remote_ip"], item["forwarded_ip"], item["useragent"], item["cookie"]))
|
cur.execute("INSERT INTO blocklist VALUES ('%s', '%s', '%s', '%s')" % (item["remote_ip"], item["forwarded_ip"], item["useragent"], item["cookie"]))
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
CC=gcc
|
|
||||||
|
|
||||||
all: instr.sqlext
|
|
||||||
|
|
||||||
instr.sqlext: sqlite_instr.c
|
|
||||||
$(CC) -shared -fPIC -Isqlite3 -o instr.sqlext sqlite_instr.c
|
|
Binary file not shown.
|
@ -1,35 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
#include <sqlite3ext.h>
|
|
||||||
|
|
||||||
SQLITE_EXTENSION_INIT1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The sqlite3_instr() SQL function returns the location of a substring match. An
|
|
||||||
** implementation of MySQL's instr() function.
|
|
||||||
*/
|
|
||||||
void sqlite3_instr(sqlite3_context* pContext, int argc, sqlite3_value** argv)
|
|
||||||
{
|
|
||||||
const char *str1 = (const char *) sqlite3_value_text(argv[0]);
|
|
||||||
const char *str2 = (const char *) sqlite3_value_text(argv[1]);
|
|
||||||
|
|
||||||
char *p = strstr(str1, str2);
|
|
||||||
int nResult = 0;
|
|
||||||
|
|
||||||
if(p != NULL) {
|
|
||||||
nResult = p - str1 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlite3_result_int(pContext, nResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SQLite invokes this routine once when it loads the extension.
|
|
||||||
** Create new functions, collating sequences, and virtual table
|
|
||||||
** modules here. This is usually the only exported symbol in
|
|
||||||
** the shared library.
|
|
||||||
*/
|
|
||||||
int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi)
|
|
||||||
{
|
|
||||||
SQLITE_EXTENSION_INIT2(pApi)
|
|
||||||
sqlite3_create_function(db, "instr", 2, SQLITE_ANY, 0, sqlite3_instr, 0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in a new issue