Fix: Proxy DNS resolution - support remote DNS for all proxy types#61
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #61 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 19 19
Lines 1207 1236 +29
Branches 144 148 +4
=========================================
+ Hits 1207 1236 +29
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Sentry.
|
|
@hawktang hello, thank you for your contribution. Please check status of pipeline. |
|
I have updated the test. |
|
@hawktang run pre-commit locally |
|
I have run the pre commit and fixed the issues |
5701fb1 to
894734f
Compare
|
@hawktang you need to raise coverage of tests for required |
|
I will try add this weekend. |
- Updated `make_request` to skip local DNS resolution when using a proxy, allowing the proxy to handle DNS, especially for `socks5h://` proxies. - Adjusted request URL construction to use the hostname instead of the resolved IP address when a proxy is specified. - Added tests to verify correct proxy usage for various proxy types (HTTP, HTTPS, SOCKS5) and scenarios, including authentication and redirects.
e064e89 to
ef70ecc
Compare
- Remove trailing whitespace - Apply ruff formatting
|
I have raise coverage of tests. |
…nt variables - Updated `make_request` to check for proxy environment variables, allowing for hostname usage instead of IP when a proxy is specified. - Added a fixture to clear proxy environment variables in tests for consistent behavior. - Implemented a test to verify that proxy environment variables are respected during requests, ensuring DNS resolution is skipped when set.
|
example.com should be OK for pytest cases |
|
finished for the pr |
Add detection for proxies that perform remote DNS (socks5h, http, https) vs those that use local DNS (socks5) and use that to decide whether to skip local hostname resolution. Introduce helpers to resolve the effective proxy (honoring HTTPS_PROXY/HTTP_PROXY/ALL_PROXY and NO_PROXY exclusions) and to detect remote-DNS proxy schemes. Skip local DNS resolution when the selected proxy resolves hostnames remotely to avoid sending IPs to proxies that expect hostnames (prevents CONNECT/TLS mismatches). Also avoid running active TLS inspection when any proxy is in use since the inspector would bypass the proxy. Expand and refactor tests and fixtures to validate NO_PROXY handling, proxy detection, and DNS-skipping behavior. This prevents TLS/connect failures with proxies that require hostnames and aligns proxy/DNS behavior with common environment variable conventions. fix(http_client): simplify no_proxy match and fix test context-manager names Simplifies the no_proxy host-pattern match to use set membership for the exact-match checks, and normalizes environment lookup call formatting. Also fixes test context-manager method signatures to use standard "self" parameter names so the tests behave correctly and satisfy linters. These changes improve readability and correctness of pattern matching logic and ensure test context managers are implemented conventionally. fix(docs): clarify SOCKS5/SOCKS5H proxy DNS behavior and update related docs/tests Clarify how DNS resolution is handled for proxy protocols (explicitly document that socks5h delegates DNS to the proxy while socks5 resolves locally), add examples and environment-variable precedence, and surface proxy-related flags (cacert/ignore-ssl) in the CLI usage. Update documentation and examples across API, usage, and advanced guides to reflect the timing/collector and interface naming revisions, adjust tests to use a direct math.ceil replacement for portability, and bump several development and runtime dependencies to current tested versions. These changes improve user understanding of proxy DNS semantics, reduce confusion when routing through SOCKS proxies, and align docs/tests with recent API and dependency updates for more reliable developer experience. chore(project): add Python 3.15 support, update docs URL and release status Add Python 3.15 to CI matrix, supported classifiers, and documentation/README/SECURITY requirements to reflect compatibility. Update project development status to Production/Stable and point project docs URL to the official docs site. These updates ensure tests run on Python 3.15, packaging metadata accurately advertises supported versions and stability, and users are directed to the canonical documentation location. ci(workflows): use --only-group with uv sync in CI installs Update CI workflow to pass --only-group to uv sync when installing typing and test groups. This ensures only the requested dependency groups are installed, avoiding accidental installation of other groups, reducing CI setup time and side effects during type checking and test runs. ci(deps): group dev dependencies and scope CI jobs to groups Organizes development dependencies into focused groups (lint, typing, test, precommit) and updates the lock metadata accordingly. Adds argcomplete to dev requirements and removes the monolithic dev list to allow selective installs. Updates CI workflow commands to run dependency-group-scoped tasks (mypy and pytest) via the package manager so actions only install and run the relevant groups, speeding up and isolating type-checking and test steps. This improves CI efficiency and dependency management clarity. ci(infra): exclude dev deps during dependency sync and normalize license Update CI dependency sync to skip development packages and ensure type/test jobs install only needed groups, reducing unnecessary installs and making checks consistent across workflow runs. Also normalize project license metadata from a table to a simple string to align with packaging/tooling expectations. These changes improve CI performance and package metadata consistency.
4c81c6e to
46f9041
Compare
Replace direct typing_extensions.Self imports in tests with a conditional import that uses typing.Self when running on Python 3.11 or newer, falling back to typing_extensions otherwise. Add missing sys imports required for the version check. This reduces reliance on typing_extensions for supported Python versions and ensures tests remain compatible across Python 3.10 and 3.11+ environments.
Fix: Proxy DNS resolution - support remote DNS for all proxy types
Summary
Fixes TLS handshake errors when using proxies by implementing correct DNS resolution behavior for all proxy types. Proxies that use remote DNS resolution (socks5h, http, https) now correctly receive hostnames instead of resolved IPs.
Problem
Since v0.4.1 (commit 438337b), httptap performs local DNS resolution and connects to the resolved IP address. While this optimization improves performance for direct connections, it breaks proxy types that require remote DNS resolution.
Proxy DNS Resolution Requirements
Different proxy types have different DNS resolution requirements:
Remote DNS (proxy resolves):
Local DNS (client resolves):
Error Symptoms
When using proxies that require remote DNS, users experience:
This happens because:
api.example.com→203.0.113.10locallyCONNECT 203.0.113.10:443to the proxySolution
Detect all proxy types that require remote DNS and skip local resolution:
When remote DNS proxy is detected:
When remote DNS is NOT needed:
Testing
Manual Testing
Before fix (v0.4.1):
After fix:
Automated Tests
Added comprehensive test suite (
TestProxyDNSResolution) covering:Detection tests:
Behavior tests:
All tests pass:
Changes
Core Changes (
httptap/http_client.py)Renamed function for broader scope
_is_socks5h_proxy()→_needs_remote_dns()Extended proxy detection
http://)https://)Updated DNS resolution logic
Updated request URL construction
Test Changes (
tests/test_http_client.py)TestSOCKS5HProxy→TestProxyDNSResolutionCompatibility
socks5h://http://https://socks5://Related Issues
This fix addresses the regression introduced in v0.4.1 (commit 438337b) where the performance optimization broke all proxy types that require remote DNS resolution, not just SOCKS5H.
Why HTTP/HTTPS Proxies Need Remote DNS
HTTP/HTTPS CONNECT proxies work like SOCKS5H:
CONNECT hostname:443 HTTP/1.1HTTP/1.1 200 Connection establishedIf client sends resolved IP instead:
CONNECT 203.0.113.10:443(no hostname)Checklist
References