diff --git a/src/acl.c b/src/acl.c index aa1da28c..11336a50 100644 --- a/src/acl.c +++ b/src/acl.c @@ -49,75 +49,10 @@ static struct cork_dllist white_list_rules; static int acl_mode = BLACK_LIST; -static struct cache *block_list; - static struct ip_set outbound_block_list_ipv4; static struct ip_set outbound_block_list_ipv6; static struct cork_dllist outbound_block_list_rules; -void -init_block_list() -{ - cache_create(&block_list, 256, NULL); -} - -void -free_block_list() -{ - cache_clear(block_list, 0); // Remove all items -} - -int -remove_from_block_list(char *addr) -{ - size_t addr_len = strlen(addr); - return cache_remove(block_list, addr, addr_len); -} - -void -clear_block_list() -{ - cache_clear(block_list, 3600); // Clear items older than 1 hour -} - -int -check_block_list(char *addr) -{ - size_t addr_len = strlen(addr); - - if (cache_key_exist(block_list, addr, addr_len)) { - int *count = NULL; - cache_lookup(block_list, addr, addr_len, &count); - - if (count != NULL && *count > MAX_TRIES) - return 1; - } - - return 0; -} - -int -update_block_list(char *addr, int err_level) -{ - size_t addr_len = strlen(addr); - - if (cache_key_exist(block_list, addr, addr_len)) { - int *count = NULL; - cache_lookup(block_list, addr, addr_len, &count); - if (count != NULL) { - if (*count > MAX_TRIES) - return 1; - (*count) += err_level; - } - } else if (err_level > 0) { - int *count = (int *)ss_malloc(sizeof(int)); - *count = 1; - cache_insert(block_list, addr, addr_len, count); - } - - return 0; -} - static void parse_addr_cidr(const char *str, char *host, int *cidr) { diff --git a/src/acl.h b/src/acl.h index 7783dcc6..197027c0 100644 --- a/src/acl.h +++ b/src/acl.h @@ -26,15 +26,8 @@ #define BLACK_LIST 0 #define WHITE_LIST 1 -#define MAX_TRIES 256 -#define MALICIOUS 8 -#define SUSPICIOUS 4 -#define BAD 2 -#define MALFORMED 1 - int init_acl(const char *path); void free_acl(void); -void clear_block_list(void); int acl_match_host(const char *ip); int acl_add_ip(const char *ip); @@ -42,12 +35,6 @@ int acl_remove_ip(const char *ip); int get_acl_mode(void); -void init_block_list(); -void free_block_list(); -int check_block_list(char *addr); -int update_block_list(char *addr, int err_level); -int remove_from_block_list(char *addr); - int outbound_block_match_host(const char *host); #endif // _ACL_H diff --git a/src/common.h b/src/common.h index 2eb91afd..696248f6 100644 --- a/src/common.h +++ b/src/common.h @@ -54,6 +54,7 @@ int send_traffic_stat(uint64_t tx, uint64_t rx); #define STAGE_SNI 3 /* Parse HTTP/SNI header */ #define STAGE_RESOLVE 4 /* Resolve the hostname */ #define STAGE_STREAM 5 /* Stream between client and server */ +#define STAGE_STOP 6 /* Server stop to response */ /* Vals for long options */ enum { diff --git a/src/jconf.h b/src/jconf.h index 9a2209b5..ff324868 100644 --- a/src/jconf.h +++ b/src/jconf.h @@ -27,7 +27,7 @@ #define MAX_DSCP_NUM 64 #define MAX_CONF_SIZE 128 * 1024 #define MAX_CONNECT_TIMEOUT 10 -#define MAX_REQUEST_TIMEOUT 60 +#define MAX_REQUEST_TIMEOUT 30 #define MIN_UDP_TIMEOUT 10 #define DSCP_EF 0x2E diff --git a/src/server.c b/src/server.c index 21ec535a..b7d805b8 100644 --- a/src/server.c +++ b/src/server.c @@ -93,7 +93,6 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents); static void remote_recv_cb(EV_P_ ev_io *w, int revents); static void remote_send_cb(EV_P_ ev_io *w, int revents); static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents); -static void block_list_clear_cb(EV_P_ ev_timer *watcher, int revents); static remote_t *new_remote(int fd); static server_t *new_server(int fd, listen_ctx_t *listener); @@ -138,7 +137,6 @@ uint64_t rx = 0; #ifndef __MINGW32__ ev_timer stat_update_watcher; #endif -ev_timer block_list_watcher; static struct ev_signal sigint_watcher; static struct ev_signal sigterm_watcher; @@ -269,43 +267,19 @@ get_peer_name(int fd) return peer_name; } -#ifdef __linux__ static void -set_linger(int fd) +stop_server(EV_P_ server_t *server) { - struct linger so_linger; - memset(&so_linger, 0, sizeof(struct linger)); - so_linger.l_onoff = 1; - so_linger.l_linger = 0; - setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger); -} - -#endif - -static void -reset_addr(int fd) -{ - char *peer_name; - peer_name = get_peer_name(fd); - if (peer_name != NULL) { - remove_from_block_list(peer_name); - } + server->stage = STAGE_STOP; } static void -report_addr(int fd, int err_level, const char *info) +report_addr(int fd, const char *info) { -#ifdef __linux__ - set_linger(fd); -#endif - char *peer_name; peer_name = get_peer_name(fd); if (peer_name != NULL) { LOGE("failed to handshake with %s: %s", peer_name, info); - // Avoid block local plugins - if (strcmp(peer_name, "127.0.0.1") != 0) - update_block_list(peer_name, err_level); } } @@ -724,10 +698,16 @@ server_recv_cb(EV_P_ ev_io *w, int revents) buffer_t *buf = server->buf; + // Ignore any new packet if the server is stopped + if (server->stage == STAGE_STOP) { + return; + } + if (server->stage == STAGE_STREAM) { remote = server->remote; buf = remote->buf; + // Only timer the watcher if a valid connection is established ev_timer_again(EV_A_ & server->recv_ctx->watcher); } @@ -760,15 +740,13 @@ server_recv_cb(EV_P_ ev_io *w, int revents) int err = crypto->decrypt(buf, server->d_ctx, SOCKET_BUF_SIZE); if (err == CRYPTO_ERROR) { - report_addr(server->fd, MALICIOUS, "authentication error"); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "authentication error"); + stop_server(EV_A_ server); return; } else if (err == CRYPTO_NEED_MORE) { if (server->stage != STAGE_STREAM && server->frag > MAX_FRAG) { - report_addr(server->fd, MALICIOUS, "malicious fragmentation"); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "malicious fragmentation"); + stop_server(EV_A_ server); return; } server->frag++; @@ -830,8 +808,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) host, INET_ADDRSTRLEN); offset += in_addr_len; } else { - report_addr(server->fd, MALFORMED, "invalid length for ipv4 address"); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "invalid length for ipv4 address"); + stop_server(EV_A_ server); return; } addr->sin_port = *(uint16_t *)(server->buf->data + offset); @@ -847,8 +825,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) memcpy(host, server->buf->data + offset + 1, name_len); offset += name_len + 1; } else { - report_addr(server->fd, MALFORMED, "invalid host name length"); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "invalid host name length"); + stop_server(EV_A_ server); return; } if (acl && outbound_block_match_host(host) == 1) { @@ -880,8 +858,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) } } else { if (!validate_hostname(host, name_len)) { - report_addr(server->fd, MALFORMED, "invalid host name"); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "invalid host name"); + stop_server(EV_A_ server); return; } need_query = 1; @@ -898,8 +876,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) offset += in6_addr_len; } else { LOGE("invalid header with addr type %d", atyp); - report_addr(server->fd, MALFORMED, "invalid length for ipv6 address"); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "invalid length for ipv6 address"); + stop_server(EV_A_ server); return; } addr->sin6_port = *(uint16_t *)(server->buf->data + offset); @@ -911,8 +889,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) } if (offset == 1) { - report_addr(server->fd, MALFORMED, "invalid address type"); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "invalid address type"); + stop_server(EV_A_ server); return; } @@ -921,8 +899,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) offset += 2; if (server->buf->len < offset) { - report_addr(server->fd, MALFORMED, "invalid request length"); - close_and_free_server(EV_A_ server); + report_addr(server->fd, "invalid request length"); + stop_server(EV_A_ server); return; } else { server->buf->len -= offset; @@ -1036,12 +1014,6 @@ server_send_cb(EV_P_ ev_io *w, int revents) } } -static void -block_list_clear_cb(EV_P_ ev_timer *watcher, int revents) -{ - clear_block_list(); -} - static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents) { @@ -1135,6 +1107,11 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) remote_t *remote = remote_recv_ctx->remote; server_t *server = remote->server; + // Ignore any new packet if the server is stopped + if (server->stage == STAGE_STOP) { + return; + } + if (server == NULL) { LOGE("invalid server"); close_and_free_remote(EV_A_ remote); @@ -1266,9 +1243,6 @@ remote_send_cb(EV_P_ ev_io *w, int revents) } remote_send_ctx->connected = 1; - // Clear the state of this address in the block list - reset_addr(server->fd); - if (remote->buf->len == 0) { server->stage = STAGE_STREAM; ev_io_stop(EV_A_ & remote_send_ctx->io); @@ -1554,26 +1528,14 @@ accept_cb(EV_P_ ev_io *w, int revents) char *peer_name = get_peer_name(serverfd); if (peer_name != NULL) { - int in_white_list = 0; if (acl) { if ((get_acl_mode() == BLACK_LIST && acl_match_host(peer_name) == 1) || (get_acl_mode() == WHITE_LIST && acl_match_host(peer_name) >= 0)) { LOGE("Access denied from %s", peer_name); close(serverfd); return; - } else if (acl_match_host(peer_name) == -1) { - in_white_list = 1; } } - if (!in_white_list && plugin == NULL - && check_block_list(peer_name)) { - LOGE("block all requests from %s", peer_name); -#ifdef __linux__ - set_linger(serverfd); -#endif - close(serverfd); - return; - } } int opt = 1; @@ -2101,9 +2063,6 @@ main(int argc, char **argv) } #endif - ev_timer_init(&block_list_watcher, block_list_clear_cb, UPDATE_INTERVAL, UPDATE_INTERVAL); - ev_timer_start(EV_DEFAULT, &block_list_watcher); - #ifndef __MINGW32__ // setuid if (user != NULL && !run_as(user)) { @@ -2115,9 +2074,6 @@ main(int argc, char **argv) } #endif - // init block list - init_block_list(); - // Init connections cork_dllist_init(&connections); @@ -2128,17 +2084,12 @@ main(int argc, char **argv) LOGI("closed gracefully"); } - // Free block list - free_block_list(); - #ifndef __MINGW32__ if (manager_addr != NULL) { ev_timer_stop(EV_DEFAULT, &stat_update_watcher); } #endif - ev_timer_stop(EV_DEFAULT, &block_list_watcher); - if (plugin != NULL) { stop_plugin(); }