Browse Source

Refine SNI parser in ss-local

pull/1879/head
Max Lv 6 years ago
parent
commit
512891c66f
5 changed files with 35 additions and 29 deletions
  1. 12
      src/CMakeLists.txt
  2. 17
      src/Makefile.am
  3. 6
      src/common.h
  4. 27
      src/local.c
  5. 2
      src/redir.c

12
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}
)

17
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)

6
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 {

27
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);

2
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"

Loading…
Cancel
Save