예제 #1
0
static void
client_recv_cb(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) {
    struct server_context *server = container_of(handle, struct server_context, udp);
    if (nread > 0) {
        char key[KEY_BYTES + 1] = {0};
        crypto_generickey((uint8_t *)key, sizeof(key) -1, (uint8_t*)addr, sizeof(*addr), NULL, 0);

        struct client_context *client = NULL;
        uv_mutex_lock(&mutex);
        cache_lookup(cache, key, (void *)&client);
        uv_mutex_unlock(&mutex);

        if (client == NULL) {
            client = new_client();
            client->addr = *addr;
            client->local_handle = handle;
            memcpy(client->key, key, sizeof(key));
            uv_timer_init(handle->loop, client->timer);
            uv_udp_init(handle->loop, &client->server_handle);
            client->server_handle.data = client;
            uv_udp_recv_start(&client->server_handle, server_alloc_cb, server_recv_cb);
            uv_mutex_lock(&mutex);
            cache_insert(cache, client->key, (void *)client);
            uv_mutex_unlock(&mutex);
        }

        int clen = nread + PRIMITIVE_BYTES + addrlen;
        int mlen = nread + addrlen;
        uint8_t *c = (uint8_t *)buf->base - PRIMITIVE_BYTES - addrlen;
        uint8_t *m = (uint8_t *)buf->base - addrlen;

        if (server->dest_addr->sa_family == AF_INET) {
            struct sockaddr_in *addr = (struct sockaddr_in *)server->dest_addr;
            m[0] = 1;
            memcpy(m + 1, &addr->sin_addr, 4);
            memcpy(m + 1 + 4, &addr->sin_port, 2);
        } else {
            struct sockaddr_in6 *addr = (struct sockaddr_in6 *)server->dest_addr;
            m[0] = 4;
            memcpy(m + 1, &addr->sin6_addr, 16);
            memcpy(m + 1 + 16, &addr->sin6_port, 2);
        }

        int rc = crypto_encrypt(c, m, mlen);
        if (!rc) {
            reset_timer(client);
            forward_to_server(server->server_addr, client, c, clen);
        }

    } else {
        goto error;
    }

    return;

error:
    free(buf->base - addrlen - PRIMITIVE_BYTES);
}
예제 #2
0
/*
 *
 * SOCKS5 UDP Request
 * +----+------+------+----------+----------+----------+
 * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
 * +----+------+------+----------+----------+----------+
 * | 2  |  1   |  1   | Variable |    2     | Variable |
 * +----+------+------+----------+----------+----------+
 *
 */
static void
client_recv_cb(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) {
    struct server_context *server = container_of(handle, struct server_context, udp);
    if (nread > 0) {
        uint8_t frag = buf->base[2];
        if (frag) {
            logger_log(LOG_ERR, "don't support udp dgram frag");
            goto err;
        }

        char key[KEY_BYTES + 1] = {0};
        crypto_generickey((uint8_t *)key, sizeof(key) -1, (uint8_t*)addr, sizeof(*addr), NULL, 0);

        struct client_context *client = NULL;
        uv_mutex_lock(&mutex);
        cache_lookup(cache, key, (void *)&client);
        uv_mutex_unlock(&mutex);

        if (client == NULL) {
            client = new_client();
            client->addr = *addr;
            client->local_handle = handle;
            memcpy(client->key, key, sizeof(key));
            uv_timer_init(handle->loop, client->timer);
            uv_udp_init(handle->loop, &client->server_handle);
            client->server_handle.data = client;
            uv_udp_recv_start(&client->server_handle, server_alloc_cb, server_recv_cb);
            uv_mutex_lock(&mutex);
            cache_insert(cache, client->key, (void *)client);
            uv_mutex_unlock(&mutex);
        }

        int clen = nread - 3 + PRIMITIVE_BYTES;
        uint8_t *c = (uint8_t *)buf->base - PRIMITIVE_BYTES;
        int rc = crypto_encrypt(c, (uint8_t*)buf->base + 3, nread - 3);
        if (!rc) {
            reset_timer(client);
            forward_to_server(server->server_addr, client, c, clen);
        }

    } else {
        goto err;
    }

    return;

err:
    free(buf->base - PRIMITIVE_BYTES);
}
예제 #3
0
static void
poll_cb(uv_poll_t *watcher, int status, int events) {
 	char buffer[1024] = {0};
    char control_buffer[64] = {0};
    struct iovec iov[1];
    struct msghdr msg;
    struct sockaddr client_addr;
    struct server_context *server = container_of(watcher, struct server_context, watcher);

    if (status >= 0) {
        msg.msg_name = &client_addr;
        msg.msg_namelen = sizeof(client_addr);
        msg.msg_control = control_buffer;
        msg.msg_controllen = sizeof(control_buffer);
        iov[0].iov_base = buffer;
        iov[0].iov_len = sizeof(buffer);
        msg.msg_iov = iov;
        msg.msg_iovlen = 1;

        int msglen = recvmsg(watcher->io_watcher.fd, &msg, 0);
        if (msglen <= 0) {
            logger_stderr("receive from client error: %s", strerror(errno));
        }

        struct sockaddr dest_addr;
        if (getdestaddr(&msg, &dest_addr)) {
            logger_stderr("can not get destination address");
        }

        int addrlen = dest_addr.sa_family == AF_INET ? IPV4_HEADER_LEN : IPV6_HEADER_LEN;

        int mlen = addrlen + msglen;
        int clen = PRIMITIVE_BYTES + mlen;
        uint8_t *c = malloc(clen);
        uint8_t *m = c + PRIMITIVE_BYTES;

        /*
         *
         * xsocks UDP Request
         * +------+----------+----------+----------+
         * | ATYP | DST.ADDR | DST.PORT |   DATA   |
         * +------+----------+----------+----------+
         * |  1   | Variable |    2     | Variable |
         * +------+----------+----------+----------+
         *
         */
        if (dest_addr.sa_family == AF_INET) {
            struct sockaddr_in *addr = (struct sockaddr_in *)&dest_addr;
            m[0] = ATYP_IPV4;
            memcpy(m + 1, &addr->sin_addr, 4);
            memcpy(m + 1 + 4, &addr->sin_port, 2);

        } else {
            struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&dest_addr;
            m[0] = ATYP_IPV6;
            memcpy(m + 1, &addr->sin6_addr, 16);
            memcpy(m + 1 + 16, &addr->sin6_port, 2);
        }
        memcpy(m + addrlen, buffer, msglen);

        int rc = crypto_encrypt(c, m, mlen);
        if (!rc) {
            char key[KEY_BYTES + 1] = {0};
            crypto_generickey((uint8_t *)key, sizeof(key) -1, (uint8_t *)&client_addr, sizeof(client_addr), NULL, 0);

            struct client_context *client = NULL;
            uv_mutex_lock(&mutex);
            cache_lookup(cache, key, (void *)&client);
            uv_mutex_unlock(&mutex);
            if (client == NULL) {
                client = new_client();
                client->addr = client_addr;
                memcpy(client->key, key, sizeof(key));

                uv_timer_init(watcher->loop, client->timer);

                uv_udp_init(watcher->loop, &client->server_handle);
                client->server_handle.data = client;
                uv_udp_recv_start(&client->server_handle, server_alloc_cb, server_recv_cb);

                uv_mutex_lock(&mutex);
                cache_insert(cache, client->key, (void *)client);
                uv_mutex_unlock(&mutex);
            }

            reset_timer(client);
            forward_to_server(server->server_addr, client, c, clen);
        }
    }
}