static void remote_send_cb(EV_P_ ev_io *w, int revents) { remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w; remote_t *remote = remote_send_ctx->remote; server_t *server = remote->server; if (!remote_send_ctx->connected) { struct sockaddr_storage addr; socklen_t len = sizeof addr; int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len); if (r == 0) { remote_send_ctx->connected = 1; ev_io_stop(EV_A_ & remote_send_ctx->io); ev_io_stop(EV_A_ & server->recv_ctx->io); ev_timer_stop(EV_A_ & remote_send_ctx->watcher); ev_timer_start(EV_A_ & remote->recv_ctx->watcher); // send destaddr buffer_t ss_addr_to_send; buffer_t *abuf = &ss_addr_to_send; balloc(abuf, BUF_SIZE); if (server->hostname_len > 0) { // HTTP/SNI uint16_t port; if (AF_INET6 == server->destaddr.ss_family) { // IPv6 port = (((struct sockaddr_in6 *)&(server->destaddr))->sin6_port); } else { // IPv4 port = (((struct sockaddr_in *)&(server->destaddr))->sin_port); } abuf->array[abuf->len++] = 3; // Type 3 is hostname abuf->array[abuf->len++] = server->hostname_len; memcpy(abuf->array + abuf->len, server->hostname, server->hostname_len); abuf->len += server->hostname_len; memcpy(abuf->array + abuf->len, &port, 2); } else if (AF_INET6 == server->destaddr.ss_family) { // IPv6 abuf->array[abuf->len++] = 4; // Type 4 is IPv6 address size_t in6_addr_len = sizeof(struct in6_addr); memcpy(abuf->array + abuf->len, &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_addr), in6_addr_len); abuf->len += in6_addr_len; memcpy(abuf->array + abuf->len, &(((struct sockaddr_in6 *)&(server->destaddr))->sin6_port), 2); } else { // IPv4 abuf->array[abuf->len++] = 1; // Type 1 is IPv4 address size_t in_addr_len = sizeof(struct in_addr); memcpy(abuf->array + abuf->len, &((struct sockaddr_in *)&(server->destaddr))->sin_addr, in_addr_len); abuf->len += in_addr_len; memcpy(abuf->array + abuf->len, &((struct sockaddr_in *)&(server->destaddr))->sin_port, 2); } abuf->len += 2; if (auth) { abuf->array[0] |= ONETIMEAUTH_FLAG; ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE); } brealloc(remote->buf, remote->buf->len + abuf->len, BUF_SIZE); memmove(remote->buf->array + abuf->len, remote->buf->array, remote->buf->len); memcpy(remote->buf->array, abuf->array, abuf->len); remote->buf->len += abuf->len; bfree(abuf); int err = ss_encrypt(remote->buf, server->e_ctx, BUF_SIZE); if (err) { LOGE("invalid password or cipher"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } ev_io_start(EV_A_ & remote->recv_ctx->io); } else { ERROR("getpeername"); // not connected close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } if (remote->buf->len == 0) { // close and free close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else { // has data to send ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx, remote->buf->len, 0); if (s == -1) { if (errno != EAGAIN && errno != EWOULDBLOCK) { ERROR("send"); // close and free close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); } return; } else if (s < remote->buf->len) { // partly sent, move memory, wait for the next time to send remote->buf->len -= s; remote->buf->idx += s; return; } else { // all sent out, wait for reading remote->buf->len = 0; remote->buf->idx = 0; ev_io_stop(EV_A_ & remote_send_ctx->io); ev_io_start(EV_A_ & server->recv_ctx->io); } } }
int ss_encrypt_all(buffer_t *plain, int method, int auth, size_t capacity) { if (method > TABLE) { cipher_ctx_t evp; cipher_context_init(&evp, method, 1); size_t iv_len = enc_iv_len; int err = 1; static buffer_t tmp = { 0, 0, 0, NULL }; brealloc(&tmp, iv_len + plain->len, capacity); buffer_t *cipher = &tmp; cipher->len = plain->len; uint8_t iv[MAX_IV_LENGTH]; rand_bytes(iv, iv_len); cipher_context_set_iv(&evp, iv, iv_len, 1); memcpy(cipher->array, iv, iv_len); if (auth) { ss_onetimeauth(plain, iv, capacity); cipher->len = plain->len; } if (method >= SALSA20) { crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len), (const uint8_t *)plain->array, (uint64_t)(plain->len), (const uint8_t *)iv, 0, enc_key, method); } else { err = cipher_context_update(&evp, (uint8_t *)(cipher->array + iv_len), &cipher->len, (const uint8_t *)plain->array, plain->len); } if (!err) { bfree(plain); cipher_context_release(&evp); return -1; } #ifdef DEBUG dump("PLAIN", plain->array, plain->len); dump("CIPHER", cipher->array + iv_len, cipher->len); #endif cipher_context_release(&evp); brealloc(plain, iv_len + cipher->len, capacity); memcpy(plain->array, cipher->array, iv_len + cipher->len); plain->len = iv_len + cipher->len; return 0; } else { char *begin = plain->array; char *ptr = plain->array; while (ptr < begin + plain->len) { *ptr = (char)enc_table[(uint8_t)*ptr]; ptr++; } return 0; } }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { struct server_ctx *server_recv_ctx = (struct server_ctx *)w; struct server *server = server_recv_ctx->server; struct remote *remote = server->remote; char *buf; if (remote == NULL) { buf = server->buf; } else { buf = remote->buf; } ssize_t r; r = recv(server->fd, buf, BUF_SIZE, 0); if (r == 0) { // connection closed close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data // continue to wait for recv return; } else { ERROR("server_recv_cb_recv"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } while (1) { // local socks5 server if (server->stage == 5) { if (remote == NULL) { LOGE("invalid remote"); close_and_free_server(EV_A_ server); return; } if (!remote->direct && remote->send_ctx->connected && auth) { remote->buf = ss_gen_hash(remote->buf, &r, &remote->counter, server->e_ctx, BUF_SIZE); } // insert shadowsocks header if (!remote->direct) { remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx); if (remote->buf == NULL) { LOGE("invalid password or cipher"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } if (!remote->send_ctx->connected) { #ifdef ANDROID if (vpn) { if (protect_socket(remote->fd) == -1) { ERROR("protect_socket"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } #endif remote->buf_idx = 0; remote->buf_len = r; if (!fast_open || remote->direct) { // connecting, wait until connected connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len); // wait on remote connected event ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); } else { #ifdef TCP_FASTOPEN int s = sendto(remote->fd, remote->buf, r, MSG_FASTOPEN, (struct sockaddr *)&(remote->addr), remote->addr_len); if (s == -1) { if (errno == EINPROGRESS) { // in progress, wait until connected remote->buf_idx = 0; remote->buf_len = r; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("sendto"); if (errno == ENOTCONN) { LOGE( "fast open is not supported on this platform"); // just turn it off fast_open = 0; } close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s < r) { remote->buf_len = r - s; remote->buf_idx = s; } // Just connected remote->send_ctx->connected = 1; ev_timer_stop(EV_A_ & remote->send_ctx->watcher); ev_io_start(EV_A_ & remote->recv_ctx->io); #else // if TCP_FASTOPEN is not defined, fast_open will always be 0 LOGE("can't come here"); exit(1); #endif } } else { int s = send(remote->fd, remote->buf, r, 0); if (s == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data, wait for send remote->buf_idx = 0; remote->buf_len = r; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("server_recv_cb_send"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s < r) { remote->buf_len = r - s; remote->buf_idx = s; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } } // all processed return; } else if (server->stage == 0) { struct method_select_response response; response.ver = SVERSION; response.method = 0; char *send_buf = (char *)&response; send(server->fd, send_buf, sizeof(response), 0); server->stage = 1; return; } else if (server->stage == 1) { struct socks5_request *request = (struct socks5_request *)buf; struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); int udp_assc = 0; if (mode != TCP_ONLY && request->cmd == 3) { udp_assc = 1; socklen_t addr_len = sizeof(sock_addr); getsockname(server->fd, (struct sockaddr *)&sock_addr, &addr_len); if (verbose) { LOGI("udp assc request accepted"); } } else if (request->cmd != 1) { LOGE("unsupported cmd: %d", request->cmd); struct socks5_response response; response.ver = SVERSION; response.rep = CMD_NOT_SUPPORTED; response.rsv = 0; response.atyp = 1; char *send_buf = (char *)&response; send(server->fd, send_buf, 4, 0); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else { char host[256], port[16]; char ss_addr_to_send[320]; ssize_t addr_len = 0; ss_addr_to_send[addr_len++] = request->atyp; // get remote addr and port if (request->atyp == 1) { // IP V4 size_t in_addr_len = sizeof(struct in_addr); memcpy(ss_addr_to_send + addr_len, buf + 4, in_addr_len + 2); addr_len += in_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf + 4 + in_addr_len)); dns_ntop(AF_INET, (const void *)(buf + 4), host, INET_ADDRSTRLEN); sprintf(port, "%d", p); } } else if (request->atyp == 3) { // Domain name uint8_t name_len = *(uint8_t *)(buf + 4); ss_addr_to_send[addr_len++] = name_len; memcpy(ss_addr_to_send + addr_len, buf + 4 + 1, name_len + 2); addr_len += name_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf + 4 + 1 + name_len)); memcpy(host, buf + 4 + 1, name_len); host[name_len] = '\0'; sprintf(port, "%d", p); } } else if (request->atyp == 4) { // IP V6 size_t in6_addr_len = sizeof(struct in6_addr); memcpy(ss_addr_to_send + addr_len, buf + 4, in6_addr_len + 2); addr_len += in6_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf + 4 + in6_addr_len)); dns_ntop(AF_INET6, (const void *)(buf + 4), host, INET6_ADDRSTRLEN); sprintf(port, "%d", p); } } else { LOGE("unsupported addrtype: %d", request->atyp); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } server->stage = 5; r -= (3 + addr_len); buf += (3 + addr_len); if (verbose) { LOGI("connect to %s:%s", host, port); } if ((acl && (request->atyp == 1 || request->atyp == 4) && acl_contains_ip(host))) { if (verbose) { LOGI("bypass %s:%s", host, port); } struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); if (get_sockaddr(host, port, &storage, 0) != -1) { remote = create_remote(server->listener, (struct sockaddr *)&storage); remote->direct = 1; } } else { remote = create_remote(server->listener, NULL); } if (remote == NULL) { LOGE("invalid remote addr"); close_and_free_server(EV_A_ server); return; } if (!remote->direct) { if (auth) { ss_addr_to_send[0] |= ONETIMEAUTH_FLAG; ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx); addr_len += ONETIMEAUTH_BYTES; } memcpy(remote->buf, ss_addr_to_send, addr_len); if (r > 0) { if (auth) { buf = ss_gen_hash(buf, &r, &remote->counter, server->e_ctx, BUF_SIZE); } memcpy(remote->buf + addr_len, buf, r); } r += addr_len; } else { if (r > 0) { memcpy(remote->buf, buf, r); } } server->remote = remote; remote->server = server; } // Fake reply struct socks5_response response; response.ver = SVERSION; response.rep = 0; response.rsv = 0; response.atyp = 1; memcpy(server->buf, &response, sizeof(struct socks5_response)); memcpy(server->buf + sizeof(struct socks5_response), &sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); memcpy(server->buf + sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr), &sock_addr.sin_port, sizeof(sock_addr.sin_port)); int reply_size = sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); int s = send(server->fd, server->buf, reply_size, 0); if (s < reply_size) { LOGE("failed to send fake reply"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } if (udp_assc) { close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } } }
static void remote_send_cb(EV_P_ ev_io *w, int revents) { struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w; struct remote *remote = remote_send_ctx->remote; struct server *server = remote->server; if (!remote_send_ctx->connected) { struct sockaddr_storage addr; socklen_t len = sizeof addr; int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len); if (r == 0) { remote_send_ctx->connected = 1; ev_io_stop(EV_A_ & remote_send_ctx->io); ev_timer_stop(EV_A_ & remote_send_ctx->watcher); char *ss_addr_to_send = malloc(BUF_SIZE); ssize_t addr_len = 0; ss_addr_t *sa = &server->destaddr; struct cork_ip ip; if (cork_ip_init(&ip, sa->host) != -1) { if (ip.version == 4) { // send as IPv4 struct in_addr host; int host_len = sizeof(struct in_addr); if (dns_pton(AF_INET, sa->host, &host) == -1) { FATAL("IP parser error"); } ss_addr_to_send[addr_len++] = 1; memcpy(ss_addr_to_send + addr_len, &host, host_len); addr_len += host_len; } else if (ip.version == 6) { // send as IPv6 struct in6_addr host; int host_len = sizeof(struct in6_addr); if (dns_pton(AF_INET6, sa->host, &host) == -1) { FATAL("IP parser error"); } ss_addr_to_send[addr_len++] = 4; memcpy(ss_addr_to_send + addr_len, &host, host_len); addr_len += host_len; } else { FATAL("IP parser error"); } } else { // send as domain int host_len = strlen(sa->host); ss_addr_to_send[addr_len++] = 3; ss_addr_to_send[addr_len++] = host_len; memcpy(ss_addr_to_send + addr_len, sa->host, host_len); addr_len += host_len; } uint16_t port = htons(atoi(sa->port)); memcpy(ss_addr_to_send + addr_len, &port, 2); addr_len += 2; if (auth) { ss_addr_to_send[0] |= ONETIMEAUTH_FLAG; ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx->evp.iv); addr_len += ONETIMEAUTH_BYTES; } ss_addr_to_send = ss_encrypt(BUF_SIZE, ss_addr_to_send, &addr_len, server->e_ctx); if (ss_addr_to_send == NULL) { LOGE("invalid password or cipher"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } int s = send(remote->fd, ss_addr_to_send, addr_len, 0); free(ss_addr_to_send); if (s < addr_len) { LOGE("failed to send addr"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } ev_io_start(EV_A_ & remote->recv_ctx->io); ev_io_start(EV_A_ & server->recv_ctx->io); return; } else { ERROR("getpeername"); // not connected close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else { if (remote->buf_len == 0) { // close and free close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else { // has data to send ssize_t s = send(remote->fd, remote->buf + remote->buf_idx, remote->buf_len, 0); if (s < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { ERROR("send"); // close and free close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); } return; } else if (s < remote->buf_len) { // partly sent, move memory, wait for the next time to send remote->buf_len -= s; remote->buf_idx += s; return; } else { // all sent out, wait for reading remote->buf_len = 0; remote->buf_idx = 0; ev_io_stop(EV_A_ & remote_send_ctx->io); ev_io_start(EV_A_ & server->recv_ctx->io); } } } }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { server_ctx_t *server_recv_ctx = (server_ctx_t *)w; server_t *server = server_recv_ctx->server; remote_t *remote = server->remote; buffer_t *buf; if (remote == NULL) { buf = server->buf; } else { buf = remote->buf; } ssize_t r; r = recv(server->fd, buf->array, BUF_SIZE, 0); if (r == 0) { // connection closed close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data // continue to wait for recv return; } else { ERROR("server_recv_cb_recv"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } buf->len = r; while (1) { // local socks5 server if (server->stage == 5) { if (remote == NULL) { LOGE("invalid remote"); close_and_free_server(EV_A_ server); return; } if (!remote->direct && remote->send_ctx->connected && auth) { ss_gen_hash(remote->buf, &remote->counter, server->e_ctx); } // insert shadowsocks header if (!remote->direct) { // SSR beg if (server->protocol_plugin) { obfs_class *protocol_plugin = server->protocol_plugin; if (protocol_plugin->client_pre_encrypt) { remote->buf->len = protocol_plugin->client_pre_encrypt(server->protocol, &remote->buf->array, remote->buf->len, &remote->buf->capacity); } } int err = ss_encrypt(remote->buf, server->e_ctx); if (err) { LOGE("server invalid password or cipher"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } if (server->obfs_plugin) { obfs_class *obfs_plugin = server->obfs_plugin; if (obfs_plugin->client_encode) { remote->buf->len = obfs_plugin->client_encode(server->obfs, &remote->buf->array, remote->buf->len, &remote->buf->capacity); } } // SSR end #ifdef ANDROID tx += r; #endif } if (!remote->send_ctx->connected) { #ifdef ANDROID if (vpn) { if (protect_socket(remote->fd) == -1) { ERROR("protect_socket"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } #endif remote->buf->idx = 0; if (!fast_open || remote->direct) { // connecting, wait until connected connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len); // wait on remote connected event ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); } else { #ifdef TCP_FASTOPEN #ifdef __APPLE__ ((struct sockaddr_in*)&(remote->addr))->sin_len = sizeof(struct sockaddr_in); sa_endpoints_t endpoints; bzero((char*)&endpoints, sizeof(endpoints)); endpoints.sae_dstaddr = (struct sockaddr*)&(remote->addr); endpoints.sae_dstaddrlen = remote->addr_len; int s = connectx(remote->fd, &endpoints, SAE_ASSOCID_ANY, CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT, NULL, 0, NULL, NULL); if (s == 0) { s = send(remote->fd, remote->buf->array, remote->buf->len, 0); } #else int s = sendto(remote->fd, remote->buf->array, remote->buf->len, MSG_FASTOPEN, (struct sockaddr *)&(remote->addr), remote->addr_len); #endif if (s == -1) { if (errno == EINPROGRESS) { // in progress, wait until connected remote->buf->idx = 0; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("sendto"); if (errno == ENOTCONN) { LOGE( "fast open is not supported on this platform"); // just turn it off fast_open = 0; } close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s <= remote->buf->len) { remote->buf->len -= s; remote->buf->idx = s; } // Just connected remote->send_ctx->connected = 1; ev_timer_stop(EV_A_ & remote->send_ctx->watcher); ev_io_start(EV_A_ & remote->recv_ctx->io); #else // if TCP_FASTOPEN is not defined, fast_open will always be 0 LOGE("can't come here"); exit(1); #endif } } else { int s = send(remote->fd, remote->buf->array, remote->buf->len, 0); if (s == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data, wait for send remote->buf->idx = 0; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("server_recv_cb_send"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s < remote->buf->len) { remote->buf->len -= s; remote->buf->idx = s; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } } // all processed return; } else if (server->stage == 0) { struct method_select_response response; response.ver = SVERSION; response.method = 0; char *send_buf = (char *)&response; send(server->fd, send_buf, sizeof(response), 0); server->stage = 1; int off = (buf->array[1] & 0xff) + 2; if (buf->array[0] == 0x05 && off < buf->len) { memmove(buf->array, buf->array + off, buf->len - off); buf->len -= off; continue; } return; } else if (server->stage == 1) { struct socks5_request *request = (struct socks5_request *)buf->array; struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); int udp_assc = 0; if (mode != TCP_ONLY && request->cmd == 3) { udp_assc = 1; socklen_t addr_len = sizeof(sock_addr); getsockname(server->fd, (struct sockaddr *)&sock_addr, &addr_len); if (verbose) { LOGI("udp assc request accepted"); } } else if (request->cmd != 1) { LOGE("unsupported cmd: %d", request->cmd); struct socks5_response response; response.ver = SVERSION; response.rep = CMD_NOT_SUPPORTED; response.rsv = 0; response.atyp = 1; char *send_buf = (char *)&response; send(server->fd, send_buf, 4, 0); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else { char host[256], port[16]; buffer_t ss_addr_to_send; buffer_t *abuf = &ss_addr_to_send; balloc(abuf, BUF_SIZE); abuf->array[abuf->len++] = request->atyp; // get remote addr and port if (request->atyp == 1) { // IP V4 size_t in_addr_len = sizeof(struct in_addr); memcpy(abuf->array + abuf->len, buf->array + 4, in_addr_len + 2); abuf->len += in_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len)); dns_ntop(AF_INET, (const void *)(buf->array + 4), host, INET_ADDRSTRLEN); sprintf(port, "%d", p); } } else if (request->atyp == 3) { // Domain name uint8_t name_len = *(uint8_t *)(buf->array + 4); abuf->array[abuf->len++] = name_len; memcpy(abuf->array + abuf->len, buf->array + 4 + 1, name_len + 2); abuf->len += name_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + 1 + name_len)); memcpy(host, buf->array + 4 + 1, name_len); host[name_len] = '\0'; sprintf(port, "%d", p); } } else if (request->atyp == 4) { // IP V6 size_t in6_addr_len = sizeof(struct in6_addr); memcpy(abuf->array + abuf->len, buf->array + 4, in6_addr_len + 2); abuf->len += in6_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in6_addr_len)); dns_ntop(AF_INET6, (const void *)(buf->array + 4), host, INET6_ADDRSTRLEN); sprintf(port, "%d", p); } } else { bfree(abuf); LOGE("unsupported addrtype: %d", request->atyp); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } server->stage = 5; buf->len -= (3 + abuf->len); if (buf->len > 0) { memmove(buf->array, buf->array + 3 + abuf->len, buf->len); } if (verbose) { LOGI("connect to %s:%s", host, port); } if ((acl && (request->atyp == 1 || request->atyp == 4) && acl_match_ip(host))) { if (verbose) { LOGI("bypass %s:%s", host, port); } struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); if (get_sockaddr(host, port, &storage, 0) != -1) { remote = create_remote(server->listener, (struct sockaddr *)&storage); remote->direct = 1; } } else { remote = create_remote(server->listener, NULL); } if (remote == NULL) { bfree(abuf); LOGE("invalid remote addr"); close_and_free_server(EV_A_ server); return; } // SSR beg if (server->listener->list_obfs_global[remote->remote_index] == NULL && server->obfs_plugin) { server->listener->list_obfs_global[remote->remote_index] = server->obfs_plugin->init_data(); } if (server->listener->list_protocol_global[remote->remote_index] == NULL && server->protocol_plugin) { server->listener->list_protocol_global[remote->remote_index] = server->protocol_plugin->init_data(); } server_info _server_info; memset(&_server_info, 0, sizeof(server_info)); strcpy(_server_info.host, inet_ntoa(((struct sockaddr_in*)&remote->addr)->sin_addr)); _server_info.port = ((struct sockaddr_in*)&remote->addr)->sin_port; _server_info.port = _server_info.port >> 8 | _server_info.port << 8; _server_info.param = server->listener->obfs_param; _server_info.g_data = server->listener->list_obfs_global[remote->remote_index]; _server_info.head_len = get_head_size(ss_addr_to_send.array, 320, 30); _server_info.iv = server->e_ctx->evp.iv; _server_info.iv_len = enc_get_iv_len(); _server_info.key = enc_get_key(); _server_info.key_len = enc_get_key_len(); _server_info.tcp_mss = 1440; if (server->obfs_plugin) server->obfs_plugin->set_server_info(server->obfs, &_server_info); _server_info.param = NULL; _server_info.g_data = server->listener->list_protocol_global[remote->remote_index]; if (server->protocol_plugin) server->protocol_plugin->set_server_info(server->protocol, &_server_info); // SSR end if (!remote->direct) { if (auth) { abuf->array[0] |= ONETIMEAUTH_FLAG; ss_onetimeauth(abuf, server->e_ctx->evp.iv); } brealloc(remote->buf, buf->len + abuf->len, BUF_SIZE); memcpy(remote->buf->array, abuf->array, abuf->len); remote->buf->len = buf->len + abuf->len; if (buf->len > 0) { if (auth) { ss_gen_hash(buf, &remote->counter, server->e_ctx); } memcpy(remote->buf->array + abuf->len, buf->array, buf->len); } } else { if (buf->len > 0) { memcpy(remote->buf->array, buf->array, buf->len); remote->buf->len = buf->len; } } server->remote = remote; remote->server = server; bfree(abuf); } // Fake reply struct socks5_response response; response.ver = SVERSION; response.rep = 0; response.rsv = 0; response.atyp = 1; memcpy(server->buf->array, &response, sizeof(struct socks5_response)); memcpy(server->buf->array + sizeof(struct socks5_response), &sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); memcpy(server->buf->array + sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr), &sock_addr.sin_port, sizeof(sock_addr.sin_port)); int reply_size = sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); int s = send(server->fd, server->buf->array, reply_size, 0); if (s < reply_size) { LOGE("failed to send fake reply"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } if (udp_assc) { close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } } }
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method, int auth) { if (method > TABLE) { cipher_ctx_t evp; cipher_context_init(&evp, method, 1); size_t p_len = *len, c_len = *len; size_t iv_len = enc_iv_len; int err = 1; static int tmp_len = 0; static char *tmp_buf = NULL; int buf_len = max(iv_len + c_len, buf_size); if (tmp_len < buf_len) { tmp_len = buf_len; tmp_buf = realloc(tmp_buf, buf_len); } char *ciphertext = tmp_buf; uint8_t iv[MAX_IV_LENGTH]; rand_bytes(iv, iv_len); cipher_context_set_iv(&evp, iv, iv_len, 1); memcpy(ciphertext, iv, iv_len); if (auth) { char hash[ONETIMEAUTH_BYTES * 2]; ss_onetimeauth(hash, plaintext, p_len, iv); if (buf_size < ONETIMEAUTH_BYTES + p_len) { plaintext = realloc(plaintext, ONETIMEAUTH_BYTES + p_len); } memcpy(plaintext + p_len, hash, ONETIMEAUTH_BYTES); p_len = c_len = p_len + ONETIMEAUTH_BYTES; } if (method >= SALSA20) { crypto_stream_xor_ic((uint8_t *)(ciphertext + iv_len), (const uint8_t *)plaintext, (uint64_t)(p_len), (const uint8_t *)iv, 0, enc_key, method); } else { err = cipher_context_update(&evp, (uint8_t *)(ciphertext + iv_len), &c_len, (const uint8_t *)plaintext, p_len); } if (!err) { free(plaintext); cipher_context_release(&evp); return NULL; } #ifdef DEBUG dump("PLAIN", plaintext, *len); dump("CIPHER", ciphertext + iv_len, c_len); #endif cipher_context_release(&evp); if (buf_size < iv_len + c_len) { plaintext = realloc(plaintext, iv_len + c_len); } *len = iv_len + c_len; memcpy(plaintext, ciphertext, *len); return plaintext; } else { char *begin = plaintext; while (plaintext < begin + *len) { *plaintext = (char)enc_table[(uint8_t)*plaintext]; plaintext++; } return begin; } }