Browse Source

Refine incomplete header handling

pull/773/head
Max Lv 8 years ago
parent
commit
46afbdcfd6
5 changed files with 130 additions and 45 deletions
  1. 26
      src/local.c
  2. 18
      src/redir.c
  3. 109
      src/server.c
  4. 1
      src/server.h
  5. 21
      src/tunnel.c

26
src/local.c

@ -78,7 +78,7 @@
#define BUF_SIZE 2048 #define BUF_SIZE 2048
#endif #endif
int verbose = 0;
int verbose = 0;
int keep_resolving = 1; int keep_resolving = 1;
#ifdef ANDROID #ifdef ANDROID
@ -267,7 +267,8 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
int not_protect = 0; int not_protect = 0;
if (remote->addr.ss_family == AF_INET) { if (remote->addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&remote->addr; struct sockaddr_in *s = (struct sockaddr_in *)&remote->addr;
if (s->sin_addr.s_addr == inet_addr("127.0.0.1")) not_protect = 1;
if (s->sin_addr.s_addr == inet_addr("127.0.0.1"))
not_protect = 1;
} }
if (!not_protect) { if (!not_protect) {
if (protect_socket(remote->fd) == -1) { if (protect_socket(remote->fd) == -1) {
@ -294,7 +295,8 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
} }
if (r == 0) { if (r == 0) {
if (verbose) LOGI("connected immediately");
if (verbose)
LOGI("connected immediately");
remote_send_cb(EV_A_ & remote->send_ctx->io, 0); remote_send_cb(EV_A_ & remote->send_ctx->io, 0);
} else { } else {
// wait on remote connected event // wait on remote connected event
@ -302,7 +304,6 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
ev_io_start(EV_A_ & remote->send_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io);
ev_timer_start(EV_A_ & remote->send_ctx->watcher); ev_timer_start(EV_A_ & remote->send_ctx->watcher);
} }
} else { } else {
#ifdef TCP_FASTOPEN #ifdef TCP_FASTOPEN
#ifdef __APPLE__ #ifdef __APPLE__
@ -986,7 +987,8 @@ void accept_cb(EV_P_ ev_io *w, int revents)
ev_io_start(EV_A_ & server->recv_ctx->io); ev_io_start(EV_A_ & server->recv_ctx->io);
} }
void resolve_int_cb(int dummy) {
void resolve_int_cb(int dummy)
{
keep_resolving = 0; keep_resolving = 0;
} }
@ -1015,11 +1017,11 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
{ "fast-open", no_argument , 0, 0 },
{ "acl" , required_argument, 0, 0 },
{ "mtu" , required_argument, 0, 0 },
{ "mptcp" , no_argument , 0, 0 },
{ "help" , no_argument , 0, 0 },
{ "fast-open", no_argument, 0, 0 },
{ "acl", required_argument, 0, 0 },
{ "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
@ -1228,7 +1230,7 @@ int main(int argc, char **argv)
// ignore SIGPIPE // ignore SIGPIPE
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN); signal(SIGABRT, SIG_IGN);
signal(SIGINT, resolve_int_cb);
signal(SIGINT, resolve_int_cb);
signal(SIGTERM, resolve_int_cb); signal(SIGTERM, resolve_int_cb);
#endif #endif
@ -1319,7 +1321,6 @@ int main(int argc, char **argv)
ss_free(listen_ctx.remote_addr); ss_free(listen_ctx.remote_addr);
} }
if (mode != TCP_ONLY) { if (mode != TCP_ONLY) {
free_udprelay(); free_udprelay();
} }
@ -1416,7 +1417,6 @@ int start_ss_local_server(profile_t profile)
listen_ctx.mptcp = mptcp; listen_ctx.mptcp = mptcp;
if (mode != UDP_ONLY) { if (mode != UDP_ONLY) {
// Setup socket // Setup socket
int listenfd; int listenfd;
listenfd = create_and_bind(local_addr, local_port_str); listenfd = create_and_bind(local_addr, local_port_str);

18
src/redir.c

@ -81,7 +81,7 @@ static void close_and_free_remote(EV_P_ remote_t *remote);
static void free_server(server_t *server); static void free_server(server_t *server);
static void close_and_free_server(EV_P_ server_t *server); static void close_and_free_server(EV_P_ server_t *server);
int verbose = 0;
int verbose = 0;
int keep_resolving = 1; int keep_resolving = 1;
static int mode = TCP_ONLY; static int mode = TCP_ONLY;
@ -669,7 +669,8 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
} }
if (r == 0) { if (r == 0) {
if (verbose) LOGI("connected immediately");
if (verbose)
LOGI("connected immediately");
remote_send_cb(EV_A_ & remote->send_ctx->io, 0); remote_send_cb(EV_A_ & remote->send_ctx->io, 0);
} else { } else {
// listen to remote connected event // listen to remote connected event
@ -680,7 +681,8 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
ev_io_start(EV_A_ & server->recv_ctx->io); ev_io_start(EV_A_ & server->recv_ctx->io);
} }
void signal_cb(int dummy) {
void signal_cb(int dummy)
{
keep_resolving = 0; keep_resolving = 0;
exit(-1); exit(-1);
} }
@ -708,10 +710,10 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
{ "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument , 0, 0 },
{ "help", no_argument , 0, 0 },
{ 0, 0 , 0, 0 }
{ "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
}; };
opterr = 0; opterr = 0;
@ -880,7 +882,7 @@ int main(int argc, char **argv)
// ignore SIGPIPE // ignore SIGPIPE
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN); signal(SIGABRT, SIG_IGN);
signal(SIGINT, signal_cb);
signal(SIGINT, signal_cb);
signal(SIGTERM, signal_cb); signal(SIGTERM, signal_cb);
// Setup keys // Setup keys

109
src/server.c

@ -106,6 +106,7 @@ static void server_resolve_cb(struct sockaddr *addr, void *data);
static void query_free_cb(void *data); static void query_free_cb(void *data);
static size_t parse_header_len(const char atyp, const char *data, size_t offset); static size_t parse_header_len(const char atyp, const char *data, size_t offset);
static int is_header_complete(const buffer_t *buf);
int verbose = 0; int verbose = 0;
@ -235,6 +236,42 @@ static size_t parse_header_len(const char atyp, const char *data, size_t offset)
return len; return len;
} }
static int is_header_complete(const buffer_t *buf)
{
size_t header_len = 0;
size_t buf_len = buf->len;
char atyp = buf->array[header_len];
// 1 byte for atyp
header_len++;
if ((atyp & ADDRTYPE_MASK) == 1) {
// IP V4
header_len += sizeof(struct in_addr);
} else if ((atyp & ADDRTYPE_MASK) == 3) {
// Domain name
// domain len + len of domain
if (buf_len < header_len + 1)
return 0;
uint8_t name_len = *(uint8_t *)(buf->array + header_len);
header_len += name_len + 1;
} else if ((atyp & ADDRTYPE_MASK) == 4) {
// IP V6
header_len += sizeof(struct in6_addr);
}
// len of port
header_len += 2;
// size of ONETIMEAUTH_BYTES
if (auth || (atyp & ONETIMEAUTH_FLAG)) {
header_len += ONETIMEAUTH_BYTES;
}
return buf_len >= header_len;
}
static char *get_peer_name(int fd) static char *get_peer_name(int fd)
{ {
static char peer_name[INET6_ADDRSTRLEN] = { 0 }; static char peer_name[INET6_ADDRSTRLEN] = { 0 };
@ -513,7 +550,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
ev_timer_again(EV_A_ & server->recv_ctx->watcher); ev_timer_again(EV_A_ & server->recv_ctx->watcher);
if (server->stage != 0) {
if (server->stage > 2) {
remote = server->remote; remote = server->remote;
buf = remote->buf; buf = remote->buf;
len = 0; len = 0;
@ -544,16 +581,16 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
tx += r; tx += r;
// handle incomplete header
// handle incomplete header part 1
if (server->stage == 0) { if (server->stage == 0) {
buf->len += r; buf->len += r;
if (buf->len <= enc_get_iv_len()) {
if (buf->len <= enc_get_iv_len() + 1) {
// wait for more // wait for more
if (verbose) { if (verbose) {
#ifdef __MINGW32__ #ifdef __MINGW32__
LOGI("incomplete header: %u", r);
LOGI("incomplete IV: %u", r);
#else #else
LOGI("incomplete header: %zu", r);
LOGI("incomplete IV: %zu", r);
#endif #endif
} }
return; return;
@ -572,6 +609,42 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
return; return;
} }
// handle incomplete header part 2
if (server->stage == 0) {
if (is_header_complete(server->buf)) {
bfree(server->header_buf);
ss_free(server->header_buf);
server->stage = 2;
} else {
server->stage = 1;
}
}
if (server->stage == 1) {
size_t header_len = server->header_buf->len;
brealloc(server->header_buf, server->buf->len + header_len, BUF_SIZE);
memcpy(server->header_buf->array + header_len,
server->buf->array, server->buf->len);
server->header_buf->len = server->buf->len + header_len;
if (is_header_complete(server->header_buf)) {
brealloc(server->buf, server->header_buf->len, BUF_SIZE);
memcpy(server->buf->array, server->header_buf->array, server->header_buf->len);
server->buf->len = server->header_buf->len;
bfree(server->header_buf);
ss_free(server->header_buf);
server->stage = 2;
} else {
#ifdef __MINGW32__
LOGI("incomplete header: %u", server->header_buf->len);
#else
LOGI("incomplete header: %zu", server->header_buf->len);
#endif
server->buf->len = 0;
server->buf->idx = 0;
return;
}
}
// handshake and transmit data // handshake and transmit data
if (server->stage == 5) { if (server->stage == 5) {
if (server->auth && !ss_check_hash(remote->buf, server->chunk, server->d_ctx, BUF_SIZE)) { if (server->auth && !ss_check_hash(remote->buf, server->chunk, server->d_ctx, BUF_SIZE)) {
@ -600,7 +673,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
ev_io_start(EV_A_ & remote->send_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io);
} }
return; return;
} else if (server->stage == 0) {
} else if (server->stage == 2) {
/* /*
* Shadowsocks TCP Relay Header: * Shadowsocks TCP Relay Header:
* *
@ -793,7 +866,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
} }
if (!need_query) { if (!need_query) {
int connected = 0;
int connected = 0;
remote_t *remote = connect_to_remote(&info, server, &connected); remote_t *remote = connect_to_remote(&info, server, &connected);
if (remote == NULL) { if (remote == NULL) {
@ -830,7 +903,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
server->stage = 4; server->stage = 4;
server->query = resolv_query(host, server_resolve_cb, server->query = resolv_query(host, server_resolve_cb,
query_free_cb, query, port);
query_free_cb, query, port);
ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_stop(EV_A_ & server_recv_ctx->io);
} }
@ -947,7 +1020,7 @@ static void server_resolve_cb(struct sockaddr *addr, void *data)
info.ai_addrlen = sizeof(struct sockaddr_in6); info.ai_addrlen = sizeof(struct sockaddr_in6);
} }
int connected = 0;
int connected = 0;
remote_t *remote = connect_to_remote(&info, server, &connected); remote_t *remote = connect_to_remote(&info, server, &connected);
if (remote == NULL) { if (remote == NULL) {
@ -1206,6 +1279,7 @@ static server_t *new_server(int fd, listen_ctx_t *listener)
server->recv_ctx = ss_malloc(sizeof(server_ctx_t)); server->recv_ctx = ss_malloc(sizeof(server_ctx_t));
server->send_ctx = ss_malloc(sizeof(server_ctx_t)); server->send_ctx = ss_malloc(sizeof(server_ctx_t));
server->buf = ss_malloc(sizeof(buffer_t)); server->buf = ss_malloc(sizeof(buffer_t));
server->header_buf = ss_malloc(sizeof(buffer_t));
server->fd = fd; server->fd = fd;
server->recv_ctx->server = server; server->recv_ctx->server = server;
server->recv_ctx->connected = 0; server->recv_ctx->connected = 0;
@ -1232,6 +1306,7 @@ static server_t *new_server(int fd, listen_ctx_t *listener)
min(MAX_CONNECT_TIMEOUT, listener->timeout), listener->timeout); min(MAX_CONNECT_TIMEOUT, listener->timeout), listener->timeout);
balloc(server->buf, BUF_SIZE); balloc(server->buf, BUF_SIZE);
balloc(server->header_buf, BUF_SIZE);
server->chunk = (chunk_t *)malloc(sizeof(chunk_t)); server->chunk = (chunk_t *)malloc(sizeof(chunk_t));
memset(server->chunk, 0, sizeof(chunk_t)); memset(server->chunk, 0, sizeof(chunk_t));
@ -1269,6 +1344,10 @@ static void free_server(server_t *server)
bfree(server->buf); bfree(server->buf);
ss_free(server->buf); ss_free(server->buf);
} }
if (server->header_buf != NULL) {
bfree(server->header_buf);
ss_free(server->header_buf);
}
ss_free(server->recv_ctx); ss_free(server->recv_ctx);
ss_free(server->send_ctx); ss_free(server->send_ctx);
@ -1363,12 +1442,12 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
{ "fast-open" , no_argument , 0, 0 },
{ "acl" , required_argument, 0, 0 },
{ "fast-open", no_argument, 0, 0 },
{ "acl", required_argument, 0, 0 },
{ "manager-address", required_argument, 0, 0 }, { "manager-address", required_argument, 0, 0 },
{ "mtu" , required_argument, 0, 0 },
{ "mptcp" , no_argument , 0, 0 },
{ "help" , no_argument , 0, 0 },
{ "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
@ -1659,7 +1738,7 @@ int main(int argc, char **argv)
// Setup UDP // Setup UDP
if (mode != TCP_ONLY) { if (mode != TCP_ONLY) {
init_udprelay(server_host[index], server_port, mtu, m, init_udprelay(server_host[index], server_port, mtu, m,
auth, atoi(timeout), iface);
auth, atoi(timeout), iface);
} }
LOGI("listening at %s:%s", host ? host : "*", server_port); LOGI("listening at %s:%s", host ? host : "*", server_port);

1
src/server.h

@ -53,6 +53,7 @@ typedef struct server {
int fd; int fd;
int stage; int stage;
buffer_t *buf; buffer_t *buf;
buffer_t *header_buf;
int auth; int auth;
struct chunk *chunk; struct chunk *chunk;

21
src/tunnel.c

@ -90,7 +90,7 @@ int vpn = 0;
char *prefix; char *prefix;
#endif #endif
int verbose = 0;
int verbose = 0;
int keep_resolving = 1; int keep_resolving = 1;
static int mode = TCP_ONLY; static int mode = TCP_ONLY;
@ -636,7 +636,8 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
int not_protect = 0; int not_protect = 0;
if (remote_addr->sa_family == AF_INET) { if (remote_addr->sa_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)remote_addr; struct sockaddr_in *s = (struct sockaddr_in *)remote_addr;
if (s->sin_addr.s_addr == inet_addr("127.0.0.1")) not_protect = 1;
if (s->sin_addr.s_addr == inet_addr("127.0.0.1"))
not_protect = 1;
} }
if (!not_protect) { if (!not_protect) {
if (protect_socket(remotefd) == -1) { if (protect_socket(remotefd) == -1) {
@ -685,7 +686,8 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
} }
if (r == 0) { if (r == 0) {
if (verbose) LOGI("connected immediately");
if (verbose)
LOGI("connected immediately");
remote_send_cb(EV_A_ & remote->send_ctx->io, 0); remote_send_cb(EV_A_ & remote->send_ctx->io, 0);
} else { } else {
// listen to remote connected event // listen to remote connected event
@ -694,7 +696,8 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
} }
} }
void signal_cb(int dummy) {
void signal_cb(int dummy)
{
keep_resolving = 0; keep_resolving = 0;
exit(-1); exit(-1);
} }
@ -726,10 +729,10 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
{ "mtu", required_argument, 0, 0 },
{ "mptcp",no_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
{ "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
}; };
opterr = 0; opterr = 0;
@ -935,7 +938,7 @@ int main(int argc, char **argv)
// ignore SIGPIPE // ignore SIGPIPE
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN); signal(SIGABRT, SIG_IGN);
signal(SIGINT, signal_cb);
signal(SIGINT, signal_cb);
signal(SIGTERM, signal_cb); signal(SIGTERM, signal_cb);
#endif #endif

Loading…
Cancel
Save