Exemple #1
0
static void
client_send_cb(uv_write_t *req, int status) {
    struct client_context *client = req->data;
    struct remote_context *remote = client->remote;

    if (status == 0) {
        if (client->stage == XSTAGE_REQUEST) {
            receive_from_client(client);

        } else if (client->stage == XSTAGE_FORWARD) {
            receive_from_remote(remote);

        } else if (client->stage == XSTAGE_TERMINATE) {
            close_client(client);
            close_remote(remote);
        }

    } else {
        char addrbuf[INET6_ADDRSTRLEN + 1] = {0};
        int port = ip_name(&client->addr, addrbuf, sizeof addrbuf);
        if (client->stage == XSTAGE_FORWARD) {
            logger_log(LOG_ERR, "%s:%d <- %s failed: %s", addrbuf, port, client->target_addr, uv_strerror(status));
        } else {
            logger_log(LOG_ERR, "forward to %s:%d failed: %s", addrbuf, port, uv_strerror(status));
        }
    }

    free(req);
}
Exemple #2
0
static void
client_recv_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
    struct client_context *client = stream->data;
    struct remote_context *remote = client->remote;
    int clen;

    if (nread > 0) {
        reset_timer(remote);
        uv_read_stop(&client->handle.stream);

        switch (client->stage) {
        case XSTAGE_HANDSHAKE:
            if (verify_methods(buf->base, nread)) {
                handshake(client);
            } else {
                logger_log(LOG_ERR, "invalid method packet");
                close_client(client);
                close_remote(remote);
            }

            break;

        case XSTAGE_REQUEST:
            if (verify_request(buf->base, nread)) {
                request_start(client, buf->base);
            } else {
                logger_log(LOG_ERR, "invalid request packet");
                close_client(client);
                close_remote(remote);
            }

            break;

        case XSTAGE_FORWARD:
            clen = nread + PRIMITIVE_BYTES;
            uint8_t *c = client->buf + HEADER_BYTES;
            int rc = crypto_encrypt(c, (uint8_t*)buf->base, nread);
            if (rc) {
                logger_log(LOG_ERR, "encrypt failed");
                close_client(client);
                close_remote(remote);
            }
            forward_to_remote(remote, c, clen);

            break;

        default:
            break;
        }

    } else if (nread < 0) {
        if (nread != UV_EOF) {
            char addrbuf[INET6_ADDRSTRLEN + 1] = {0};
            uint16_t port = ip_name(&client->addr, addrbuf, sizeof addrbuf);
            logger_log(LOG_ERR, "receive from %s:%d failed: %s", addrbuf, port, uv_strerror(nread));
        }
        close_client(client);
        close_remote(remote);
    }
}
Exemple #3
0
static void
remote_timer_expire(uv_timer_t *handle) {
    struct remote_context *remote = handle->data;
    struct client_context *client = remote->client;
    if (verbose) {
        struct sockaddr peername;
        int namelen = sizeof peername;
        uv_tcp_getpeername(&client->handle.tcp, &peername, &namelen);
        char addr1[INET6_ADDRSTRLEN + 1];
        char addr2[INET6_ADDRSTRLEN + 1];
        int p1 = ip_name(&peername, addr1, sizeof addr2);
        int p2 = ip_name(&client->target_addr, addr2, sizeof(addr2));
        logger_log(LOG_WARNING, "%s:%d <-> %s:%d connection timeout", addr1, p1, addr2, p2);
    }
    close_client(client);
    close_remote(remote);
}
Exemple #4
0
void
cache_log(uint8_t atyp, const struct sockaddr *src_addr, const struct sockaddr *dst_addr,
            const char *host, uint16_t port, int hit) {
    char src[INET6_ADDRSTRLEN + 1] = {0};
    char dst[INET6_ADDRSTRLEN + 1] = {0};
    uint16_t src_port = 0, dst_port = 0;
    char *hint = hit ? "hit" : "miss";
    src_port = ip_name(src_addr, src, sizeof src);
    if (atyp == ATYP_HOST) {
        logger_log(hit ? LOG_INFO : LOG_WARNING, "[udp] cache %s: %s:%d -> %s:%d",
          hint, src, src_port, host, ntohs(port));
    } else {
        dst_port = ip_name(dst_addr, dst, sizeof dst);
        logger_log(hit ? LOG_INFO : LOG_WARNING, "[udp] cache %s: %s:%d -> %s:%d",
          hint, src, src_port, dst, dst_port);
    }
}
Exemple #5
0
static void
forward_to_server(struct sockaddr *server_addr, struct client_context *client, uint8_t *data, ssize_t datalen) {
    if (verbose) {
        char src[INET6_ADDRSTRLEN + 1] = {0};
        char dst[INET6_ADDRSTRLEN + 1] = {0};
        uint16_t dst_port = 0, src_port = 0;
        src_port = ip_name(&client->addr, src, sizeof src);
        dst_port = ip_name(&client->dest_addr, dst, sizeof dst);
        logger_log(LOG_INFO, "%s:%d -> %s:%d", src, src_port, dst, dst_port);
    }
    uv_udp_send_t *write_req = malloc(sizeof(*write_req) + sizeof(uv_buf_t));
    uv_buf_t *buf = (uv_buf_t *)(write_req + 1);
    buf->base = (char *)data;
    buf->len = datalen;
    write_req->data = client;;
    uv_udp_send(write_req, &client->server_handle, buf, 1, server_addr, server_send_cb);
}
Exemple #6
0
static void
handle_invalid_packet(struct client_context *client) {
    int port = 0;
    char remote[INET_ADDRSTRLEN + 1];
    port = ip_name(&client->addr, remote, sizeof(remote));
    logger_log(LOG_ERR, "Invalid tcp packet from %s:%d", remote, port);
    packet_reset(&client->packet);
    close_client(client);
}
Exemple #7
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);
        logger_log(LOG_WARNING, "%s:%d <-> %s connection timeout", addrbuf, port, client->target_addr);
    }
    close_client(remote->client);
    close_remote(remote);
}
Exemple #8
0
static void
inet_recv_cb(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
             const struct sockaddr *addr, unsigned flags)
{
    struct tundev_context *ctx = container_of(handle, struct tundev_context,
                                              inet_udp);

    if (nread > 0) {
        uint8_t *m = (uint8_t *)buf->base;
        ssize_t mlen = nread - PRIMITIVE_BYTES;

        int rc = crypto_decrypt(m, (uint8_t *)buf->base, nread);
        if (rc) {
            int port = 0;
            char remote[INET_ADDRSTRLEN + 1];
            port = ip_name(addr, remote, sizeof(remote));
            logger_log(LOG_ERR, "Invalid udp packet from %s:%d", remote, port);
            return;
        }

        if (mode == xTUN_SERVER) {
            struct iphdr *iphdr = (struct iphdr *) m;

            in_addr_t client_network = iphdr->saddr & htonl(ctx->tun->netmask);
            if (client_network != ctx->tun->network) {
                char *a = inet_ntoa(*(struct in_addr *) &iphdr->saddr);
                logger_log(LOG_ERR, "Invalid client: %s", a);
                return;
            }

            // TODO: Compare source address
            uv_rwlock_rdlock(&rwlock);
            struct peer *peer = lookup_peer(iphdr->saddr, peers);
            uv_rwlock_rdunlock(&rwlock);
            if (peer == NULL) {
                char saddr[24] = {0}, daddr[24] = {0};
                parse_addr(iphdr, saddr, daddr);
                logger_log(LOG_WARNING, "[UDP] Cache miss: %s -> %s", saddr, daddr);
                uv_rwlock_wrlock(&rwlock);
                peer = save_peer(iphdr->saddr, (struct sockaddr *) addr, peers);
                uv_rwlock_wrunlock(&rwlock);

            } else {
                if (memcmp(&peer->remote_addr, addr, sizeof(*addr))) {
                    peer->remote_addr = *addr;
                }
            }
            peer->protocol = xTUN_UDP;
        }

        network_to_tun(ctx->tunfd, m, mlen);
    }
}
Exemple #9
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) {
        char addrbuf[INET6_ADDRSTRLEN + 1];
        ip_name(&server_addr, addrbuf, sizeof(addrbuf));
        logger_log(LOG_ERR, "connect to %s error: %s", addrbuf, uv_strerror(rc));
        close_client(remote->client);
        close_remote(remote);
    }
}
Exemple #10
0
static void
remote_recv_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
    struct remote_context *remote;
    struct client_context *client;

    remote = stream->data;
    client = remote->client;

    if (nread > 0) {
        reset_timer(remote);
        struct packet *packet = &remote->packet;
        int rc = packet_filter(packet, buf->base, nread);
        if (rc == PACKET_COMPLETED) {
            int clen = packet->size;
            int mlen = packet->size - PRIMITIVE_BYTES;
            uint8_t *c = packet->buf, *m = packet->buf;

            assert(mlen > 0 && mlen <= MAX_PACKET_SIZE - PRIMITIVE_BYTES);

            int err = crypto_decrypt(m, c, clen);
            if (err) {
                goto error;
            }

            uv_read_stop(&remote->handle.stream);
            forward_to_client(client, m, mlen);

        } else if (rc == PACKET_INVALID) {
            goto error;
        }

    } else if (nread < 0){
        if (nread != UV_EOF && verbose) {
            char addrbuf[INET6_ADDRSTRLEN + 1];
            int port = ip_name(&client->target_addr, addrbuf, sizeof(addrbuf));
            logger_log(LOG_ERR, "receive from %s:%d failed: %s", addrbuf, port, uv_strerror(nread));
        }
        close_client(client);
        close_remote(remote);
    }

    return;

error:
    logger_log(LOG_ERR, "invalid tcp packet");
    if (verbose) {
        dump_hex(buf->base, nread, "invalid tcp Packet");
    }
    close_client(client);
    close_remote(remote);
}
Exemple #11
0
static void
remote_send_cb(uv_write_t *req, int status) {
    struct remote_context *remote = (struct remote_context *)req->data;
    struct client_context *client = remote->client;

    if (status == 0) {
        receive_from_client(client);

    } else {
        char addrbuf[INET6_ADDRSTRLEN + 1] = {0};
        uint16_t port = ip_name(&client->addr, addrbuf, sizeof addrbuf);
        logger_log(LOG_ERR, "%s:%d -> failed: %s", addrbuf, port, client->target_addr, uv_strerror(status));
    }

    free(req);
}
Exemple #12
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);
}
Exemple #13
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) {
        reset_timer(remote);
        client->stage = XSTAGE_FORWARD;
        remote->stage = XSTAGE_FORWARD;
        request_to_server(remote);
        receive_from_remote(remote);

    } else {
        if (status != UV_ECANCELED) {
            char addrbuf[INET6_ADDRSTRLEN + 1];
            ip_name(&server_addr, addrbuf, sizeof(addrbuf));
            logger_log(LOG_ERR, "connect to %s failed: %s", addrbuf, uv_strerror(status));
            close_client(client);
            close_remote(remote);
        }
    }
}