[Feature Request]: Docker egress proxy: opt-in hostname passthrough for public destinations (residential proxy providers require hostnames) #2257
sergeesteves
started this conversation in
Feature requests
Replies: 2 comments
|
Update: instead of the SNI gateway mentioned above, I implemented the proposed # _handle_absolute(), upstream branch
- out = f"{method} http://{_bracket(pin.ip)}:{port}{path} HTTP/1.1\r\n".encode("latin-1")
+ out = f"{method} http://{_bracket(pin.host)}:{port}{path} HTTP/1.1\r\n".encode("latin-1")
# _dial()
- dst = f"{_bracket(pin.ip)}:{port}"
+ dst = f"{_bracket(pin.host)}:{port}"
A proper contribution would add what this quick patch lacks: an opt-in env var |
0 replies
|
Follow-up: confirmed in production with the proxy provider. With the patch, their |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
What needs to be done?
Add an opt-in mode to the Docker server's egress pinning proxy so that, when
traffic is chained through an upstream proxy, the upstream receives
CONNECT <hostname>:<port>instead ofCONNECT <pinned-ip>:<port>for publicdestinations.
Today (0.9.3), every proxied request is an IP-only CONNECT. #2142 lists this as a
known limitation ("proxies that refuse CONNECT-to-an-IP are not supported yet")
and mentions a possible future opt-in hostname mode. This request is for that
mode, covering public-web crawling.
What problem does this solve?
Commercial residential proxy providers (e.g. Webshare) enforce trust & safety
rules that require the destination hostname on every request. My account was
suspended for "requests without hostname", and support asked me to reconfigure
the software to connect to hostnames instead of IP addresses.
With the current design this is impossible: the pinning proxy resolves locally
and always sends the pinned IP upstream. Commercial proxy providers with such
rules therefore cannot be used with the Docker server at all.
#2152 does not solve it either. It delegates hostnames only for an explicit list
of DNS suffixes, with wildcards rejected. That fits private networks with known
suffixes, but not public-web crawling, where target domains are arbitrary and
unknown in advance.
Target users/beneficiaries
(residential, ISP or datacenter) that require hostnames for compliance.
CONNECT to bare IPs (the limitation already listed in Docker: Chain egress proxy through upstream HTTP(S)_PROXY #2142).
suffix allowlist (Feat/upstream proxy hostname passthrough #2152) cannot be maintained.
Current alternatives/workarounds
sniffing.destOverride: ["http","tls"]): it answers the CONNECT, reads thehostname from the TLS ClientHello (or the Host header for plain HTTP), then
re-issues the CONNECT upstream with the hostname. It works, but it is an extra
service to run and secure, it holds the proxy credentials, and upstream errors
(e.g. 402/407) surface in Crawl4AI as closed connections instead of explicit
failures.
CRAWL4AI_ALLOW_INTERNAL_URLS=true: drops the entry-point check for everydestination and still does not send hostnames upstream. Not a real option.
the Docker server and its security hardening.
Proposed approach
An opt-in env var on the upstream path only, e.g.
CRAWL4AI_UPSTREAM_PROXY_HOSTNAME_PASSTHROUGH=public:resolve_and_pin()as a validation step: resolve locally and rejectnon-global addresses, exactly as today.
CONNECT <hostname>:<port>to the upstreaminstead of the pinned IP (and the absolute-form hostname for plain HTTP).
current pinned path. NO_PROXY behaviour is unchanged. The upstream is never
bypassed and the target is never dialed directly.
Trust model: the connection is only ever handed to the operator-configured
upstream, so the crawler's own network stays unreachable even if a name
re-resolves differently on the upstream side. The remaining gap (the upstream
resolving to another address than the one validated) is the same deliberate
trust decision already accepted in #2152, but narrower: private destinations
are still rejected at validation time, and no suffix list is required.
It could also be a keyword of #2152's variable (e.g. accepting
publicas aspecial value) rather than a separate variable, if maintainers prefer one knob.
Happy to test a branch.
All reactions