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); uv_read_stop(&remote->handle.stream); int clen = nread + PRIMITIVE_BYTES; uint8_t *c = remote->buf + HEADER_BYTES; int rc = crypto_encrypt(c, (uint8_t*)buf->base, nread); if (!rc) { forward_to_client(client, c, clen); } else { logger_log(LOG_ERR, "invalid tcp packet"); close_client(client); close_remote(remote); } } else if (nread < 0){ if (nread != UV_EOF) { logger_log(LOG_ERR, "receive from %s failed: %s", client->target_addr, uv_strerror(nread)); } close_client(client); close_remote(remote); } }
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); } }
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); }
void client_accept_cb(uv_stream_t *server, int status) { struct client_context *client = new_client(); struct remote_context *remote = new_remote(idle_timeout); client->remote = remote; remote->client = client; uv_timer_init(server->loop, remote->timer); uv_tcp_init(server->loop, &client->handle.tcp); uv_tcp_init(server->loop, &remote->handle.tcp); int rc = uv_accept(server, &client->handle.stream); if (rc == 0) { int namelen = sizeof client->addr; uv_tcp_getpeername(&client->handle.tcp, &client->addr, &namelen); reset_timer(remote); // start timer connect_to_remote(remote); } else { logger_log(LOG_ERR, "accept error: %s", uv_strerror(rc)); close_client(client); close_remote(remote); } }
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); }
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) { uint8_t *m = packet->buf; int mlen = packet->size - PRIMITIVE_BYTES; int err = crypto_decrypt(m, packet->buf, packet->size); 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) { logger_log(LOG_ERR, "receive from %s failed: %s", dest_addr_buf, uv_strerror(nread)); } close_client(client); close_remote(remote); } return; error: logger_log(LOG_ERR, "invalid tcp packet"); close_client(client); close_remote(remote); }
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, &remote->addr, remote_connect_cb); if (rc) { logger_log(LOG_ERR, "connect to %s error: %s", remote->client->target_addr, uv_strerror(rc)); close_client(remote->client); close_remote(remote); } }
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); }
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); } }
void resolve_remote(struct remote_context *remote, char *host, uint16_t port) { if (verbose) { logger_log(LOG_INFO, "resolve %s", host); } struct resolver_context *dns = uv_key_get(&thread_resolver_key); remote->stage = XSTAGE_RESOLVE; remote->host_query = resolver_query(dns, host, port, resolve_cb, remote); if (remote->host_query == NULL) { remote->stage = XSTAGE_TERMINATE; close_client(remote->client); close_remote(remote); } }
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 addr[INET6_ADDRSTRLEN + 1]; int port = ip_name(&peername, addr, sizeof addr); logger_log(LOG_WARNING, "%s:%d <-> %s connection timeout", addr, port, dest_addr_buf); } close_client(client); close_remote(remote); }
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 timeout", addr1, p1, addr2, p2); } close_client(client); close_remote(remote); }
static void resolve_cb(struct sockaddr *addr, void *data) { struct remote_context *remote = data; if (addr == NULL) { logger_log(LOG_ERR, "resolve %s failed: %s", remote->client->target_addr, resolver_lasterror(remote->host_query)); remote->stage = XSTAGE_TERMINATE; close_client(remote->client); close_remote(remote); } else { if (verbose) { logger_log(LOG_INFO, "connect to %s", remote->client->target_addr); } remote->addr = *addr; connect_to_remote(remote); } }
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) { logger_log(LOG_ERR, "connect to server failed: %s", uv_strerror(status)); close_client(client); close_remote(remote); } } }
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); } } }