Compare commits

..

8 Commits

  1. 8
      filters/named.preg
  2. 7
      filters/postfix.preg
  3. 2
      src/backends/redis.c
  4. 5
      src/csocket.c
  5. 1
      src/ipaddr.c
  6. 78
      src/jail.c
  7. 6
      src/jail.h
  8. 1
      t/t_ipaddr.c

8
filters/named.preg

@ -1,2 +1,6 @@
<HOST>#[0-9]+ .* query \(cache\) '[0-9.]+.in-addr.arpa/PTR/IN' denied # set: defscore=10
<HOST>#[0-9]+ .* query \(cache\) './ANY/IN' denied <HOST>#[0-9]+ .* query \(cache\) '[0-9.]+.in-addr.arpa/(PTR|SOA)/IN' denied
# requests to '.' or top-level domains
<HOST>#[0-9]+ .* query \(cache\) '[a-z.]+/ANY/IN' denied
# set: defscore=1
<HOST>#[0-9]+ .* query \(cache\) '[0-9a-z.-]+/RRSIG/IN' denied

7
filters/postfix.preg

@ -1,8 +1,11 @@
# set: defscore=10
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 450 4\.7\.1 Client host rejected NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 450 4\.7\.1 Client host rejected
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 454 4\.7\.1 Service unavailable; Client host \[[[:print:]]+\] blocked NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 454 4\.7\.1 Service unavailable; Client host \[[[:print:]]+\] blocked
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 450 4\.7\.1 <[[:print:]]+>: Helo command rejected: Host not found
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 454 4\.7\.1 <[[:print:]]+>: Relay access denied NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 454 4\.7\.1 <[[:print:]]+>: Relay access denied
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 504 5\.5\.2 <[[:print:]]+>: Helo command rejected: need fully-qualified hostname
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 554 5\.7\.1 <[[:print:]]+>: Relay access denied NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 554 5\.7\.1 <[[:print:]]+>: Relay access denied
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 550 5\.1\.1 <[[:print:]]+>: Recipient address rejected: undeliverable address
warning: [[:print:]]+\[<HOST>\]: SASL [A-Z0-9-]+ authentication failed warning: [[:print:]]+\[<HOST>\]: SASL [A-Z0-9-]+ authentication failed
# set: defscore=5
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 450 4\.7\.1 <[[:print:]]+>: Helo command rejected: Host not found
NOQUEUE: reject: RCPT from [[:print:]]+\[<HOST>\]: 504 5\.5\.2 <[[:print:]]+>: Helo command rejected: need fully-qualified hostname
lost connection after AUTH from [[:print:]]+\[<HOST>\] lost connection after AUTH from [[:print:]]+\[<HOST>\]

2
src/backends/redis.c

@ -129,7 +129,7 @@ config(cfg_t *cfg, const char *key, const char *value) {
return true; return true;
} }
if (strcmp(key, "shared") == 0) { if (strcmp(key, "shared") == 0) {
cfg->shared = (strcmp(value, "yes") ? true : false); cfg->shared = (strcmp(value, "yes") == 0 ? true : false);
return true; return true;
} }
if (strcmp(key, "host") == 0) { if (strcmp(key, "host") == 0) {

5
src/csocket.c

@ -14,6 +14,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/select.h> #include <sys/select.h>
@ -485,6 +486,7 @@ f2b_csocket_poll(void (*cb)(const f2b_cmd_t *cmd, f2b_buf_t *res)) {
if ((conn = f2b_conn_create(RBUF_SIZE, WBUF_SIZE)) != NULL) { if ((conn = f2b_conn_create(RBUF_SIZE, WBUF_SIZE)) != NULL) {
conn->flags = csock.listen[i]->flags; conn->flags = csock.listen[i]->flags;
if (csock.listen[i]->flags & CSOCKET_CONN_TYPE_UNIX) { if (csock.listen[i]->flags & CSOCKET_CONN_TYPE_UNIX) {
#ifdef __linux__
struct ucred peer; struct ucred peer;
socklen_t peerlen = 0; socklen_t peerlen = 0;
peerlen = sizeof(peer); peerlen = sizeof(peer);
@ -493,6 +495,9 @@ f2b_csocket_poll(void (*cb)(const f2b_cmd_t *cmd, f2b_buf_t *res)) {
} else { } else {
f2b_log_msg(log_debug, "new local connection from uid %d, socket %d", peer.uid, sock); f2b_log_msg(log_debug, "new local connection from uid %d, socket %d", peer.uid, sock);
} }
#else
f2b_log_msg(log_debug, "new local connection from socket %d", sock);
#endif
conn->flags |= CSOCKET_CONN_AUTH_OK; conn->flags |= CSOCKET_CONN_AUTH_OK;
} else /* CSOCKET_CONN_TYPE_INET */ { } else /* CSOCKET_CONN_TYPE_INET */ {
if (addr.ss_family == AF_INET) { if (addr.ss_family == AF_INET) {

1
src/ipaddr.c

@ -8,6 +8,7 @@
#include "matches.h" #include "matches.h"
#include "ipaddr.h" #include "ipaddr.h"
#include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
f2b_ipaddr_t * f2b_ipaddr_t *

78
src/jail.c

@ -127,8 +127,6 @@ f2b_jail_set_param(f2b_jail_t *jail, const char *param, const char *value) {
void void
f2b_jail_apply_config(f2b_jail_t *jail, f2b_config_section_t *section) { f2b_jail_apply_config(f2b_jail_t *jail, f2b_config_section_t *section) {
char name[CONFIG_KEY_MAX];
char init[CONFIG_KEY_MAX];
f2b_config_param_t *param = NULL; f2b_config_param_t *param = NULL;
assert(jail != NULL); assert(jail != NULL);
@ -141,20 +139,17 @@ f2b_jail_apply_config(f2b_jail_t *jail, f2b_config_section_t *section) {
continue; continue;
} }
if (strcmp(param->name, "source") == 0) { if (strcmp(param->name, "source") == 0) {
f2b_jail_parse_compound_value(param->value, name, init); f2b_jail_parse_compound_value(param->value, jail->source_name, jail->source_init);
jail->source = f2b_source_create(name, init);
jail->flags |= JAIL_HAS_SOURCE; jail->flags |= JAIL_HAS_SOURCE;
continue; continue;
} }
if (strcmp(param->name, "filter") == 0) { if (strcmp(param->name, "filter") == 0) {
f2b_jail_parse_compound_value(param->value, name, init); f2b_jail_parse_compound_value(param->value, jail->filter_name, jail->filter_init);
jail->filter = f2b_filter_create(name, init);
jail->flags |= JAIL_HAS_FILTER; jail->flags |= JAIL_HAS_FILTER;
continue; continue;
} }
if (strcmp(param->name, "backend") == 0) { if (strcmp(param->name, "backend") == 0) {
f2b_jail_parse_compound_value(param->value, name, init); f2b_jail_parse_compound_value(param->value, jail->backend_name, jail->backend_init);
jail->backend = f2b_backend_create(name, init);
jail->flags |= JAIL_HAS_BACKEND; jail->flags |= JAIL_HAS_BACKEND;
continue; continue;
} }
@ -269,6 +264,13 @@ f2b_jail_create(f2b_config_section_t *section) {
strlcpy(jail->name, section->name, sizeof(jail->name)); strlcpy(jail->name, section->name, sizeof(jail->name));
f2b_jail_apply_config(jail, section); f2b_jail_apply_config(jail, section);
if (jail->flags & JAIL_HAS_SOURCE)
jail->source = f2b_source_create(jail->source_name, jail->source_init);
if (jail->flags & JAIL_HAS_FILTER)
jail->filter = f2b_filter_create(jail->filter_name, jail->filter_init);
if (jail->flags & JAIL_HAS_BACKEND)
jail->backend = f2b_backend_create(jail->backend_name, jail->backend_init);
return jail; return jail;
} }
@ -410,6 +412,11 @@ f2b_jail_init(f2b_jail_t *jail, f2b_config_t *config) {
assert(jail != NULL); assert(jail != NULL);
assert(config != NULL); assert(config != NULL);
if ((jail->flags & (JAIL_HAS_SOURCE | JAIL_HAS_BACKEND)) == 0) {
f2b_log_msg(log_error, "jail '%s': misconfigured, at least source or backend must be set", jail->name);
return false;
}
if (jail->flags & JAIL_HAS_STATE) { if (jail->flags & JAIL_HAS_STATE) {
jail->sfile = f2b_statefile_create(appconfig.statedir_path, jail->name); jail->sfile = f2b_statefile_create(appconfig.statedir_path, jail->name);
if (jail->sfile == NULL) { if (jail->sfile == NULL) {
@ -502,26 +509,31 @@ f2b_jail_start(f2b_jail_t *jail) {
if (jail->flags & JAIL_HAS_STATE) if (jail->flags & JAIL_HAS_STATE)
jail->ipaddrs = f2b_statefile_load(jail->sfile); jail->ipaddrs = f2b_statefile_load(jail->sfile);
/* addrlist cleanup */
for (f2b_ipaddr_t *addr = jail->ipaddrs; addr != NULL; addr = addr->next) { for (f2b_ipaddr_t *addr = jail->ipaddrs; addr != NULL; addr = addr->next) {
hostc++; hostc++;
if (!addr->banned) if (addr->banned && now >= addr->release_at)
continue; /* if list NOW contains such addresses, it may be bug */
if (f2b_backend_check(jail->backend, addr->text))
continue; /* already banned or backend don't support check() */
if (now >= addr->release_at) {
addr->banned = false; addr->banned = false;
continue; /* ban time already expired */
}
if (f2b_backend_ban(jail->backend, addr->text)) {
remains = addr->release_at - now;
f2b_log_msg(log_note, "jail '%s': restored ban of ip %s (%.1fhrs remain)",
jail->name, addr->text, (float) remains / 3600);
} else {
f2b_log_msg(log_error, "jail '%s': can't ban ip %s", jail->name, addr->text);
}
} }
jail->stats.hosts = hostc; jail->stats.hosts = hostc;
/* actual ban restore */
if (jail->flags & JAIL_HAS_BACKEND) {
for (f2b_ipaddr_t *addr = jail->ipaddrs; addr != NULL; addr = addr->next) {
if (!addr->banned)
continue;
if (f2b_backend_check(jail->backend, addr->text))
continue; /* already banned or backend don't support check() */
if (f2b_backend_ban(jail->backend, addr->text)) {
remains = addr->release_at - now;
f2b_log_msg(log_note, "jail '%s': restored ban of ip %s (%.1fhrs remain)",
jail->name, addr->text, (float) remains / 3600);
} else {
f2b_log_msg(log_error, "jail '%s': can't ban ip %s", jail->name, addr->text);
}
}
}
f2b_log_msg(log_info, "jail '%s' started", jail->name); f2b_log_msg(log_info, "jail '%s' started", jail->name);
return true; return true;
@ -547,22 +559,21 @@ f2b_jail_stop(f2b_jail_t *jail) {
f2b_filter_destroy(jail->filter); f2b_filter_destroy(jail->filter);
} }
for (f2b_ipaddr_t *addr = jail->ipaddrs; addr != NULL; addr = addr->next) {
if (!addr->banned)
continue;
if (f2b_jail_unban(jail, addr))
continue;
errors = true;
}
f2b_addrlist_destroy(jail->ipaddrs);
if (jail->flags & JAIL_HAS_BACKEND) { if (jail->flags & JAIL_HAS_BACKEND) {
for (f2b_ipaddr_t *addr = jail->ipaddrs; addr != NULL; addr = addr->next) {
if (!addr->banned)
continue;
if (f2b_jail_unban(jail, addr))
continue;
errors = true;
}
if (!f2b_backend_stop(jail->backend)) { if (!f2b_backend_stop(jail->backend)) {
f2b_log_msg(log_error, "jail '%s': action 'stop' for backend failed", jail->name); f2b_log_msg(log_error, "jail '%s': action 'stop' for backend failed", jail->name);
errors = true; errors = true;
} }
f2b_backend_destroy(jail->backend); f2b_backend_destroy(jail->backend);
} }
f2b_addrlist_destroy(jail->ipaddrs);
if (jail->flags & JAIL_HAS_STATE) { if (jail->flags & JAIL_HAS_STATE) {
f2b_statefile_destroy(jail->sfile); f2b_statefile_destroy(jail->sfile);
@ -650,6 +661,11 @@ f2b_jail_cmd_ip_xxx(char *res, size_t ressize, f2b_jail_t *jail, int op, const c
assert(jail != NULL); assert(jail != NULL);
assert(ip != NULL); assert(ip != NULL);
if ((jail->flags & JAIL_HAS_BACKEND) == 0 && op != 0) {
strlcpy(res, "-jail has no configured backend\n", ressize);
return;
}
if ((addr = f2b_addrlist_lookup(jail->ipaddrs, ip)) == NULL) { if ((addr = f2b_addrlist_lookup(jail->ipaddrs, ip)) == NULL) {
/* address not found in list */ /* address not found in list */
if (op > 0) { if (op > 0) {

6
src/jail.h

@ -41,6 +41,12 @@ typedef struct f2b_jail_t {
unsigned int bans; /**< number of ban events */ unsigned int bans; /**< number of ban events */
unsigned int matches; /**< number of match events */ unsigned int matches; /**< number of match events */
} stats; } stats;
char source_name[CONFIG_KEY_MAX];
char source_init[CONFIG_VAL_MAX];
char filter_name[CONFIG_KEY_MAX];
char filter_init[CONFIG_VAL_MAX];
char backend_name[CONFIG_KEY_MAX];
char backend_init[CONFIG_VAL_MAX];
f2b_source_t *source; /**< pointer to source */ f2b_source_t *source; /**< pointer to source */
f2b_filter_t *filter; /**< pointer to filter */ f2b_filter_t *filter; /**< pointer to filter */
f2b_backend_t *backend; /**< pointer to backend */ f2b_backend_t *backend; /**< pointer to backend */

1
t/t_ipaddr.c

@ -2,6 +2,7 @@
#include "../src/matches.h" #include "../src/matches.h"
#include "../src/ipaddr.h" #include "../src/ipaddr.h"
#include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
int main() { int main() {

Loading…
Cancel
Save