Browse Source

Refine IPv6 handling in ACL

pull/946/head
Max Lv 8 years ago
parent
commit
d5e1c4308d
1 changed files with 63 additions and 35 deletions
  1. 98
      src/acl.c

98
src/acl.c

@ -55,7 +55,6 @@ static struct cork_dllist outbound_block_list_rules;
#define FIREWALLD_MODE 2
static int mode = NO_FIREWALL_MODE;
static int rule_count = 0;
static char chain_name[64];
static char *iptables_init_chain =
@ -65,25 +64,47 @@ static char *iptables_remove_chain =
static char *iptables_add_rule = "iptables -A %s -d %s -j DROP";
static char *iptables_remove_rule = "iptables -D %s -d %s -j DROP";
static char *ip6tables_init_chain =
"ip6tables -N %s; ip6tables -F %s; ip6tables -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
static char *ip6tables_remove_chain =
"ip6tables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; ip6tables -F %s; ip6tables -X %s";
static char *ip6tables_add_rule = "ip6tables -A %s -d %s -j DROP";
static char *ip6tables_remove_rule = "ip6tables -D %s -d %s -j DROP";
static char *firewalld_init_chain =
"firewall-cmd --direct --add-chain ipv4 filter %s; \
firewall-cmd --direct --add-rule ipv4 filter OUTPUT -p tcp --tcp-flags RST RST -j %s";
firewall-cmd --direct --passthrough ipv4 -F %s; \
firewall-cmd --direct --passthrough ipv4 -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
static char *firewalld_remove_chain =
"firewall-cmd --direct --remove-rule ipv4 filter OUTPUT -p tcp --tcp-flags RST RST -j %s; \
"firewall-cmd --direct --passthrough ipv4 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \
firewall-cmd --direct --passthrough ipv4 -F %s; \
firewall-cmd --direct --remove-chain ipv4 filter %s";
static char *firewalld_add_rule = "firewall-cmd --direct --add-rule ipv4 filter %s -d %s -j DROP";
static char *firewalld_remove_rule = "firewall-cmd --direct --remove-rule ipv4 filter %s -d %s -j DROP";
static char *firewalld_remove_rule_by_id = "firewall-cmd --direct --remove-rule ipv4 filter %s %d";
static char *firewalld_add_rule = "firewall-cmd --direct --passthrough ipv4 -A %s -d %s -j DROP";
static char *firewalld_remove_rule = "firewall-cmd --direct --passthrough ipv4 -D %s -d %s -j DROP";
static char *firewalld6_init_chain =
"firewall-cmd --direct --add-chain ipv6 filter %s; \
firewall-cmd --direct --passthrough ipv6 -F %s; \
firewall-cmd --direct --passthrough ipv6 -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
static char *firewalld6_remove_chain =
"firewall-cmd --direct --passthrough ipv6 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \
firewall-cmd --direct --passthrough ipv6 -F %s; \
firewall-cmd --direct --remove-chain ipv6 filter %s";
static char *firewalld6_add_rule = "firewall-cmd --direct --passthrough ipv6 -A %s -d %s -j DROP";
static char *firewalld6_remove_rule = "firewall-cmd --direct --passthrough ipv6 -D %s -d %s -j DROP";
static int
run_cmd(const char *cmdstring)
run_cmd(const char *cmd)
{
pid_t pid;
int status = 0;
char cmdstring[256];
if (cmdstring == NULL)
if (cmd == NULL)
return -1;
sprintf(cmdstring, "%s &> /dev/null", cmd);
if ((pid = fork()) < 0) {
status = -1;
} else if (pid == 0) {
@ -95,8 +116,9 @@ run_cmd(const char *cmdstring)
}
static int
init_iptables()
init_firewall()
{
int ret = 0;
char cli[256];
FILE *fp;
@ -117,65 +139,71 @@ init_iptables()
sprintf(chain_name, "SHADOWSOCKS_LIBEV_%d", getpid());
if (mode == FIREWALLD_MODE) {
sprintf(cli, firewalld6_init_chain, chain_name, chain_name, chain_name);
ret |= system(cli);
sprintf(cli, firewalld_init_chain, chain_name, chain_name, chain_name);
return system(cli);
ret |= system(cli);
} else if (mode == IPTABLES_MODE) {
sprintf(cli, ip6tables_init_chain, chain_name, chain_name, chain_name);
ret |= system(cli);
sprintf(cli, iptables_init_chain, chain_name, chain_name, chain_name);
return system(cli);
ret |= system(cli);
}
return -1;
return ret;
}
static int
clean_iptables()
reset_firewall()
{
int i, ret;
int ret = 0;
char cli[256];
if (geteuid() != 0)
return -1;
if (mode == IPTABLES_MODE) {
sprintf(cli, ip6tables_remove_chain, chain_name, chain_name, chain_name);
ret |= system(cli);
sprintf(cli, iptables_remove_chain, chain_name, chain_name, chain_name);
return system(cli);
ret |= system(cli);
} else if (mode == FIREWALLD_MODE) {
for (i = 0; i < rule_count; i++) {
sprintf(cli, firewalld_remove_rule_by_id, chain_name, i + 1);
ret = system(cli);
}
sprintf(cli, firewalld6_remove_chain, chain_name, chain_name, chain_name);
ret |= system(cli);
sprintf(cli, firewalld_remove_chain, chain_name, chain_name, chain_name);
ret = system(cli);
return ret;
ret |= system(cli);
}
return 0;
return ret;
}
static int
set_iptables_rules(char *addr, int add)
set_firewall_rule(char *addr, int add)
{
char cli[256];
struct cork_ip ip;
if (geteuid() != 0)
return -1;
if (add)
rule_count++;
else
rule_count = rule_count > 0 ? rule_count - 1 : 0;
if (cork_ip_init(&ip, addr))
return -1;
if (add) {
if (mode == IPTABLES_MODE)
sprintf(cli, iptables_add_rule, chain_name, addr);
sprintf(cli, ip.version == 4 ? iptables_add_rule : ip6tables_add_rule,
chain_name, addr);
else if (mode == FIREWALLD_MODE)
sprintf(cli, firewalld_add_rule, chain_name, addr);
sprintf(cli, ip.version == 4 ? firewalld_add_rule : firewalld6_add_rule,
chain_name, addr);
return run_cmd(cli);
} else {
if (mode == IPTABLES_MODE)
sprintf(cli, iptables_remove_rule, chain_name, addr);
sprintf(cli, ip.version == 4 ? iptables_remove_rule : ip6tables_remove_rule,
chain_name, addr);
else if (mode == FIREWALLD_MODE)
sprintf(cli, firewalld_remove_rule, chain_name, addr);
sprintf(cli, ip.version == 4 ? firewalld_remove_rule : firewalld6_remove_rule,
chain_name, addr);
return run_cmd(cli);
}
@ -189,7 +217,7 @@ init_block_list()
{
// Initialize cache
#ifdef __linux__
init_iptables();
init_firewall();
#endif
cache_create(&block_list, 256, NULL);
}
@ -198,7 +226,7 @@ void
free_block_list()
{
#ifdef __linux__
clean_iptables();
reset_firewall();
#endif
cache_clear(block_list, 0); // Remove all items
}
@ -210,7 +238,7 @@ remove_from_block_list(char *addr)
#ifdef __linux__
if (cache_key_exist(block_list, addr, addr_len))
set_iptables_rules(addr, 0);
set_firewall_rule(addr, 0);
#endif
return cache_remove(block_list, addr, addr_len);
@ -240,7 +268,7 @@ check_block_list(char *addr, int err_level)
*count = 1;
cache_insert(block_list, addr, addr_len, count);
#ifdef __linux__
set_iptables_rules(addr, 1);
set_firewall_rule(addr, 1);
#endif
}

Loading…
Cancel
Save