Skip to content

Commit

Permalink
Someday I will learn how to program. Until then I will stumble through
Browse files Browse the repository at this point in the history
poor choices in hopes of making something usable.
  • Loading branch information
abedra committed Sep 13, 2018
1 parent ef4bdf8 commit c9bc77c
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 62 deletions.
23 changes: 9 additions & 14 deletions ngx_http_bot_verifier_address_tools.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include <ngx_http.h>

ngx_int_t
remote_address(u_char *connected_address, u_char *xff_header, ngx_str_t *address)
remote_address(ngx_http_request_t *r, u_char *xff_header, char *address)
{
if ((connected_address == NULL && xff_header == NULL) || address == NULL) {
if ((r == NULL && xff_header == NULL) || address == NULL) {
return NGX_DECLINED;
}

Expand All @@ -25,22 +25,19 @@ remote_address(u_char *connected_address, u_char *xff_header, ngx_str_t *address
unsigned char buf[sizeof(struct in_addr)];

if (inet_pton(AF_INET, (const char *)test_address, buf) == 1) {
address->len = length + 1;
address->data = malloc(sizeof(u_char *) * address->len);
ngx_memcpy(address->data, test_address, address->len);
memcpy(address, test_address, length);
return NGX_OK;
} else {
return NGX_ERROR;
}
} else {
address->data = connected_address;
address->len = strlen((const char *)connected_address);
memcpy(address, r->connection->addr_text.data, r->connection->addr_text.len);
return NGX_OK;
}
}

ngx_int_t
ngx_http_bot_verifier_module_determine_address(ngx_http_request_t *r, ngx_str_t *address)
ngx_http_bot_verifier_module_determine_address(ngx_http_request_t *r, char *address)
{
ngx_int_t result;
ngx_table_elt_t *xff = NULL;
Expand All @@ -51,19 +48,17 @@ ngx_http_bot_verifier_module_determine_address(ngx_http_request_t *r, ngx_str_t
}

if (xff == NULL) {
address->data = r->connection->addr_text.data;
address->len = r->connection->addr_text.len;

memcpy(address, r->connection->addr_text.data, r->connection->addr_text.len);
return NGX_OK;
} else {
result = remote_address(r->connection->addr_text.data, xff->value.data, address);
result = remote_address(r, xff->value.data, address);
if (result == NGX_OK) {
return NGX_OK;
} else if (result == NGX_DECLINED) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Not enough information to determine connecting IP address");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cannot determine IP address");
return NGX_ERROR;
} else {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "The address supplied is not a valid IP address");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "IP address is not valid");
return NGX_ERROR;
}
}
Expand Down
4 changes: 2 additions & 2 deletions ngx_http_bot_verifier_address_tools.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef __NGX_HTTP_BOT_VERIFIER_ADDRESS_TOOLS_H__
#define __NGX_HTTP_BOT_VERIFIER_ADDRESS_TOOLS_H__

ngx_int_t remote_address(char *connected_address, char *xff_header, ngx_str_t *address);
ngx_int_t ngx_http_bot_verifier_module_determine_address(ngx_http_request_t *r, ngx_str_t *address);
ngx_int_t remote_address(ngx_http_request_t *r, char *xff_header, char *address);
ngx_int_t ngx_http_bot_verifier_module_determine_address(ngx_http_request_t *r, char *address);

#endif
10 changes: 5 additions & 5 deletions ngx_http_bot_verifier_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ reset_connection(ngx_http_bot_verifier_module_loc_conf_t *loc_conf)
}

ngx_int_t
lookup_verification_status(redisContext *context, ngx_str_t *address)
lookup_verification_status(redisContext *context, char *address)
{
redisReply *reply;

reply = redisCommand(context, "GET %s:bvs", (char *)address->data);
reply = redisCommand(context, "GET %s:bvs", address);
if (reply) {
if (reply->type == REDIS_REPLY_STRING) {
if (strncmp("failure", reply->str, strlen("failure")) == 0) {
Expand All @@ -93,14 +93,14 @@ lookup_verification_status(redisContext *context, ngx_str_t *address)
}

ngx_int_t
persist_verification_status(redisContext *context, ngx_str_t *address, ngx_int_t status, ngx_int_t expiry)
persist_verification_status(redisContext *context, char *address, ngx_int_t status, ngx_int_t expiry)
{
redisReply *reply = NULL;

if (status == NGX_OK) {
reply = redisCommand(context, "SETEX %s:bvs %d %s", (char *)address->data, expiry, "success");
reply = redisCommand(context, "SETEX %s:bvs %d %s", address, expiry, "success");
} else if (status == NGX_DECLINED) {
reply = redisCommand(context, "SETEX %s:bvs %d %s", (char *)address->data, expiry, "failure");
reply = redisCommand(context, "SETEX %s:bvs %d %s", address, expiry, "failure");
}

if (reply) {
Expand Down
4 changes: 2 additions & 2 deletions ngx_http_bot_verifier_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
ngx_int_t check_connection(redisContext *context);
void cleanup_connection(ngx_http_bot_verifier_module_loc_conf_t *loc_conf);
ngx_int_t reset_connection(ngx_http_bot_verifier_module_loc_conf_t *loc_conf);
ngx_int_t lookup_verification_status(redisContext *context, ngx_str_t *address);
ngx_int_t persist_verification_status(redisContext *context, ngx_str_t *address, ngx_int_t status, ngx_int_t expiry);
ngx_int_t lookup_verification_status(redisContext *context, char *address);
ngx_int_t persist_verification_status(redisContext *context, char *address, ngx_int_t status, ngx_int_t expiry);

#endif
4 changes: 1 addition & 3 deletions ngx_http_bot_verifier_identifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ ngx_http_bot_verifier_module_identifies_as_known_bot(ngx_http_request_t *r, ngx_
n = ngx_regex_exec(re, &user_agent, captures, (1 + rc.captures) * 3);

if (n >= 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Search engine bot identified for %V", &user_agent);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "User Agent identified as provider %V", &user_agent);
return NGX_OK;
}

ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "User Agent %V not identified", &user_agent);

return NGX_DECLINED;
}
37 changes: 15 additions & 22 deletions ngx_http_bot_verifier_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ ngx_http_bot_verifier_module_handler(ngx_http_request_t *r)

ngx_int_t connection_status = check_connection(loc_conf->redis.connection);
if (connection_status == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "No cache connection found, creating a new connection");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "No cache connection, creating new connection");

if (loc_conf->redis.connection != NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cache connection error: %s", loc_conf->redis.connection->errstr);
Expand All @@ -38,7 +38,7 @@ ngx_http_bot_verifier_module_handler(ngx_http_request_t *r)
connection_status = reset_connection(loc_conf);

if (connection_status == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Unable to establish a connection to cache, bypassing");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Unable to establish cache connection, bypassing");

if (loc_conf->redis.connection != NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cache connection error: %s", loc_conf->redis.connection->errstr);
Expand All @@ -49,55 +49,48 @@ ngx_http_bot_verifier_module_handler(ngx_http_request_t *r)
}
}

ngx_str_t address;
ngx_int_t address_status = ngx_http_bot_verifier_module_determine_address(r, &address);
char address[INET_ADDRSTRLEN];
memset(address, '\0', INET_ADDRSTRLEN);
ngx_int_t address_status = ngx_http_bot_verifier_module_determine_address(r, address);

if (address_status == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Unable to determine connected address, bypassing");
return NGX_DECLINED;
}

ngx_int_t verification_status = lookup_verification_status(loc_conf->redis.connection, &address);
ngx_int_t verification_status = lookup_verification_status(loc_conf->redis.connection, address);
if (verification_status == NGX_ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Unable to lookup verification status, bypassing");
return NGX_DECLINED;
}

ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Lookup result %d", verification_status);

if (verification_status == SUCCESS) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Actor has already been verified, bypassing");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cache returned valid actor, bypassing verification and allowing request");
return NGX_DECLINED;
}

if (verification_status == FAILURE) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Actor previously failed verification, blocking request");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cache returned invalid actor, bypassing verification and blocking request");
return NGX_HTTP_FORBIDDEN;
}

if (verification_status == ERROR) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "There was an error looking up the actor, failing open");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cache error");
return NGX_DECLINED;
}

if (verification_status == NOT_FOUND) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Actor has not been verified, initiating verification process");
}

ngx_int_t ret = ngx_http_bot_verifier_module_identifies_as_known_bot(r, loc_conf);

if (ret == NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Bot identity detected");
ret = ngx_http_bot_verifier_module_verify_bot(r, loc_conf);
ret = ngx_http_bot_verifier_module_verify_bot(r, loc_conf, address);
if (ret == NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Verification successful");
persist_verification_status(loc_conf->redis.connection, &address, ret, loc_conf->redis.expiry);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Verification successful, allowing request");
persist_verification_status(loc_conf->redis.connection, address, ret, loc_conf->redis.expiry);
} else if (ret == NGX_DECLINED) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Verification failed");
persist_verification_status(loc_conf->redis.connection, &address, ret, loc_conf->redis.expiry);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Verification failed, blocking request");
persist_verification_status(loc_conf->redis.connection, address, ret, loc_conf->redis.expiry);
return NGX_HTTP_FORBIDDEN;
}
} else {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Bot does not identify");
}

return NGX_OK;
Expand Down
19 changes: 6 additions & 13 deletions ngx_http_bot_verifier_verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,20 @@ hostname_matches_provider_domain(ngx_http_request_t *r, char *hostname, ngx_http
}

ngx_int_t
ngx_http_bot_verifier_module_verify_bot(ngx_http_request_t *r, ngx_http_bot_verifier_module_loc_conf_t *loc_conf)
ngx_http_bot_verifier_module_verify_bot(ngx_http_request_t *r, ngx_http_bot_verifier_module_loc_conf_t *loc_conf, char *address)
{
ngx_str_t derived_address;
ngx_int_t error = ngx_http_bot_verifier_module_determine_address(r, &derived_address);
if (error == NGX_ERROR || error == NGX_DECLINED) {
return NGX_ERROR;
}

struct sockaddr_in sa;
sa.sin_family = AF_INET;
inet_pton(AF_INET, (const char *)derived_address.data, &(sa.sin_addr));
inet_pton(AF_INET, (const char *)address, &(sa.sin_addr));
char hostname[NI_MAXHOST];

error = getnameinfo((struct sockaddr *) &sa, sizeof(sa), hostname, sizeof(hostname), NULL, 0, NI_NAMEREQD);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "result %d", error);
int error = getnameinfo((struct sockaddr *) &sa, sizeof(sa), hostname, sizeof(hostname), NULL, 0, NI_NAMEREQD);
if (error != 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "getnameinfo() error: %s", gai_strerror(error));
return NGX_DECLINED;
}

ngx_int_t match_result = hostname_matches_provider_domain(r, (char *)hostname, loc_conf);
ngx_int_t match_result = hostname_matches_provider_domain(r, hostname, loc_conf);

if (match_result == NGX_DECLINED) {
return match_result;
Expand All @@ -83,9 +76,9 @@ ngx_http_bot_verifier_module_verify_bot(ngx_http_request_t *r, ngx_http_bot_veri
char *forward_result = inet_ntoa(forward->sin_addr);

ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Forward Result %s", forward_result);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Derived Address %s", derived_address.data);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Actor Address %s", address);

if (strcmp((const char *)derived_address.data, forward_result) == 0) {
if (strcmp((const char *)address, forward_result) == 0) {
freeaddrinfo(result);
return NGX_OK;
} else {
Expand Down
2 changes: 1 addition & 1 deletion ngx_http_bot_verifier_verifier.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef __NGX_HTTP_BOT_VERIFIER_VERIFIER_H__
#define __NGX_HTTP_BOT_VERIFIER_VERIFIER_H__

ngx_int_t ngx_http_bot_verifier_module_verify_bot(ngx_http_request_t *r, ngx_http_bot_verifier_module_loc_conf_t *loc_conf);
ngx_int_t ngx_http_bot_verifier_module_verify_bot(ngx_http_request_t *r, ngx_http_bot_verifier_module_loc_conf_t *loc_conf, char *address);

#endif

0 comments on commit c9bc77c

Please sign in to comment.