HTTP/3 y UDP sobre SOCKS5
Actualizado:
Los proxies residenciales transmiten tráfico UDP a través de SOCKS5. Úsalos para abrir páginas web mediante HTTP/3 (QUIC) desde una IP residencial y para enrutar cualquier otro protocolo UDP: DNS, WebRTC, VoIP y juegos en línea.
Funciona con todas las listas que ya tengas: mismo servidor, mismos puertos, mismo nombre de usuario y misma contraseña. No hay que activar nada ni hacer ningún pedido.
Cómo funciona
HTTP/3 se ejecuta sobre QUIC, y QUIC se ejecuta sobre UDP. El protocolo de proxy HTTP solo admite TCP, por lo que el tráfico UDP pasa por SOCKS5.
Tráfico | Proxy HTTP | SOCKS5 |
|---|---|---|
TCP: HTTP/1.1, HTTP/2 y cualquier otro protocolo TCP | ✅ | ✅ |
UDP: HTTP/3 (QUIC), DNS, WebRTC, VoIP, videojuegos | — | ✅ |
Se producen tres intercambios antes de que el primer datagrama salga de tu equipo:
Conectarse e autenticarse
Tu aplicación abre una conexión SOCKS5 con la pasarela y inicia sesión con el nombre de usuario y la contraseña de tu lista.
Solicitar un relé UDP
Envía un
UDP ASSOCIATEsolicitud (RFC 1928). La pasarela responde con una dirección de retransmisión: la IP de la pasarela y un puerto comprendido entre 30000 y 39999.Enviar datagramas
La aplicación envía datagramas UDP a ese relé. Cada datagrama comienza con una breve cabecera SOCKS5 que indica el destino. El tráfico sale desde la IP de salida residencial y las respuestas vuelven por el mismo camino.
El relé permanece activo mientras la conexión TCP SOCKS5 permanezca abierta. Si se cierra la conexión de control, el relé se cierra con ella.
Configuración de la conexión
Ambiente | Valor |
|---|---|
Protocolo | SOCKS5 con autenticación mediante nombre de usuario y contraseña |
Anfitrión |
|
Portar | cualquier puerto de tu lista (10000–10999) |
Nombre de usuario y contraseña | el nombre de usuario y la contraseña de tu lista |
Retransmisión UDP | la IP de la puerta de enlace, puertos 30000–39999 |
HTTP y SOCKS5 comparten el mismo servidor, puertos, nombre de usuario y contraseña; la pasarela detecta el protocolo por sí misma. Para cambiar una cadena de conexión a SOCKS5, modifica solo el esquema y nada más:
http://LOGIN:[email protected]:10000
socks5://LOGIN:[email protected]:10000La puerta de enlace es solo el punto de entrada. La IP de salida y su ubicación provienen de la configuración de la lista, independientemente de la puerta de enlace que utilices; por lo tanto, elige la puerta de enlace con menor latencia desde tu servidor.
Si tu red restringe el tráfico saliente, permite el tráfico UDP hacia la puerta de enlace en los puertos 30000–39999. Un rango bloqueado suele ser la causa habitual de que la comprobación UDP que se indica a continuación agote el tiempo de espera.
Compruébalo tú mismo
Comprueba la conexión
Cualquier cliente SOCKS5 servirá —
curlEs suficiente:curl -x socks5h://LOGIN:[email protected]:10000 https://api.ipify.orgLa respuesta es la IP de salida del proxy. Con
socks5h://, los nombres de dominio son resueltos por el proxy, no por tu ordenador.Comprueba UDP
Este script utiliza únicamente la biblioteca estándar de Python. Se conecta a través de SOCKS5, abre un relé UDP y envía una consulta DNS a través de él. El resolutor de OpenDNS responde
myip.opendns.comcon la dirección de la que proviene la consulta, de modo que el script muestre la IP de salida de tu tráfico UDP.Guárdalo como
socks5_udp.py, configura tu nombre de usuario y contraseña, y ejecutapython socks5_udp.py."""UDP through a residential proxy: SOCKS5 login, UDP ASSOCIATE and one DNS query. The OpenDNS resolver answers "myip.opendns.com" with the IP the query came from, so the script prints the exit IP your UDP traffic leaves from. """ import os import socket import struct PROXY_HOST = "res.proxy-seller.com" PROXY_PORT = 10000 LOGIN = "LOGIN" PASSWORD = "PASSWORD" def recv_exact(sock, n): data = b"" while len(data) < n: chunk = sock.recv(n - len(data)) if not chunk: raise ConnectionError("proxy closed the connection") data += chunk return data def udp_associate(host, port, login, password): """SOCKS5 login (RFC 1929) and UDP ASSOCIATE (RFC 1928). Returns the TCP control connection and the UDP relay address. The relay works while the TCP connection stays open. """ tcp = socket.create_connection((host, port), timeout=15) tcp.sendall(b"\x05\x01\x02") # SOCKS5, one auth method: username/password if recv_exact(tcp, 2)[1] != 0x02: raise RuntimeError("username/password authentication is not available") tcp.sendall(b"\x01" + bytes([len(login)]) + login.encode() + bytes([len(password)]) + password.encode()) if recv_exact(tcp, 2)[1] != 0x00: raise RuntimeError("wrong login or password") tcp.sendall(b"\x05\x03\x00\x01" + bytes(6)) # UDP ASSOCIATE, client address 0.0.0.0:0 _, reply, _, atyp = recv_exact(tcp, 4) if reply != 0x00: raise RuntimeError(f"UDP ASSOCIATE failed, reply code {reply}") if atyp == 0x01: relay_ip = socket.inet_ntoa(recv_exact(tcp, 4)) elif atyp == 0x03: relay_ip = recv_exact(tcp, recv_exact(tcp, 1)[0]).decode() else: raise RuntimeError("IPv6 relay address is not handled in this example") relay_port = struct.unpack("!H", recv_exact(tcp, 2))[0] if relay_ip == "0.0.0.0": relay_ip = tcp.getpeername()[0] return tcp, (relay_ip, relay_port) def strip_udp_header(datagram): """Remove the SOCKS5 UDP header from a datagram received from the relay.""" atyp = datagram[3] if atyp == 0x01: # IPv4 return datagram[10:] if atyp == 0x04: # IPv6 return datagram[22:] return datagram[7 + datagram[4]:] # domain name if __name__ == "__main__": tcp, relay = udp_associate(PROXY_HOST, PROXY_PORT, LOGIN, PASSWORD) print("UDP relay:", f"{relay[0]}:{relay[1]}") # DNS query "myip.opendns.com, type A" without EDNS: the answer ends with the IPv4 address query = (os.urandom(2) + b"\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" + b"\x04myip\x07opendns\x03com\x00" + b"\x00\x01\x00\x01") # every datagram to the relay starts with a SOCKS5 UDP header: RSV, FRAG, ATYP=IPv4, destination header = b"\x00\x00\x00\x01" + socket.inet_aton("208.67.222.222") + struct.pack("!H", 53) udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp.settimeout(10) udp.sendto(header + query, relay) answer = strip_udp_header(udp.recv(4096)) print("Exit IP over UDP:", socket.inet_ntoa(answer[-4:])) udp.close() tcp.close()Ejemplo de resultado:
UDP relay: 103.152.136.28:39631 Exit IP over UDP: 203.0.113.45Enviar una solicitud HTTP/3
En el caso de HTTP/3, los paquetes QUIC de la solicitud pasan por el mismo relé UDP. Este ejemplo utiliza el aioquic biblioteca (Python 3.11 o posterior). Carga https://cloudflare-quic.com/cdn-cgi/trace, una página de texto sin formato que muestra el protocolo y la IP del cliente.
Instala las dependencias y guarda el script como
http3_via_socks5.pyjunto asocks5_udp.py, y ejecútalo:pip install aioquic certifi python http3_via_socks5.py"""HTTP/3 (QUIC) request to a website through a residential proxy. QUIC packets go to the SOCKS5 UDP relay; the website sees an HTTP/3 connection from the exit IP. Requires: pip install aioquic certifi, and socks5_udp.py from the previous example in the same folder. """ import socket import struct import time import certifi from aioquic.h3.connection import H3_ALPN, H3Connection from aioquic.h3.events import DataReceived, HeadersReceived from aioquic.quic.configuration import QuicConfiguration from aioquic.quic.connection import QuicConnection from aioquic.quic.events import ConnectionTerminated, HandshakeCompleted from socks5_udp import LOGIN, PASSWORD, PROXY_HOST, PROXY_PORT, strip_udp_header, udp_associate TARGET_HOST = "cloudflare-quic.com" TARGET_PATH = "/cdn-cgi/trace" # plain text: shows the protocol (http=http/3) and the client IP tcp, relay = udp_associate(PROXY_HOST, PROXY_PORT, LOGIN, PASSWORD) udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # the destination goes into the SOCKS5 UDP header as a domain name (ATYP=3): the proxy resolves it header = b"\x00\x00\x00\x03" + bytes([len(TARGET_HOST)]) + TARGET_HOST.encode() + struct.pack("!H", 443) config = QuicConfiguration(is_client=True, alpn_protocols=H3_ALPN, server_name=TARGET_HOST) config.load_verify_locations(certifi.where()) quic = QuicConnection(configuration=config) peer = ("0.0.0.0", 443) # placeholder: only the proxy knows the real address quic.connect(peer, now=time.time()) h3 = H3Connection(quic) def send_pending(): for datagram, _ in quic.datagrams_to_send(now=time.time()): udp.sendto(header + datagram, relay) send_pending() stream_id, body, done = None, b"", False deadline = time.time() + 20 while not done and time.time() < deadline: timer = quic.get_timer() udp.settimeout(0.5 if timer is None else min(0.5, max(0.01, timer - time.time()))) try: quic.receive_datagram(strip_udp_header(udp.recv(65535)), peer, now=time.time()) except socket.timeout: if timer is not None and time.time() >= timer: quic.handle_timer(now=time.time()) event = quic.next_event() while event is not None: if isinstance(event, HandshakeCompleted): stream_id = quic.get_next_available_stream_id() h3.send_headers(stream_id, [ (b":method", b"GET"), (b":scheme", b"https"), (b":authority", TARGET_HOST.encode()), (b":path", TARGET_PATH.encode()), ], end_stream=True) elif isinstance(event, ConnectionTerminated): done = True for h3_event in h3.handle_event(event): if isinstance(h3_event, (HeadersReceived, DataReceived)) and h3_event.stream_id == stream_id: if isinstance(h3_event, DataReceived): body += h3_event.data done = done or h3_event.stream_ended event = quic.next_event() send_pending() print(body.decode() or "No HTTP/3 response within 20 seconds") quic.close() send_pending() udp.close() tcp.close()Resultado (resumido):
ip=203.0.113.45 http=http/3 loc=GB tls=TLSv1.3http=http/3significa que el sitio web recibió la solicitud a través de HTTP/3.ipylocson la IP de salida del proxy y su país.
HTTP/3 en navegadores y otras aplicaciones
Una aplicación solo puede enviar UDP a través de un proxy si es compatible con UDP sobre SOCKS5 (UDP ASSOCIATE).
Chrome y Firefox no envían UDP a través de un proxy SOCKS5 configurado en sus propios ajustes. Por lo tanto, las páginas web se abren mediante HTTP/2 o HTTP/1.1 en lugar de HTTP/3.
Para utilizar HTTP/3 en un navegador u otra aplicación, redirige su tráfico a través de una herramienta que reenvía UDP por SOCKS5. La aplicación nunca ve el proxy, por lo que utiliza HTTP/3 como de costumbre, y la herramienta envía los paquetes QUIC a través de la pasarela.
Windows, macOS, Linux. Añade un socks envía un correo con los detalles de tu lista y un tun entrante para capturar el tráfico de tus aplicaciones. El protocolo UDP está habilitado en el socks saliente por defecto:
{
"type": "socks",
"tag": "residential",
"server": "res.proxy-seller.com",
"server_port": 10000,
"version": "5",
"username": "LOGIN",
"password": "PASSWORD"
}Windows. Desvía el tráfico de las aplicaciones seleccionadas a través de SOCKS5, incluyendo UDP y QUIC. Elige las aplicaciones que deben pasar por el proxy y configura el perfil con el mismo servidor, puerto, nombre de usuario y contraseña.
Limitaciones
UDP solo funciona a través de SOCKS5. Las conexiones de proxy HTTP utilizan TCP.
No se admite la conexión al propio proxy a través de HTTPS (TLS) o HTTP/3; utiliza
http://osocks5://.Una sesión UDP puede obtener una dirección IP de salida diferente a la de las conexiones TCP en el mismo puerto.
Preguntas frecuentes
No. UDP y HTTP/3 funcionan en todas las listas, con el nombre de usuario y la contraseña que ya tienes.
No. HTTP y SOCKS5 sobre TCP siguen funcionando exactamente igual que antes.
La que tenga la latencia más baja desde tu servidor. La puerta de enlace no modifica la IP de salida ni su ubicación; estas se obtienen de la configuración de la lista.
Asegúrate de que tu cortafuegos o tu proveedor de alojamiento no bloquee el tráfico UDP saliente hacia la pasarela en los puertos 30000–39999. Y mantén abierta la conexión TCP SOCKS5 mientras envías UDP: el relé se cierra al mismo tiempo que esta.
Una nueva lista tarda entre 1 y 2 minutos en activarse. Hasta entonces, el proxy puede responder con el error 407. Espera un momento y vuelve a intentarlo.