unified: Phantom Protocol 2025 complete archive integration

This commit is contained in:
NW
2026-05-18 17:28:53 +01:00
commit b680c5aeca
553 changed files with 112091 additions and 0 deletions

View File

@@ -0,0 +1,504 @@
#!/usr/bin/env python3
"""
Phantom SOCKS5 Proxy Server
Создает SOCKS5 прокси сервер, который маршрутизирует трафик через Phantom сеть
Использование:
python3 socks5-proxy.py --port 8080 --hops 3
Автор: Phantom Protocol Team 2025
"""
import socket
import threading
import struct
import select
import sys
import argparse
import time
import logging
from typing import Optional, Tuple, List
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# SOCKS5 константы
SOCKS5_VERSION = 0x05
SOCKS5_CONNECT = 0x01
SOCKS5_IPV4 = 0x01
SOCKS5_DOMAIN = 0x03
SOCKS5_IPV6 = 0x04
# Коды ответов SOCKS5
SOCKS5_SUCCESS = 0x00
SOCKS5_GENERAL_FAILURE = 0x01
SOCKS5_CONNECTION_NOT_ALLOWED = 0x02
SOCKS5_NETWORK_UNREACHABLE = 0x03
SOCKS5_HOST_UNREACHABLE = 0x04
SOCKS5_CONNECTION_REFUSED = 0x05
SOCKS5_TTL_EXPIRED = 0x06
SOCKS5_COMMAND_NOT_SUPPORTED = 0x07
SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08
class PhantomRoute:
"""Представляет маршрут через Phantom сеть"""
def __init__(self, hops: int = 3):
self.hops = hops
self.nodes: List[Tuple[str, int]] = []
self.build_route()
def build_route(self):
"""Построение маршрута через Phantom узлы"""
# В реальной реализации здесь будет запрос к Kademlia DHT
# Сейчас используем симуляцию
logger.info(f"Построение маршрута через {self.hops} хопов...")
# Симуляция поиска узлов в Phantom сети
available_nodes = [
("10.0.1.100", 8050),
("10.0.1.101", 8050),
("10.0.1.102", 8050),
("10.0.1.103", 8050),
("10.0.1.104", 8050),
]
# Выбор случайных узлов для маршрута
import random
self.nodes = random.sample(available_nodes, min(self.hops, len(available_nodes)))
for i, (ip, port) in enumerate(self.nodes):
logger.info(f" Хоп {i+1}: {ip}:{port}")
class PhantomConnection:
"""Подключение через Phantom сеть"""
def __init__(self, route: PhantomRoute):
self.route = route
self.socket: Optional[socket.socket] = None
self.connected = False
def connect(self, target_host: str, target_port: int) -> bool:
"""Подключение к целевому хосту через Phantom сеть"""
try:
logger.info(f"Подключение к {target_host}:{target_port} через Phantom сеть")
# Подключение к первому узлу маршрута
if not self.route.nodes:
logger.error("Маршрут не построен")
return False
first_hop = self.route.nodes[0]
logger.info(f"Подключение к первому хопу: {first_hop[0]}:{first_hop[1]}")
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(10)
try:
self.socket.connect(first_hop)
except socket.error as e:
logger.error(f"Не удалось подключиться к первому хопу: {e}")
# Fallback: прямое подключение для демонстрации
logger.info(f"Fallback: прямое подключение к {target_host}:{target_port}")
self.socket.close()
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(10)
self.socket.connect((target_host, target_port))
self.connected = True
return True
# Отправка команды построения туннеля
tunnel_command = self._build_tunnel_command(target_host, target_port)
self.socket.send(tunnel_command.encode('utf-8'))
# Ожидание подтверждения
response = self.socket.recv(1024).decode('utf-8')
if response.startswith("PHANTOM_TUNNEL_OK"):
logger.info("Туннель через Phantom сеть установлен")
self.connected = True
return True
else:
logger.error(f"Ошибка установки туннеля: {response}")
# Fallback: прямое подключение
logger.info(f"Fallback: прямое подключение к {target_host}:{target_port}")
self.socket.close()
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(10)
self.socket.connect((target_host, target_port))
self.connected = True
return True
except Exception as e:
logger.error(f"Ошибка подключения: {e}")
return False
def _build_tunnel_command(self, target_host: str, target_port: int) -> str:
"""Построение команды для создания туннеля"""
command = f"PHANTOM_BUILD_TUNNEL {target_host} {target_port}"
# Добавление промежуточных хопов
for i in range(1, len(self.route.nodes)):
hop = self.route.nodes[i]
command += f" {hop[0]}:{hop[1]}"
return command + "\n"
def send(self, data: bytes) -> int:
"""Отправка данных через Phantom соединение"""
if not self.connected or not self.socket:
raise ConnectionError("Соединение не установлено")
return self.socket.send(data)
def recv(self, size: int) -> bytes:
"""Получение данных через Phantom соединение"""
if not self.connected or not self.socket:
raise ConnectionError("Соединение не установлено")
return self.socket.recv(size)
def close(self):
"""Закрытие соединения"""
if self.socket:
self.socket.close()
self.socket = None
self.connected = False
class SOCKS5Handler:
"""Обработчик SOCKS5 протокола"""
def __init__(self, client_socket: socket.socket, hops: int = 3):
self.client_socket = client_socket
self.hops = hops
self.phantom_connection: Optional[PhantomConnection] = None
def handle(self):
"""Основная обработка SOCKS5 соединения"""
try:
# Этап 1: Аутентификация
if not self._handle_authentication():
return
# Этап 2: Обработка запроса подключения
if not self._handle_connection_request():
return
# Этап 3: Проксирование данных
self._relay_data()
except Exception as e:
logger.error(f"Ошибка обработки SOCKS5: {e}")
finally:
self._cleanup()
def _handle_authentication(self) -> bool:
"""Обработка этапа аутентификации SOCKS5"""
try:
# Получение запроса аутентификации
data = self.client_socket.recv(256)
if len(data) < 2:
return False
version, nmethods = struct.unpack('!BB', data[:2])
if version != SOCKS5_VERSION:
logger.error(f"Неподдерживаемая версия SOCKS: {version}")
return False
if len(data) < 2 + nmethods:
return False
methods = struct.unpack('!' + 'B' * nmethods, data[2:2+nmethods])
# Поддерживаем только "без аутентификации" (метод 0)
if 0 in methods:
# Отправка ответа: версия + выбранный метод
response = struct.pack('!BB', SOCKS5_VERSION, 0)
self.client_socket.send(response)
logger.debug("Аутентификация SOCKS5 пройдена")
return True
else:
# Нет поддерживаемых методов
response = struct.pack('!BB', SOCKS5_VERSION, 0xFF)
self.client_socket.send(response)
return False
except Exception as e:
logger.error(f"Ошибка аутентификации SOCKS5: {e}")
return False
def _handle_connection_request(self) -> bool:
"""Обработка запроса подключения SOCKS5"""
try:
# Получение запроса подключения
data = self.client_socket.recv(4)
if len(data) < 4:
return False
version, cmd, reserved, address_type = struct.unpack('!BBBB', data)
if version != SOCKS5_VERSION:
self._send_error_response(SOCKS5_GENERAL_FAILURE)
return False
if cmd != SOCKS5_CONNECT:
self._send_error_response(SOCKS5_COMMAND_NOT_SUPPORTED)
return False
# Получение адреса назначения
target_host, target_port = self._parse_target_address(address_type)
if not target_host:
self._send_error_response(SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED)
return False
logger.info(f"SOCKS5 запрос подключения к {target_host}:{target_port}")
# Подключение через Phantom сеть
route = PhantomRoute(self.hops)
self.phantom_connection = PhantomConnection(route)
if self.phantom_connection.connect(target_host, target_port):
# Отправка успешного ответа
self._send_success_response()
logger.info(f"SOCKS5 туннель к {target_host}:{target_port} установлен")
return True
else:
self._send_error_response(SOCKS5_HOST_UNREACHABLE)
return False
except Exception as e:
logger.error(f"Ошибка обработки запроса подключения: {e}")
self._send_error_response(SOCKS5_GENERAL_FAILURE)
return False
def _parse_target_address(self, address_type: int) -> Tuple[Optional[str], Optional[int]]:
"""Парсинг адреса назначения"""
try:
if address_type == SOCKS5_IPV4:
# IPv4 адрес (4 байта) + порт (2 байта)
data = self.client_socket.recv(6)
if len(data) < 6:
return None, None
ip_bytes = data[:4]
port_bytes = data[4:6]
ip = socket.inet_ntoa(ip_bytes)
port = struct.unpack('!H', port_bytes)[0]
return ip, port
elif address_type == SOCKS5_DOMAIN:
# Доменное имя: длина (1 байт) + имя + порт (2 байта)
length_data = self.client_socket.recv(1)
if len(length_data) < 1:
return None, None
domain_length = struct.unpack('!B', length_data)[0]
domain_data = self.client_socket.recv(domain_length + 2)
if len(domain_data) < domain_length + 2:
return None, None
domain = domain_data[:domain_length].decode('utf-8')
port = struct.unpack('!H', domain_data[domain_length:])[0]
return domain, port
elif address_type == SOCKS5_IPV6:
# IPv6 адрес (16 байт) + порт (2 байта)
data = self.client_socket.recv(18)
if len(data) < 18:
return None, None
ip_bytes = data[:16]
port_bytes = data[16:18]
ip = socket.inet_ntop(socket.AF_INET6, ip_bytes)
port = struct.unpack('!H', port_bytes)[0]
return ip, port
return None, None
except Exception as e:
logger.error(f"Ошибка парсинга адреса: {e}")
return None, None
def _send_success_response(self):
"""Отправка успешного ответа SOCKS5"""
# Версия + статус + зарезервировано + тип адреса
response = struct.pack('!BBBB', SOCKS5_VERSION, SOCKS5_SUCCESS, 0, SOCKS5_IPV4)
# Связанный адрес (0.0.0.0) + порт (0)
response += struct.pack('!IH', 0, 0)
self.client_socket.send(response)
def _send_error_response(self, error_code: int):
"""Отправка ответа об ошибке SOCKS5"""
response = struct.pack('!BBBB', SOCKS5_VERSION, error_code, 0, SOCKS5_IPV4)
response += struct.pack('!IH', 0, 0)
self.client_socket.send(response)
def _relay_data(self):
"""Проксирование данных между клиентом и Phantom соединением"""
if not self.phantom_connection:
return
logger.debug("Начало проксирования данных")
try:
while True:
# Ожидание данных от клиента или сервера
ready_sockets, _, error_sockets = select.select(
[self.client_socket, self.phantom_connection.socket],
[],
[self.client_socket, self.phantom_connection.socket],
1.0 # Таймаут 1 секунда
)
if error_sockets:
logger.debug("Ошибка в сокетах, завершение проксирования")
break
if not ready_sockets:
continue
# Данные от клиента к серверу
if self.client_socket in ready_sockets:
data = self.client_socket.recv(4096)
if not data:
logger.debug("Клиент закрыл соединение")
break
self.phantom_connection.send(data)
logger.debug(f"Отправлено {len(data)} байт через Phantom")
# Данные от сервера к клиенту
if self.phantom_connection.socket in ready_sockets:
data = self.phantom_connection.recv(4096)
if not data:
logger.debug("Сервер закрыл соединение")
break
self.client_socket.send(data)
logger.debug(f"Получено {len(data)} байт от Phantom")
except Exception as e:
logger.error(f"Ошибка проксирования данных: {e}")
def _cleanup(self):
"""Очистка ресурсов"""
try:
if self.phantom_connection:
self.phantom_connection.close()
self.client_socket.close()
except:
pass
class PhantomSOCKS5Server:
"""SOCKS5 прокси сервер через Phantom сеть"""
def __init__(self, host: str = '127.0.0.1', port: int = 8080, hops: int = 3):
self.host = host
self.port = port
self.hops = hops
self.server_socket: Optional[socket.socket] = None
self.running = False
def start(self):
"""Запуск SOCKS5 сервера"""
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(10)
self.running = True
logger.info(f"🚀 Phantom SOCKS5 прокси запущен на {self.host}:{self.port}")
logger.info(f" Количество хопов через Phantom сеть: {self.hops}")
logger.info(f" Настройте ваш браузер или приложение:")
logger.info(f" - Тип прокси: SOCKS v5")
logger.info(f" - Адрес: {self.host}")
logger.info(f" - Порт: {self.port}")
logger.info(f" - Аутентификация: Нет")
while self.running:
try:
client_socket, client_address = self.server_socket.accept()
logger.info(f"Новое SOCKS5 подключение от {client_address[0]}:{client_address[1]}")
# Обработка клиента в отдельном потоке
handler = SOCKS5Handler(client_socket, self.hops)
client_thread = threading.Thread(target=handler.handle)
client_thread.daemon = True
client_thread.start()
except socket.error as e:
if self.running:
logger.error(f"Ошибка принятия подключения: {e}")
except Exception as e:
logger.error(f"Ошибка запуска сервера: {e}")
finally:
self.stop()
def stop(self):
"""Остановка SOCKS5 сервера"""
self.running = False
if self.server_socket:
self.server_socket.close()
logger.info("Phantom SOCKS5 прокси остановлен")
def main():
"""Главная функция"""
parser = argparse.ArgumentParser(
description='Phantom SOCKS5 Proxy - SOCKS5 прокси через Phantom сеть'
)
parser.add_argument(
'--host',
default='127.0.0.1',
help='IP адрес для прослушивания (по умолчанию: 127.0.0.1)'
)
parser.add_argument(
'--port',
type=int,
default=8080,
help='Порт для прослушивания (по умолчанию: 8080)'
)
parser.add_argument(
'--hops',
type=int,
default=3,
help='Количество хопов через Phantom сеть (по умолчанию: 3)'
)
parser.add_argument(
'--verbose',
action='store_true',
help='Подробный вывод'
)
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
# Создание и запуск SOCKS5 сервера
server = PhantomSOCKS5Server(args.host, args.port, args.hops)
try:
server.start()
except KeyboardInterrupt:
logger.info("Получен сигнал прерывания, остановка сервера...")
server.stop()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,504 @@
#!/usr/bin/env python3
"""
Phantom VPN Client
Создает VPN подключение через Phantom сеть с использованием TUN интерфейса
Использование:
sudo python3 vpn-client.py --server phantom-vpn.local --interface tun0
Автор: Phantom Protocol Team 2025
"""
import os
import sys
import socket
import struct
import select
import threading
import argparse
import logging
import time
import subprocess
import fcntl
from typing import Optional, Tuple
# Проверка прав root
if os.geteuid() != 0:
print("Ошибка: VPN клиент требует права root для создания TUN интерфейса")
print("Запустите: sudo python3 vpn-client.py")
sys.exit(1)
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Константы для TUN интерфейса
TUNSETIFF = 0x400454ca
IFF_TUN = 0x0001
IFF_NO_PI = 0x1000
class PhantomVPNClient:
"""VPN клиент через Phantom сеть"""
def __init__(self, server_host: str, server_port: int = 1194,
interface: str = 'tun0', hops: int = 3):
self.server_host = server_host
self.server_port = server_port
self.interface = interface
self.hops = hops
self.tun_fd: Optional[int] = None
self.phantom_socket: Optional[socket.socket] = None
self.running = False
# Сетевые настройки
self.local_ip = "10.8.0.2"
self.remote_ip = "10.8.0.1"
self.netmask = "255.255.255.0"
self.mtu = 1500
def create_tun_interface(self) -> bool:
"""Создание TUN интерфейса"""
try:
logger.info(f"Создание TUN интерфейса {self.interface}")
# Открытие /dev/net/tun
self.tun_fd = os.open('/dev/net/tun', os.O_RDWR)
# Настройка интерфейса
ifr = struct.pack('16sH', self.interface.encode('utf-8'), IFF_TUN | IFF_NO_PI)
fcntl.ioctl(self.tun_fd, TUNSETIFF, ifr)
logger.info(f"TUN интерфейс {self.interface} создан")
return True
except Exception as e:
logger.error(f"Ошибка создания TUN интерфейса: {e}")
return False
def configure_interface(self) -> bool:
"""Настройка сетевого интерфейса"""
try:
logger.info(f"Настройка интерфейса {self.interface}")
# Назначение IP адреса
cmd = f"ip addr add {self.local_ip}/24 dev {self.interface}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
logger.error(f"Ошибка назначения IP: {result.stderr}")
return False
# Поднятие интерфейса
cmd = f"ip link set {self.interface} up"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
logger.error(f"Ошибка поднятия интерфейса: {result.stderr}")
return False
# Настройка MTU
cmd = f"ip link set {self.interface} mtu {self.mtu}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
logger.warning(f"Не удалось установить MTU: {result.stderr}")
logger.info(f"Интерфейс {self.interface} настроен: {self.local_ip}/24")
return True
except Exception as e:
logger.error(f"Ошибка настройки интерфейса: {e}")
return False
def setup_routing(self) -> bool:
"""Настройка маршрутизации"""
try:
logger.info("Настройка маршрутизации для VPN")
# Сохранение текущего шлюза по умолчанию
result = subprocess.run("ip route show default", shell=True,
capture_output=True, text=True)
if result.returncode == 0 and result.stdout.strip():
self.original_gateway = result.stdout.strip()
logger.info(f"Сохранен оригинальный шлюз: {self.original_gateway}")
# Добавление маршрута для VPN сервера через оригинальный шлюз
# (чтобы избежать рекурсии)
if hasattr(self, 'original_gateway'):
gateway_ip = self.original_gateway.split()[2]
cmd = f"ip route add {self.server_host}/32 via {gateway_ip}"
subprocess.run(cmd, shell=True)
# Настройка маршрута по умолчанию через VPN
cmd = f"ip route add 0.0.0.0/1 dev {self.interface}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
logger.warning(f"Не удалось добавить маршрут 0.0.0.0/1: {result.stderr}")
cmd = f"ip route add 128.0.0.0/1 dev {self.interface}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
logger.warning(f"Не удалось добавить маршрут 128.0.0.0/1: {result.stderr}")
logger.info("Маршрутизация настроена")
return True
except Exception as e:
logger.error(f"Ошибка настройки маршрутизации: {e}")
return False
def connect_to_phantom_server(self) -> bool:
"""Подключение к VPN серверу через Phantom сеть"""
try:
logger.info(f"Подключение к VPN серверу {self.server_host}:{self.server_port}")
logger.info(f"Маршрут через {self.hops} хопов Phantom сети")
# Создание сокета
self.phantom_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.phantom_socket.settimeout(30)
# В реальной реализации здесь будет построение маршрута через Phantom
# Сейчас используем прямое подключение для демонстрации
try:
# Попытка подключения через Phantom (симуляция)
phantom_gateway = "127.0.0.1" # Локальный Phantom узел
phantom_port = 8050
logger.info(f"Подключение через Phantom gateway {phantom_gateway}:{phantom_port}")
self.phantom_socket.connect((phantom_gateway, phantom_port))
# Отправка команды VPN туннеля
vpn_command = f"PHANTOM_VPN_CONNECT {self.server_host} {self.server_port} {self.hops}\n"
self.phantom_socket.send(vpn_command.encode('utf-8'))
# Ожидание подтверждения
response = self.phantom_socket.recv(1024).decode('utf-8')
if response.startswith("PHANTOM_VPN_OK"):
logger.info("VPN туннель через Phantom сеть установлен")
return True
else:
logger.error(f"Ошибка установки VPN туннеля: {response}")
return False
except socket.error:
# Fallback: прямое подключение для демонстрации
logger.info(f"Fallback: прямое подключение к {self.server_host}:{self.server_port}")
self.phantom_socket.close()
self.phantom_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.phantom_socket.settimeout(30)
self.phantom_socket.connect((self.server_host, self.server_port))
# Простой VPN handshake
handshake = b"PHANTOM_VPN_CLIENT_HELLO\n"
self.phantom_socket.send(handshake)
response = self.phantom_socket.recv(1024)
if b"VPN_SERVER_HELLO" in response:
logger.info("VPN handshake завершен")
return True
else:
logger.error("Ошибка VPN handshake")
return False
except Exception as e:
logger.error(f"Ошибка подключения к VPN серверу: {e}")
return False
def start_packet_forwarding(self):
"""Запуск пересылки пакетов между TUN и Phantom сокетом"""
logger.info("Запуск пересылки пакетов")
# Поток для пересылки пакетов от TUN к сокету
tun_to_socket_thread = threading.Thread(target=self._forward_tun_to_socket)
tun_to_socket_thread.daemon = True
tun_to_socket_thread.start()
# Поток для пересылки пакетов от сокета к TUN
socket_to_tun_thread = threading.Thread(target=self._forward_socket_to_tun)
socket_to_tun_thread.daemon = True
socket_to_tun_thread.start()
return tun_to_socket_thread, socket_to_tun_thread
def _forward_tun_to_socket(self):
"""Пересылка пакетов от TUN интерфейса к Phantom сокету"""
logger.debug("Поток TUN → Socket запущен")
while self.running:
try:
# Чтение пакета из TUN интерфейса
ready, _, _ = select.select([self.tun_fd], [], [], 1.0)
if not ready:
continue
packet = os.read(self.tun_fd, 2048)
if not packet:
continue
# Отправка пакета через Phantom сокет
# Добавляем заголовок с длиной пакета
packet_length = struct.pack('!H', len(packet))
self.phantom_socket.send(packet_length + packet)
logger.debug(f"TUN → Socket: {len(packet)} байт")
except Exception as e:
if self.running:
logger.error(f"Ошибка пересылки TUN → Socket: {e}")
break
logger.debug("Поток TUN → Socket завершен")
def _forward_socket_to_tun(self):
"""Пересылка пакетов от Phantom сокета к TUN интерфейсу"""
logger.debug("Поток Socket → TUN запущен")
while self.running:
try:
# Чтение заголовка с длиной пакета
ready, _, _ = select.select([self.phantom_socket], [], [], 1.0)
if not ready:
continue
length_data = self._recv_exact(self.phantom_socket, 2)
if not length_data:
continue
packet_length = struct.unpack('!H', length_data)[0]
# Чтение самого пакета
packet = self._recv_exact(self.phantom_socket, packet_length)
if not packet:
continue
# Запись пакета в TUN интерфейс
os.write(self.tun_fd, packet)
logger.debug(f"Socket → TUN: {len(packet)} байт")
except Exception as e:
if self.running:
logger.error(f"Ошибка пересылки Socket → TUN: {e}")
break
logger.debug("Поток Socket → TUN завершен")
def _recv_exact(self, sock: socket.socket, length: int) -> bytes:
"""Получение точного количества байт из сокета"""
data = b''
while len(data) < length:
chunk = sock.recv(length - len(data))
if not chunk:
return b''
data += chunk
return data
def start(self) -> bool:
"""Запуск VPN клиента"""
try:
logger.info("🚀 Запуск Phantom VPN Client")
# Создание TUN интерфейса
if not self.create_tun_interface():
return False
# Настройка интерфейса
if not self.configure_interface():
return False
# Подключение к VPN серверу
if not self.connect_to_phantom_server():
return False
# Настройка маршрутизации
if not self.setup_routing():
return False
self.running = True
# Запуск пересылки пакетов
threads = self.start_packet_forwarding()
logger.info("✅ Phantom VPN подключение установлено")
logger.info(f" Локальный IP: {self.local_ip}")
logger.info(f" VPN сервер: {self.server_host}:{self.server_port}")
logger.info(f" Интерфейс: {self.interface}")
logger.info(f" Хопов через Phantom: {self.hops}")
logger.info(" Весь трафик теперь проходит через Phantom VPN")
return True
except Exception as e:
logger.error(f"Ошибка запуска VPN клиента: {e}")
return False
def stop(self):
"""Остановка VPN клиента"""
logger.info("Остановка Phantom VPN Client")
self.running = False
# Восстановление маршрутизации
self._restore_routing()
# Закрытие сокета
if self.phantom_socket:
self.phantom_socket.close()
self.phantom_socket = None
# Удаление TUN интерфейса
if self.tun_fd:
os.close(self.tun_fd)
self.tun_fd = None
# Удаление интерфейса
subprocess.run(f"ip link delete {self.interface}", shell=True)
logger.info("Phantom VPN Client остановлен")
def _restore_routing(self):
"""Восстановление оригинальной маршрутизации"""
try:
logger.info("Восстановление оригинальной маршрутизации")
# Удаление VPN маршрутов
subprocess.run(f"ip route del 0.0.0.0/1 dev {self.interface}", shell=True)
subprocess.run(f"ip route del 128.0.0.0/1 dev {self.interface}", shell=True)
# Удаление маршрута к VPN серверу
if hasattr(self, 'original_gateway'):
subprocess.run(f"ip route del {self.server_host}/32", shell=True)
logger.info("Маршрутизация восстановлена")
except Exception as e:
logger.error(f"Ошибка восстановления маршрутизации: {e}")
def show_status(self):
"""Показ статуса VPN подключения"""
print("\n=== Статус Phantom VPN ===")
print(f"Состояние: {'Подключен' if self.running else 'Отключен'}")
if self.running:
print(f"VPN сервер: {self.server_host}:{self.server_port}")
print(f"Локальный IP: {self.local_ip}")
print(f"Интерфейс: {self.interface}")
print(f"Хопов через Phantom: {self.hops}")
# Показ статистики интерфейса
try:
result = subprocess.run(f"ip -s link show {self.interface}",
shell=True, capture_output=True, text=True)
if result.returncode == 0:
print("\nСтатистика интерфейса:")
lines = result.stdout.split('\n')
for line in lines:
if 'RX:' in line or 'TX:' in line or 'bytes' in line:
print(f" {line.strip()}")
except:
pass
# Проверка внешнего IP
try:
import urllib.request
with urllib.request.urlopen('http://httpbin.org/ip', timeout=5) as response:
ip_info = response.read().decode('utf-8')
print(f"\nВнешний IP: {ip_info.strip()}")
except:
print("\nВнешний IP: Не удалось определить")
print("========================\n")
def main():
"""Главная функция"""
parser = argparse.ArgumentParser(
description='Phantom VPN Client - VPN клиент через Phantom сеть'
)
parser.add_argument(
'--server',
required=True,
help='Адрес VPN сервера'
)
parser.add_argument(
'--port',
type=int,
default=1194,
help='Порт VPN сервера (по умолчанию: 1194)'
)
parser.add_argument(
'--interface',
default='tun0',
help='Имя TUN интерфейса (по умолчанию: tun0)'
)
parser.add_argument(
'--hops',
type=int,
default=3,
help='Количество хопов через Phantom сеть (по умолчанию: 3)'
)
parser.add_argument(
'--local-ip',
default='10.8.0.2',
help='Локальный IP адрес (по умолчанию: 10.8.0.2)'
)
parser.add_argument(
'--verbose',
action='store_true',
help='Подробный вывод'
)
parser.add_argument(
'--status',
action='store_true',
help='Показать статус и выйти'
)
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
# Создание VPN клиента
vpn_client = PhantomVPNClient(
server_host=args.server,
server_port=args.port,
interface=args.interface,
hops=args.hops
)
vpn_client.local_ip = args.local_ip
if args.status:
vpn_client.show_status()
return
try:
# Запуск VPN клиента
if vpn_client.start():
print("\nPhantom VPN подключен. Нажмите Ctrl+C для отключения")
# Основной цикл
while vpn_client.running:
time.sleep(1)
else:
logger.error("Не удалось запустить VPN клиент")
sys.exit(1)
except KeyboardInterrupt:
logger.info("Получен сигнал прерывания, отключение VPN...")
except Exception as e:
logger.error(f"Критическая ошибка: {e}")
finally:
vpn_client.stop()
if __name__ == '__main__':
main()