Browse Source

Make SO_REUSEPORT disabled by default

pull/1179/head
Max Lv 8 years ago
parent
commit
7b290f30d6
18 changed files with 140 additions and 44 deletions
  1. 6
      doc/shadowsocks-libev.asciidoc
  2. 7
      doc/ss-local.asciidoc
  3. 6
      doc/ss-manager.asciidoc
  4. 5
      doc/ss-redir.asciidoc
  5. 7
      doc/ss-server.asciidoc
  6. 7
      doc/ss-tunnel.asciidoc
  7. 14
      src/common.h
  8. 4
      src/jconf.c
  9. 1
      src/jconf.h
  10. 17
      src/local.c
  11. 33
      src/manager.c
  12. 1
      src/manager.h
  13. 16
      src/redir.c
  14. 21
      src/server.c
  15. 16
      src/tunnel.c
  16. 9
      src/udprelay.c
  17. 2
      src/utils.c
  18. 12
      src/utils.h

6
doc/shadowsocks-libev.asciidoc

@ -126,6 +126,11 @@ Enable TCP fast open.
+
Not available in redir nor tunnel mode, with Linux kernel > 3.7.0.
--reuse-port::
Enable port reuse.
+
Only available with Linux kernel > 3.9.0.
--acl <acl_config>::
Enable ACL (Access Control List) and specify config file.
+
@ -166,6 +171,7 @@ The config file equivalent of command line options is listed as example below.
| -t 60 | "timeout": 60
| -a nobody | "user": "nobody"
| --fast-open | "fast_open": true
| --reuse-port | "reuse_port": true
| --plugin "obfs-server" | "plugin": "obfs-server"
| --plugin-opts "obfs=http" | "plugin_opts": "obfs=http"
| -6 | "ipv6_first": true

7
doc/ss-local.asciidoc

@ -13,7 +13,7 @@ SYNOPSIS
[-k <password>] [-m <encrypt_method>] [-f <pid_file>]
[-t <timeout>] [-c <config_file>] [-i <interface>]
[-a <user_name>] [-b <local_address] [-n <nofile>]
[--fast-open] [--acl <acl_config>] [--mtu <MTU>]
[--fast-open] [--reuse-port] [--acl <acl_config>] [--mtu <MTU>]
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
DESCRIPTION
@ -102,6 +102,11 @@ Enable TCP fast open.
+
Only available with Linux kernel > 3.7.0.
--reuse-port::
Enable port reuse.
+
Only available with Linux kernel > 3.9.0.
--acl <acl_config>::
Enable ACL (Access Control List) and specify config file.

6
doc/ss-manager.asciidoc

@ -15,6 +15,7 @@ SYNOPSIS
[-b <local_addr>] [-a <user_name>]
[--manager-address <path_to_unix_domain>]
[--executable <path_to_server_executable>]
[--fast-open] [--reuse-port]
[--plugin <plugin_name>] [--plugin-opts <plugin_options>]
DESCRIPTION
@ -93,6 +94,11 @@ Enable TCP fast open.
+
Only available with Linux kernel > 3.7.0.
--reuse-port::
Enable port reuse.
+
Only available with Linux kernel > 3.9.0.
--acl <acl_config>::
Enable ACL (Access Control List) and specify config file.

5
doc/ss-redir.asciidoc

@ -99,6 +99,11 @@ Enable Multipath TCP.
+
Only available with MPTCP enabled Linux kernel.
--reuse-port::
Enable port reuse.
+
Only available with Linux kernel > 3.9.0.
--plugin <plugin_name>::
Enable SIP003 plugin. (Experimental)

7
doc/ss-server.asciidoc

@ -13,7 +13,7 @@ SYNOPSIS
[-k <password>] [-m <encrypt_method>] [-f <pid_file>]
[-t <timeout>] [-c <config_file>] [-i <interface>]
[-a <user_name>] [-d <addr>] [-n <nofile>]
[-b <local_address] [--fast-open] [--mptcp]
[-b <local_address] [--fast-open] [--reuse-port] [--mptcp]
[--acl <acl_config>] [--mtu <MTU>]
[--manager-address <path_to_unix_domain>]
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
@ -104,6 +104,11 @@ Enable TCP fast open.
+
Only available with Linux kernel > 3.7.0.
--reuse-port::
Enable port reuse.
+
Only available with Linux kernel > 3.9.0.
--acl <acl_config>::
Enable ACL (Access Control List) and specify config file.

7
doc/ss-tunnel.asciidoc

@ -13,7 +13,7 @@ SYNOPSIS
[-k <password>] [-m <encrypt_method>] [-f <pid_file>]
[-t <timeout>] [-c <config_file>] [-i <interface>]
[-b <local_addr>] [-a <user_name>] [-n <nofile>]
[-L addr:port] [--mtu <MTU>]
[-L addr:port] [--mtu <MTU>] [--mptcp] [--reuse-port]
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
DESCRIPTION
@ -110,6 +110,11 @@ Enable Multipath TCP.
+
Only available with MPTCP enabled Linux kernel.
--reuse-port::
Enable port reuse.
+
Only available with Linux kernel > 3.9.0.
--plugin <plugin_name>::
Enable SIP003 plugin. (Experimental)

14
src/common.h

@ -57,4 +57,18 @@ int send_traffic_stat(uint64_t tx, uint64_t rx);
#define STAGE_RESOLVE 4 /* Resolve the hostname */
#define STAGE_STREAM 5 /* Stream between client and server */
/* Vals for long options */
enum {
GETOPT_VAL_HELP = 257,
GETOPT_VAL_REUSE_PORT,
GETOPT_VAL_FAST_OPEN,
GETOPT_VAL_ACL,
GETOPT_VAL_MTU,
GETOPT_VAL_MPTCP,
GETOPT_VAL_PLUGIN,
GETOPT_VAL_PLUGIN_OPTS,
GETOPT_VAL_MANAGER_ADDRESS,
GETOPT_VAL_EXECUTABLE
};
#endif // _COMMON_H

4
src/jconf.c

@ -211,6 +211,10 @@ read_jconf(const char *file)
check_json_value_type(value, json_boolean,
"invalid config file: option 'fast_open' must be a boolean");
conf.fast_open = value->u.boolean;
} else if (strcmp(name, "reuse_port") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'reuse_port' must be a boolean");
conf.reuse_port = value->u.boolean;
} else if (strcmp(name, "auth") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'auth' must be a boolean");

1
src/jconf.h

@ -60,6 +60,7 @@ typedef struct {
char *plugin_opts;
int auth;
int fast_open;
int reuse_port;
int nofile;
char *nameserver;
char *tunnel_address;

17
src/local.c

@ -86,6 +86,7 @@
#endif
int verbose = 0;
int reuse_port = 0;
int keep_resolving = 1;
#ifdef ANDROID
@ -173,9 +174,11 @@ create_and_bind(const char *addr, const char *port)
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
if (reuse_port) {
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
}
}
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
@ -1187,12 +1190,14 @@ main(int argc, char **argv)
char *remote_port = NULL;
static struct option long_options[] = {
{ "reuse-port", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
{ "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN },
{ "acl", required_argument, NULL, GETOPT_VAL_ACL },
{ "mtu", required_argument, NULL, GETOPT_VAL_MTU },
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
{ "port-reuse", no_argument , NULL, GETOPT_VAL_REUSE_PORT },
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
{ NULL, 0, NULL, 0 }
};
@ -1230,6 +1235,9 @@ main(int argc, char **argv)
case GETOPT_VAL_PLUGIN_OPTS:
plugin_opts = optarg;
break;
case GETOPT_VAL_REUSE_PORT:
reuse_port = 1;
break;
case 's':
if (remote_num < MAX_REMOTE_NUM) {
remote_addr[remote_num].host = optarg;
@ -1345,6 +1353,9 @@ main(int argc, char **argv)
if (plugin_opts == NULL) {
plugin_opts = conf->plugin_opts;
}
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
if (fast_open == 0) {
fast_open = conf->fast_open;
}

33
src/manager.c

@ -159,6 +159,10 @@ construct_command_line(struct manager_ctx *manager, struct server *server)
int len = strlen(cmd);
snprintf(cmd + len, BUF_SIZE - len, " --fast-open");
}
if (manager->reuse_port) {
int len = strlen(cmd);
snprintf(cmd + len, BUF_SIZE - len, " --reuse-port");
}
if (manager->ipv6first) {
int len = strlen(cmd);
snprintf(cmd + len, BUF_SIZE - len, " -6");
@ -313,7 +317,7 @@ create_and_bind(const char *host, const char *port, int protocol)
{
struct addrinfo hints;
struct addrinfo *result, *rp, *ipv4v6bindall;
int s, listen_sock = -1, is_port_reuse = 0;
int s, listen_sock = -1, is_reuse_port = 0;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
@ -372,14 +376,14 @@ create_and_bind(const char *host, const char *port, int protocol)
if (verbose) {
LOGI("%s port reuse enabled", protocol == IPPROTO_TCP ? "tcp" : "udp");
}
is_port_reuse = 1;
is_reuse_port = 1;
}
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
/* We managed to bind successfully! */
if (!is_port_reuse) {
if (!is_reuse_port) {
if (verbose) {
LOGI("close sock due to %s port reuse disabled", protocol == IPPROTO_TCP ? "tcp" : "udp");
}
@ -401,7 +405,7 @@ create_and_bind(const char *host, const char *port, int protocol)
return -1;
}
return is_port_reuse ? listen_sock : -2;
return is_reuse_port ? listen_sock : -2;
}
static void
@ -876,11 +880,12 @@ main(int argc, char **argv)
char *plugin = NULL;
char *plugin_opts = NULL;
int auth = 0;
int fast_open = 0;
int mode = TCP_ONLY;
int mtu = 0;
int ipv6first = 0;
int auth = 0;
int fast_open = 0;
int reuse_port = 0;
int mode = TCP_ONLY;
int mtu = 0;
int ipv6first = 0;
#ifdef HAVE_SETRLIMIT
static int nofile = 0;
@ -896,6 +901,7 @@ main(int argc, char **argv)
static struct option long_options[] = {
{ "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN },
{ "reuse-port", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
{ "acl", required_argument, NULL, GETOPT_VAL_ACL },
{ "manager-address", required_argument, NULL,
GETOPT_VAL_MANAGER_ADDRESS },
@ -915,6 +921,9 @@ main(int argc, char **argv)
while ((c = getopt_long(argc, argv, "f:s:l:k:t:m:c:i:d:a:n:6huUvA",
long_options, NULL)) != -1)
switch (c) {
case GETOPT_VAL_REUSE_PORT:
reuse_port = 1;
break;
case GETOPT_VAL_FAST_OPEN:
fast_open = 1;
break;
@ -1023,11 +1032,12 @@ main(int argc, char **argv)
if (user == NULL) {
user = conf->user;
}
#ifdef TCP_FASTOPEN
if (fast_open == 0) {
fast_open = conf->fast_open;
}
#endif
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
if (conf->nameserver != NULL) {
nameservers[nameserver_num++] = conf->nameserver;
}
@ -1105,6 +1115,7 @@ main(int argc, char **argv)
struct manager_ctx manager;
memset(&manager, 0, sizeof(struct manager_ctx));
manager.reuse_port = reuse_port;
manager.fast_open = fast_open;
manager.verbose = verbose;
manager.mode = mode;

1
src/manager.h

@ -35,6 +35,7 @@ struct manager_ctx {
ev_io io;
int fd;
int fast_open;
int reuse_port;
int verbose;
int mode;
int auth;

16
src/redir.c

@ -87,6 +87,7 @@ static void free_server(server_t *server);
static void close_and_free_server(EV_P_ server_t *server);
int verbose = 0;
int reuse_port = 0;
int keep_resolving = 1;
static crypto_t *crypto;
@ -155,9 +156,11 @@ create_and_bind(const char *addr, const char *port)
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
if (reuse_port) {
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
}
}
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
@ -803,6 +806,7 @@ main(int argc, char **argv)
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
{ "port-reuse", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
{ NULL, 0, NULL, 0 }
};
@ -828,6 +832,9 @@ main(int argc, char **argv)
case GETOPT_VAL_PLUGIN_OPTS:
plugin_opts = optarg;
break;
case GETOPT_VAL_REUSE_PORT:
reuse_port = 1;
break;
case 's':
if (remote_num < MAX_REMOTE_NUM) {
remote_addr[remote_num].host = optarg;
@ -942,6 +949,9 @@ main(int argc, char **argv)
if (mptcp == 0) {
mptcp = conf->mptcp;
}
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;

21
src/server.c

@ -99,7 +99,8 @@ static void close_and_free_server(EV_P_ server_t *server);
static void server_resolve_cb(struct sockaddr *addr, void *data);
static void query_free_cb(void *data);
int verbose = 0;
int verbose = 0;
int reuse_port = 0;
static crypto_t *crypto;
@ -379,9 +380,11 @@ create_and_bind(const char *host, const char *port, int mptcp)
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
if (reuse_port) {
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
}
}
if (mptcp == 1) {
@ -1353,6 +1356,7 @@ main(int argc, char **argv)
static struct option long_options[] = {
{ "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN },
{ "reuse-port", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
{ "acl", required_argument, NULL, GETOPT_VAL_ACL },
{ "manager-address", required_argument, NULL,
GETOPT_VAL_MANAGER_ADDRESS },
@ -1360,6 +1364,7 @@ main(int argc, char **argv)
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
{ "port-reuse", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
#ifdef __linux__
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
#endif
@ -1397,6 +1402,9 @@ main(int argc, char **argv)
mptcp = 1;
LOGI("enable multipath TCP");
break;
case GETOPT_VAL_REUSE_PORT:
reuse_port = 1;
break;
case 's':
if (server_num < MAX_REMOTE_NUM) {
server_host[server_num++] = optarg;
@ -1512,11 +1520,12 @@ main(int argc, char **argv)
if (mptcp == 0) {
mptcp = conf->mptcp;
}
#ifdef TCP_FASTOPEN
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
if (fast_open == 0) {
fast_open = conf->fast_open;
}
#endif
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;

16
src/tunnel.c

@ -85,6 +85,7 @@ int vpn = 0;
#endif
int verbose = 0;
int reuse_port = 0;
int keep_resolving = 1;
static crypto_t *crypto;
@ -137,9 +138,11 @@ create_and_bind(const char *addr, const char *port)
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
if (reuse_port) {
int err = set_reuseport(listen_sock);
if (err == 0) {
LOGI("tcp port reuse enabled");
}
}
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
@ -750,6 +753,7 @@ main(int argc, char **argv)
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
{ "port-reuse", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
{ NULL, 0, NULL, 0}
};
@ -780,6 +784,9 @@ main(int argc, char **argv)
case GETOPT_VAL_PLUGIN_OPTS:
plugin_opts = optarg;
break;
case GETOPT_VAL_REUSE_PORT:
reuse_port = 1;
break;
case 's':
if (remote_num < MAX_REMOTE_NUM) {
remote_addr[remote_num].host = optarg;
@ -911,6 +918,9 @@ main(int argc, char **argv)
if (mptcp == 0) {
mptcp = conf->mptcp;
}
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;

9
src/udprelay.c

@ -92,6 +92,7 @@ extern int vpn;
#endif
extern int verbose;
extern int reuse_port;
#ifdef MODULE_REMOTE
extern uint64_t tx;
extern uint64_t rx;
@ -425,9 +426,11 @@ create_server_socket(const char *host, const char *port)
#ifdef SO_NOSIGPIPE
set_nosigpipe(server_sock);
#endif
int err = set_reuseport(server_sock);
if (err == 0) {
LOGI("udp port reuse enabled");
if (reuse_port) {
int err = set_reuseport(server_sock);
if (err == 0) {
LOGI("udp port reuse enabled");
}
}
#ifdef IP_TOS
// Set QoS flag

2
src/utils.c

@ -337,6 +337,8 @@ usage()
printf(
" [-d <addr>] Name servers for internal DNS resolver.\n");
#endif
printf(
" [--reuse-port] Enable port reuse.\n");
#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL)
printf(
" [--fast-open] Enable TCP fast open.\n");

12
src/utils.h

@ -161,18 +161,6 @@ extern int use_syslog;
#endif // if ANDROID
/* Vals for long options */
enum { GETOPT_VAL_HELP = 257,
GETOPT_VAL_FAST_OPEN,
GETOPT_VAL_ACL,
GETOPT_VAL_MTU,
GETOPT_VAL_MPTCP,
GETOPT_VAL_PLUGIN,
GETOPT_VAL_PLUGIN_OPTS,
GETOPT_VAL_MANAGER_ADDRESS,
GETOPT_VAL_EXECUTABLE
};
void ERROR(const char *s);
char *ss_itoa(int i);

Loading…
Cancel
Save