Browse Source

Add MTU option

pull/753/head
Max Lv 8 years ago
parent
commit
34b9036b5b
13 changed files with 100 additions and 46 deletions
  1. 1
      .gitignore
  2. 5
      doc/ss-local.asciidoc
  3. 5
      doc/ss-redir.asciidoc
  4. 5
      doc/ss-server.asciidoc
  5. 5
      doc/ss-tunnel.asciidoc
  6. 2
      src/common.h
  7. 10
      src/local.c
  8. 11
      src/redir.c
  9. 9
      src/server.c
  10. 11
      src/tunnel.c
  11. 78
      src/udprelay.c
  12. 2
      src/udprelay.h
  13. 2
      src/utils.c

1
.gitignore

@ -13,7 +13,6 @@ config.log
config.status
libtool
pid
ss.*
src/ss-*
!src/ss-nat
stamp-h1

5
doc/ss-local.asciidoc

@ -12,7 +12,7 @@ SYNOPSIS
[-s <server_host>] [-p <server_port>] [-l <local_port>]
[-k <password>] [-m <encrypt_method>] [-f <pid_file>] [-t <timeout>]
[-c <config_file>] [-b <interface>] [-a <user_name>]
[-n <nofile>] [--fast-open] [--acl <acl_config>]
[-n <nofile>] [--fast-open] [--acl <acl_config>] [--mtu <MTU>]
DESCRIPTION
-----------
@ -102,6 +102,9 @@ Only available with Linux kernel > 3.7.0.
--acl <acl_config>::
Enable ACL (Access Control List) and specify config file.
--mtu <MTU>::
Specify the MTU of your network interface.
-v::
Enable verbose mode.

5
doc/ss-redir.asciidoc

@ -12,7 +12,7 @@ SYNOPSIS
[-s <server_host>] [-p <server_port>] [-l <local_port>]
[-k <password>] [-m <encrypt_method>] [-f <pid_file>]
[-t <timeout>] [-c <config_file>] [-b <local_address>]
[-a <user_name>] [-n <nofile>]
[-a <user_name>] [-n <nofile>] [--mtu <MTU>]
DESCRIPTION
-----------
@ -89,6 +89,9 @@ Enable UDP relay and disable TCP relay.
-A::
Enable onetime authentication.
--mtu <MTU>::
Specify the MTU of your network interface.
-v::
Enable verbose mode.

5
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>]
[--fast-open] [--acl <acl_config>]
[--fast-open] [--acl <acl_config>] [--mtu <MTU>]
[--manager-address <path_to_unix_domain>]
DESCRIPTION
@ -115,6 +115,9 @@ Specify UNIX domain socket address for the communication between ss-manager(1) a
+
Only available in server and manager mode.
--mtu <MTU>::
Specify the MTU of your network interface.
-v::
Enable verbose mode.

5
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]
[-L addr:port] [--mtu <MTU>]
DESCRIPTION
-----------
@ -100,6 +100,9 @@ Specify destination server address and port for local port forwarding.
+
Only used and available in tunnel mode.
--mtu <MTU>::
Specify the MTU of your network interface.
-v::
Enable verbose mode.

2
src/common.h

@ -60,7 +60,7 @@ int init_udprelay(const char *server_host, const char *server_port,
const ss_addr_t tunnel_addr,
#endif
#endif
int method, int auth, int timeout, const char *iface);
int mtu, int method, int auth, int timeout, const char *iface);
void free_udprelay(void);

10
src/local.c

@ -982,6 +982,7 @@ int main(int argc, char **argv)
{
int i, c;
int pid_flags = 0;
int mtu = 0;
char *user = NULL;
char *local_port = NULL;
char *local_addr = NULL;
@ -1002,6 +1003,7 @@ int main(int argc, char **argv)
static struct option long_options[] = {
{ "fast-open", no_argument , 0, 0 },
{ "acl" , required_argument, 0, 0 },
{ "mtu" , required_argument, 0, 0 },
{ "help" , no_argument , 0, 0 },
{ 0, 0, 0, 0 }
};
@ -1025,6 +1027,9 @@ int main(int argc, char **argv)
LOGI("initializing acl...");
acl = !init_acl(optarg, BLACK_LIST);
} else if (option_index == 2) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
} else if (option_index == 3) {
usage();
exit(EXIT_SUCCESS);
}
@ -1258,7 +1263,7 @@ int main(int argc, char **argv)
if (mode != TCP_ONLY) {
LOGI("udprelay enabled");
init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
get_sockaddr_len(listen_ctx.remote_addr[0]), m, auth, listen_ctx.timeout, iface);
get_sockaddr_len(listen_ctx.remote_addr[0]), mtu, m, auth, listen_ctx.timeout, iface);
}
LOGI("listening at %s:%s", local_addr, local_port);
@ -1318,6 +1323,7 @@ int start_ss_local_server(profile_t profile)
int remote_port = profile.remote_port;
int local_port = profile.local_port;
int timeout = profile.timeout;
int mtu = 0;
auth = profile.auth;
mode = profile.mode;
@ -1406,7 +1412,7 @@ int start_ss_local_server(profile_t profile)
LOGI("udprelay enabled");
struct sockaddr *addr = (struct sockaddr *)storage;
init_udprelay(local_addr, local_port_str, addr,
get_sockaddr_len(addr), m, auth, timeout, NULL);
get_sockaddr_len(addr), mtu, m, auth, timeout, NULL);
}
LOGI("listening at %s:%s", local_addr, local_port_str);

11
src/redir.c

@ -683,6 +683,7 @@ int main(int argc, char **argv)
int i, c;
int pid_flags = 0;
int mtu = 0;
char *user = NULL;
char *local_port = NULL;
char *local_addr = NULL;
@ -698,8 +699,9 @@ int main(int argc, char **argv)
int option_index = 0;
static struct option long_options[] = {
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
{ "mtu", required_argument, 0, 0 },
{ "help", no_argument , 0, 0 },
{ 0, 0 , 0, 0 }
};
opterr = 0;
@ -709,6 +711,9 @@ int main(int argc, char **argv)
switch (c) {
case 0:
if (option_index == 0) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
} else if (option_index == 1) {
usage();
exit(EXIT_SUCCESS);
}
@ -905,7 +910,7 @@ int main(int argc, char **argv)
if (mode != TCP_ONLY) {
LOGI("UDP relay enabled");
init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
get_sockaddr_len(listen_ctx.remote_addr[0]), m, auth, listen_ctx.timeout, NULL);
get_sockaddr_len(listen_ctx.remote_addr[0]), mtu, m, auth, listen_ctx.timeout, NULL);
}
if (mode == UDP_ONLY) {

9
src/server.c

@ -1338,6 +1338,7 @@ int main(int argc, char **argv)
{
int i, c;
int pid_flags = 0;
int mtu = 0;
char *user = NULL;
char *password = NULL;
char *timeout = NULL;
@ -1358,6 +1359,7 @@ int main(int argc, char **argv)
{ "fast-open" , no_argument , 0, 0 },
{ "acl" , required_argument, 0, 0 },
{ "manager-address", required_argument, 0, 0 },
{ "mtu" , required_argument, 0, 0 },
{ "help" , no_argument , 0, 0 },
{ 0, 0, 0, 0 }
};
@ -1379,6 +1381,9 @@ int main(int argc, char **argv)
} else if (option_index == 2) {
manager_address = optarg;
} else if (option_index == 3) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
} else if (option_index == 4) {
usage();
exit(EXIT_SUCCESS);
}
@ -1636,8 +1641,8 @@ int main(int argc, char **argv)
// Setup UDP
if (mode != TCP_ONLY) {
init_udprelay(server_host[index], server_port, m, auth, atoi(timeout),
iface);
init_udprelay(server_host[index], server_port, mtu, m,
auth, atoi(timeout), iface);
}
LOGI("listening at %s:%s", host ? host : "*", server_port);

11
src/tunnel.c

@ -692,6 +692,7 @@ int main(int argc, char **argv)
int i, c;
int pid_flags = 0;
int mtu = 0;
char *user = NULL;
char *local_port = NULL;
char *local_addr = NULL;
@ -711,8 +712,9 @@ int main(int argc, char **argv)
int option_index = 0;
static struct option long_options[] = {
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
{ "mtu", required_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
};
opterr = 0;
@ -729,6 +731,9 @@ int main(int argc, char **argv)
switch (c) {
case 0:
if (option_index == 0) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
} else if (option_index == 1) {
usage();
exit(EXIT_SUCCESS);
}
@ -959,7 +964,7 @@ int main(int argc, char **argv)
LOGI("UDP relay enabled");
init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0],
get_sockaddr_len(listen_ctx.remote_addr[0]),
tunnel_addr, m, auth, listen_ctx.timeout, iface);
tunnel_addr, mtu, m, auth, listen_ctx.timeout, iface);
}
if (mode == UDP_ONLY) {

78
src/udprelay.c

@ -81,8 +81,6 @@
#define EWOULDBLOCK EAGAIN
#endif
#define BUF_SIZE MAX_UDP_PACKET_SIZE
static void server_recv_cb(EV_P_ ev_io *w, int revents);
static void remote_recv_cb(EV_P_ ev_io *w, int revents);
static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents);
@ -101,6 +99,8 @@ extern uint64_t tx;
extern uint64_t rx;
#endif
static int packet_size = DEFAULT_PACKET_SIZE;
static int buf_size = DEFAULT_PACKET_SIZE * 2;
static int server_num = 0;
static server_ctx_t *server_ctx_list[MAX_REMOTE_NUM] = { NULL };
@ -645,27 +645,25 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
memset(&src_addr, 0, src_addr_len);
buffer_t *buf = ss_malloc(sizeof(buffer_t));
balloc(buf, BUF_SIZE);
balloc(buf, packet_size);
// recv
r = recvfrom(remote_ctx->fd, buf->array, BUF_SIZE, 0, (struct sockaddr *)&src_addr, &src_addr_len);
r = recvfrom(remote_ctx->fd, buf->array, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len);
if (r == -1) {
// error on recv
// simply drop that packet
ERROR("[udp] remote_recvfrom");
ERROR("[udp] remote_recv_recvfrom");
goto CLEAN_UP;
} else if (r > packet_size) {
LOGE("[udp] remote_recv_recvfrom fragmentation");
goto CLEAN_UP;
}
buf->len = r;
// packet size > default MTU
if (verbose && buf->len > MTU) {
LOGE("[udp] possible ip fragment, size: %d", (int)buf->len);
}
#ifdef MODULE_LOCAL
int err = ss_decrypt_all(buf, server_ctx->method, 0, BUF_SIZE);
int err = ss_decrypt_all(buf, server_ctx->method, 0, packet_size);
if (err) {
// drop the packet silently
goto CLEAN_UP;
@ -699,7 +697,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
memmove(buf->array, buf->array + len, buf->len);
#else
// Construct packet
brealloc(buf, buf->len + 3, BUF_SIZE);
brealloc(buf, buf->len + 3, packet_size);
memmove(buf->array + 3, buf->array, buf->len);
memset(buf->array, 0, 3);
buf->len += 3;
@ -720,18 +718,23 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
}
// Construct packet
brealloc(buf, buf->len + addr_header_len, BUF_SIZE);
brealloc(buf, buf->len + addr_header_len, packet_size);
memmove(buf->array + addr_header_len, buf->array, buf->len);
memcpy(buf->array, addr_header, addr_header_len);
buf->len += addr_header_len;
int err = ss_encrypt_all(buf, server_ctx->method, 0, BUF_SIZE);
int err = ss_encrypt_all(buf, server_ctx->method, 0, packet_size);
if (err) {
// drop the packet silently
goto CLEAN_UP;
}
#endif
if (buf->len > packet_size) {
LOGE("[udp] remote_recv_sendto fragmentation");
goto CLEAN_UP;
}
size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&remote_ctx->src_addr);
#ifdef MODULE_REDIR
@ -794,7 +797,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
memset(&src_addr, 0, sizeof(struct sockaddr_storage));
buffer_t *buf = ss_malloc(sizeof(buffer_t));
balloc(buf, BUF_SIZE);
balloc(buf, packet_size);
socklen_t src_addr_len = sizeof(struct sockaddr_storage);
unsigned int offset = 0;
@ -812,7 +815,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
msg.msg_controllen = sizeof(control_buffer);
iov[0].iov_base = buf->array;
iov[0].iov_len = BUF_SIZE;
iov[0].iov_len = packet_size;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
@ -820,6 +823,9 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
if (buf->len == -1) {
ERROR("[udp] server_recvmsg");
goto CLEAN_UP;
} else if (buf->len > packet_size) {
ERROR("[udp] UDP server_recv_recvmsg fragmentation");
goto CLEAN_UP;
}
if (get_dstaddr(&msg, &dst_addr)) {
@ -830,13 +836,16 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
src_addr_len = msg.msg_namelen;
#else
ssize_t r;
r = recvfrom(server_ctx->fd, buf->array, BUF_SIZE,
r = recvfrom(server_ctx->fd, buf->array, buf_size,
0, (struct sockaddr *)&src_addr, &src_addr_len);
if (r == -1) {
// error on recv
// simply drop that packet
ERROR("[udp] server_recvfrom");
ERROR("[udp] server_recv_recvfrom");
goto CLEAN_UP;
} else if (r > packet_size) {
ERROR("[udp] server_recv_recvfrom fragmentation");
goto CLEAN_UP;
}
@ -851,7 +860,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
tx += buf->len;
int err = ss_decrypt_all(buf, server_ctx->method, server_ctx->auth, BUF_SIZE);
int err = ss_decrypt_all(buf, server_ctx->method, server_ctx->auth, packet_size);
if (err) {
// drop the packet silently
goto CLEAN_UP;
@ -865,11 +874,6 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#endif
#endif
// packet size > default MTU
if (verbose && buf->len > MTU) {
LOGE("[udp] possible ip fragment, size: %d", (int)buf->len);
}
/*
*
* SOCKS5 UDP Request
@ -924,7 +928,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
}
// reconstruct the buffer
brealloc(buf, buf->len + addr_header_len, BUF_SIZE);
brealloc(buf, buf->len + addr_header_len, packet_size);
memmove(buf->array + addr_header_len, buf->array, buf->len);
memcpy(buf->array, addr_header, addr_header_len);
buf->len += addr_header_len;
@ -978,7 +982,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
addr_header_len += 2;
// reconstruct the buffer
brealloc(buf, buf->len + addr_header_len, BUF_SIZE);
brealloc(buf, buf->len + addr_header_len, packet_size);
memmove(buf->array + addr_header_len, buf->array, buf->len);
memcpy(buf->array, addr_header, addr_header_len);
buf->len += addr_header_len;
@ -1116,17 +1120,22 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
buf->array[0] |= ONETIMEAUTH_FLAG;
}
int err = ss_encrypt_all(buf, server_ctx->method, server_ctx->auth, BUF_SIZE);
int err = ss_encrypt_all(buf, server_ctx->method, server_ctx->auth, packet_size);
if (err) {
// drop the packet silently
goto CLEAN_UP;
}
if (buf->len > packet_size) {
LOGE("[udp] server_recv_sendto fragmentation");
goto CLEAN_UP;
}
int s = sendto(remote_ctx->fd, buf->array, buf->len, 0, remote_addr, remote_addr_len);
if (s == -1) {
ERROR("[udp] sendto_remote");
ERROR("[udp] server_recv_sendto");
}
#else
@ -1134,6 +1143,11 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
int cache_hit = 0;
int need_query = 0;
if (buf->len - addr_header_len > packet_size) {
LOGE("[udp] server_recv_sendto fragmentation");
goto CLEAN_UP;
}
if (remote_ctx != NULL) {
cache_hit = 1;
// detect destination mismatch
@ -1249,11 +1263,17 @@ int init_udprelay(const char *server_host, const char *server_port,
const ss_addr_t tunnel_addr,
#endif
#endif
int method, int auth, int timeout, const char *iface)
int mtu, int method, int auth, int timeout, const char *iface)
{
// Inilitialize ev loop
struct ev_loop *loop = EV_DEFAULT;
// Inilitialize MTU
if (mtu > 0) {
packet_size = mtu - 1 - 28 - 2 - 64;
buf_size = packet_size * 2;
}
// Inilitialize cache
struct cache *conn_cache;
cache_create(&conn_cache, MAX_UDP_CONN_NUM, free_cb);

2
src/udprelay.h

@ -39,7 +39,7 @@
#define MAX_UDP_PACKET_SIZE (65507)
#define MTU 1397 // 1492 - 1 - 28 - 2 - 64 = 1397, the default MTU for UDP relay
#define DEFAULT_PACKET_SIZE 1397 // 1492 - 1 - 28 - 2 - 64 = 1397, the default MTU for UDP relay
typedef struct server_ctx {
ev_io io;

2
src/utils.c

@ -309,6 +309,8 @@ void usage()
printf(
" [--executable <path>] Path to the executable of ss-server.\n");
#endif
printf(
" [--mtu <MTU>] MTU of your network interface.\n");
printf("\n");
printf(
" [-v] Verbose mode.\n");

Loading…
Cancel
Save