diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3652f62..10e83b62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,10 @@ endif () set(SS_SNI_SOURCE http.c tls.c + ) + +set(SS_ACL_SOURCE + acl.c rule.c ) @@ -35,11 +39,12 @@ set(LIBSHADOWSOCKS_LIBEV_SOURCE ${SS_SHARED_SOURCES} udprelay.c cache.c - acl.c local.c ${SS_CRYPTO_SOURCE} ${SS_PLUGIN_SOURCE} - ${SS_SNI_SOURCE}) + ${SS_SNI_SOURCE} + ${SS_ACL_SOURCE} + ) set(SS_LOCAL_SOURCE ${LIBSHADOWSOCKS_LIBEV_SOURCE} @@ -59,12 +64,12 @@ set(SS_SERVER_SOURCE ${SS_SHARED_SOURCES} udprelay.c cache.c - acl.c resolv.c server.c ${SS_CRYPTO_SOURCE} ${SS_PLUGIN_SOURCE} ${SS_SNI_SOURCE} + ${SS_ACL_SOURCE} ) set(SS_MANAGER_SOURCE @@ -79,7 +84,6 @@ set(SS_REDIR_SOURCE redir.c ${SS_CRYPTO_SOURCE} ${SS_PLUGIN_SOURCE} - ${SS_SNI_SOURCE} ) diff --git a/src/Makefile.am b/src/Makefile.am index e3964c9d..dcc5fd9b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,8 +22,10 @@ SS_COMMON_LIBS += -lev -lsodium -lm bin_PROGRAMS = ss-local ss-tunnel ss-server ss-manager sni_src = http.c \ - tls.c \ - rule.c + tls.c + +acl_src = rule.c \ + acl.c crypto_src = crypto.c \ aead.c \ @@ -38,12 +40,12 @@ ss_local_SOURCES = utils.c \ json.c \ udprelay.c \ cache.c \ - acl.c \ netutils.c \ local.c \ $(crypto_src) \ $(plugin_src) \ - $(sni_src) + $(sni_src) \ + $(acl_src) ss_tunnel_SOURCES = utils.c \ jconf.c \ @@ -61,12 +63,12 @@ ss_server_SOURCES = utils.c \ json.c \ udprelay.c \ cache.c \ - acl.c \ resolv.c \ server.c \ $(crypto_src) \ $(plugin_src) \ - $(sni_src) + $(sni_src) \ + ${acl_src} ss_manager_SOURCES = utils.c \ jconf.c \ @@ -99,8 +101,7 @@ ss_redir_SOURCES = utils.c \ udprelay.c \ redir.c \ $(crypto_src) \ - $(plugin_src) \ - $(sni_src) + $(plugin_src) ss_redir_CFLAGS = $(AM_CFLAGS) -DMODULE_REDIR ss_redir_LDADD = $(SS_COMMON_LIBS) diff --git a/src/common.h b/src/common.h index 6b9d91be..fdf0ea60 100644 --- a/src/common.h +++ b/src/common.h @@ -53,10 +53,10 @@ int send_traffic_stat(uint64_t tx, uint64_t rx); #define STAGE_ERROR -1 /* Error detected */ #define STAGE_INIT 0 /* Initial stage */ #define STAGE_HANDSHAKE 1 /* Handshake with client */ -#define STAGE_PARSE 2 /* Parse the header */ +#define STAGE_PARSE 2 /* Parse the SOCKS5 header */ +#define STAGE_SNI 3 /* Parse HTTP/SNI header */ #define STAGE_RESOLVE 4 /* Resolve the hostname */ -#define STAGE_WAIT 5 /* Wait for more data */ -#define STAGE_STREAM 6 /* Stream between client and server */ +#define STAGE_STREAM 5 /* Stream between client and server */ /* Vals for long options */ enum { diff --git a/src/local.c b/src/local.c index 95ebd726..84a9ddbc 100644 --- a/src/local.c +++ b/src/local.c @@ -253,7 +253,6 @@ delayed_connect_cb(EV_P_ ev_timer *watcher, int revents) server_t *server = cork_container_of(watcher, server_t, delayed_connect_watcher); - server->stage = STAGE_WAIT; server_recv_cb(EV_A_ & server->recv_ctx->io, revents); } @@ -266,13 +265,15 @@ server_recv_cb(EV_P_ ev_io *w, int revents) buffer_t *buf; ssize_t r; + ev_timer_stop(EV_A_ & server->delayed_connect_watcher); + if (remote == NULL) { buf = server->buf; } else { buf = remote->buf; } - if (server->stage != STAGE_WAIT) { + if (revents != EV_TIMER) { r = recv(server->fd, buf->data + buf->len, BUF_SIZE - buf->len, 0); if (r == 0) { @@ -294,8 +295,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) } } buf->len += r; - } else { - server->stage = STAGE_STREAM; } while (1) { @@ -307,8 +306,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) return; } - ev_timer_stop(EV_A_ & server->delayed_connect_watcher); - // insert shadowsocks header if (!remote->direct) { #ifdef __ANDROID__ @@ -498,7 +495,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) buf->len = 0; return; - } else if (server->stage == STAGE_HANDSHAKE || server->stage == STAGE_PARSE) { + } else if (server->stage == STAGE_HANDSHAKE || + server->stage == STAGE_PARSE || + server->stage == STAGE_SNI) { struct socks5_request *request = (struct socks5_request *)buf->data; size_t request_len = sizeof(struct socks5_request); struct sockaddr_in sock_addr; @@ -568,9 +567,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) // Wait until client closes the connection return; } - } - server->stage = STAGE_PARSE; + server->stage = STAGE_PARSE; + } char host[257], ip[INET6_ADDRSTRLEN], port[16]; @@ -650,7 +649,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) else if (dst_port == tls_protocol->default_port) ret = tls_protocol->parse_packet(buf->data + 3 + abuf->len, buf->len - 3 - abuf->len, &hostname); - if (ret == -1 && buf->len < BUF_SIZE) { + if (ret == -1 && buf->len < BUF_SIZE && server->stage != STAGE_SNI) { + server->stage = STAGE_SNI; + ev_timer_start(EV_A_ & server->delayed_connect_watcher); return; } else if (ret > 0) { sni_detected = 1; @@ -683,13 +684,16 @@ server_recv_cb(EV_P_ ev_io *w, int revents) && !(vpn && strcmp(port, "53") == 0) #endif ) { - int host_match = acl_match_host(host); int bypass = 0; int resolved = 0; struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); int err; + int host_match = 0; + if (sni_detected || atyp == 3) + host_match = acl_match_host(host); + if (host_match > 0) bypass = 1; // bypass hostnames in black list else if (host_match < 0) @@ -786,7 +790,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) remote->server = server; if (buf->len > 0 || sni_detected) { - server->stage = STAGE_STREAM; continue; } else { ev_timer_start(EV_A_ & server->delayed_connect_watcher); diff --git a/src/redir.c b/src/redir.c index a0e38883..c721cc0e 100644 --- a/src/redir.c +++ b/src/redir.c @@ -47,8 +47,6 @@ #include "config.h" #endif -#include "http.h" -#include "tls.h" #include "plugin.h" #include "netutils.h" #include "utils.h"