Saat bekerja dengan proxy, pengembang sering menghadapi kenyataan bahwa pengaturan proxy HTTP klasik tidak berfungsi untuk koneksi WebSocket, dan gRPC bahkan terputus dengan kesalahan TLS handshake. Masalah ini muncul karena WebSocket, HTTP/2, dan gRPC bukan sekadar "varian HTTP", melainkan model transportasi yang berbeda dengan persyaratan masing-masing untuk tunneling, multiplexing, dan pengolahan header. Dalam artikel ini, kita akan membahas cara memproses masing-masing protokol ini, jebakan yang sering ditemui dalam praktik, dan bagaimana memilih protokol dan jenis proxy untuk tugas tertentu — dari parsing melalui WebSocket hingga microservices gRPC yang sangat terbebani.
Apa yang membedakan protokol dan mengapa ini penting untuk proxy
HTTP/1.1 bekerja dengan model "permintaan - respons": klien membuka koneksi, mengirim permintaan, menerima respons, dan kemudian menutup koneksi atau mempertahankannya terbuka untuk permintaan berikutnya (keep-alive). Server proxy telah dioptimalkan selama beberapa dekade untuk model ini — parsing header, buffering tubuh permintaan, dan routing sederhana berdasarkan header Host.
WebSocket merusak model ini: setelah handshake HTTP awal (Upgrade: websocket), koneksi berubah menjadi saluran dua arah yang permanen, di mana data dapat mengalir ke kedua arah kapan saja. Proxy harus "melepaskan" koneksi ini dan hanya meneruskan byte ke kedua arah, tanpa mencoba menginterpretasikannya sebagai permintaan HTTP.
HTTP/2 menambahkan multiplexing — beberapa permintaan logis berjalan melalui satu koneksi TCP secara paralel, menggunakan frame biner alih-alih header teks. Untuk proxy, ini berarti bahwa tidak bisa hanya membaca teks baris demi baris — dukungan untuk protokol biner HTTP/2 pada level proxy atau tunneling TCP transparan di atas TLS diperlukan.
gRPC melangkah lebih jauh: ia dibangun secara ketat di atas HTTP/2, menggunakan Protocol Buffers untuk serialisasi dan memerlukan transportasi yang kompatibel dengan HTTP/2 di seluruh jalur dari klien ke server. Jika proxy di suatu titik "menurunkan" koneksi ke HTTP/1.1, permintaan gRPC tidak akan berhasil.
Memahami perbedaan ini sangat penting, karena memilih jenis proxy yang salah atau pengaturan tunneling yang tidak tepat dapat menyebabkan pemutusan koneksi, timeout, dan kesalahan yang sulit dijelaskan, yang sulit didiagnosis tanpa pemahaman tentang level transportasi.
WebSocket melalui proxy: pengaturan dan kode
Untuk WebSocket melalui proxy, ada dua skenario utama: proxy HTTP dengan metode CONNECT (untuk WSS, yaitu WebSocket melalui TLS) dan proxy SOCKS5, yang meneruskan koneksi TCP tanpa memeriksa protokol. SOCKS5 biasanya memberikan lebih sedikit masalah, karena awalnya dirancang sebagai "pipa transparan" untuk semua lalu lintas TCP.
Contoh koneksi ke WebSocket melalui proxy SOCKS5 di Python menggunakan pustaka websockets
dan python-socks:
import asyncio
from python_socks.sync import Proxy
import websockets
import websockets.sync.client as ws_client
def connect_ws_via_proxy():
proxy = Proxy.from_url("socks5://user:pass@proxy_host:1080")
sock = proxy.connect(dest_host="echo.websocket.events", dest_port=443)
ws = ws_client.connect(
"wss://echo.websocket.events",
sock=sock,
server_hostname="echo.websocket.events"
)
ws.send("Hello via proxy")
print(ws.recv())
ws.close()
connect_ws_via_proxy()
Di Node.js, tugas serupa diselesaikan melalui paket ws
dalam kombinasi dengan socks-proxy-agent:
const WebSocket = require('ws');
const { SocksProxyAgent } = require('socks-proxy-agent');
const agent = new SocksProxyAgent('socks5://user:pass@proxy_host:1080');
const socket = new WebSocket('wss://echo.websocket.events', { agent });
socket.on('open', () => socket.send('Hello via proxy'));
socket.on('message', (data) => console.log(data.toString()));
Jika proxy hanya tersedia melalui HTTP (dengan metode CONNECT), skema serupa — sebagian besar klien WebSocket modern dapat bekerja melalui tunnel HTTP, penting untuk memastikan bahwa proxy tidak memutus koneksi yang bertahan lama karena timeout. Ini adalah masalah umum dengan proxy pusat data murah, yang memiliki batas ketat 30-60 detik untuk koneksi yang tidak aktif — untuk tugas WebSocket streaming ini sangat penting, dan lebih baik untuk mengonfirmasi parameter keep-alive dengan penyedia.
HTTP/2 melalui proxy: multiplexing dan jebakan
Kesulitan utama dengan HTTP/2 melalui proxy adalah bahwa banyak server proxy (terutama Squid lama atau proxy forward sederhana) hanya bekerja dengan HTTP/1.1 dan secara otomatis "menurunkan" koneksi. Untuk klien, ini sering tidak terlihat (permintaan tetap dilaksanakan), tetapi keuntungan multiplexing hilang — latensi meningkat, terutama dengan banyak permintaan paralel ke satu host.
Untuk memeriksa apakah koneksi melalui proxy mendukung HTTP/2, Anda dapat menggunakan cURL dengan flag
--http2
dan output rinci:
curl -v --http2 -x http://user:pass@proxy_host:8080 https://example.com
# Dalam output, cari baris:
# * Using HTTP2, server supports multiplexing
# Jika tidak ada — koneksi turun ke HTTP/1.1
Di Python, untuk HTTP/2 melalui proxy, Anda memerlukan pustaka httpx
dengan dukungan HTTP/2 yang diaktifkan:
import httpx
proxies = {
"http://": "http://user:pass@proxy_host:8080",
"https://": "http://user:pass@proxy_host:8080",
}
with httpx.Client(proxies=proxies, http2=True) as client:
response = client.get("https://example.com")
print(response.http_version) # diharapkan "HTTP/2"
print(response.status_code)
Nuansa penting: HTTP/2 memerlukan TLS dengan ekstensi ALPN untuk negosiasi protokol, sehingga proxy harus meneruskan lalu lintas TLS secara transparan melalui CONNECT, bukan menghentikan TLS sendiri (kecuali jika itu adalah proxy yang kompatibel dengan HTTP/2 khusus). Itulah mengapa untuk tugas dengan HTTP/2, proxy residensial dan proxy pusat data berperilaku berbeda — penting untuk mengonfirmasi dengan penyedia apakah tunneling TLS end-to-end tanpa memutus negosiasi ALPN didukung.
gRPC melalui proxy: TLS, ALPN, dan persyaratan khusus
gRPC adalah protokol yang paling menuntut dalam rangkaian ini. Ia terikat ketat pada HTTP/2 dan sering menggunakan
TLS dua arah (mTLS) untuk otentikasi. Proxy forward biasa yang tidak mendukung tunneling HTTP/2 CONNECT
"sebagaimana adanya", tidak akan melewatkan lalu lintas gRPC — koneksi akan terputus dengan kesalahan seperti
UNAVAILABLE: upstream connect error.
Untuk memproses gRPC di Python (dengan pustaka grpc)
proxy ditentukan melalui variabel lingkungan, karena dukungan proxy bawaan dalam opsi saluran
secara historis tidak ada:
import os
import grpc
os.environ["grpc_proxy"] = "http://user:pass@proxy_host:8080"
os.environ["https_proxy"] = "http://user:pass@proxy_host:8080"
channel = grpc.secure_channel(
"grpc.example.com:443",
grpc.ssl_channel_credentials()
)
# Contoh panggilan melalui stub yang dihasilkan
# stub = YourServiceStub(channel)
# response = stub.YourMethod(request)
Di Node.js, proxy untuk gRPC diatur melalui opsi saluran grpc-js
dalam kombinasi dengan agen proxy yang kompatibel dengan HTTP/2:
const grpc = require('@grpc/grpc-js');
const { HttpsProxyAgent } = require('https-proxy-agent');
process.env.grpc_proxy = 'http://user:pass@proxy_host:8080';
process.env.https_proxy = 'http://user:pass@proxy_host:8080';
const client = new YourServiceClient(
'grpc.example.com:443',
grpc.credentials.createSsl()
);
Untuk operasi gRPC yang stabil melalui proxy, latensi rendah dan koneksi TCP yang stabil tanpa pemutusan yang sering sangat penting — aliran gRPC yang dimultiplex lebih sensitif terhadap gangguan jaringan dibandingkan dengan permintaan HTTP/1.1 yang terpisah. Dalam skenario seperti itu, proxy residensial sering menunjukkan stabilitas yang lebih baik dibandingkan dengan kolam pusat data murah, karena rute ke server tujuan melewati infrastruktur jaringan yang lebih dapat diprediksi.
Tabel perbandingan protokol
| Protokol | Jenis koneksi | Persyaratan untuk proxy | Jenis proxy yang direkomendasikan |
|---|---|---|---|
| HTTP/1.1 | permintaan-respons, keep-alive | minimal, proxy HTTP apa pun | Proxy pusat data |
| WebSocket | saluran dua arah permanen | dukungan untuk koneksi jangka panjang, tanpa timeout | Proxy residensial |
| HTTP/2 | stream biner yang dimultiplex | tunneling TLS end-to-end, ALPN | Proxy residensial atau pusat data |
| gRPC | HTTP/2 + Protobuf, sering mTLS | latensi rendah, stabilitas, HTTP/2 CONNECT | Proxy seluler untuk menghindari filter yang ketat |
Cara memilih protokol dan proxy untuk tumpukan Anda
Pemilihan protokol jarang menjadi keputusan yang bebas — itu ditentukan oleh API target. Namun, pemilihan jenis proxy untuk protokol ini adalah tanggung jawab Anda, dan di sini penting untuk mengandalkan skenario spesifik:
Parsing data melalui WebSocket (misalnya, streaming kutipan atau data real-time dari situs marketplace) memerlukan koneksi yang stabil dan panjang tanpa pemutusan karena timeout. Di sini, proxy residensial bekerja lebih baik — mereka jarang terjebak dalam algoritma anti-fraud dari layanan target dan mempertahankan koneksi lebih lama dibandingkan dengan kolam pusat data yang tipikal.
Integrasi dengan microservices gRPC melalui proxy eksternal (misalnya, saat menguji API dari berbagai geolokasi) memerlukan latensi rendah dan dukungan HTTP/2 di seluruh jalur. Untuk ini, IP residensial dengan routing yang baik cocok, dan untuk tugas yang sangat sensitif terhadap waktu — proxy seluler, jika layanan target secara agresif memfilter rentang pusat data.
Permintaan HTTP/2 massal ke REST/GraphQL API dengan multiplexing — adalah skenario paling umum di mana proxy pusat data yang cepat dan murah cukup, jika layanan target tidak memblokir rentang IP pusat data secara default.
Aturan umum: semakin "rewel" protokol terhadap stabilitas koneksi (WebSocket, gRPC), semakin banyak makna dalam menggunakan IP residensial atau seluler. Semakin sederhana dan lebih pendek permintaan (HTTP/1.1 biasa atau HTTP/2 tanpa sesi panjang), semakin nyaman bekerja dengan proxy pusat data — mereka lebih cepat dan memberikan bandwidth yang lebih tinggi.
Kesalahan umum dan solusinya
Kesalahan 1: WebSocket terputus setiap 30-60 detik. Penyebabnya adalah proxy atau penyeimbang beban perantara menutup koneksi "tidak aktif". Solusi: aktifkan frame ping/pong di level aplikasi dengan interval kurang dari timeout proxy (biasanya 20-25 detik sudah cukup).
Kesalahan 2: gRPC terputus dengan UNAVAILABLE melalui proxy, meskipun berfungsi langsung. Proxy tidak mendukung tunneling HTTP/2 CONNECT. Solusi: periksa dokumentasi penyedia untuk dukungan HTTP/2, atau gunakan proxy SOCKS5 yang meneruskan TCP tanpa menginterpretasikan protokol.
Kesalahan 3: HTTP/2 secara diam-diam diturunkan menjadi HTTP/1.1. Ini sering terjadi karena kurangnya dukungan ALPN pada proxy. Periksa versi protokol secara eksplisit dalam kode (seperti dalam contoh dengan httpx di atas) — jangan mengandalkan bahwa "semuanya berfungsi", jika Anda tidak memeriksa http_version dalam respons.
Kesalahan 4: Latensi tinggi saat multiplexing gRPC melalui proxy. Sering disebabkan oleh banyaknya node perantara di penyedia proxy. Solusi: uji latensi sebelumnya melalui permintaan RTT sederhana dan pilih penyedia dengan routing langsung, terutama untuk panggilan gRPC yang sensitif terhadap waktu.
Kesimpulan
WebSocket, HTTP/2, dan gRPC memerlukan pendekatan yang berbeda untuk pengaturan proxy karena mereka bekerja pada model transportasi yang berbeda: dari sekadar "melepaskan koneksi TCP" untuk WebSocket hingga dukungan ketat untuk HTTP/2 CONNECT dan ALPN untuk gRPC. Periksa versi protokol secara eksplisit dalam kode, uji stabilitas koneksi jangka panjang sebelumnya dan pilih SOCKS5 di mana diperlukan transparansi tunneling maksimum.
Jika tumpukan Anda mencakup koneksi WebSocket yang bertahan lama atau panggilan gRPC yang sensitif terhadap latensi, kami merekomendasikan untuk mencoba proxy residensial — mereka memberikan koneksi yang lebih stabil dan dapat diprediksi dibandingkan dengan kolam pusat data yang tipikal. Untuk permintaan HTTP/2 sederhana dengan bandwidth tinggi, proxy pusat data cocok, dan untuk tugas dengan filter anti-fraud yang agresif dari layanan target — proxy seluler.