Browse Source

Drop FIN packets to misbehaving clients (#925)

* Drop FIN if detecting bad clients

* Fix the command line

* Refine iptables rules

* Refine euid
pull/936/head
Max Lv 8 years ago
committed by GitHub
parent
commit
bac7ba79dd
4 changed files with 89 additions and 4 deletions
  1. 81
      src/acl.c
  2. 1
      src/acl.h
  3. 3
      src/server.c
  4. 8
      src/utils.c

81
src/acl.c

@ -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;

1
src/acl.h

@ -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);

3
src/server.c

@ -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);
}

8
src/utils.c

@ -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;

Loading…
Cancel
Save