HTTP-restricted networks that route outbound traffic through proxies often treat tunneled connections differently from plain proxy requests. Forcing cURL to use proxy CONNECT tunneling aligns command‑line behavior with browser traffic, simplifies reproduction of proxy issues, and helps validate how egress controls handle specific destinations or ports. Consistent tunneling behavior is especially useful when debugging authentication problems, deep packet inspection policies, or SSL offloading quirks.

With an HTTP proxy configured, cURL normally sends absolute-form HTTP requests for http:// URLs and reserves the CONNECT method for https:// and other tunneling scenarios. The –proxy option and environment variables such as HTTP_PROXY determine which proxy receives the traffic, while flags like --proxytunnel instruct cURL to negotiate a CONNECT tunnel to the destination host and port before any application data flows. Once the proxy replies with a successful CONNECT status, subsequent bytes travel inside the tunnel as if the client were talking directly to the origin server.

Some corporate proxies restrict tunneling to approved ports or hosts and may log or block unauthorized CONNECT attempts. The examples below assume a working HTTP proxy hostname and port, a recent cURL build with proxy support compiled in, and a terminal on a Unix‑like system; the same flags behave similarly on Windows. Excessive failed CONNECT requests can trigger rate limits or security alerts, so careful testing and coordination with network administrators reduces risk.

Steps to force proxy CONNECT tunneling with cURL:

  1. Open a terminal where cURL is available.
    $ whoami
    alice
  2. Check the installed cURL version to confirm support for proxy options.
    $ curl --version
    curl 7.81.0 (x86_64-pc-linux-gnu) libcurl/7.81.0 OpenSSL/3.0.2 zlib/1.2.11
    Release-Date: 2022-01-05
    Protocols: dict file ftp ftps gopher http https imap imaps pop3
    Features: AsynchDNS HTTP2 HTTPS-proxy IPv6 Largefile libz TLS-SRP
    ##### snipped #####

    Any reasonably recent cURL release includes --proxy and --proxytunnel; exact versions and linked libraries vary by platform.

  3. Send an HTTP request through the proxy without tunneling to observe the default proxy behavior for a plain http:// URL.
    $ curl --verbose --proxy http://proxy.example.local:3128 http://example.com/ -o /dev/null
    *   Trying 192.0.2.10:3128...
    * Connected to proxy.example.local (192.0.2.10) port 3128 (#0)
    > GET http://example.com/ HTTP/1.1
    > Host: example.com
    > User-Agent: curl/7.81.0
    > Accept: */*
    < HTTP/1.1 200 OK
    ##### snipped #####

    The absence of a CONNECT request shows that the proxy is handling the HTTP request directly instead of creating a tunnel to the origin server.

  4. Force use of the HTTP CONNECT method by repeating the request with --proxytunnel so the proxy establishes a tunnel to the target host and port.
    $ curl --verbose --proxy http://proxy.example.local:3128 --proxytunnel http://example.com/ -o /dev/null
    *   Trying 192.0.2.10:3128...
    * Connected to proxy.example.local (192.0.2.10) port 3128 (#0)
    > CONNECT example.com:80 HTTP/1.1
    > Host: example.com:80
    > User-Agent: curl/7.81.0
    > Proxy-Connection: Keep-Alive
    < HTTP/1.1 200 Connection established
    ##### snipped #####

    Some proxies block CONNECT entirely or restrict it to specific ports (often 443); repeated failed CONNECT attempts can trigger intrusion‑detection rules or temporary client bans.

  5. Include proxy authentication options when the proxy requires credentials before allowing tunnel creation.
    $ curl --verbose \
      --proxy http://proxy.example.local:3128 \
      --proxy-user user:password \
      --proxytunnel http://example.com/ -o /dev/null
    * Proxy auth using Basic with user 'user'
    > CONNECT example.com:80 HTTP/1.1
    > Host: example.com:80
    > Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==
    < HTTP/1.1 200 Connection established
    ##### snipped #####

    Replace the placeholder credentials with real proxy details or use --proxy-header for custom tokens when the proxy expects non‑Basic authentication schemes.

  6. Configure proxy settings via environment variables when multiple commands need the same HTTP proxy while still enabling CONNECT tunneling with --proxytunnel.
    $ export HTTP_PROXY=http://proxy.example.local:3128
    $ curl --verbose --proxytunnel http://example.com/ -o /dev/null
    ##### snipped #####

    Environment variables such as HTTP_PROXY and HTTPS_PROXY keep command lines shorter while preserving control over tunneling behavior with --proxytunnel.

  7. Confirm that proxy CONNECT tunneling is active by searching the verbose output for the CONNECT request and a successful Connection established response from the proxy.
    $ curl --verbose --proxy http://proxy.example.local:3128 --proxytunnel http://example.com/ -o /dev/null 2>&1 \
      | grep -E 'CONNECT|Connection established'
    > CONNECT example.com:80 HTTP/1.1
    < HTTP/1.1 200 Connection established

    Successful tunneling is indicated by a visible CONNECT request line, a 2xx response such as 200 Connection established from the proxy, and subsequent application traffic flowing through the tunnel.

Discuss the article:

Comment anonymously. Login not required.