Browse Source

New feature: ss-server outbound block (#905)

* New feature: server outbound block

* Update server_block_chn.acl

* Update server_block_chn.acl

Add Baidu-HK

* cleanup
pull/911/head
Kim 8 years ago
committed by Max Lv
parent
commit
a7f5359cab
4 changed files with 3961 additions and 1 deletions
  1. 3811
      acl/server_block_chn.acl
  2. 85
      src/acl.c
  3. 3
      src/acl.h
  4. 63
      src/server.c

3811
acl/server_block_chn.acl
File diff suppressed because it is too large
View File

85
src/acl.c

@ -41,6 +41,9 @@ static int acl_mode = BLACK_LIST;
static struct cache *block_list; static struct cache *block_list;
static struct ip_set outbound_block_list_ipv4;
static struct ip_set outbound_block_list_ipv6;
void void
init_block_list() init_block_list()
{ {
@ -327,3 +330,85 @@ acl_remove_ip(const char *ip)
return 0; return 0;
} }
int
init_outbound_block(const char *path)
{
// initialize ipset
ipset_init_library();
ipset_init(&outbound_block_list_ipv4);
ipset_init(&outbound_block_list_ipv6);
FILE *f = fopen(path, "r");
if (f == NULL) {
LOGE("Invalid outbound block list path.");
return -1;
}
char buf[257];
while (!feof(f))
if (fgets(buf, 256, f)) {
// Trim the newline
int len = strlen(buf);
if (len > 0 && buf[len - 1] == '\n') {
buf[len - 1] = '\0';
}
char *line = trimwhitespace(buf);
if (line[0] == '#') continue; // Skip comment line
if (strlen(line) == 0) continue; // Skip empty line
if (strcmp(line, "[outbound_block_list]") == 0) continue; // Skip section line
char host[257];
int cidr;
parse_addr_cidr(line, host, &cidr);
struct cork_ip addr;
int err = cork_ip_init(&addr, host);
if (!err) {
if (addr.version == 4) {
if (cidr >= 0) {
ipset_ipv4_add_network(&outbound_block_list_ipv4, &(addr.ip.v4), cidr);
} else {
ipset_ipv4_add(&outbound_block_list_ipv4, &(addr.ip.v4));
}
} else if (addr.version == 6) {
if (cidr >= 0) {
ipset_ipv6_add_network(&outbound_block_list_ipv6, &(addr.ip.v6), cidr);
} else {
ipset_ipv6_add(&outbound_block_list_ipv6, &(addr.ip.v6));
}
}
}
}
fclose(f);
return 0;
}
/*
* Return 0, if not match.
* Return 1, if match black list.
*/
int
outbound_block_match_host(const char *ipstr)
{
struct cork_ip addr;
int ret = 0;
int err = cork_ip_init(&addr, ipstr);
if (err) return 0;
if (addr.version == 4) {
if (ipset_contains_ipv4(&outbound_block_list_ipv4, &(addr.ip.v4)))
ret = 1;
} else if (addr.version == 6) {
if (ipset_contains_ipv6(&outbound_block_list_ipv6, &(addr.ip.v6)))
ret = 1;
}
return ret;
}

3
src/acl.h

@ -46,4 +46,7 @@ void init_block_list();
int check_block_list(char* addr, int err_level); int check_block_list(char* addr, int err_level);
int remove_from_block_list(char *addr); int remove_from_block_list(char *addr);
int init_outbound_block(const char *path);
int outbound_block_match_host(const char *host);
#endif // _ACL_H #endif // _ACL_H

63
src/server.c

@ -115,6 +115,8 @@ static int mode = TCP_ONLY;
static int auth = 0; static int auth = 0;
static int ipv6first = 0; static int ipv6first = 0;
static int outbound_block = 0;
static int fast_open = 0; static int fast_open = 0;
#ifdef HAVE_SETRLIMIT #ifdef HAVE_SETRLIMIT
static int nofile = 0; static int nofile = 0;
@ -463,6 +465,49 @@ create_and_bind(const char *host, const char *port, int mptcp)
return listen_sock; return listen_sock;
} }
void print_addrinfo(struct addrinfo *ai)
{
// TODO: move this function to somewhere like 'debug.c'
char ipstr[INET6_ADDRSTRLEN];
unsigned short int port = 0;
bzero(ipstr, INET6_ADDRSTRLEN);
printf("addrinfo=>{");
printf("ai_flags=");
switch (ai->ai_flags) {
case AI_PASSIVE: printf("AI_PASSIVE"); break;
case AI_CANONNAME: printf("AI_CANONNAME"); break;
default: printf("ERROR(%d)", ai->ai_flags);
}
printf(", ai_family=");
switch (ai->ai_family) {
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ipstr, INET_ADDRSTRLEN);
port = htons(((struct sockaddr_in *)ai->ai_addr)->sin_port);
printf("AF_INET");
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr), ipstr, INET6_ADDRSTRLEN);
port = htons(((struct sockaddr_in6 *)ai->ai_addr)->sin6_port);
printf("AF_INET6");
break;
case AF_UNSPEC: printf("AF_UNSPEC"); break;
default: printf("ERROR(%d)", ai->ai_family);
}
printf(", ai_socktype=");
switch (ai->ai_socktype) {
case SOCK_STREAM: printf("SOCK_STREAM"); break;
case SOCK_DGRAM: printf("SOCK_SGRAM"); break;
default: printf("ERROR(%d)", ai->ai_socktype);
}
printf(", ai_protocol=%d", ai->ai_protocol);
printf(", ai_addrlen=%d", ai->ai_addrlen);
printf(", ai_addr=%s:%d", ipstr, port);
printf(", ai_canonname=%s", ai->ai_canonname);
printf(", ai_next=%p", ai->ai_next);
printf("}\n");
}
static remote_t * static remote_t *
connect_to_remote(struct addrinfo *res, connect_to_remote(struct addrinfo *res,
server_t *server) server_t *server)
@ -472,6 +517,17 @@ connect_to_remote(struct addrinfo *res,
const char *iface = server->listen_ctx->iface; const char *iface = server->listen_ctx->iface;
#endif #endif
if (outbound_block) {
char ipstr[INET6_ADDRSTRLEN];
bzero(ipstr, INET6_ADDRSTRLEN);
inet_ntop(AF_INET, &(((struct sockaddr_in *)res->ai_addr)->sin_addr), ipstr, INET_ADDRSTRLEN);
if (outbound_block_match_host(ipstr) == 1) {
LOGI("outbound blocked %s", ipstr);
return NULL;
}
}
// initialize remote socks // initialize remote socks
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd == -1) { if (sockfd == -1) {
@ -1053,7 +1109,8 @@ server_resolve_cb(struct sockaddr *addr, void *data)
remote_t *remote = connect_to_remote(&info, server); remote_t *remote = connect_to_remote(&info, server);
if (remote == NULL) { if (remote == NULL) {
LOGE("connect error");
if (!outbound_block)
LOGE("connect error");
close_and_free_server(EV_A_ server); close_and_free_server(EV_A_ server);
} else { } else {
server->remote = remote; server->remote = remote;
@ -1499,6 +1556,7 @@ main(int argc, char **argv)
{ "mtu", required_argument, 0, 0 }, { "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument, 0, 0 }, { "mptcp", no_argument, 0, 0 },
{ "help", no_argument, 0, 0 }, { "help", no_argument, 0, 0 },
{ "outbound-block", required_argument, 0, 0 },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
@ -1526,6 +1584,9 @@ main(int argc, char **argv)
} else if (option_index == 5) { } else if (option_index == 5) {
usage(); usage();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (option_index == 6) {
LOGI("initializing outbound block...");
outbound_block = !init_outbound_block(optarg);
} }
break; break;
case 's': case 's':

Loading…
Cancel
Save