mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-29 12:36:53 +00:00
Drop FIN packets to misbehaving clients (#925)
* Drop FIN if detecting bad clients * Fix the command line * Refine iptables rules * Refine euid
This commit is contained in:
@@ -45,18 +45,96 @@ static struct ip_set outbound_block_list_ipv4;
|
||||
static struct ip_set outbound_block_list_ipv6;
|
||||
static struct cork_dllist outbound_block_list_rules;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static int
|
||||
run_cmd(const char *cmdstring)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
if (cmdstring == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if ((pid = fork()) < 0) {
|
||||
status = -1;
|
||||
} else if (pid == 0) {
|
||||
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
|
||||
_exit(127);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
init_iptables()
|
||||
{
|
||||
if (geteuid() != 0)
|
||||
return -1;
|
||||
char cli[256];
|
||||
sprintf(cli, "iptables -N SHADOWSOCKS_LIBEV; \
|
||||
iptables -F SHADOWSOCKS_LIBEV; \
|
||||
iptables -A OUTPUT -p tcp --tcp-flags FIN FIN -j SHADOWSOCKS_LIBEV");
|
||||
return run_cmd(cli);
|
||||
}
|
||||
|
||||
static int
|
||||
clean_iptables()
|
||||
{
|
||||
if (geteuid() != 0)
|
||||
return -1;
|
||||
char cli[256];
|
||||
sprintf(cli, "iptables -D OUTPUT -p tcp --tcp-flags FIN FIN -j SHADOWSOCKS_LIBEV; \
|
||||
iptables -F SHADOWSOCKS_LIBEV; \
|
||||
iptables -X SHADOWSOCKS_LIBEV");
|
||||
return run_cmd(cli);
|
||||
}
|
||||
|
||||
static int
|
||||
set_iptables_rules(char *addr, int add)
|
||||
{
|
||||
if (geteuid() != 0)
|
||||
return -1;
|
||||
char cli[256];
|
||||
if (add)
|
||||
sprintf(cli, "iptables -A SHADOWSOCKS_LIBEV -d %s -j DROP", addr);
|
||||
else
|
||||
sprintf(cli, "iptables -D SHADOWSOCKS_LIBEV -d %s -j DROP", addr);
|
||||
return run_cmd(cli);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
init_block_list()
|
||||
{
|
||||
// Initialize cache
|
||||
#ifdef __linux__
|
||||
init_iptables();
|
||||
#endif
|
||||
cache_create(&block_list, 256, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
free_block_list()
|
||||
{
|
||||
#ifdef __linux__
|
||||
clean_iptables();
|
||||
#endif
|
||||
cache_clear(block_list, 0); // Remove all items
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
remove_from_block_list(char *addr)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
|
||||
#ifdef __linux__
|
||||
if (cache_key_exist(block_list, addr, addr_len))
|
||||
set_iptables_rules(addr, 0);
|
||||
#endif
|
||||
|
||||
return cache_remove(block_list, addr, addr_len);
|
||||
}
|
||||
|
||||
@@ -83,6 +161,9 @@ check_block_list(char *addr, int err_level)
|
||||
int *count = (int *)ss_malloc(sizeof(int));
|
||||
*count = 1;
|
||||
cache_insert(block_list, addr, addr_len, count);
|
||||
#ifdef __linux__
|
||||
set_iptables_rules(addr, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -43,6 +43,7 @@ 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 err_level);
|
||||
int remove_from_block_list(char *addr);
|
||||
|
||||
|
||||
@@ -1866,6 +1866,9 @@ main(int argc, char **argv)
|
||||
LOGI("closed gracefully");
|
||||
}
|
||||
|
||||
// Free block list
|
||||
free_block_list();
|
||||
|
||||
if (manager_address != NULL) {
|
||||
ev_timer_stop(EV_DEFAULT, &stat_update_watcher);
|
||||
}
|
||||
|
||||
+4
-4
@@ -109,14 +109,14 @@ run_as(const char *user)
|
||||
|
||||
if (err == 0 && pwd) {
|
||||
/* setgid first, because we may not be allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0) {
|
||||
if (setresgid(pwd->pw_gid, 0, pwd->pw_gid) != 0) {
|
||||
LOGE(
|
||||
"Could not change group id to that of run_as user '%s': %s",
|
||||
user, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setuid(pwd->pw_uid) != 0) {
|
||||
if (setresuid(pwd->pw_uid, 0, pwd->pw_uid) != 0) {
|
||||
LOGE(
|
||||
"Could not change user id to that of run_as user '%s': %s",
|
||||
user, strerror(errno));
|
||||
@@ -150,12 +150,12 @@ run_as(const char *user)
|
||||
return 0;
|
||||
}
|
||||
/* setgid first, because we may not allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0) {
|
||||
if (setresgid(pwd->pw_gid, 0, pwd->pwd_gid) != 0) {
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
user, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (setuid(pwd->pw_uid) != 0) {
|
||||
if (setresuid(pwd->pw_uid, 0, pwd->pwd_uid) != 0) {
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
user, strerror(errno));
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user