tun_enabled config + socks/http stress test (50 reqs, 2 workers)

- config_parser: tun_enabled в [global] (по умолчанию yes), не дефолтить
  tun_ifname если TUN не нужен
- utun_instance: уважать tun_enabled, чистые дефолты tcp_proxy TUN
- socks_proxy: фикс дэдлока — reply сразу после CONNECT, без ожидания DATA
- utun.conf.sample: документирован tun_enabled, tun_ifname
- test_socks_http_proxy: 50 запросов (SOCKS+HTTP), 2 воркера параллельно,
  файлы 1k..100k, сверка через cmp, python http.server + curl
This commit is contained in:
Evgeny committed 2026-07-01 22:14:37 +03:00
1 parent dfdec06a17
commit a01e2f0899
7 files changed
+300 -47

No files matched your search

+16 -4
View File
@@ -357,6 +357,10 @@ static int parse_global(const char *key, const char *value, struct global_config
global->my_node_id = strtoull(value, NULL, 16);
return 0;
}
if (strcmp(key, "tun_enabled") == 0) {
global->tun_enabled = strcasecmp(value, "yes") == 0 || strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0;
return 0;
}
if (strcmp(key, "tun_ifname") == 0) {
snprintf(global->tun_ifname, sizeof(global->tun_ifname), "%s", value);
return 0;
@@ -937,10 +941,18 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
cfg->clients = cur_client;
}
// Set default TUN interface name if not provided
if (cfg->global.tun_ifname[0] == '\0') {
snprintf(cfg->global.tun_ifname, sizeof(cfg->global.tun_ifname), "tun0");
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Auto-generated TUN interface name: %s", cfg->global.tun_ifname);
// Post-parse defaults: tun_enabled=1 if not explicitly disabled
if (!cfg->global.tun_enabled && cfg->global.tun_ifname[0] == '\0' && cfg->global.tun_ip.family == AF_UNSPEC) {
// No TUN config at all — treat as explicitly off (for non-root SOCKS/HTTP-only mode)
} else if (!cfg->global.tun_enabled) {
// TUN was explicitly disabled via tun_enabled=no
} else {
// TUN enabled (default) — set default ifname if not provided
cfg->global.tun_enabled = 1;
if (cfg->global.tun_ifname[0] == '\0') {
snprintf(cfg->global.tun_ifname, sizeof(cfg->global.tun_ifname), "tun0");
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Auto-generated TUN interface name: %s", cfg->global.tun_ifname);
}
}
return cfg;
+1
View File
@@ -95,6 +95,7 @@ struct global_config {
char my_private_key_hex[MAX_KEY_LEN];
char my_public_key_hex[MAX_KEY_LEN];
uint64_t my_node_id;
int tun_enabled; // 1 = create TUN (default), 0 = skip TUN (run without root)
char tun_ifname[16]; // TUN interface name (e.g., "tun12")
struct IP tun_ip;
int mtu;
+7 -39
View File
@@ -159,11 +159,11 @@ static void process_socks_request(struct socks_proxy_conn* c) {
}
c->buf_len = 0;
c->state = SOCKS_STATE_CONNECTING;
c->state = SOCKS_STATE_RELAY; // relay immediately, no waiting for first DATA
uint8_t reply[] = { 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
write_to_client(c, reply, 10);
if (send_connect(c) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "socks_proxy: send_connect failed sid=%08x", c->stream_id);
uint8_t err_reply[] = { 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
write_to_client(c, err_reply, 10);
tcp_conn_push_close(c->tc);
}
return;
@@ -212,10 +212,11 @@ static void process_http_request(struct socks_proxy_conn* c) {
host_port, c->dest_ip[0], c->dest_ip[1], c->dest_ip[2], c->dest_ip[3], port);
c->buf_len = 0;
c->state = HTTP_STATE_CONNECTING;
c->state = HTTP_STATE_RELAY; // reply immediately, no waiting
uint8_t resp[] = "HTTP/1.1 200 Connection Established\r\n\r\n";
write_to_client(c, resp, (uint16_t)strlen((char*)resp));
if (send_connect(c) < 0) {
uint8_t resp[] = "HTTP/1.1 502 Bad Gateway\r\n\r\n";
write_to_client(c, resp, (uint16_t)strlen((char*)resp)); tcp_conn_push_close(c->tc);
tcp_conn_push_close(c->tc);
}
return;
@@ -261,12 +262,6 @@ static void on_read_cb(struct ll_queue* q, void* arg) {
}
// RELAY = релей данных в ETCP
if (c->state == SOCKS_STATE_CONNECTING || c->state == HTTP_STATE_CONNECTING) {
// буферизуем данные пока ждём ответа от exit
memory_pool_free(c->tc->data_pool, e->dgram); queue_entry_free(e);
queue_resume_callback(q); return;
}
int ret = send_data(c, e->dgram, e->len);
DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "SOCKS PROXY SEND sid=%08x len=%u", c->stream_id, e->len);
if (ret == 0) {
@@ -365,17 +360,6 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count,
if (!c) return 0;
if (subcmd == TCP_PROXY_SUBCMD_DATA) {
if (c->state == SOCKS_STATE_CONNECTING) {
uint8_t reply[] = { 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
write_to_client(c, reply, 10);
c->state = SOCKS_STATE_RELAY;
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "socks_proxy: SOCKS connect ok sid=%08x → RELAY", stream_id);
} else if (c->state == HTTP_STATE_CONNECTING) {
uint8_t resp[] = "HTTP/1.1 200 Connection Established\r\n\r\n";
write_to_client(c, resp, (uint16_t)strlen((char*)resp));
c->state = HTTP_STATE_RELAY;
DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "socks_proxy: HTTP connect ok sid=%08x → RELAY", stream_id);
}
if (data_len > 0) {
struct ll_entry* e = queue_entry_new_from_pool(c->tc->entry_pool);
uint8_t* buf = memory_pool_alloc(c->tc->data_pool);
@@ -392,15 +376,6 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count,
if (subcmd == TCP_PROXY_SUBCMD_CLOSE) {
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socks_proxy: REM_CLOSED sid=%08x", stream_id);
if (c->state == SOCKS_STATE_CONNECTING || c->state == HTTP_STATE_CONNECTING) {
if (c->is_http) {
uint8_t resp[] = "HTTP/1.1 502 Bad Gateway\r\n\r\n";
write_to_client(c, resp, (uint16_t)strlen((char*)resp));
} else {
uint8_t err_reply[] = { 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
write_to_client(c, err_reply, 10);
}
}
c->rem_closed = 1;
etcp_router_waiter_cancel(c->inst, c->via_node_id, &c->tx_waiter);
tcp_conn_push_close(c->tc);
@@ -409,13 +384,6 @@ int socks_proxy_handle_etcp(struct socks_proxy_conn** head, int* count,
if (subcmd == TCP_PROXY_SUBCMD_ERROR) {
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "socks_proxy: ERROR from exit sid=%08x", stream_id);
if (c->state == SOCKS_STATE_CONNECTING) {
uint8_t err_reply[] = { 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
write_to_client(c, err_reply, 10);
} else if (c->state == HTTP_STATE_CONNECTING) {
uint8_t resp[] = "HTTP/1.1 502 Bad Gateway\r\n\r\n";
write_to_client(c, resp, (uint16_t)strlen((char*)resp));
}
c->rem_closed = 1;
etcp_router_waiter_cancel(c->inst, c->via_node_id, &c->tx_waiter);
tcp_conn_push_close(c->tc);
+4 -4
View File
@@ -95,7 +95,7 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
return -1;
}
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module created");
if (g_tun_init_enabled) {
if (g_tun_init_enabled && config->global.tun_enabled) {
instance->tun = tun_init(ua, config);
if (!instance->tun) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to initialize TUN device");
@@ -162,9 +162,9 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
// TCP proxy client (from [tcp_proxy] config section)
if (config->global.tcp_proxy_client_enabled || config->global.tcp_proxy_client_socks_enabled || config->global.tcp_proxy_client_http_proxy_enabled) {
const char* tun_name = config->global.tcp_proxy_client_tun_name[0] ? config->global.tcp_proxy_client_tun_name : "tun_tcp";
const char* tun_ip = config->global.tcp_proxy_client_tun_ip[0] ? config->global.tcp_proxy_client_tun_ip : "10.99.0.1";
int mtu = config->global.tcp_proxy_client_mtu > 0 ? config->global.tcp_proxy_client_mtu : 1500;
const char* tun_name = config->global.tcp_proxy_client_tun_name;
const char* tun_ip = config->global.tcp_proxy_client_tun_ip;
int mtu = config->global.tcp_proxy_client_mtu;
instance->tcp_proxy_client = tcp_proxy_client_create(instance, ua, tun_name, tun_ip, mtu, g_tun_init_enabled ? 0 : 1,
config->global.tcp_proxy_client_mappings, config->global.tcp_proxy_client_mapping_count,
config->global.tcp_proxy_client_via_node_id,