Repository navigation
[Feature] SOCKS5 proxy support for outbound provider calls - and fail fast on unsupported proxy schemes #2894
Description
Activity
github-actions commented
on Aug 29, 2026 on Aug 29, 2026 – with GitHub ActionsContributorMore actionsIssue reopened
The report now contains the information required by the automated check. Thanks for updating it.
- addedenhancementNew feature or requestNew feature or requestaccount-poolOAuth, credentials, Codex pool, quota, failover, plansOAuth, credentials, Codex pool, quota, failover, plans
on Aug 29, 2026 리뷰 · 우선순위 55 / 80
설명
제한된 네트워크에서 업스트림으로 나갈 때 (1) HTTP만이 아니라 SOCKS5(
sing-box,ssh -D, Tor 등)로 전체 provider 트래픽을 보내고, (2) 프로바이더마다 다른 프록시/다이렉트를 고르고 싶다는 기능 요청입니다. 오늘config.proxy는 HTTP(S) URL만 가정하고, Bun fetch는 SOCKS를 구현하지 않으며(미구현 이슈 oven-sh/bun#16812), 모르는 스킴을 HTTP로 조용히 취급해 실패가 늦어집니다.현재
dev에서src/config.ts의 proxy→HTTP(S)_PROXY 미러링과src/cli/doctor.ts의config.proxy진단이 이 표면입니다. SOCKS5 문자열을 검색해도 제품 경로에 정식 지원은 없습니다. Omniroute식 "기본 프록시 + 프로바이더별 override(direct/default/custom)"는 account-pool 라벨과도 맞닿지만, 지금은 라우팅 전략(#2050 combo, #2875 kiro quota)과 다른 전송 계층 요구입니다.구현 난이도가 큽니다. Bun 런타임이 SOCKS를 안 하면
undici/socks-proxy-agent같은 우회 fetch 스택을 프로바이더별로 갈라야 하고, 네이티브 fetch에 의존하는 경로가 많으면 구멍 mid-flight가 생깁니다. "미지원 스킴은 즉시 실패"는 상대적으로 싸고 지금 당장 가치가 있습니다. doctor가socks5://를 보고 HTTP로 오인하지 않게 하는 가드가 첫 단계로 적합합니다.types/config 분할 캠페인과 겹칩니다.
config.proxy스키마·프로바이더별 override를 넣으면types.ts/config.ts대형 PR과 충돌하기 쉽습니다. 분할이 끝나기 전에 큰 스키마 확장 PR이 오면 close-don't-rebase를 권하는 기존 방침이 적용될 수 있습니다.경로 config.proxy / src/config.ts - HTTP(S)만 env로 미러. socks5는 Bun이 협상하지 않아 연결이 이상하게 실패하거나 오인됩니다.
경로 src/cli/doctor.ts config.proxy - 스킴 검증을 강화해 SOCKS/unknown을 명시적으로 거부·경고하는 편이 안전합니다. 전체 SOCKS 구현보다 우선 가능합니다.
경로 프로바이더별 프록시 - 스키마·GUI·풀 라우팅까지 범위가 커집니다. Omniroute 패리티를 한 PR에 넣지 말고 단계를 나누어야 합니다.
경로 런타임 - Bun SOCKS 미지원이 막히면 Node undici 전환 또는 외부 forward proxy(HTTP로 SOCKS에 다시 붙는 local relay) 문서화가 현실적 대안입니다.메인테이너의 판단이 필요한 지점
- 단기: 미지원 스킴 fail-fast + 문서만 할지, SOCKS 지원을 정식 로드맵에 올릴지
- 프로바이더별 프록시 override를 config 분할 이후로 미룰지
- Bun 업스트림 지원을 기다릴지, 우회 HTTP 클라이언트를 도입할지
- 보안/유출 리뷰가 필요한 전송 변경이므로 non-author 승인 거버넌스 적용 여부
너의 추천
enhancement로 유지하되, 먼저 "SOCKS/unknown 스킴 fail-fast + doctor 경고"만 작은 PR로 받고, 실제 SOCKS 전송과 per-provider override는 config 분할 이후 설계 이슈로 분리하세요. 지금 큰 구현 PR이 오면 분할 캠페인에 무효화될 가능성이 있어 close-don't-rebase 대상이 될 수 있다고 명시합니다.이 댓글은 grok-bot이 작성했습니다
Thanks, this materially improves the upstream path. I checked oven-sh/bun#40461: it is currently open, unmerged, and blocked on review at head 9a66e8508862b55f97851a2726824d083d2d7d12, so it is not available in the Bun 1.3.14 runtime OpenCodex currently pins.
The near-term order therefore stays the same: first reject unsupported or unknown proxy schemes at config/apply time and surface a precise doctor message instead of letting Bun silently treat SOCKS as HTTP. Once the upstream PR is merged into a Bun release we can actually pin and test, we should re-evaluate native socks5 and socks5h support before introducing a second fetch stack. Per-provider direct/default/custom egress remains a separate transport-design slice because it must cover model calls, OAuth refresh, quota probes, discovery, and sidecars consistently.
Reacted by agentHitsPost-main scope consolidation at 7c625fc (2.60.0): the global SOCKS5 HTTP/SSE transport is delivered through #4986 and its content-coding / lifecycle follow-ups (#5070, #5126, #5127). This is not a remaining request to implement global SOCKS5 from scratch.
Keep this issue open for its distinct per-provider egress requirement: an explicit inherit/direct/proxy decision, correct noProxy and protocol handling, and the same decision for inference, provider discovery, quota and OAuth refresh without leaking proxy credentials. #3901 is the existing HTTP(S)-override implementation candidate, not proof that every SOCKS/control-plane case is delivered. #5087 covers the separate prerequisite that a proxy must actually apply to the destination before direct-route DNS pinning can be relaxed.
Use those existing PRs rather than opening another competing egress implementation. Preserve unsupported transport cases as explicit refusals; a missing effective proxy must not silently change the admitted direct destination.
- added 4 commits that reference this issue
on Sep 20, 2026 Closing as delivered. The global SOCKS5 transport shipped through #4986 and its follow-ups (#5070, #5126, #5127), and the remaining per-provider egress requirement recorded in the 2026-09-20 scope note landed later that day in #5289:
providers.<name>.proxyaccepts absent (inherit),"direct"/null,http(s)://andsocks5(h)://, andproviders.<name>.noProxyapplies to whichever route resolved. The authority issrc/lib/provider-egress.tsondev. If a specific provider or transport still ignores its per-provider route, please open a new issue with that route and a redacted config.
Area
Proxy and routing
What are you trying to accomplish?
Two related needs when reaching model upstreams from restricted networks:
ssh -D, Tor), which is the most common listen mode for those tools.proxyfor everything cannot express this — exactly the split Omniroute has: a common default proxy plus a per-provider override with a "direct / default / custom" choice.What prevents this today?
config.proxysupports HTTP(S) proxy URLs only. Bun's fetch (the bundled runtime) does not implement SOCKS —socks5://is not negotiated (upstream Add SOCKS support oven-sh/bun#16812 open), and worse, Bun silently treats the unknown scheme as HTTP instead of failing (Bun treating unknown proxy protocol as HTTP instead of fail oven-sh/bun#11343). The config layer accepts any string without scheme validation, soproxy: "socks5://127.0.0.1:1080"is stored, mirrored intoHTTP_PROXY/HTTPS_PROXYbyapplyProxyEnv(), and only produces confusing network-level errors at request time. A user with only a SOCKS5 endpoint must spin up an extra HTTP listener (privoxy/glider/sing-box mixed port) as a workaround.proxyexists only at the top level ofOcxConfig(src/types/config.ts:506).OcxProviderConfig(src/types/provider.ts:138) has no proxy field of any kind, so per-provider egress is impossible: either everything goes through the single proxy (regional upstreams suffer), or nothing does (restricted upstreams are unreachable).What should OpenCodex do?
A. Per-provider proxy with a global default (Omniroute-style two-level model):
proxy/noProxykeep working exactly as today and become the default for every provider.proxy+noProxywith three effective states:null/""→ force direct egress, exempting the provider from the global proxy.ocx inspect(orocx provider test <name>) should show which proxy each provider resolves to (global / custom / direct), andocx doctorshould probe each configured proxy.B. SOCKS5 support:
socks5://(local DNS) and ideallysocks5h://(remote DNS — normally what users behind restrictive networks want) in both the global and per-provider fields; RFC 1928 handshake + RFC 1929 user/pass auth.socks5*://with a clear message ("SOCKS proxies are not supported yet — use the HTTP inbound of your tunnel client") instead of the current silent misrouting.Example usage or interface
Effective-resolution view (illustrative):
Alternatives or workarounds
proxyat it — works, but adds a moving part per machine and still cannot split providers onto different exits.proxyvalues and split catalogs — heavy, doubles the service/dashboard footprint, and clients must know which port to call.Additional context
Bun.connect/netfor proxied calls until Bun grows SOCKS support (community drop-in implementations exist and are MIT-licensed).Checks