GeoIP Info implemented
This commit is contained in:
4
Makefile
4
Makefile
@ -7,11 +7,11 @@ packages:
|
||||
|
||||
compile:
|
||||
@mkdir -p bin
|
||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz
|
||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb
|
||||
|
||||
compile-debian:
|
||||
@mkdir -p bin
|
||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz \
|
||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb \
|
||||
-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" \
|
||||
-D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
|
||||
|
||||
|
52
src/client.c
52
src/client.c
@ -15,7 +15,7 @@
|
||||
int server_keep_alive = 1;
|
||||
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr,
|
||||
*log_client_prefix, *log_conn_prefix, *log_req_prefix,
|
||||
*client_host_str;
|
||||
*client_host_str, *client_geoip;
|
||||
|
||||
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
||||
|
||||
@ -460,10 +460,56 @@ int client_connection_handler(sock *client, unsigned long client_num) {
|
||||
client_host_str = NULL;
|
||||
}
|
||||
|
||||
// TODO get geoip data for ip address
|
||||
client_geoip = malloc(GEOIP_MAX_SIZE);
|
||||
long str_off = 0;
|
||||
for (int i = 0; i < MAX_MMDB && mmdbs[i].filename != NULL; i++) {
|
||||
int gai_error, mmdb_res;
|
||||
MMDB_lookup_result_s result = MMDB_lookup_string(&mmdbs[i], "62.47.28.246", &gai_error, &mmdb_res);
|
||||
if (mmdb_res != MMDB_SUCCESS) {
|
||||
print(ERR_STR "Unable to lookup geoip info: %s" CLR_STR "\n", MMDB_strerror(mmdb_res));
|
||||
continue;
|
||||
} else if (gai_error != 0) {
|
||||
print(ERR_STR "Unable to lookup geoip info" CLR_STR "\n");
|
||||
continue;
|
||||
} else if (!result.found_entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MMDB_entry_data_list_s *list;
|
||||
mmdb_res = MMDB_get_entry_data_list(&result.entry, &list);
|
||||
if (mmdb_res != MMDB_SUCCESS) {
|
||||
print(ERR_STR "Unable to lookup geoip info: %s" CLR_STR "\n", MMDB_strerror(mmdb_res));
|
||||
continue;
|
||||
}
|
||||
|
||||
long prev = str_off;
|
||||
if (str_off != 0) {
|
||||
str_off--;
|
||||
}
|
||||
mmdb_json(list, client_geoip, &str_off, GEOIP_MAX_SIZE);
|
||||
if (prev != 0) {
|
||||
client_geoip[prev - 1] = ',';
|
||||
}
|
||||
|
||||
MMDB_free_entry_data_list(list);
|
||||
}
|
||||
|
||||
char client_cc[3];
|
||||
client_cc[0] = 0;
|
||||
if (str_off == 0) {
|
||||
free(client_geoip);
|
||||
client_geoip = NULL;
|
||||
} else {
|
||||
char *pos = strstr(client_geoip, "\"iso_code\":\"");
|
||||
if (pos != NULL) {
|
||||
pos += 12;
|
||||
strncpy(client_cc, pos, 2);
|
||||
}
|
||||
}
|
||||
|
||||
print("Connection accepted from %s %s%s%s[%s]", client_addr_str, client_host_str != NULL ? "(" : "",
|
||||
client_host_str != NULL ? client_host_str : "", client_host_str != NULL ? ") " : "", "N/A");
|
||||
client_host_str != NULL ? client_host_str : "", client_host_str != NULL ? ") " : "",
|
||||
client_cc[0] != 0 ? client_cc : "N/A");
|
||||
|
||||
client_timeout.tv_sec = CLIENT_TIMEOUT;
|
||||
client_timeout.tv_usec = 0;
|
||||
|
@ -142,6 +142,9 @@ int fastcgi_init(fastcgi_conn *conn, unsigned int client_num, unsigned int req_n
|
||||
param_ptr = fastcgi_add_param(param_ptr, "CONTENT_LENGTH", content_length != NULL ? content_length : "");
|
||||
char *content_type = http_get_header_field(&req->hdr, "Content-Type");
|
||||
param_ptr = fastcgi_add_param(param_ptr, "CONTENT_TYPE", content_type != NULL ? content_type : "");
|
||||
if (client_geoip != NULL) {
|
||||
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_INFO", client_geoip);
|
||||
}
|
||||
|
||||
for (int i = 0; i < req->hdr.field_num; i++) {
|
||||
char *ptr = buf0;
|
||||
|
@ -172,6 +172,10 @@ int main(int argc, const char *argv[]) {
|
||||
struct sockaddr_in6 client_addr;
|
||||
unsigned int client_addr_len = sizeof(client_addr);
|
||||
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
memset(children, 0, sizeof(children));
|
||||
memset(mmdbs, 0, sizeof(mmdbs));
|
||||
|
||||
struct timeval timeout;
|
||||
|
||||
const struct sockaddr_in6 addresses[2] = {
|
||||
@ -189,12 +193,12 @@ int main(int argc, const char *argv[]) {
|
||||
const char *arg = argv[i];
|
||||
unsigned long len = strlen(arg);
|
||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-FILE>] [-d <DNS-SERVER>]\n"
|
||||
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-DIR>] [-d <DNS-SERVER>]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -c, --cert <CERT-FILE> path to the full chain certificate file\n"
|
||||
" -d, --dns <DNS-SERVER> ip address or hostname of a DNS server for dig\n"
|
||||
" -g, --geoip <DB-FILE> path to a Maxmind GeoIP Database file\n"
|
||||
" -g, --geoip <DB-DIR> path to a Maxmind GeoIP Database file\n"
|
||||
" -h, --help print this dialogue\n"
|
||||
" -p, --privkey <KEY-FILE> path to the private key file\n"
|
||||
" -w, --webroot <PATH> path to the web root directory\n");
|
||||
@ -219,10 +223,10 @@ int main(int argc, const char *argv[]) {
|
||||
key_file = argv[++i];
|
||||
} else if (strcmp(arg, "-g") == 0 || strcmp(arg, "--geoip") == 0) {
|
||||
if (i == argc - 1) {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-FILE>" CLR_STR "\n", arg);
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-DIR>" CLR_STR "\n", arg);
|
||||
return 1;
|
||||
}
|
||||
geoip_file = argv[++i];
|
||||
geoip_dir = argv[++i];
|
||||
} else if (strcmp(arg, "-d") == 0 || strcmp(arg, "--dns") == 0) {
|
||||
if (i == argc - 1) {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --dns <DNS-SERVER>" CLR_STR "\n", arg);
|
||||
@ -274,15 +278,35 @@ int main(int argc, const char *argv[]) {
|
||||
signal(SIGINT, terminate);
|
||||
signal(SIGTERM, terminate);
|
||||
|
||||
ret = cache_init();
|
||||
if (ret < 0) {
|
||||
return 1;
|
||||
} else if (ret != 0) {
|
||||
return 0;
|
||||
if (geoip_dir != NULL) {
|
||||
DIR *geoip = opendir(geoip_dir);
|
||||
if (geoip == NULL) {
|
||||
fprintf(stderr, ERR_STR "Unable to open GeoIP dir: %s" CLR_STR "\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
struct dirent *dir;
|
||||
int i = 0;
|
||||
while ((dir = readdir(geoip)) != NULL) {
|
||||
if (strcmp(dir->d_name + strlen(dir->d_name) - 5, ".mmdb") != 0) continue;
|
||||
if (i >= MAX_MMDB) {
|
||||
fprintf(stderr, ERR_STR "Too many .mmdb files" CLR_STR "\n");
|
||||
return 1;
|
||||
}
|
||||
sprintf(buf, "%s/%s", geoip_dir, dir->d_name);
|
||||
ret = MMDB_open(buf, 0, &mmdbs[i]);
|
||||
if (ret != MMDB_SUCCESS) {
|
||||
fprintf(stderr, ERR_STR "Unable to open .mmdb file: %s" CLR_STR "\n", MMDB_strerror(ret));
|
||||
return 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i == 0) {
|
||||
fprintf(stderr, ERR_STR "No .mmdb files found in %s" CLR_STR "\n", geoip_dir);
|
||||
return 1;
|
||||
}
|
||||
closedir(geoip);
|
||||
}
|
||||
|
||||
// TODO init geoip database
|
||||
|
||||
openssl_init();
|
||||
|
||||
client.buf = NULL;
|
||||
@ -322,6 +346,13 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
ret = cache_init();
|
||||
if (ret < 0) {
|
||||
return 1;
|
||||
} else if (ret != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Ready to accept connections\n");
|
||||
|
||||
while (active) {
|
||||
|
@ -25,10 +25,13 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <maxminddb.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
#define NUM_SOCKETS 2
|
||||
#define MAX_CHILDREN 1024
|
||||
#define MAX_MMDB 3
|
||||
#define LISTEN_BACKLOG 16
|
||||
#define REQ_PER_CONNECTION 100
|
||||
#define CLIENT_TIMEOUT 3600
|
||||
@ -37,6 +40,7 @@
|
||||
#define CLIENT_MAX_HEADER_SIZE 8192
|
||||
#define FILE_CACHE_SIZE 1024
|
||||
#define SHM_KEY 255641
|
||||
#define GEOIP_MAX_SIZE 8192
|
||||
|
||||
#define ERR_STR "\x1B[1;31m"
|
||||
#define CLR_STR "\x1B[0m"
|
||||
@ -67,8 +71,9 @@
|
||||
|
||||
int sockets[NUM_SOCKETS];
|
||||
pid_t children[MAX_CHILDREN];
|
||||
MMDB_s mmdbs[MAX_MMDB];
|
||||
|
||||
const char *cert_file, *key_file, *webroot_base, *geoip_file, *dns_server;
|
||||
const char *cert_file, *key_file, *webroot_base, *geoip_dir, *dns_server;
|
||||
|
||||
typedef struct {
|
||||
unsigned int enc:1;
|
||||
|
61
src/utils.c
61
src/utils.c
@ -94,3 +94,64 @@ int url_decode(const char *str, char *dec, ssize_t *size) {
|
||||
*size = ptr - dec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) {
|
||||
switch (list->entry_data.type) {
|
||||
case MMDB_DATA_TYPE_MAP:
|
||||
*str_off += sprintf(str + *str_off, "{");
|
||||
break;
|
||||
case MMDB_DATA_TYPE_ARRAY:
|
||||
*str_off += sprintf(str + *str_off, "[");
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UTF8_STRING:
|
||||
*str_off += sprintf(str + *str_off, "\"%.*s\"", list->entry_data.data_size, list->entry_data.utf8_string);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UINT16:
|
||||
*str_off += sprintf(str + *str_off, "%u", list->entry_data.uint16);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UINT32:
|
||||
*str_off += sprintf(str + *str_off, "%u", list->entry_data.uint32);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UINT64:
|
||||
*str_off += sprintf(str + *str_off, "%lu", list->entry_data.uint64);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_UINT128:
|
||||
*str_off += sprintf(str + *str_off, "%llu", list->entry_data.uint128);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_INT32:
|
||||
*str_off += sprintf(str + *str_off, "%i", list->entry_data.uint32);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_BOOLEAN:
|
||||
*str_off += sprintf(str + *str_off, "%s", list->entry_data.boolean ? "true" : "false");
|
||||
break;
|
||||
case MMDB_DATA_TYPE_FLOAT:
|
||||
*str_off += sprintf(str + *str_off, "%f", list->entry_data.float_value);
|
||||
break;
|
||||
case MMDB_DATA_TYPE_DOUBLE:
|
||||
*str_off += sprintf(str + *str_off, "%f", list->entry_data.double_value);
|
||||
break;
|
||||
}
|
||||
if (list->entry_data.type != MMDB_DATA_TYPE_MAP && list->entry_data.type != MMDB_DATA_TYPE_ARRAY) {
|
||||
return list->next;
|
||||
}
|
||||
MMDB_entry_data_list_s *next = list->next;
|
||||
int stat = 0;
|
||||
for (int i = 0; i < list->entry_data.data_size; i++) {
|
||||
next = mmdb_json(next, str, str_off, str_len);
|
||||
if (list->entry_data.type == MMDB_DATA_TYPE_MAP) {
|
||||
stat = !stat;
|
||||
if (stat) {
|
||||
i--;
|
||||
*str_off += sprintf(str + *str_off, ":");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i != list->entry_data.data_size - 1) *str_off += sprintf(str + *str_off, ",");
|
||||
}
|
||||
if (list->entry_data.type == MMDB_DATA_TYPE_MAP) {
|
||||
*str_off += sprintf(str + *str_off, "}");
|
||||
} else {
|
||||
*str_off += sprintf(str + *str_off, "]");
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
Reference in New Issue
Block a user