1063 lines
36 KiB
C
1063 lines
36 KiB
C
/**
|
||
* Phantom Tunnel - Система туннелирования трафика через Phantom сеть
|
||
*
|
||
* Эта утилита создает зашифрованные туннели через Phantom сеть,
|
||
* позволяя безопасно передавать любой TCP трафик через несколько
|
||
* промежуточных узлов для обеспечения анонимности.
|
||
*
|
||
* Примеры использования:
|
||
* ./phantom-tunnel --local 8080 --remote example.com:80 --hops 3
|
||
* ./phantom-tunnel --ssh-tunnel 2222 remote.server.com
|
||
* ./phantom-tunnel --vpn-mode --interface tun0
|
||
*
|
||
* Автор: Phantom Protocol Team 2025
|
||
* Версия: 1.0.0
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <getopt.h>
|
||
#include <signal.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <arpa/inet.h>
|
||
#include <pthread.h>
|
||
#include <time.h>
|
||
#include <errno.h>
|
||
#include <fcntl.h>
|
||
#include <sys/select.h>
|
||
#include <netdb.h>
|
||
|
||
// Включение основных модулей Phantom
|
||
#include "../src/config.h"
|
||
#include "../src/kademlia.h"
|
||
#include "../src/path.h"
|
||
|
||
#define PHANTOM_TUNNEL_VERSION "1.0.0"
|
||
#define MAX_HOPS 10
|
||
#define MAX_CONNECTIONS 100
|
||
#define BUFFER_SIZE 8192
|
||
#define DEFAULT_TIMEOUT 30
|
||
|
||
// Типы туннелей
|
||
typedef enum {
|
||
TUNNEL_TYPE_TCP, // Простой TCP туннель
|
||
TUNNEL_TYPE_HTTP, // HTTP прокси туннель
|
||
TUNNEL_TYPE_SOCKS5, // SOCKS5 прокси туннель
|
||
TUNNEL_TYPE_SSH, // SSH туннель
|
||
TUNNEL_TYPE_VPN // VPN туннель
|
||
} tunnel_type_t;
|
||
|
||
// Состояние туннеля
|
||
typedef enum {
|
||
TUNNEL_STATE_DISCONNECTED,
|
||
TUNNEL_STATE_CONNECTING,
|
||
TUNNEL_STATE_CONNECTED,
|
||
TUNNEL_STATE_ERROR
|
||
} tunnel_state_t;
|
||
|
||
// Структура узла маршрута
|
||
typedef struct {
|
||
char node_id[64];
|
||
char ip_address[INET6_ADDRSTRLEN];
|
||
uint16_t port;
|
||
uint32_t latency; // в миллисекундах
|
||
uint32_t bandwidth; // в Кбит/с
|
||
float reliability; // 0.0 - 1.0
|
||
} phantom_route_node_t;
|
||
|
||
// Структура маршрута
|
||
typedef struct {
|
||
phantom_route_node_t hops[MAX_HOPS];
|
||
int hop_count;
|
||
uint32_t total_latency;
|
||
uint32_t min_bandwidth;
|
||
float route_reliability;
|
||
time_t created_time;
|
||
} phantom_route_t;
|
||
|
||
// Структура подключения
|
||
typedef struct {
|
||
int id;
|
||
int client_socket;
|
||
int phantom_socket;
|
||
tunnel_state_t state;
|
||
|
||
char remote_host[256];
|
||
uint16_t remote_port;
|
||
|
||
phantom_route_t route;
|
||
|
||
uint64_t bytes_sent;
|
||
uint64_t bytes_received;
|
||
time_t start_time;
|
||
time_t last_activity;
|
||
|
||
pthread_t thread;
|
||
bool is_active;
|
||
} phantom_connection_t;
|
||
|
||
// Структура туннеля
|
||
typedef struct {
|
||
tunnel_type_t type;
|
||
tunnel_state_t state;
|
||
|
||
// Локальные настройки
|
||
char bind_address[INET6_ADDRSTRLEN];
|
||
uint16_t local_port;
|
||
int listen_socket;
|
||
|
||
// Удаленные настройки
|
||
char remote_host[256];
|
||
uint16_t remote_port;
|
||
|
||
// Настройки маршрутизации
|
||
int desired_hops;
|
||
bool use_exit_nodes;
|
||
char preferred_countries[10][3]; // ISO коды стран
|
||
int country_count;
|
||
|
||
// Подключения
|
||
phantom_connection_t connections[MAX_CONNECTIONS];
|
||
int connection_count;
|
||
pthread_mutex_t connections_lock;
|
||
|
||
// Статистика
|
||
uint64_t total_bytes_sent;
|
||
uint64_t total_bytes_received;
|
||
uint32_t total_connections;
|
||
time_t start_time;
|
||
|
||
// Управление
|
||
bool is_running;
|
||
pthread_t accept_thread;
|
||
pthread_t monitor_thread;
|
||
} phantom_tunnel_t;
|
||
|
||
// Глобальная переменная туннеля
|
||
static phantom_tunnel_t *g_tunnel = NULL;
|
||
|
||
// Прототипы функций
|
||
phantom_tunnel_t* phantom_tunnel_create(tunnel_type_t type);
|
||
int phantom_tunnel_bind(phantom_tunnel_t *tunnel, const char *address, uint16_t port);
|
||
int phantom_tunnel_set_target(phantom_tunnel_t *tunnel, const char *host, uint16_t port);
|
||
int phantom_tunnel_start(phantom_tunnel_t *tunnel);
|
||
int phantom_tunnel_stop(phantom_tunnel_t *tunnel);
|
||
void phantom_tunnel_destroy(phantom_tunnel_t *tunnel);
|
||
|
||
phantom_route_t phantom_build_route(const char *target_host, uint16_t target_port, int hops);
|
||
int phantom_connect_through_route(const phantom_route_t *route, const char *target_host, uint16_t target_port);
|
||
void* phantom_tunnel_accept_thread(void *arg);
|
||
void* phantom_tunnel_connection_thread(void *arg);
|
||
void* phantom_tunnel_monitor_thread(void *arg);
|
||
|
||
void phantom_tunnel_show_status(phantom_tunnel_t *tunnel);
|
||
void phantom_tunnel_show_help(void);
|
||
void phantom_tunnel_signal_handler(int signal);
|
||
|
||
/**
|
||
* Создание туннеля
|
||
*/
|
||
phantom_tunnel_t* phantom_tunnel_create(tunnel_type_t type) {
|
||
phantom_tunnel_t *tunnel = calloc(1, sizeof(phantom_tunnel_t));
|
||
if (!tunnel) {
|
||
fprintf(stderr, "Не удалось выделить память для туннеля\n");
|
||
return NULL;
|
||
}
|
||
|
||
tunnel->type = type;
|
||
tunnel->state = TUNNEL_STATE_DISCONNECTED;
|
||
tunnel->desired_hops = 3;
|
||
tunnel->use_exit_nodes = true;
|
||
tunnel->listen_socket = -1;
|
||
tunnel->is_running = false;
|
||
tunnel->connection_count = 0;
|
||
|
||
strcpy(tunnel->bind_address, "127.0.0.1");
|
||
|
||
// Инициализация мутекса
|
||
if (pthread_mutex_init(&tunnel->connections_lock, NULL) != 0) {
|
||
free(tunnel);
|
||
return NULL;
|
||
}
|
||
|
||
tunnel->start_time = time(NULL);
|
||
|
||
printf("Phantom Tunnel создан (тип: %s)\n",
|
||
phantom_tunnel_type_to_string(type));
|
||
|
||
return tunnel;
|
||
}
|
||
|
||
/**
|
||
* Привязка туннеля к локальному адресу
|
||
*/
|
||
int phantom_tunnel_bind(phantom_tunnel_t *tunnel, const char *address, uint16_t port) {
|
||
if (!tunnel || !address) {
|
||
return -1;
|
||
}
|
||
|
||
strncpy(tunnel->bind_address, address, sizeof(tunnel->bind_address) - 1);
|
||
tunnel->local_port = port;
|
||
|
||
// Создание серверного сокета
|
||
tunnel->listen_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||
if (tunnel->listen_socket < 0) {
|
||
perror("socket");
|
||
return -1;
|
||
}
|
||
|
||
// Разрешение повторного использования адреса
|
||
int opt = 1;
|
||
setsockopt(tunnel->listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||
|
||
// Настройка адреса
|
||
struct sockaddr_in bind_addr;
|
||
memset(&bind_addr, 0, sizeof(bind_addr));
|
||
bind_addr.sin_family = AF_INET;
|
||
bind_addr.sin_port = htons(port);
|
||
|
||
if (inet_pton(AF_INET, address, &bind_addr.sin_addr) <= 0) {
|
||
fprintf(stderr, "Неверный IP адрес: %s\n", address);
|
||
close(tunnel->listen_socket);
|
||
tunnel->listen_socket = -1;
|
||
return -1;
|
||
}
|
||
|
||
// Привязка сокета
|
||
if (bind(tunnel->listen_socket, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) < 0) {
|
||
perror("bind");
|
||
close(tunnel->listen_socket);
|
||
tunnel->listen_socket = -1;
|
||
return -1;
|
||
}
|
||
|
||
printf("Туннель привязан к %s:%d\n", address, port);
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* Установка целевого адреса
|
||
*/
|
||
int phantom_tunnel_set_target(phantom_tunnel_t *tunnel, const char *host, uint16_t port) {
|
||
if (!tunnel || !host) {
|
||
return -1;
|
||
}
|
||
|
||
strncpy(tunnel->remote_host, host, sizeof(tunnel->remote_host) - 1);
|
||
tunnel->remote_port = port;
|
||
|
||
printf("Целевой адрес установлен: %s:%d\n", host, port);
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* Запуск туннеля
|
||
*/
|
||
int phantom_tunnel_start(phantom_tunnel_t *tunnel) {
|
||
if (!tunnel) {
|
||
return -1;
|
||
}
|
||
|
||
if (tunnel->is_running) {
|
||
printf("Туннель уже запущен\n");
|
||
return 0;
|
||
}
|
||
|
||
if (tunnel->listen_socket < 0) {
|
||
fprintf(stderr, "Туннель не привязан к адресу\n");
|
||
return -1;
|
||
}
|
||
|
||
printf("Запуск Phantom Tunnel...\n");
|
||
|
||
// Прослушивание подключений
|
||
if (listen(tunnel->listen_socket, 10) < 0) {
|
||
perror("listen");
|
||
return -1;
|
||
}
|
||
|
||
tunnel->is_running = true;
|
||
tunnel->state = TUNNEL_STATE_CONNECTED;
|
||
|
||
// Запуск потока принятия подключений
|
||
if (pthread_create(&tunnel->accept_thread, NULL,
|
||
phantom_tunnel_accept_thread, tunnel) != 0) {
|
||
perror("pthread_create accept");
|
||
tunnel->is_running = false;
|
||
return -1;
|
||
}
|
||
|
||
// Запуск потока мониторинга
|
||
if (pthread_create(&tunnel->monitor_thread, NULL,
|
||
phantom_tunnel_monitor_thread, tunnel) != 0) {
|
||
perror("pthread_create monitor");
|
||
tunnel->is_running = false;
|
||
pthread_cancel(tunnel->accept_thread);
|
||
return -1;
|
||
}
|
||
|
||
printf("✅ Phantom Tunnel запущен\n");
|
||
printf(" Локальный адрес: %s:%d\n", tunnel->bind_address, tunnel->local_port);
|
||
printf(" Удаленный адрес: %s:%d\n", tunnel->remote_host, tunnel->remote_port);
|
||
printf(" Количество хопов: %d\n", tunnel->desired_hops);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* Остановка туннеля
|
||
*/
|
||
int phantom_tunnel_stop(phantom_tunnel_t *tunnel) {
|
||
if (!tunnel || !tunnel->is_running) {
|
||
return 0;
|
||
}
|
||
|
||
printf("Остановка Phantom Tunnel...\n");
|
||
|
||
tunnel->is_running = false;
|
||
tunnel->state = TUNNEL_STATE_DISCONNECTED;
|
||
|
||
// Закрытие серверного сокета
|
||
if (tunnel->listen_socket >= 0) {
|
||
close(tunnel->listen_socket);
|
||
tunnel->listen_socket = -1;
|
||
}
|
||
|
||
// Остановка потоков
|
||
pthread_cancel(tunnel->accept_thread);
|
||
pthread_cancel(tunnel->monitor_thread);
|
||
|
||
// Закрытие всех подключений
|
||
pthread_mutex_lock(&tunnel->connections_lock);
|
||
for (int i = 0; i < tunnel->connection_count; i++) {
|
||
phantom_connection_t *conn = &tunnel->connections[i];
|
||
if (conn->is_active) {
|
||
conn->is_active = false;
|
||
if (conn->client_socket >= 0) {
|
||
close(conn->client_socket);
|
||
}
|
||
if (conn->phantom_socket >= 0) {
|
||
close(conn->phantom_socket);
|
||
}
|
||
pthread_cancel(conn->thread);
|
||
}
|
||
}
|
||
tunnel->connection_count = 0;
|
||
pthread_mutex_unlock(&tunnel->connections_lock);
|
||
|
||
printf("✅ Phantom Tunnel остановлен\n");
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* Уничтожение туннеля
|
||
*/
|
||
void phantom_tunnel_destroy(phantom_tunnel_t *tunnel) {
|
||
if (!tunnel) {
|
||
return;
|
||
}
|
||
|
||
phantom_tunnel_stop(tunnel);
|
||
pthread_mutex_destroy(&tunnel->connections_lock);
|
||
free(tunnel);
|
||
}
|
||
|
||
/**
|
||
* Построение маршрута через Phantom сеть
|
||
*/
|
||
phantom_route_t phantom_build_route(const char *target_host, uint16_t target_port, int hops) {
|
||
phantom_route_t route;
|
||
memset(&route, 0, sizeof(route));
|
||
|
||
printf("Построение маршрута к %s:%d через %d хопов...\n",
|
||
target_host, target_port, hops);
|
||
|
||
// Симуляция построения маршрута
|
||
// В реальной реализации здесь будет использоваться Kademlia DHT
|
||
// для поиска оптимальных узлов
|
||
|
||
route.hop_count = hops;
|
||
route.created_time = time(NULL);
|
||
|
||
for (int i = 0; i < hops && i < MAX_HOPS; i++) {
|
||
phantom_route_node_t *node = &route.hops[i];
|
||
|
||
// Генерация случайного узла (в реальности - поиск в DHT)
|
||
snprintf(node->node_id, sizeof(node->node_id), "phantom-node-%d", i + 1);
|
||
snprintf(node->ip_address, sizeof(node->ip_address), "10.0.%d.%d",
|
||
(i + 1), 100 + (rand() % 50));
|
||
node->port = 8050 + i;
|
||
node->latency = 50 + (rand() % 200); // 50-250ms
|
||
node->bandwidth = 1000 + (rand() % 9000); // 1-10 Мбит/с
|
||
node->reliability = 0.8 + (rand() % 20) / 100.0; // 0.8-1.0
|
||
|
||
route.total_latency += node->latency;
|
||
if (i == 0 || node->bandwidth < route.min_bandwidth) {
|
||
route.min_bandwidth = node->bandwidth;
|
||
}
|
||
route.route_reliability *= node->reliability;
|
||
|
||
printf(" Хоп %d: %s (%s:%d) - задержка: %dms, пропускная способность: %d Кбит/с\n",
|
||
i + 1, node->node_id, node->ip_address, node->port,
|
||
node->latency, node->bandwidth);
|
||
}
|
||
|
||
printf("Маршрут построен: общая задержка %dms, пропускная способность %d Кбит/с, надежность %.2f\n",
|
||
route.total_latency, route.min_bandwidth, route.route_reliability);
|
||
|
||
return route;
|
||
}
|
||
|
||
/**
|
||
* Подключение через маршрут
|
||
*/
|
||
int phantom_connect_through_route(const phantom_route_t *route,
|
||
const char *target_host, uint16_t target_port) {
|
||
if (!route || !target_host) {
|
||
return -1;
|
||
}
|
||
|
||
printf("Подключение к %s:%d через маршрут из %d хопов...\n",
|
||
target_host, target_port, route->hop_count);
|
||
|
||
// Создание сокета для подключения к первому хопу
|
||
int phantom_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||
if (phantom_socket < 0) {
|
||
perror("socket");
|
||
return -1;
|
||
}
|
||
|
||
// Подключение к первому узлу маршрута
|
||
if (route->hop_count > 0) {
|
||
const phantom_route_node_t *first_hop = &route->hops[0];
|
||
|
||
struct sockaddr_in hop_addr;
|
||
memset(&hop_addr, 0, sizeof(hop_addr));
|
||
hop_addr.sin_family = AF_INET;
|
||
hop_addr.sin_port = htons(first_hop->port);
|
||
|
||
if (inet_pton(AF_INET, first_hop->ip_address, &hop_addr.sin_addr) <= 0) {
|
||
fprintf(stderr, "Неверный IP адрес узла: %s\n", first_hop->ip_address);
|
||
close(phantom_socket);
|
||
return -1;
|
||
}
|
||
|
||
printf("Подключение к первому хопу: %s:%d\n",
|
||
first_hop->ip_address, first_hop->port);
|
||
|
||
if (connect(phantom_socket, (struct sockaddr*)&hop_addr, sizeof(hop_addr)) < 0) {
|
||
perror("connect to first hop");
|
||
close(phantom_socket);
|
||
return -1;
|
||
}
|
||
|
||
// Отправка команды построения туннеля через все хопы
|
||
char tunnel_command[1024];
|
||
snprintf(tunnel_command, sizeof(tunnel_command),
|
||
"PHANTOM_BUILD_TUNNEL %s %d", target_host, target_port);
|
||
|
||
// Добавление информации о хопах
|
||
for (int i = 1; i < route->hop_count; i++) {
|
||
char hop_info[128];
|
||
snprintf(hop_info, sizeof(hop_info), " %s:%d",
|
||
route->hops[i].ip_address, route->hops[i].port);
|
||
strncat(tunnel_command, hop_info, sizeof(tunnel_command) - strlen(tunnel_command) - 1);
|
||
}
|
||
|
||
strncat(tunnel_command, "\n", sizeof(tunnel_command) - strlen(tunnel_command) - 1);
|
||
|
||
if (send(phantom_socket, tunnel_command, strlen(tunnel_command), 0) < 0) {
|
||
perror("send tunnel command");
|
||
close(phantom_socket);
|
||
return -1;
|
||
}
|
||
|
||
// Ожидание подтверждения
|
||
char response[256];
|
||
ssize_t received = recv(phantom_socket, response, sizeof(response) - 1, 0);
|
||
if (received <= 0) {
|
||
fprintf(stderr, "Не получен ответ от первого хопа\n");
|
||
close(phantom_socket);
|
||
return -1;
|
||
}
|
||
|
||
response[received] = '\0';
|
||
|
||
if (strncmp(response, "PHANTOM_TUNNEL_OK", 17) != 0) {
|
||
fprintf(stderr, "Ошибка построения туннеля: %s\n", response);
|
||
close(phantom_socket);
|
||
return -1;
|
||
}
|
||
|
||
printf("✅ Туннель через Phantom сеть установлен\n");
|
||
}
|
||
|
||
return phantom_socket;
|
||
}
|
||
|
||
/**
|
||
* Поток принятия подключений
|
||
*/
|
||
void* phantom_tunnel_accept_thread(void *arg) {
|
||
phantom_tunnel_t *tunnel = (phantom_tunnel_t*)arg;
|
||
|
||
printf("Поток принятия подключений запущен\n");
|
||
|
||
while (tunnel->is_running) {
|
||
struct sockaddr_in client_addr;
|
||
socklen_t client_len = sizeof(client_addr);
|
||
|
||
// Принятие подключения
|
||
int client_socket = accept(tunnel->listen_socket,
|
||
(struct sockaddr*)&client_addr, &client_len);
|
||
|
||
if (client_socket < 0) {
|
||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||
usleep(100000); // 100ms
|
||
continue;
|
||
}
|
||
if (tunnel->is_running) {
|
||
perror("accept");
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// Получение IP адреса клиента
|
||
char client_ip[INET_ADDRSTRLEN];
|
||
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
|
||
|
||
printf("Новое подключение от %s:%d\n", client_ip, ntohs(client_addr.sin_port));
|
||
|
||
// Поиск свободного слота для подключения
|
||
pthread_mutex_lock(&tunnel->connections_lock);
|
||
|
||
int connection_id = -1;
|
||
for (int i = 0; i < MAX_CONNECTIONS; i++) {
|
||
if (!tunnel->connections[i].is_active) {
|
||
connection_id = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (connection_id == -1) {
|
||
printf("Достигнуто максимальное количество подключений\n");
|
||
close(client_socket);
|
||
pthread_mutex_unlock(&tunnel->connections_lock);
|
||
continue;
|
||
}
|
||
|
||
// Инициализация подключения
|
||
phantom_connection_t *conn = &tunnel->connections[connection_id];
|
||
memset(conn, 0, sizeof(phantom_connection_t));
|
||
|
||
conn->id = connection_id;
|
||
conn->client_socket = client_socket;
|
||
conn->phantom_socket = -1;
|
||
conn->state = TUNNEL_STATE_CONNECTING;
|
||
conn->is_active = true;
|
||
conn->start_time = time(NULL);
|
||
conn->last_activity = time(NULL);
|
||
|
||
strcpy(conn->remote_host, tunnel->remote_host);
|
||
conn->remote_port = tunnel->remote_port;
|
||
|
||
if (connection_id >= tunnel->connection_count) {
|
||
tunnel->connection_count = connection_id + 1;
|
||
}
|
||
|
||
tunnel->total_connections++;
|
||
|
||
pthread_mutex_unlock(&tunnel->connections_lock);
|
||
|
||
// Запуск потока обработки подключения
|
||
if (pthread_create(&conn->thread, NULL,
|
||
phantom_tunnel_connection_thread, conn) != 0) {
|
||
perror("pthread_create connection");
|
||
close(client_socket);
|
||
conn->is_active = false;
|
||
continue;
|
||
}
|
||
|
||
pthread_detach(conn->thread);
|
||
}
|
||
|
||
printf("Поток принятия подключений завершен\n");
|
||
return NULL;
|
||
}
|
||
|
||
/**
|
||
* Поток обработки подключения
|
||
*/
|
||
void* phantom_tunnel_connection_thread(void *arg) {
|
||
phantom_connection_t *conn = (phantom_connection_t*)arg;
|
||
|
||
printf("Обработка подключения #%d\n", conn->id);
|
||
|
||
// Построение маршрута к целевому серверу
|
||
conn->route = phantom_build_route(conn->remote_host, conn->remote_port,
|
||
g_tunnel->desired_hops);
|
||
|
||
// Подключение через Phantom сеть
|
||
conn->phantom_socket = phantom_connect_through_route(&conn->route,
|
||
conn->remote_host,
|
||
conn->remote_port);
|
||
|
||
if (conn->phantom_socket < 0) {
|
||
printf("Не удалось установить туннель для подключения #%d\n", conn->id);
|
||
conn->state = TUNNEL_STATE_ERROR;
|
||
close(conn->client_socket);
|
||
conn->is_active = false;
|
||
return NULL;
|
||
}
|
||
|
||
conn->state = TUNNEL_STATE_CONNECTED;
|
||
printf("✅ Туннель для подключения #%d установлен\n", conn->id);
|
||
|
||
// Проксирование данных между клиентом и Phantom сетью
|
||
phantom_tunnel_relay_data(conn);
|
||
|
||
// Закрытие подключения
|
||
printf("Закрытие подключения #%d\n", conn->id);
|
||
|
||
if (conn->client_socket >= 0) {
|
||
close(conn->client_socket);
|
||
}
|
||
if (conn->phantom_socket >= 0) {
|
||
close(conn->phantom_socket);
|
||
}
|
||
|
||
conn->is_active = false;
|
||
conn->state = TUNNEL_STATE_DISCONNECTED;
|
||
|
||
return NULL;
|
||
}
|
||
|
||
/**
|
||
* Проксирование данных
|
||
*/
|
||
void phantom_tunnel_relay_data(phantom_connection_t *conn) {
|
||
if (!conn) {
|
||
return;
|
||
}
|
||
|
||
fd_set read_fds;
|
||
int max_fd = (conn->client_socket > conn->phantom_socket) ?
|
||
conn->client_socket : conn->phantom_socket;
|
||
|
||
char buffer[BUFFER_SIZE];
|
||
|
||
while (conn->is_active && g_tunnel->is_running) {
|
||
FD_ZERO(&read_fds);
|
||
FD_SET(conn->client_socket, &read_fds);
|
||
FD_SET(conn->phantom_socket, &read_fds);
|
||
|
||
struct timeval timeout = {1, 0}; // 1 секунда
|
||
int activity = select(max_fd + 1, &read_fds, NULL, NULL, &timeout);
|
||
|
||
if (activity < 0) {
|
||
perror("select");
|
||
break;
|
||
}
|
||
|
||
if (activity == 0) {
|
||
// Проверка таймаута неактивности
|
||
if (time(NULL) - conn->last_activity > DEFAULT_TIMEOUT) {
|
||
printf("Таймаут неактивности для подключения #%d\n", conn->id);
|
||
break;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// Данные от клиента к Phantom сети
|
||
if (FD_ISSET(conn->client_socket, &read_fds)) {
|
||
ssize_t received = recv(conn->client_socket, buffer, sizeof(buffer), 0);
|
||
if (received <= 0) {
|
||
if (received < 0) {
|
||
perror("recv from client");
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (send(conn->phantom_socket, buffer, received, 0) <= 0) {
|
||
perror("send to phantom");
|
||
break;
|
||
}
|
||
|
||
conn->bytes_sent += received;
|
||
g_tunnel->total_bytes_sent += received;
|
||
conn->last_activity = time(NULL);
|
||
}
|
||
|
||
// Данные от Phantom сети к клиенту
|
||
if (FD_ISSET(conn->phantom_socket, &read_fds)) {
|
||
ssize_t received = recv(conn->phantom_socket, buffer, sizeof(buffer), 0);
|
||
if (received <= 0) {
|
||
if (received < 0) {
|
||
perror("recv from phantom");
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (send(conn->client_socket, buffer, received, 0) <= 0) {
|
||
perror("send to client");
|
||
break;
|
||
}
|
||
|
||
conn->bytes_received += received;
|
||
g_tunnel->total_bytes_received += received;
|
||
conn->last_activity = time(NULL);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Поток мониторинга
|
||
*/
|
||
void* phantom_tunnel_monitor_thread(void *arg) {
|
||
phantom_tunnel_t *tunnel = (phantom_tunnel_t*)arg;
|
||
|
||
printf("Поток мониторинга запущен\n");
|
||
|
||
while (tunnel->is_running) {
|
||
sleep(10); // Мониторинг каждые 10 секунд
|
||
|
||
pthread_mutex_lock(&tunnel->connections_lock);
|
||
|
||
int active_connections = 0;
|
||
uint64_t total_sent = 0;
|
||
uint64_t total_received = 0;
|
||
|
||
for (int i = 0; i < tunnel->connection_count; i++) {
|
||
phantom_connection_t *conn = &tunnel->connections[i];
|
||
if (conn->is_active) {
|
||
active_connections++;
|
||
total_sent += conn->bytes_sent;
|
||
total_received += conn->bytes_received;
|
||
}
|
||
}
|
||
|
||
pthread_mutex_unlock(&tunnel->connections_lock);
|
||
|
||
printf("📊 Статистика туннеля: %d активных подключений, "
|
||
"отправлено %llu байт, получено %llu байт\n",
|
||
active_connections, total_sent, total_received);
|
||
}
|
||
|
||
printf("Поток мониторинга завершен\n");
|
||
return NULL;
|
||
}
|
||
|
||
/**
|
||
* Показ статуса туннеля
|
||
*/
|
||
void phantom_tunnel_show_status(phantom_tunnel_t *tunnel) {
|
||
if (!tunnel) {
|
||
return;
|
||
}
|
||
|
||
printf("\n=== Статус Phantom Tunnel ===\n");
|
||
printf("Версия: %s\n", PHANTOM_TUNNEL_VERSION);
|
||
printf("Тип: %s\n", phantom_tunnel_type_to_string(tunnel->type));
|
||
printf("Состояние: %s\n", phantom_tunnel_state_to_string(tunnel->state));
|
||
|
||
if (tunnel->is_running) {
|
||
printf("Локальный адрес: %s:%d\n", tunnel->bind_address, tunnel->local_port);
|
||
printf("Удаленный адрес: %s:%d\n", tunnel->remote_host, tunnel->remote_port);
|
||
printf("Количество хопов: %d\n", tunnel->desired_hops);
|
||
|
||
time_t uptime = time(NULL) - tunnel->start_time;
|
||
printf("Время работы: %ld сек\n", uptime);
|
||
|
||
pthread_mutex_lock(&tunnel->connections_lock);
|
||
|
||
int active_connections = 0;
|
||
for (int i = 0; i < tunnel->connection_count; i++) {
|
||
if (tunnel->connections[i].is_active) {
|
||
active_connections++;
|
||
}
|
||
}
|
||
|
||
printf("Активных подключений: %d\n", active_connections);
|
||
printf("Всего подключений: %u\n", tunnel->total_connections);
|
||
printf("Отправлено: %llu байт\n", tunnel->total_bytes_sent);
|
||
printf("Получено: %llu байт\n", tunnel->total_bytes_received);
|
||
|
||
pthread_mutex_unlock(&tunnel->connections_lock);
|
||
}
|
||
|
||
printf("============================\n\n");
|
||
}
|
||
|
||
/**
|
||
* Показ справки
|
||
*/
|
||
void phantom_tunnel_show_help(void) {
|
||
printf("Phantom Tunnel v%s - Система туннелирования через Phantom сеть\n\n",
|
||
PHANTOM_TUNNEL_VERSION);
|
||
printf("Использование:\n");
|
||
printf(" phantom-tunnel [ОПЦИИ]\n\n");
|
||
printf("Опции:\n");
|
||
printf(" -l, --local АДРЕС:ПОРТ Локальный адрес для прослушивания\n");
|
||
printf(" -r, --remote АДРЕС:ПОРТ Удаленный адрес назначения\n");
|
||
printf(" -h, --hops КОЛИЧЕСТВО Количество хопов (по умолчанию: 3)\n");
|
||
printf(" -t, --type ТИП Тип туннеля (tcp, http, socks5, ssh, vpn)\n");
|
||
printf(" -c, --countries СТРАНЫ Предпочитаемые страны (ISO коды)\n");
|
||
printf(" -e, --exit-nodes Использовать exit-ноды\n");
|
||
printf(" -s, --status Показать статус\n");
|
||
printf(" -d, --daemon Запуск в режиме демона\n");
|
||
printf(" -v, --verbose Подробный вывод\n");
|
||
printf(" --help Показать эту справку\n\n");
|
||
printf("Примеры:\n");
|
||
printf(" # Простой TCP туннель\n");
|
||
printf(" phantom-tunnel -l 8080 -r example.com:80\n\n");
|
||
printf(" # SSH туннель через 5 хопов\n");
|
||
printf(" phantom-tunnel -l 2222 -r remote.server.com:22 -h 5\n\n");
|
||
printf(" # SOCKS5 прокси\n");
|
||
printf(" phantom-tunnel -l 1080 -t socks5\n\n");
|
||
printf(" # HTTP прокси с предпочтением определенных стран\n");
|
||
printf(" phantom-tunnel -l 8888 -t http -c US,DE,NL\n\n");
|
||
}
|
||
|
||
/**
|
||
* Преобразование типа туннеля в строку
|
||
*/
|
||
const char* phantom_tunnel_type_to_string(tunnel_type_t type) {
|
||
switch (type) {
|
||
case TUNNEL_TYPE_TCP: return "TCP";
|
||
case TUNNEL_TYPE_HTTP: return "HTTP Proxy";
|
||
case TUNNEL_TYPE_SOCKS5: return "SOCKS5 Proxy";
|
||
case TUNNEL_TYPE_SSH: return "SSH Tunnel";
|
||
case TUNNEL_TYPE_VPN: return "VPN Tunnel";
|
||
default: return "Unknown";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Преобразование состояния туннеля в строку
|
||
*/
|
||
const char* phantom_tunnel_state_to_string(tunnel_state_t state) {
|
||
switch (state) {
|
||
case TUNNEL_STATE_DISCONNECTED: return "Отключен";
|
||
case TUNNEL_STATE_CONNECTING: return "Подключение";
|
||
case TUNNEL_STATE_CONNECTED: return "Подключен";
|
||
case TUNNEL_STATE_ERROR: return "Ошибка";
|
||
default: return "Неизвестно";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик сигналов
|
||
*/
|
||
void phantom_tunnel_signal_handler(int signal) {
|
||
printf("\nПолучен сигнал %d, завершение работы...\n", signal);
|
||
|
||
if (g_tunnel) {
|
||
phantom_tunnel_stop(g_tunnel);
|
||
}
|
||
|
||
exit(0);
|
||
}
|
||
|
||
/**
|
||
* Главная функция
|
||
*/
|
||
int main(int argc, char *argv[]) {
|
||
printf("Phantom Tunnel v%s\n", PHANTOM_TUNNEL_VERSION);
|
||
printf("Система туннелирования трафика через Phantom сеть\n\n");
|
||
|
||
// Установка обработчиков сигналов
|
||
signal(SIGINT, phantom_tunnel_signal_handler);
|
||
signal(SIGTERM, phantom_tunnel_signal_handler);
|
||
|
||
// Парсинг аргументов командной строки
|
||
static struct option long_options[] = {
|
||
{"local", required_argument, 0, 'l'},
|
||
{"remote", required_argument, 0, 'r'},
|
||
{"hops", required_argument, 0, 'h'},
|
||
{"type", required_argument, 0, 't'},
|
||
{"countries", required_argument, 0, 'c'},
|
||
{"exit-nodes", no_argument, 0, 'e'},
|
||
{"status", no_argument, 0, 's'},
|
||
{"daemon", no_argument, 0, 'd'},
|
||
{"verbose", no_argument, 0, 'v'},
|
||
{"help", no_argument, 0, 0},
|
||
{0, 0, 0, 0}
|
||
};
|
||
|
||
tunnel_type_t tunnel_type = TUNNEL_TYPE_TCP;
|
||
char local_address[256] = "127.0.0.1";
|
||
uint16_t local_port = 0;
|
||
char remote_host[256] = "";
|
||
uint16_t remote_port = 0;
|
||
int hops = 3;
|
||
bool daemon_mode = false;
|
||
bool verbose = false;
|
||
bool show_status = false;
|
||
|
||
int option_index = 0;
|
||
int c;
|
||
|
||
while ((c = getopt_long(argc, argv, "l:r:h:t:c:esdv", long_options, &option_index)) != -1) {
|
||
switch (c) {
|
||
case 'l': {
|
||
char *colon = strchr(optarg, ':');
|
||
if (colon) {
|
||
*colon = '\0';
|
||
strcpy(local_address, optarg);
|
||
local_port = atoi(colon + 1);
|
||
} else {
|
||
local_port = atoi(optarg);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case 'r': {
|
||
char *colon = strchr(optarg, ':');
|
||
if (colon) {
|
||
*colon = '\0';
|
||
strcpy(remote_host, optarg);
|
||
remote_port = atoi(colon + 1);
|
||
} else {
|
||
strcpy(remote_host, optarg);
|
||
remote_port = 80; // По умолчанию HTTP
|
||
}
|
||
break;
|
||
}
|
||
|
||
case 'h':
|
||
hops = atoi(optarg);
|
||
if (hops < 1 || hops > MAX_HOPS) {
|
||
fprintf(stderr, "Количество хопов должно быть от 1 до %d\n", MAX_HOPS);
|
||
return 1;
|
||
}
|
||
break;
|
||
|
||
case 't':
|
||
if (strcmp(optarg, "tcp") == 0) {
|
||
tunnel_type = TUNNEL_TYPE_TCP;
|
||
} else if (strcmp(optarg, "http") == 0) {
|
||
tunnel_type = TUNNEL_TYPE_HTTP;
|
||
} else if (strcmp(optarg, "socks5") == 0) {
|
||
tunnel_type = TUNNEL_TYPE_SOCKS5;
|
||
} else if (strcmp(optarg, "ssh") == 0) {
|
||
tunnel_type = TUNNEL_TYPE_SSH;
|
||
} else if (strcmp(optarg, "vpn") == 0) {
|
||
tunnel_type = TUNNEL_TYPE_VPN;
|
||
} else {
|
||
fprintf(stderr, "Неизвестный тип туннеля: %s\n", optarg);
|
||
return 1;
|
||
}
|
||
break;
|
||
|
||
case 'c':
|
||
// TODO: Обработка списка стран
|
||
printf("Предпочитаемые страны: %s\n", optarg);
|
||
break;
|
||
|
||
case 'e':
|
||
printf("Использование exit-нодов включено\n");
|
||
break;
|
||
|
||
case 's':
|
||
show_status = true;
|
||
break;
|
||
|
||
case 'd':
|
||
daemon_mode = true;
|
||
break;
|
||
|
||
case 'v':
|
||
verbose = true;
|
||
break;
|
||
|
||
case 0:
|
||
if (strcmp(long_options[option_index].name, "help") == 0) {
|
||
phantom_tunnel_show_help();
|
||
return 0;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
phantom_tunnel_show_help();
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
// Проверка обязательных параметров
|
||
if (local_port == 0) {
|
||
fprintf(stderr, "Не указан локальный порт\n");
|
||
phantom_tunnel_show_help();
|
||
return 1;
|
||
}
|
||
|
||
if (tunnel_type == TUNNEL_TYPE_TCP && strlen(remote_host) == 0) {
|
||
fprintf(stderr, "Для TCP туннеля необходимо указать удаленный адрес\n");
|
||
phantom_tunnel_show_help();
|
||
return 1;
|
||
}
|
||
|
||
// Создание туннеля
|
||
g_tunnel = phantom_tunnel_create(tunnel_type);
|
||
if (!g_tunnel) {
|
||
return 1;
|
||
}
|
||
|
||
g_tunnel->desired_hops = hops;
|
||
|
||
// Привязка к локальному адресу
|
||
if (phantom_tunnel_bind(g_tunnel, local_address, local_port) != 0) {
|
||
phantom_tunnel_destroy(g_tunnel);
|
||
return 1;
|
||
}
|
||
|
||
// Установка удаленного адреса
|
||
if (strlen(remote_host) > 0) {
|
||
if (phantom_tunnel_set_target(g_tunnel, remote_host, remote_port) != 0) {
|
||
phantom_tunnel_destroy(g_tunnel);
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
// Показ статуса
|
||
if (show_status) {
|
||
phantom_tunnel_show_status(g_tunnel);
|
||
phantom_tunnel_destroy(g_tunnel);
|
||
return 0;
|
||
}
|
||
|
||
// Запуск в режиме демона
|
||
if (daemon_mode) {
|
||
if (daemon(0, 0) != 0) {
|
||
perror("daemon");
|
||
phantom_tunnel_destroy(g_tunnel);
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
// Запуск туннеля
|
||
if (phantom_tunnel_start(g_tunnel) != 0) {
|
||
phantom_tunnel_destroy(g_tunnel);
|
||
return 1;
|
||
}
|
||
|
||
printf("\nPhantom Tunnel запущен. Нажмите Ctrl+C для остановки\n\n");
|
||
|
||
// Основной цикл
|
||
while (g_tunnel->is_running) {
|
||
if (!daemon_mode && verbose) {
|
||
phantom_tunnel_show_status(g_tunnel);
|
||
}
|
||
sleep(30);
|
||
}
|
||
|
||
// Очистка
|
||
phantom_tunnel_destroy(g_tunnel);
|
||
|
||
printf("Phantom Tunnel завершен\n");
|
||
return 0;
|
||
}
|
||
|