Faster bootstrap

This commit is contained in:
Quentin Dufour 2019-02-15 15:45:56 +01:00
parent 1dd5dd1203
commit 449c661cb3
6 changed files with 128 additions and 39 deletions

View file

@ -5,35 +5,22 @@ void load_onion_services(struct donar_client_ctx* ctx, char* onion_file, int por
tor_os_read (&(ctx->tos));
}
void init_tcp_clients(struct donar_client_ctx* ctx) {
for (uint16_t i = 0; i < CLIENT_PORT_SIZE ; i++) {
ctx->ports[i] = 7500 + i;
}
int sock1, sock2, err;
char target_host[255];
void init_tcp_client(struct donar_client_ctx* ctx, int i) {
for (int i = 0; i < CLIENT_PORT_SIZE; ) {
ctx->ports[i] = 7500 + i;
int sock1, err;
while (1) {
sock1 = create_tcp_client("127.0.0.1", "9050");
err = socks5_handshake(sock1);
if (err < 0) goto failed_socks5;
if (strlen(ctx->tos.keys[i].pub) > 254) {
fprintf(stderr, "Domain name is too long\n");
exit(EXIT_FAILURE);
}
sprintf(target_host, "%s.onion", ctx->tos.keys[i].pub);
err = socks5_connect_dns(sock1, target_host, ctx->ports[i]);
if (err < 0) goto failed_socks5;
err = socks5_reply(sock1);
if (err < 0) goto failed_socks5;
ctx->client_sock[i].fd = sock1;
ctx->client_sock[i].state = SOCKS5_STATE_NEW;
evt_core_add_fd (&(ctx->evts), "configure-socks5", sock1);
//@FIXME: We suppose that we will be able to do the whole write at once which is wrong too
err = socks5_handshake_syn(sock1);
if (err) goto failed_socks5;
sock2 = dup(sock1);
if (sock2 < 0) goto failed_socks5;
evt_core_add_fd (&(ctx->evts), "tcp-read", sock1);
evt_core_add_fd (&(ctx->evts), "tcp-write", sock2);
printf("Socket %d/%d %s:%d has been added to the pool\n", i+1, CLIENT_PORT_SIZE, target_host, ctx->ports[i]);
i++;
continue;
break;
failed_socks5:
fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE);
close(sock1);
@ -41,6 +28,66 @@ failed_socks5:
}
}
void configure_tcp_clients(struct evt_core_ctx* ctx, struct evt_core_cat* cat, int fd) {
int err, pos;
struct donar_client_ctx* app_ctx = (struct donar_client_ctx*) cat->app_ctx;
pos = -1;
for (int i = 0; i < CLIENT_PORT_SIZE; i++) {
if (app_ctx->client_sock[i].fd == fd) {
pos = i;
}
}
char target_host[255];
if (strlen(app_ctx->tos.keys[pos].pub) > 254) {
fprintf(stderr, "Domain name is too long\n");
exit(EXIT_FAILURE);
}
sprintf(target_host, "%s.onion", app_ctx->tos.keys[pos].pub);
switch (app_ctx->client_sock[pos].state) {
case SOCKS5_STATE_NEW:
//@FIXME: We suppose that we will be able to do the whole read at once which is wrong
err = socks5_handshake_ack (fd);
if (err < 0) goto on_socks5_err;
//@FIXME: We suppose that we will be able to do the whole write at once which is wrong too
err = socks5_connect_dns(fd, target_host, app_ctx->ports[pos]);
if (err < 0) goto on_socks5_err;
app_ctx->client_sock[pos].state = SOCKS5_STATE_ACK;
printf("Socket %d/%d %s:%d is connecting...\n", pos+1, CLIENT_PORT_SIZE, target_host, app_ctx->ports[pos]);
break;
case SOCKS5_STATE_ACK:
//@FIXME: We suppose that we will be able to do the whole read at once which is wrong too
err = socks5_reply (fd);
if (err < 0) goto on_socks5_err;
app_ctx->client_sock[pos].state = SOCKS5_STATE_RDY;
int sock1, sock2;
sock1 = dup(fd);
sock2 = dup(fd);
if (sock1 < 0 || sock2 < 0) goto on_socks5_err;
void* fdcat = evt_core_rm_fd (ctx, fd);
if (fdcat == NULL) goto on_socks5_err;
evt_core_add_fd (ctx, "tcp-write", sock1);
evt_core_add_fd (ctx, "tcp-read", sock2);
printf("Socket %d/%d %s:%d has been added to the pool!\n", pos+1, CLIENT_PORT_SIZE, target_host, app_ctx->ports[pos]);
break;
case SOCKS5_STATE_RDY:
goto on_socks5_err;
break;
case SOCKS5_STATE_ERR:
goto on_socks5_err;
break;
}
return;
on_socks5_err:
perror("An error occured while connecting to an Onion Service");
app_ctx->client_sock[pos].state = SOCKS5_STATE_ERR;
evt_core_rm_fd (ctx, fd);
init_tcp_client (app_ctx, pos);
}
void init_udp_server(struct donar_client_ctx* ctx, char* port) {
int sock1, sock2;
sock1 = create_udp_server(port);
@ -58,6 +105,15 @@ socket_failed:
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* onion_file, char* port) {
evt_core_init (&(ctx->evts));
struct evt_core_cat init_socks5 = {
.app_ctx = ctx,
.free_app_ctx = NULL,
.cb = configure_tcp_clients,
.name = "configure-socks5",
.flags = EPOLLIN | EPOLLET,
.socklist = NULL
};
evt_core_add_cat (&(ctx->evts), &init_socks5);
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_co));
evt_core_add_cat (&(ctx->evts), &(algo->on_udp_read));
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_read));
@ -68,7 +124,9 @@ void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* on
load_onion_services (ctx, onion_file, CLIENT_PORT_SIZE);
printf("--- Onion services loaded\n");
init_tcp_clients(ctx);
for (int i = 0; i < CLIENT_PORT_SIZE; i++) {
init_tcp_client(ctx, i);
}
printf("--- TCP Clients Connected\n");
init_udp_server (ctx, port);

View file

@ -11,6 +11,10 @@ struct donar_client_ctx {
struct tor_os_str tos;
struct evt_core_ctx evts;
uint16_t ports[CLIENT_PORT_SIZE];
struct {
int fd;
enum socks5_state state;
} client_sock[CLIENT_PORT_SIZE];
};
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* as, char* onion_file, char* port);

View file

@ -84,6 +84,19 @@ void evt_core_add_fd(struct evt_core_ctx* ctx, char* name, int fd) {
add_fd_to_epoll(ctx->epollfd, fd, cat->flags);
}
struct evt_core_cat* evt_core_rm_fd(struct evt_core_ctx* ctx, int fd) {
struct evt_core_cat* cat = g_hash_table_lookup (ctx->socklist, &fd);
if (cat == NULL) return NULL;
g_hash_table_remove(ctx->socklist, &fd);
for (int i = 0; i < cat->socklist->len; i++) {
if (g_array_index(cat->socklist, int, i) == fd) {
g_array_remove_index(cat->socklist, i);
}
}
return cat;
}
void evt_core_free(struct evt_core_ctx* ctx) {
g_hash_table_destroy(ctx->socklist);
g_hash_table_destroy(ctx->catlist);
@ -109,19 +122,13 @@ void evt_core_loop(struct evt_core_ctx* ctx) {
if (evt & EPOLLRDHUP) fprintf(stderr, "Epoll Read Hup Event. ");
if (evt & EPOLLHUP) fprintf(stderr, "Epoll Hup Event. ");
if (evt & EPOLLERR) fprintf(stderr, "Epoll Err Event. ");
fprintf (stderr, "Epoll error or stream closed for fd=%d. Updating our data structures...\n", err_fd);
struct evt_core_cat* cat = g_hash_table_lookup (ctx->socklist, &err_fd);
cat = evt_core_rm_fd (ctx, err_fd);
if (cat != NULL) {
fprintf(stderr, "The fd was belonging to category %s, clearing it.\n", cat->name);
g_hash_table_remove(ctx->socklist, &err_fd);
for (int i = 0; i < cat->socklist->len; i++) {
if (g_array_index(cat->socklist, int, i) == err_fd) {
g_array_remove_index(cat->socklist, i);
}
}
fprintf(stderr, "Clearing fd=%d on cat=%s\n", err_fd, cat->name);
} else {
fprintf(stderr, "The file descriptor is not registered in a category, this is probably a logic error\n");
close (events[n].data.fd);
close (err_fd);
}
continue;
}

View file

@ -34,5 +34,6 @@ struct evt_core_ctx {
void evt_core_init(struct evt_core_ctx* ctx);
void evt_core_add_cat(struct evt_core_ctx* ctx, struct evt_core_cat* cat);
void evt_core_add_fd(struct evt_core_ctx* ctx, char* name, int fd);
struct evt_core_cat* evt_core_rm_fd(struct evt_core_ctx* ctx, int fd);
void evt_core_free(struct evt_core_ctx* ctx);
void evt_core_loop(struct evt_core_ctx* ctx);

View file

@ -1,6 +1,7 @@
#include "socks5.h"
int socks5_handshake(int sock) {
int socks5_handshake_syn(int sock) {
//@TODO: Refactor the client handshake management
struct client_handshake ch = {
.ver = 0x05,
.nmethods = 0x01,
@ -9,10 +10,19 @@ int socks5_handshake(int sock) {
int size = sizeof(uint8_t) * (2 + ch.nmethods);
if (size != write(sock, &ch, size)) {
fprintf(stderr, "partial/failed write\n");
perror("write failed on tcp socket in socks5");
return -1;
}
return 0;
}
int socks5_handshake_ack(int sock) {
//@TODO: Refactor the client handshake management
struct client_handshake ch = {
.ver = 0x05,
.nmethods = 0x01,
.methods = {0x00}
};
struct server_handshake sh = {0};
int err = read_entity(sock, &sh, sizeof(struct server_handshake));
if (err == -1) {
@ -82,4 +92,5 @@ int socks5_connect_dns(int sock, char* addr, uint16_t port) {
fprintf(stderr, "partial/failed write\n");
return -1;
}
return 0;
}

View file

@ -8,6 +8,13 @@
#include <string.h>
#include "net_tools.h"
enum socks5_state {
SOCKS5_STATE_NEW,
SOCKS5_STATE_ACK,
SOCKS5_STATE_RDY,
SOCKS5_STATE_ERR
};
enum cmd {
CMD_CONNECT = 0x01,
CMD_BIND = 0x02,
@ -76,6 +83,7 @@ struct server_reply {
uint16_t port;
};
int socks5_handshake(int sock);
int socks5_handshake_syn(int sock);
int socks5_handshake_ack(int sock);
int socks5_connect_dns(int sock, char* addr, uint16_t port);
int socks5_reply(int sock);