diff --git a/src/local.c b/src/local.c index 4f94cb24..6ce18a24 100644 --- a/src/local.c +++ b/src/local.c @@ -439,248 +439,246 @@ server_recv_cb(EV_P_ ev_io *w, int revents) close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; - } else { - char host[257], ip[INET6_ADDRSTRLEN], port[16]; + } - buffer_t ss_addr_to_send; - buffer_t *abuf = &ss_addr_to_send; - balloc(abuf, BUF_SIZE); + // Fake reply + if (server->stage == 1) { + struct socks5_response response; + response.ver = SVERSION; + response.rep = 0; + response.rsv = 0; + response.atyp = 1; - abuf->array[abuf->len++] = request->atyp; - int atyp = request->atyp; + buffer_t resp_to_send; + buffer_t *resp_buf = &resp_to_send; + balloc(resp_buf, BUF_SIZE); - // get remote addr and port - if (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; + memcpy(resp_buf->array, &response, sizeof(struct socks5_response)); + memcpy(resp_buf->array + sizeof(struct socks5_response), + &sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); + memcpy(resp_buf->array + sizeof(struct socks5_response) + + sizeof(sock_addr.sin_addr), + &sock_addr.sin_port, sizeof(sock_addr.sin_port)); - if (acl || verbose) { - uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len)); - dns_ntop(AF_INET, (const void *)(buf->array + 4), - ip, INET_ADDRSTRLEN); - sprintf(port, "%d", p); - } - } else if (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; + int reply_size = sizeof(struct socks5_response) + + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); - 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 (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; + int s = send(server->fd, resp_buf->array, reply_size, 0); - if (acl || verbose) { - uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in6_addr_len)); - dns_ntop(AF_INET6, (const void *)(buf->array + 4), - ip, INET6_ADDRSTRLEN); - sprintf(port, "%d", p); - } - } else { - bfree(abuf); - LOGE("unsupported addrtype: %d", request->atyp); + bfree(resp_buf); + + 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; + } + } - if (server->stage == 1) { - // Fake reply - struct socks5_response response; - response.ver = SVERSION; - response.rep = 0; - response.rsv = 0; - response.atyp = 1; - - buffer_t resp_to_send; - buffer_t *resp_buf = &resp_to_send; - balloc(resp_buf, BUF_SIZE); - - memcpy(resp_buf->array, &response, sizeof(struct socks5_response)); - memcpy(resp_buf->array + sizeof(struct socks5_response), - &sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); - memcpy(resp_buf->array + sizeof(struct socks5_response) + - sizeof(sock_addr.sin_addr), - &sock_addr.sin_port, sizeof(sock_addr.sin_port)); + char host[257], ip[INET6_ADDRSTRLEN], port[16]; - int reply_size = sizeof(struct socks5_response) + - sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); + buffer_t ss_addr_to_send; + buffer_t *abuf = &ss_addr_to_send; + balloc(abuf, BUF_SIZE); - int s = send(server->fd, resp_buf->array, reply_size, 0); + abuf->array[abuf->len++] = request->atyp; + int atyp = request->atyp; - bfree(resp_buf); + // get remote addr and port + if (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 (s < reply_size) { - LOGE("failed to send fake reply"); - bfree(abuf); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); - return; - } - if (udp_assc) { - bfree(abuf); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); - return; - } + if (acl || verbose) { + uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len)); + dns_ntop(AF_INET, (const void *)(buf->array + 4), + ip, INET_ADDRSTRLEN); + sprintf(port, "%d", p); + } + } else if (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 (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), + ip, 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; + } - size_t abuf_len = abuf->len; - int sni_detected = 0; - - if (atyp == 1 || atyp == 4) { - char *hostname; - uint16_t p = ntohs(*(uint16_t *)(abuf->array + abuf->len - 2)); - int ret = 0; - if (p == http_protocol->default_port) - ret = http_protocol->parse_packet(buf->array + 3 + abuf->len, - buf->len - 3 - abuf->len, &hostname); - else if (p == tls_protocol->default_port) - ret = tls_protocol->parse_packet(buf->array + 3 + abuf->len, - buf->len - 3 - abuf->len, &hostname); - if (ret == -1) { - server->stage = 2; - bfree(abuf); - return; - } else if (ret > 0) { - sni_detected = 1; - - // Reconstruct address buffer - abuf->len = 0; - abuf->array[abuf->len++] = 3; - abuf->array[abuf->len++] = ret; - memcpy(abuf->array + abuf->len, hostname, ret); - abuf->len += ret; - p = htons(p); - memcpy(abuf->array + abuf->len, &p, 2); - abuf->len += 2; - - if (acl || verbose) { - memcpy(host, hostname, ret); - host[ret] = '\0'; - } + size_t abuf_len = abuf->len; + int sni_detected = 0; + + if (atyp == 1 || atyp == 4) { + char *hostname; + uint16_t p = ntohs(*(uint16_t *)(abuf->array + abuf->len - 2)); + int ret = 0; + if (p == http_protocol->default_port) + ret = http_protocol->parse_packet(buf->array + 3 + abuf->len, + buf->len - 3 - abuf->len, &hostname); + else if (p == tls_protocol->default_port) + ret = tls_protocol->parse_packet(buf->array + 3 + abuf->len, + buf->len - 3 - abuf->len, &hostname); + if (ret == -1) { + server->stage = 2; + bfree(abuf); + return; + } else if (ret > 0) { + sni_detected = 1; + + // Reconstruct address buffer + abuf->len = 0; + abuf->array[abuf->len++] = 3; + abuf->array[abuf->len++] = ret; + memcpy(abuf->array + abuf->len, hostname, ret); + abuf->len += ret; + p = htons(p); + memcpy(abuf->array + abuf->len, &p, 2); + abuf->len += 2; - ss_free(hostname); + if (acl || verbose) { + memcpy(host, hostname, ret); + host[ret] = '\0'; } - } - server->stage = 5; - - buf->len -= (3 + abuf_len); - if (buf->len > 0) { - memmove(buf->array, buf->array + 3 + abuf_len, buf->len); + ss_free(hostname); } + } - if (verbose) { - if (sni_detected || atyp == 3) - LOGI("connect to %s:%s", host, port); - else if (atyp == 1) - LOGI("connect to %s:%s", ip, port); - else if (atyp == 4) - LOGI("connect to [%s]:%s", ip, port); - } + server->stage = 5; - if (acl) { - int host_match = acl_match_host(host); - int ip_match = acl_match_host(ip); + buf->len -= (3 + abuf_len); + if (buf->len > 0) { + memmove(buf->array, buf->array + 3 + abuf_len, buf->len); + } - int bypass = get_acl_mode() == WHITE_LIST; + if (verbose) { + if (sni_detected || atyp == 3) + LOGI("connect to %s:%s", host, port); + else if (atyp == 1) + LOGI("connect to %s:%s", ip, port); + else if (atyp == 4) + LOGI("connect to [%s]:%s", ip, port); + } - if (get_acl_mode() == BLACK_LIST) { - if (ip_match > 0) - bypass = 1; // bypass IPs in black list + if (acl) { + int host_match = acl_match_host(host); + int ip_match = acl_match_host(ip); - if (host_match > 0) - bypass = 1; // bypass hostnames in black list - else if (host_match < 0) - bypass = 0; // proxy hostnames in white list - } else if (get_acl_mode() == WHITE_LIST) { - if (ip_match < 0) - bypass = 0; // proxy IPs in white list + int bypass = get_acl_mode() == WHITE_LIST; - if (host_match < 0) - bypass = 0; // proxy hostnames in white list - else if (host_match > 0) - bypass = 1; // bypass hostnames in black list - } + if (get_acl_mode() == BLACK_LIST) { + if (ip_match > 0) + bypass = 1; // bypass IPs in black list - if (bypass) { - if (verbose) { - if (sni_detected || atyp == 3) - LOGI("bypass %s:%s", host, port); - else if (atyp == 1) - LOGI("bypass %s:%s", ip, port); - else if (atyp == 4) - LOGI("bypass [%s]:%s", ip, port); - } - struct sockaddr_storage storage; - int err; - memset(&storage, 0, sizeof(struct sockaddr_storage)); - if (atyp == 1 || atyp == 4) { - err = get_sockaddr(ip, port, &storage, 0); - } else { - err = get_sockaddr(host, port, &storage, 1); - } - if (err != -1) { - remote = create_remote(server->listener, (struct sockaddr *)&storage); - remote->direct = 1; - } - } - } + if (host_match > 0) + bypass = 1; // bypass hostnames in black list + else if (host_match < 0) + bypass = 0; // proxy hostnames in white list + } else if (get_acl_mode() == WHITE_LIST) { + if (ip_match < 0) + bypass = 0; // proxy IPs in white list - // Not match ACL - if (remote == NULL) { - remote = create_remote(server->listener, NULL); + if (host_match < 0) + bypass = 0; // proxy hostnames in white list + else if (host_match > 0) + bypass = 1; // bypass hostnames in black list } - if (remote == NULL) { - bfree(abuf); - LOGE("invalid remote addr"); - close_and_free_server(EV_A_ server); - return; + if (bypass) { + if (verbose) { + if (sni_detected || atyp == 3) + LOGI("bypass %s:%s", host, port); + else if (atyp == 1) + LOGI("bypass %s:%s", ip, port); + else if (atyp == 4) + LOGI("bypass [%s]:%s", ip, port); + } + struct sockaddr_storage storage; + int err; + memset(&storage, 0, sizeof(struct sockaddr_storage)); + if (atyp == 1 || atyp == 4) { + err = get_sockaddr(ip, port, &storage, 0); + } else { + err = get_sockaddr(host, port, &storage, 1); + } + if (err != -1) { + remote = create_remote(server->listener, (struct sockaddr *)&storage); + remote->direct = 1; + } } + } - if (!remote->direct) { - if (auth) { - abuf->array[0] |= ONETIMEAUTH_FLAG; - ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE); - } + // Not match ACL + if (remote == NULL) { + remote = create_remote(server->listener, NULL); + } - if (buf->len > 0 && auth) { - ss_gen_hash(buf, &remote->counter, server->e_ctx, BUF_SIZE); - } + if (remote == NULL) { + bfree(abuf); + LOGE("invalid remote addr"); + close_and_free_server(EV_A_ server); + return; + } - 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 (!remote->direct) { + if (auth) { + abuf->array[0] |= ONETIMEAUTH_FLAG; + ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE); + } - if (buf->len > 0) { - 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; - } + if (buf->len > 0 && auth) { + ss_gen_hash(buf, &remote->counter, server->e_ctx, BUF_SIZE); } - server->remote = remote; - remote->server = server; + brealloc(remote->buf, buf->len + abuf->len, BUF_SIZE); + memcpy(remote->buf->array, abuf->array, abuf->len); + remote->buf->len = buf->len + abuf->len; - bfree(abuf); + if (buf->len > 0) { + 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); } } }