Beispiel #1
0
void
connect_to_remote(struct remote_context *remote) {
    remote->stage = XSTAGE_CONNECT;
    remote->connect_req.data = remote;
    int rc = uv_tcp_connect(&remote->connect_req, &remote->handle.tcp, &server_addr, remote_connect_cb);
    if (rc) {
        logger_log(LOG_ERR, "connect to server error: %s", uv_strerror(rc));
        request_ack(remote->client, S5_REP_NETWORK_UNREACHABLE);
    }
}
Beispiel #2
0
static void
remote_timer_expire(uv_timer_t *handle) {
    struct remote_context *remote = handle->data;
    struct client_context *client = remote->client;
    if (verbose) {
        char addrbuf[INET6_ADDRSTRLEN + 1] = {0};
        uint16_t port = ip_name(&client->addr, addrbuf, sizeof addrbuf);
        if (client->stage < XSTAGE_FORWARD) {
            logger_log(LOG_WARNING, "%s:%d connection timeout", addrbuf, port);
        } else {
            logger_log(LOG_WARNING, "%s:%d <-> %s connection timeout", addrbuf, port, client->target_addr);
        }
    }

    assert(client->stage != XSTAGE_TERMINATE);
    request_ack(client, S5_REP_TTL_EXPIRED);
}
Beispiel #3
0
static void
remote_connect_cb(uv_connect_t *req, int status) {
    struct remote_context *remote = (struct remote_context *)req->data;
    struct client_context *client = remote->client;


    if (status == 0) {
        remote->stage = XSTAGE_FORWARD;
        reset_timer(remote);
        receive_from_client(client);
        receive_from_remote(remote);

    } else {
        if (status != UV_ECANCELED) {
            logger_log(LOG_ERR, "connect to server failed: %s", uv_strerror(status));
            request_ack(client, S5_REP_HOST_UNREACHABLE);
        }
    }
}
Beispiel #4
0
static void
request_start(struct client_context *client, char *req_buf) {
    struct socks5_request *req = (struct socks5_request *)req_buf;
    struct remote_context *remote = client->remote;

    assert(remote->stage == XSTAGE_FORWARD);

    client->cmd = req->cmd;

    if (req->cmd != S5_CMD_CONNECT && req->cmd != S5_CMD_UDP_ASSOCIATE) {
        logger_log(LOG_ERR, "unsupported cmd: 0x%02x", req->cmd);
        request_ack(client, S5_REP_CMD_NOT_SUPPORTED);
        return;
    }

    if (req->cmd == S5_CMD_UDP_ASSOCIATE) {
        request_ack(client, S5_REP_SUCCESSED);
        return;
    }

    char buf[260] = {0};
    size_t buflen;
    uint16_t portlen = 2;

    /*
     *
     * xsocks request
     * +------+----------+----------+
     * | ATYP | BND.ADDR | BND.PORT |
     * +------+----------+----------+
     * |  1   | Variable |    2     |
     * +------+----------+----------+
     *
     */
    if (req->atyp == ATYP_IPV4) {
        size_t in_addr_len = sizeof(struct in_addr);
        buflen = sizeof(struct xsocks_request) + in_addr_len + portlen;
        buf[0] = ATYP_IPV4;
        memcpy(buf + 1, req->addr, in_addr_len);
        memcpy(buf + 1 + in_addr_len, req->addr + in_addr_len, portlen);

        uv_inet_ntop(AF_INET, (const void *)(req->addr), client->target_addr, INET_ADDRSTRLEN);
        uint16_t port = read_size((uint8_t*)(req->addr + in_addr_len));
        sprintf(client->target_addr, "%s:%u", client->target_addr, port);

    } else if (req->atyp == ATYP_HOST) {
        uint8_t namelen = *(uint8_t *)(req->addr);
        if (namelen > 0xFF) {
            logger_log(LOG_ERR, "unsupported address type: 0x%02x", req->atyp);
            request_ack(client, S5_REP_ADDRESS_TYPE_NOT_SUPPORTED);
            return;
        }
        buflen = sizeof(struct xsocks_request) + 1 + namelen + portlen;
        buf[0] = ATYP_HOST;
        memcpy(buf + 1, req->addr, 1 + namelen);
        memcpy(buf + 1 + 1 + namelen, req->addr + 1 + namelen, portlen);

        memcpy(client->target_addr, req->addr + 1, namelen);
        uint16_t port = read_size((uint8_t*)(req->addr + 1 + namelen));
        sprintf(client->target_addr, "%s:%u", client->target_addr, port);

    } else if (req->atyp == ATYP_IPV6) {
        size_t in6_addr_len = sizeof(struct in6_addr);
        buflen = sizeof(struct xsocks_request) + in6_addr_len + portlen;
        buf[0] = ATYP_IPV6;
        memcpy(buf + 1, req->addr, in6_addr_len);
        memcpy(buf + 1 + in6_addr_len, req->addr + in6_addr_len, portlen);

        uv_inet_ntop(AF_INET6, (const void *)(req->addr), client->target_addr, INET_ADDRSTRLEN);
        uint16_t port = read_size((uint8_t*)(req->addr + in6_addr_len));
        sprintf(client->target_addr, "%s:%u", client->target_addr, port);

    } else {
        logger_log(LOG_ERR, "unsupported address type: 0x%02x", req->atyp);
        request_ack(client, S5_REP_ADDRESS_TYPE_NOT_SUPPORTED);
        return;
    }

    request_ack(client, S5_REP_SUCCESSED);

    // TODO: handle UDP ASSOCIATE
    if (req->cmd == S5_CMD_CONNECT) {
        if (verbose) {
            logger_log(LOG_INFO, "connect to %s", client->target_addr);
        }
        int clen = buflen + PRIMITIVE_BYTES;
        uint8_t *c = client->buf + HEADER_BYTES;
        int rc = crypto_encrypt(c, (uint8_t *)buf, buflen);
        if (!rc) {
            forward_to_remote(remote, c, clen);
        }
    }
}