HTTP/3 e UDP su SOCKS5
Updated:
I proxy residenziali trasportano il traffico UDP tramite SOCKS5. Utilizzali per aprire siti web tramite HTTP/3 (QUIC) da un IP residenziale e per instradare qualsiasi altro protocollo UDP: DNS, WebRTC, VoIP, giochi online.
Funziona su tutte le liste che già possiedi: stesso host, stesse porte, stesso nome utente e stessa password. Non c’è nulla da abilitare né da ordinare.
Come funziona
HTTP/3 funziona su QUIC, e QUIC funziona su UDP. Il protocollo proxy HTTP supporta solo TCP, quindi il traffico UDP passa attraverso SOCKS5.
Traffico | Proxy HTTP | SOCKS5 |
|---|---|---|
TCP: HTTP/1.1, HTTP/2, qualsiasi altro protocollo TCP | ✅ | ✅ |
UDP: HTTP/3 (QUIC), DNS, WebRTC, VoIP, giochi | — | ✅ |
Prima che il primo datagramma lasci il tuo computer, avvengono tre scambi:
Connettiti ed effettua l'autenticazione
La tua app apre una connessione SOCKS5 al gateway ed effettua l'accesso utilizzando l'ID utente e la password presenti nel tuo elenco.
Richiedi un relay UDP
Invia un
UDP ASSOCIATErichiesta (RFC 1928). Il gateway risponde con un indirizzo di inoltro: l’IP del gateway e una porta compresa nell’intervallo 30000–39999.Invia datagrammi
L'app invia datagrammi UDP a quel relay. Ogni datagramma inizia con una breve intestazione SOCKS5 che indica la destinazione. Il traffico parte dall'IP di uscita residenziale e le risposte tornano lungo lo stesso percorso.
Il relay rimane attivo finché la connessione TCP SOCKS5 rimane aperta. Chiudendo la connessione di controllo, anche il relay si chiude.
Impostazioni di connessione
Ambientazione | Valore |
|---|---|
Protocollo | SOCKS5 con autenticazione tramite nome utente/password |
Host |
|
Portare | una porta qualsiasi dalla tua lista (10000–10999) |
Nome utente e password | il nome utente e la password presenti nel tuo elenco |
Relè UDP | l'IP del gateway, porte 30000–39999 |
HTTP e SOCKS5 condividono lo stesso host, le stesse porte, lo stesso nome utente e la stessa password: il gateway rileva automaticamente il protocollo. Per passare a SOCKS5, modificare solo lo schema e nient’altro:
http://LOGIN:[email protected]:10000
socks5://LOGIN:[email protected]:10000Il gateway è solo il punto di ingresso. L’IP di uscita e la sua posizione derivano dalle impostazioni dell’elenco, indipendentemente dal gateway utilizzato; scegli quindi il gateway con la latenza più bassa rispetto al tuo server.
Se la tua rete limita il traffico in uscita, consenti il traffico UDP verso il gateway sulle porte 30000–39999. Un intervallo di porte bloccato è il motivo più comune per cui il controllo UDP riportato di seguito va in timeout.
Controlla tu stesso
Verifica la connessione
Va bene qualsiasi client SOCKS5 —
curlÈ sufficiente:curl -x socks5h://LOGIN:[email protected]:10000 https://api.ipify.orgLa risposta è l'IP di uscita del proxy. Con
socks5h://, i nomi di dominio vengono risolti dal proxy, non dal tuo computer.Controlla UDP
Questo script utilizza esclusivamente la libreria standard di Python. Effettua l’accesso tramite SOCKS5, apre un relay UDP e invia una query DNS attraverso di esso. Il resolver OpenDNS risponde
myip.opendns.comcon l'indirizzo da cui proviene la richiesta, in modo che lo script visualizzi l'IP di uscita del tuo traffico UDP.Salvarlo come
socks5_udp.py, imposta il tuo nome utente e la password, quindi avviapython 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()Esempio di risultato:
UDP relay: 103.152.136.28:39631 Exit IP over UDP: 203.0.113.45Invia una richiesta HTTP/3
Per HTTP/3, i pacchetti QUIC della richiesta passano attraverso lo stesso relay UDP. Questo esempio utilizza il aioquic libreria (Python 3.11 o versioni successive). Carica https://cloudflare-quic.com/cdn-cgi/trace, una pagina in testo semplice che mostra il protocollo e l’IP del client.
Installare le dipendenze, salvare lo script come
http3_via_socks5.pyaccanto asocks5_udp.py, ed eseguirlo: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()Risultato (versione abbreviata):
ip=203.0.113.45 http=http/3 loc=GB tls=TLSv1.3http=http/3significa che il sito web ha ricevuto la richiesta tramite HTTP/3.ipelocsono l'IP di uscita del proxy e il suo paese.
HTTP/3 nei browser e in altre app
Un’app può inviare UDP tramite un proxy solo se supporta UDP su SOCKS5 (UDP ASSOCIATE).
Chrome e Firefox non inviano pacchetti UDP attraverso un proxy SOCKS5 configurato nelle proprie impostazioni. I siti web vengono quindi aperti tramite HTTP/2 o HTTP/1.1 anziché HTTP/3.
Per utilizzare HTTP/3 in un browser o in un'altra app, instradare il traffico attraverso uno strumento che inoltri UDP tramite SOCKS5. L'app non vede mai il proxy, quindi utilizza HTTP/3 come di consueto, mentre lo strumento invia i pacchetti QUIC attraverso il gateway.
Windows, macOS, Linux. Aggiungere un socks in uscita con i dettagli del tuo elenco e un tun in entrata per acquisire il traffico delle tue app. Il protocollo UDP è abilitato nel socks in uscita per impostazione predefinita:
{
"type": "socks",
"tag": "residential",
"server": "res.proxy-seller.com",
"server_port": 10000,
"version": "5",
"username": "LOGIN",
"password": "PASSWORD"
}Windows. Reindirizza il traffico delle app selezionate tramite SOCKS5, inclusi UDP e QUIC. Scegli le app che devono passare attraverso il proxy e imposta il profilo indicando lo stesso host, la stessa porta, lo stesso nome utente e la stessa password.
Limiti
UDP funziona solo su SOCKS5. Le connessioni proxy HTTP utilizzano il protocollo TCP.
La connessione al proxy stesso tramite HTTPS (TLS) o HTTP/3 non è supportata — utilizzare
http://oppuresocks5://.Una sessione UDP può ottenere un indirizzo IP di uscita diverso rispetto alle connessioni TCP sulla stessa porta.
Domande frequenti
No. UDP e HTTP/3 funzionano su ogni elenco, con le credenziali di accesso che già possiedi.
No. HTTP e SOCKS5 su TCP continuano a funzionare esattamente come prima.
Quello con la latenza più bassa dal tuo server. Il gateway non modifica l’IP di uscita né la sua posizione: questi dati provengono dalle impostazioni dell’elenco.
Assicurati che il tuo firewall o il tuo provider di hosting non blocchi il traffico UDP in uscita verso il gateway sulle porte 30000–39999. Mantieni aperta la connessione TCP SOCKS5 mentre invii il traffico UDP: il relay si chiude contemporaneamente alla chiusura di tale connessione.
L'attivazione di un nuovo elenco richiede 1–2 minuti. Fino ad allora il proxy potrebbe restituire l'errore 407. Attendere qualche istante e riprovare.