Tools / src /network_utils.py
jebin2's picture
Refactor: Standardize logging by replacing print statements with logger calls and adjusting verbosity levels.
503d4ac
import logging
import socket
import json
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
logger = logging.getLogger(__name__)
# Cache for resolved IPs to avoid spamming DoH
_DNS_CACHE = {}
_ORIGINAL_GETADDRINFO = socket.getaddrinfo
def resolve_via_doh(hostname):
"""
Resolve hostname using Google DNS-over-HTTPS.
Bypasses local system resolver (/etc/resolv.conf).
"""
if hostname in _DNS_CACHE:
return _DNS_CACHE[hostname]
try:
# We must use an IP for the DoH server to avoid DNS loop!
# 8.8.8.8 is Google DNS.
doh_url = f"https://8.8.8.8/resolve?name={hostname}&type=A"
# Use a fresh simple session without adapters to avoid recursion
# But wait, requests might try to resolve 8.8.8.8? No, it's an IP.
resp = requests.get(doh_url, timeout=5, verify=False) # Skip verify for DoH to be fast/safe
data = resp.json()
if 'Answer' in data:
for answer in data['Answer']:
if answer['type'] == 1: # A Record
ip = answer['data']
logger.debug(f"🔍 DoH Resolved {hostname} -> {ip}")
_DNS_CACHE[hostname] = ip
return ip
except Exception as e:
logger.error(f"⚠️ DoH Resolution failed for {hostname}: {e}")
return None
def patched_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
"""
Custom getaddrinfo that attempts DoH if system resolution fails or for specific hosts.
"""
# Only intervene for Facebook/Instagram APIs which are failing in this environment
if host in ('graph.facebook.com', 'www.facebook.com', 'api.instagram.com', 'graph.instagram.com'):
ip = resolve_via_doh(host)
if ip:
# Call original with IP instead of hostname
# Log usage for debugging
# logger.debug(f"Redirecting {host} to {ip}")
return _ORIGINAL_GETADDRINFO(ip, port, family, type, proto, flags)
# Fallback to system resolver
return _ORIGINAL_GETADDRINFO(host, port, family, type, proto, flags)
def force_ipv4_requests():
"""
Installs the DNS patch.
Named 'force_ipv4_requests' for backward compatibility with existing calls.
"""
if socket.getaddrinfo != patched_getaddrinfo:
socket.getaddrinfo = patched_getaddrinfo
logger.debug("🛡️ Installed DoH-based DNS patch for Facebook API")
else:
logger.debug("🛡️ DNS patch already active")
def get_resilient_session():
"""
Returns a session with retry logic.
"""
session = requests.Session()
retry = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('https://', adapter)
session.mount('http://', adapter)
# Ensure patch is applied whenever we get a session
force_ipv4_requests()
return session