Faster bootstrap
This commit is contained in:
parent
1dd5dd1203
commit
449c661cb3
6 changed files with 128 additions and 39 deletions
|
@ -5,35 +5,22 @@ void load_onion_services(struct donar_client_ctx* ctx, char* onion_file, int por
|
||||||
tor_os_read (&(ctx->tos));
|
tor_os_read (&(ctx->tos));
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_tcp_clients(struct donar_client_ctx* ctx) {
|
void init_tcp_client(struct donar_client_ctx* ctx, int i) {
|
||||||
for (uint16_t i = 0; i < CLIENT_PORT_SIZE ; i++) {
|
|
||||||
ctx->ports[i] = 7500 + i;
|
|
||||||
}
|
|
||||||
int sock1, sock2, err;
|
|
||||||
char target_host[255];
|
|
||||||
|
|
||||||
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");
|
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;
|
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);
|
break;
|
||||||
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;
|
|
||||||
failed_socks5:
|
failed_socks5:
|
||||||
fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE);
|
fprintf(stderr, "Failed connection for socket %d/%d. Sleeping 2 seconds...\n",i+1, CLIENT_PORT_SIZE);
|
||||||
close(sock1);
|
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) {
|
void init_udp_server(struct donar_client_ctx* ctx, char* port) {
|
||||||
int sock1, sock2;
|
int sock1, sock2;
|
||||||
sock1 = create_udp_server(port);
|
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) {
|
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* algo, char* onion_file, char* port) {
|
||||||
evt_core_init (&(ctx->evts));
|
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_tcp_co));
|
||||||
evt_core_add_cat (&(ctx->evts), &(algo->on_udp_read));
|
evt_core_add_cat (&(ctx->evts), &(algo->on_udp_read));
|
||||||
evt_core_add_cat (&(ctx->evts), &(algo->on_tcp_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);
|
load_onion_services (ctx, onion_file, CLIENT_PORT_SIZE);
|
||||||
printf("--- Onion services loaded\n");
|
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");
|
printf("--- TCP Clients Connected\n");
|
||||||
|
|
||||||
init_udp_server (ctx, port);
|
init_udp_server (ctx, port);
|
||||||
|
|
|
@ -11,6 +11,10 @@ struct donar_client_ctx {
|
||||||
struct tor_os_str tos;
|
struct tor_os_str tos;
|
||||||
struct evt_core_ctx evts;
|
struct evt_core_ctx evts;
|
||||||
uint16_t ports[CLIENT_PORT_SIZE];
|
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);
|
void donar_client(struct donar_client_ctx* ctx, struct algo_skel* as, char* onion_file, char* port);
|
||||||
|
|
|
@ -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);
|
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) {
|
void evt_core_free(struct evt_core_ctx* ctx) {
|
||||||
g_hash_table_destroy(ctx->socklist);
|
g_hash_table_destroy(ctx->socklist);
|
||||||
g_hash_table_destroy(ctx->catlist);
|
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 & EPOLLRDHUP) fprintf(stderr, "Epoll Read Hup Event. ");
|
||||||
if (evt & EPOLLHUP) fprintf(stderr, "Epoll Hup Event. ");
|
if (evt & EPOLLHUP) fprintf(stderr, "Epoll Hup Event. ");
|
||||||
if (evt & EPOLLERR) fprintf(stderr, "Epoll Err 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) {
|
if (cat != NULL) {
|
||||||
fprintf(stderr, "The fd was belonging to category %s, clearing it.\n", cat->name);
|
fprintf(stderr, "Clearing fd=%d on cat=%s\n", err_fd, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "The file descriptor is not registered in a category, this is probably a logic error\n");
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,5 +34,6 @@ struct evt_core_ctx {
|
||||||
void evt_core_init(struct evt_core_ctx* 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_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);
|
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_free(struct evt_core_ctx* ctx);
|
||||||
void evt_core_loop(struct evt_core_ctx* ctx);
|
void evt_core_loop(struct evt_core_ctx* ctx);
|
||||||
|
|
15
src/socks5.c
15
src/socks5.c
|
@ -1,6 +1,7 @@
|
||||||
#include "socks5.h"
|
#include "socks5.h"
|
||||||
|
|
||||||
int socks5_handshake(int sock) {
|
int socks5_handshake_syn(int sock) {
|
||||||
|
//@TODO: Refactor the client handshake management
|
||||||
struct client_handshake ch = {
|
struct client_handshake ch = {
|
||||||
.ver = 0x05,
|
.ver = 0x05,
|
||||||
.nmethods = 0x01,
|
.nmethods = 0x01,
|
||||||
|
@ -9,10 +10,19 @@ int socks5_handshake(int sock) {
|
||||||
|
|
||||||
int size = sizeof(uint8_t) * (2 + ch.nmethods);
|
int size = sizeof(uint8_t) * (2 + ch.nmethods);
|
||||||
if (size != write(sock, &ch, size)) {
|
if (size != write(sock, &ch, size)) {
|
||||||
fprintf(stderr, "partial/failed write\n");
|
perror("write failed on tcp socket in socks5");
|
||||||
return -1;
|
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};
|
struct server_handshake sh = {0};
|
||||||
int err = read_entity(sock, &sh, sizeof(struct server_handshake));
|
int err = read_entity(sock, &sh, sizeof(struct server_handshake));
|
||||||
if (err == -1) {
|
if (err == -1) {
|
||||||
|
@ -82,4 +92,5 @@ int socks5_connect_dns(int sock, char* addr, uint16_t port) {
|
||||||
fprintf(stderr, "partial/failed write\n");
|
fprintf(stderr, "partial/failed write\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
10
src/socks5.h
10
src/socks5.h
|
@ -8,6 +8,13 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "net_tools.h"
|
#include "net_tools.h"
|
||||||
|
|
||||||
|
enum socks5_state {
|
||||||
|
SOCKS5_STATE_NEW,
|
||||||
|
SOCKS5_STATE_ACK,
|
||||||
|
SOCKS5_STATE_RDY,
|
||||||
|
SOCKS5_STATE_ERR
|
||||||
|
};
|
||||||
|
|
||||||
enum cmd {
|
enum cmd {
|
||||||
CMD_CONNECT = 0x01,
|
CMD_CONNECT = 0x01,
|
||||||
CMD_BIND = 0x02,
|
CMD_BIND = 0x02,
|
||||||
|
@ -76,6 +83,7 @@ struct server_reply {
|
||||||
uint16_t port;
|
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_connect_dns(int sock, char* addr, uint16_t port);
|
||||||
int socks5_reply(int sock);
|
int socks5_reply(int sock);
|
||||||
|
|
Loading…
Reference in a new issue