fix proxy detect
This commit is contained in:
@@ -104,6 +104,48 @@ class Proxy:
|
||||
return None
|
||||
|
||||
|
||||
async def detect_proxy_type(
|
||||
ip: str,
|
||||
port: str,
|
||||
login: Optional[str] = None,
|
||||
password: Optional[str] = None,
|
||||
timeout: float = 5.0,
|
||||
test_url: str = "http://api.ipify.org"
|
||||
) -> Optional[ProxyType]:
|
||||
"""
|
||||
Определяет тип прокси подключением.
|
||||
Пробует SOCKS5 → SOCKS4 → HTTP. Возвращает первый рабочий или None.
|
||||
"""
|
||||
import aiohttp
|
||||
|
||||
candidates = [
|
||||
(ProxyType.SOCKS5, f"socks5://{ip}:{port}"),
|
||||
(ProxyType.SOCKS4, f"socks4://{ip}:{port}"),
|
||||
(ProxyType.HTTP, f"http://{ip}:{port}"),
|
||||
]
|
||||
|
||||
auth = aiohttp.BasicAuth(login, password) if login and password else None
|
||||
|
||||
for proxy_type, proxy_url in candidates:
|
||||
try:
|
||||
connector = aiohttp.TCPConnector(ssl=False)
|
||||
async with aiohttp.ClientSession(connector=connector) as session:
|
||||
async with session.get(
|
||||
test_url,
|
||||
proxy=proxy_url,
|
||||
proxy_auth=auth,
|
||||
timeout=aiohttp.ClientTimeout(total=timeout),
|
||||
) as resp:
|
||||
if resp.status == 200:
|
||||
logger.info(f"Proxy {ip}:{port} detected as {proxy_type.value}")
|
||||
return proxy_type
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
logger.warning(f"Proxy {ip}:{port} — type not detected")
|
||||
return None
|
||||
|
||||
|
||||
class ProxyManager:
|
||||
"""
|
||||
Менеджер прокси с поддержкой SOCKS5 и HTTP.
|
||||
|
||||
+45
-19
@@ -12,6 +12,7 @@ from dataclasses import dataclass
|
||||
|
||||
from camoufox import DefaultAddons
|
||||
from camoufox.async_api import AsyncCamoufox
|
||||
from camoufox.exceptions import InvalidIP
|
||||
|
||||
from config.settings import settings
|
||||
from managers.proxy_manager import ProxyManager, Proxy, ProxyType
|
||||
@@ -20,23 +21,43 @@ from services.socks5_to_http_proxy import Socks5ProxyPool
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _patch_camoufox():
|
||||
"""Патчит camoufox.utils.generate_fingerprint чтобы убирать screen constraint при ошибке."""
|
||||
import camoufox.utils as _cu
|
||||
_orig = _cu.generate_fingerprint
|
||||
_socks5_real_ip: Optional[str] = None
|
||||
|
||||
def _patched(**config):
|
||||
|
||||
def _patch_camoufox():
|
||||
"""Патчит camoufox чтобы:
|
||||
1. Убирать screen constraint из generate_fingerprint при ошибке
|
||||
2. Возвращать реальный IP SOCKS5 прокси вместо попытки запроса через туннель
|
||||
"""
|
||||
import camoufox.utils as _cu
|
||||
import camoufox.ip as _ci
|
||||
|
||||
# Патч 1: generate_fingerprint — убираем screen при ошибке
|
||||
_orig_gf = _cu.generate_fingerprint
|
||||
|
||||
def _patched_gf(**config):
|
||||
try:
|
||||
return _orig(**config)
|
||||
return _orig_gf(**config)
|
||||
except ValueError:
|
||||
config.pop("screen", None)
|
||||
try:
|
||||
return _orig(**config)
|
||||
return _orig_gf(**config)
|
||||
except ValueError:
|
||||
minimal = {k: v for k, v in config.items() if k == "locale"}
|
||||
return _orig(**minimal)
|
||||
return _orig_gf(**minimal)
|
||||
|
||||
_cu.generate_fingerprint = _patched
|
||||
_cu.generate_fingerprint = _patched_gf
|
||||
|
||||
# Патч 2: public_ip — возвращаем реальный IP прокси вместо HTTP-запроса через туннель
|
||||
_orig_ip = _ci.public_ip
|
||||
|
||||
def _patched_ip(proxy_string: str) -> str:
|
||||
global _socks5_real_ip
|
||||
if _socks5_real_ip and "127.0.0.1" in str(proxy_string):
|
||||
return _socks5_real_ip
|
||||
return _orig_ip(proxy_string)
|
||||
|
||||
_ci.public_ip = _patched_ip
|
||||
|
||||
_patch_camoufox()
|
||||
|
||||
@@ -101,20 +122,25 @@ class BrowserService:
|
||||
if self.proxy_manager.has_proxies():
|
||||
proxy = await self.proxy_manager.acquire_proxy(timeout=30)
|
||||
|
||||
socks5_locale = None
|
||||
global _socks5_real_ip
|
||||
proxy_locale = None
|
||||
|
||||
if proxy and proxy.proxy_type in [ProxyType.SOCKS5, ProxyType.SOCKS4]:
|
||||
proxy_config = await self.socks5_pool.get_proxy_config(proxy)
|
||||
use_socks5 = True
|
||||
# При SOCKS5 camoufox видит 127.0.0.1 → geoip берёт IP сервера → ru-Cyrl-RU
|
||||
# Делаем lookup по реальному IP прокси сами и передаём чистый locale
|
||||
real_ip = proxy.id.split("://")[-1].split(":")[0]
|
||||
socks5_locale = _locale_for_ip(real_ip)
|
||||
logger.info(f"Using SOCKS5 tunnel for: {proxy.id} locale={socks5_locale}")
|
||||
_socks5_real_ip = real_ip
|
||||
proxy_locale = _locale_for_ip(real_ip)
|
||||
logger.info(f"Using SOCKS5 tunnel for: {proxy.id} locale={proxy_locale}")
|
||||
elif proxy:
|
||||
proxy_config = proxy.proxy_config
|
||||
logger.info(f"Using HTTP proxy: {proxy.id}")
|
||||
real_ip = proxy.id.split("://")[-1].split(":")[0]
|
||||
_socks5_real_ip = real_ip
|
||||
proxy_locale = _locale_for_ip(real_ip)
|
||||
logger.info(f"Using HTTP proxy: {proxy.id} locale={proxy_locale}")
|
||||
else:
|
||||
proxy_config = None
|
||||
_socks5_real_ip = None
|
||||
logger.info("Direct connection")
|
||||
|
||||
if proxy_config:
|
||||
@@ -125,8 +151,8 @@ class BrowserService:
|
||||
exclude_addons=[DefaultAddons.UBO],
|
||||
proxy=proxy_config,
|
||||
)
|
||||
if socks5_locale:
|
||||
camoufox_kwargs["locale"] = socks5_locale
|
||||
if proxy_locale:
|
||||
camoufox_kwargs["locale"] = proxy_locale
|
||||
async with AsyncCamoufox(**camoufox_kwargs) as browser:
|
||||
result = await self._browse_page(
|
||||
browser, url,
|
||||
@@ -152,8 +178,8 @@ class BrowserService:
|
||||
|
||||
return result
|
||||
|
||||
except ValueError as e:
|
||||
logger.warning(f"Visit attempt {attempt + 1} fingerprint error, retrying with new proxy: {e}")
|
||||
except (ValueError, InvalidIP) as e:
|
||||
logger.warning(f"Visit attempt {attempt + 1} proxy error, retrying: {e}")
|
||||
if proxy:
|
||||
await self.proxy_manager.release_proxy(proxy, success=False)
|
||||
if use_socks5:
|
||||
|
||||
Reference in New Issue
Block a user