Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 7 min read

Your Browser Works, but curl Fails: Check Proxy Settings Before Blaming the VPN

A website loads in your browser. The same address times out in curl. Your VPN is connected, so it becomes the obvious suspect. But the browser and curl may be using different proxy settings, different exclusions or diff

A website loads in your browser. The same address times out in curl.

Your VPN is connected, so it becomes the obvious suspect. But the browser and curl may be using different proxy settings, different exclusions or different configuration files.

A successful browser request does not establish that curl takes the same network path. Before changing VPN settings, find out what curl is actually trying to connect to.

This walkthrough uses POSIX-style shell examples for Linux and macOS. The diagnostic sequence is useful elsewhere, but shell syntax and platform behaviour can differ.

A proxy and a VPN can both affect one request

An application-level proxy receives a request on behalf of a client. A VPN affects traffic according to its routing and filtering policies.

The two can operate together.

For example, curl might connect to a proxy through the VPN. Or a browser might use a configured proxy while curl attempts a connection without one.

Neither arrangement can be inferred from β€œthe VPN is connected.”

Browser configuration can also include a proxy auto-configuration script, commonly called a PAC file. curl does not automatically evaluate a browser’s PAC script.

Start by establishing the settings used by each application rather than assuming they match.

1. Record the failing request

Choose a repeatable URL you are authorised to test. Prefer a simple endpoint without authentication, cookies or state-changing behaviour.

Set it once:

debug_url='REPLACE_WITH_YOUR_TEST_URL'

Replace the placeholder with the complete URL.

Then record the curl executable and version:

command -V curl
curl --version

command -V can reveal an alias, function or wrapper that changes how the command runs.

On Windows, use curl.exe when you intend to invoke the curl executable rather than a shell command with the same name. The remaining examples use Unix shell syntax.

Keep the VPN connection and network unchanged during the initial comparisons.

2. Check which proxy variables are present

curl can obtain proxy settings from its environment.

Check the relevant variable names without printing their values:

for proxy_var in \
  http_proxy https_proxy all_proxy no_proxy \
  HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY
do
  if printenv "$proxy_var" >/dev/null 2>&1; then
    printf '%s is set\n' "$proxy_var"
  fi
done

This reports presence, including variables with empty values. Inspect the actual values privately.

A proxy address may contain credentials, so avoid pasting a full environment dump into a support ticket.

For curl, the important relationships are:

  • Scheme-specific variables such as https_proxy select a proxy for that URL scheme.
  • A scheme-specific setting takes precedence over ALL_PROXY.
  • NO_PROXY and no_proxy define destinations that should bypass the selected proxy.
  • curl deliberately treats lowercase http_proxy differently from uppercase HTTP_PROXY; on case-sensitive systems, the uppercase form is not its HTTP proxy setting.

Do not assume another HTTP client implements identical rules.

If conflicting uppercase and lowercase values exist, remove the ambiguity through your approved configuration rather than assuming the client chooses the value you intended.

3. Inspect one ordinary curl request

Run a bounded request with verbose output:

curl --verbose \
  --connect-timeout 5 \
  --max-time 20 \
  --output /dev/null \
  "$debug_url"

Look for the stage where it stops:

  • Resolving a proxy hostname.
  • Connecting to a proxy.
  • Establishing an HTTP CONNECT tunnel.
  • Resolving or connecting to the destination directly.
  • Negotiating TLS.
  • Receiving an HTTP response.

Verbose output can expose headers, hostnames and other sensitive details. Review and redact it before sharing.

Also distinguish an HTTP error from a connection failure. A 403 response means an HTTP exchange occurred; it does not mean the response was useful or that the VPN caused the rejection.

A timeout gives less information. You still need to identify which connection attempt timed out.

4. Repeat without curl’s default configuration file

Environment variables are only part of curl’s configuration.

A default curl configuration file can add options you did not type, including proxy settings. Its location depends on the platform and environment.

Compare the previous request with:

curl -q \
  --verbose \
  --connect-timeout 5 \
  --max-time 20 \
  --output /dev/null \
  "$debug_url"

Put -q first among curl’s arguments. It prevents curl from loading its default configuration file.

It does not remove proxy environment variables. It also does not neutralise options inserted by a wrapper or an explicitly supplied configuration file.

If the ordinary request fails but this request works, investigate the default configuration file. Something loaded from it is affecting the result; that does not yet establish that a proxy option is responsible.

Inspect the difference before deleting the file or changing unrelated settings.

5. Test without an explicit proxy, where permitted

If your network permits direct access to the test destination, make one more comparison:

curl -q \
  --noproxy '*' \
  --verbose \
  --connect-timeout 5 \
  --max-time 20 \
  --output /dev/null \
  "$debug_url"

Quote the asterisk so the shell does not expand it into filenames.

This tells curl not to use a selected application-level proxy for the request. It does not disconnect the VPN, bypass its routing policy or remove transparent network intermediaries.

Do not run this comparison where direct access would violate a managed network policy.

Keep the observations narrow:

Result What to investigate
Ordinary request fails; -q works Options in curl’s default configuration file
-q fails; -q --noproxy '*' works Proxy selection, reachability, authentication or handling of the destination
Proxy-enabled request works; no-proxy request fails Whether the destination requires the approved proxy or a different network path
All requests fail DNS, routing, TLS, destination access or another shared cause
Requests return different HTTP statuses Different server/proxy responses, authentication or request handling

These comparisons narrow the cause. They do not prove that a VPN is healthy or faulty.

6. Check whether NO_PROXY matches the intended destination

An exclusion can explain why one hostname works while another fails.

For example, a curl configuration might exclude:

localhost,127.0.0.1,.corp.example

That may be intentional for internal services.

But a stale exclusion can also make curl attempt a direct connection to a destination that requires a proxy.

The opposite problem is possible too: an internal hostname may be sent to a proxy that cannot reach it.

Review the actual hostname in the request, the exclusion list and any redirects. Do not assume every HTTP library interprets domain patterns and exclusions the same way.

Avoid globally setting NO_PROXY=* as a repair. It changes proxy selection for every matching request made by clients that honour that setting.

A one-command comparison is easier to reason about than a permanent environment change.

7. Compare with the approved proxy explicitly

If you know which proxy the request should use, test that configuration directly.

debug_proxy='REPLACE_WITH_YOUR_APPROVED_PROXY_ADDRESS'

curl -q \
  --proxy "$debug_proxy" \
  --noproxy "" \
  --verbose \
  --connect-timeout 5 \
  --max-time 20 \
  --output /dev/null \
  "$debug_url"

Use the approved proxy address, including the appropriate scheme and port.

The empty no-proxy list prevents an environment exclusion from silently skipping this proxy during the comparison.

This example does not configure proxy authentication. Follow your organisation’s supported authentication method rather than placing passwords in shell history.

If this works while the environment-driven request fails, compare the effective proxy and exclusion settings.

If it fails, identify the stage: proxy lookup, proxy connection, authentication, tunnel establishment or the destination request.

8. If proxy selection is correct, investigate the next layer

A browser and curl can still differ after you align their proxy paths.

Possible differences include:

  • Certificate trust stores or required enterprise certificates.
  • Browser login sessions and cookies.
  • Application-specific VPN exclusions.
  • DNS configuration.
  • IPv4 and IPv6 availability.
  • Request headers or server-side access rules.

Do not make --insecure the permanent answer to a certificate error. Investigate the certificate chain and the approved trust configuration.

Similarly, copying every browser header into curl can obscure the issue. Establish which part of the request is required rather than changing many variables together.

When checking whether a VPN is working, remember that a browser-based observation describes that browser request. A terminal application needs its own investigation when its behaviour differs.

End with a finding that identifies the next step

Instead of:

The browser works, so curl must be broken.

Write:

curl attempts to reach an old proxy from its environment. The same request succeeds without that explicit proxy on a network where direct access is permitted.

Or:

The approved proxy is reachable, but curl receives a proxy authentication error. The next step is authentication configuration.

Or:

Both applications use the intended proxy, but curl fails certificate validation. We need to investigate its trust configuration.

Each statement gives you a specific problem to solve.

Check the executable, configuration file, proxy variables and exclusions before changing VPN settings. The useful result is an explanation of the request pathβ€”not simply a command that happens to succeed.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.