curlのプロキシ設定: 認証、HTTPS CONNECT、確実な確認

10分

curlのプロキシを明示し、-U と -u を分け、HTTPSは -k なしのCONNECTで通し、実際に使った経路で終了コードを確認します。

PATHにcurlがある人が、証明できるHTTPまたはSOCKSのホップを必要とするときの案内です。以下の確認は、供給元の口座ではなく、ローカルのループバックオリジンとダミーのプロキシを使いました。Top ProxyはIPを売りません。無料の鍵もありません。ブラウザの自分のIPは、ブラウザの経路を示します。このcurlプロセスではありません。

01動いているプロキシで確認する

この記事の数値は、curl 8.7.1での制御したループバック測定から来ています。それは方法です。このページのキットではありません。公開のダウンロードもありません。

いま動いているプロキシとオリジンに、普通のcurlを使ってください。ダミーの lab-user:lab-pass はラベルであり、口座ではありません。コマンドには、いまのホスト、ポート、CAを入れてください。記録した実行の60585系ポートは再利用しないでください。測定が終わったとき、それらの端点はもうありませんでした。

curl -q -sS --noproxy '' -x http://127.0.0.1:PROXY_PORT --proxy-user lab-user:lab-pass http://127.0.0.1:ORIGIN_PORT/identity

同じHTTPホップ越しのHTTPSも、CONNECTを使います。いま話しているオリジンに合うCAを信頼してください。

curl -q -sS --noproxy '' -x http://127.0.0.1:PROXY_PORT --proxy-user lab-user:lab-pass --cacert ca.pem https://localhost:ORIGIN_HTTPS_PORT/identity

02明示的なHTTPプロキシを指定し、経路を確かめる

curlは、最初のオプションを -q にして始めてください。導入した8.7.1の man curl とcurlのmanページは、先頭の -q が curlrc を飛ばすと書いています。オンラインのマニュアルは、より新しいフラグを説明することがあります。この手順は8.7.1のままです。rcファイルがプロキシ、CAバンドル、--user を注入するなら、あとのフラグは見えない設定と争うことになります。ファイルを隠すためにHOMEを書き換えないでください。-q は、バイナリがもともと持っている隔離です。

ホップは -x / --proxy で指してください。スキームが無いとき、curlはそのホストをHTTPプロキシとして扱います。everything curlのHTTPプロキシは、HTTP対象のabsolute-form転送を説明しています。実験のalphaプロキシは GET http://127.0.0.1:60585/identity を記録し、オリジンのJSONを返しました。ステータス200だけでは経路ではありません。オリジンは via_proxy_header: alpha をエコーしました。同じ呼び出しで、観測用の二番目のプロキシbetaはアイドルのままでした。

  1. curl -q --version を実行し、libcurlの行を残してください。この手順はcurl 8.7.1、libcurl 8.7.1、SecureTransportとLibreSSL 3.3.6を使いました。機能一覧に HTTPS-proxy がありました。そのフラグは、プロキシへのTLSについてのものです。SOCKSの証明ではありません。CONNECTの証明でもありません。
  2. -x なしで、一度オリジンを呼んでください。直接のHTTPはexit 0、HTTP 200、オリジンid http-origin を返し、ダミーのプロキシは何も受けませんでした。それが対照です。
  3. 同じURLを -x、--noproxy ''、ダミーの --proxy-user で呼んでください。--noproxy '' は、シェルの NO_PROXY がループバックを飛ばすときでも、プロキシを強制します。オリジンの本文はalphaを指名しました。ホップはProxy-Authorizationを消費しました。オリジンはそれを見ませんでした。
  4. stdoutだけでなく、プロキシのログを読んでください。このフィクスチャで資格情報が無いとHTTP 407が返り、--fail がオフだったのでcurlのexitは0でした。
curl -q -sS --noproxy '' -x http://127.0.0.1:PROXY_PORT --proxy-user lab-user:lab-pass http://127.0.0.1:ORIGIN_PORT/identity

PROXY_PORT と ORIGIN_PORT は、いま動いているフィクスチャから取ってください。保存した結果の期限切れポートではありません。

実行した明示的なHTTPプロキシ確認。exit 0、HTTP 200、経路はalpha

間違ったダミー資格情報も407とexit 0を返しました。フィクスチャは auth: wrong と印を付けました。正しい資格情報はオリジン200と auth: correct を返しました。ダミーパスワードの予約文字は、貼り付けたURLではなく --proxy-user を通りました。コンポーネントごとのURLエンコードが、もう一つの正当な経路です。避けられるなら、本物のパスワードをargvに置かないでください。プロセス一覧は、一瞬でも引数を見ます。8.7.1のマニュアルもそう書いています。

ホストがHTTPに応答するかどうかだけ知りたいなら、プロキシチェッカーを使ってください。到達の道具です。このcurlプロセスではありません。

03プロキシ認証とオリジン認証を分けておく

-U / --proxy-user はプロキシへ認証します。-u / --user はオリジンへ認証します。everything curlのプロキシ認証は、意図して独立に扱っています。混ぜると、ゲートウェイのパスワードがアプリのログインへ漏れるか、その逆になります。

実験のオリジンは、独自のBasicチャレンジで /origin-auth を出しました。一つのコマンドが、ダミーの -U をalphaへ、ダミーの -u をオリジンへ送りました。オリジンのJSONは origin_authorized: true と proxy_authorization_present: false でした。ホップはProxy-Authorizationを消費しました。オリジンはそれを見ませんでした。

  1. プロキシの資格情報は -U、またはプロキシURLのuserinfoへ入れてください。-u には入れないでください。
  2. オリジンの資格情報は -u、意図したnetrc、またはオリジンURLへ入れてください。この実験は空の私的netrcを使い、--netrc も付けなかったので、不意のログインはバグだったはずです。
  3. オリジンを確認してください。プロキシからの200とオリジンからの401は、ホップからの407とは別の失敗です。
curl -q -sS --noproxy '' -x http://127.0.0.1:PROXY_PORT --proxy-user lab-user:lab-pass -u origin-user:origin-pass http://127.0.0.1:ORIGIN_PORT/origin-auth
実行した -U のプロキシ認証と -u のオリジン認証。オリジンは認可され、プロキシヘッダーは漏れない

--fail なしのHTTP 407は、このビルドでcurlをexit 0のままにしました。同じ資格情報なしの呼び出しに -f を足すと、HTTP 407とexit 22が返りました。導入したマニュアルは、401と407が --fail をすり抜けることがあると警告しています。この実行の8.7.1ではすり抜けませんでした。将来のすべてのcurlへ一般化しないでください。ステータス、CONNECTのステータス、終了コードは別々に記録してください。--fail-with-body は、文書をまだ書き出す兄弟です。ここでの既定ではありませんでした。

この記事のダミーユーザーはラベルです。口座ではありません。実験の詳細トレースは、ディスクへ書く前にAuthorizationとProxy-Authorizationの値を [REDACTED] へ削っています。

04TLSを切らずに、CONNECTでHTTPSへ届く

HTTPプロキシの前にあるHTTPSのサイトでも、プロキシはHTTPプロキシのままです。curlは CONNECT host:port を送り、プロキシがTCPを開き、そのトンネル越しにオリジンへTLSが走ります。そのために https:// のプロキシスキームは要りません。https:// のプロキシスキームは、プロキシ自身へのTLSです。everything curlのHTTPプロキシとHTTPSプロキシの章は、それらのホップを分けています。この実験はHTTPSプロキシを立てていません。--proxy-cacert は未測定のままです。--cacert は、CONNECTのあとにオリジンを検証しました。

  1. URLが https://localhost:PORT/identity でも、-x は http://127.0.0.1:PORT のままにしてください。
  2. 実験のCAは --cacert で信頼してください。-k は足さないでください。
  3. 200を信じる前に、CONNECTのログ行を要求してください。alphaは CONNECT localhost:60586 を auth: correct とステータス200で記録し、オリジンの本文は https-origin を指名しました。
  4. --cacert なしでもう一度繰り返してください。CONNECTは成功したままです。curlはそのあとexit 60、TLSのピア証明書失敗で終わりました。トンネルは問題ありませんでした。証明書が問題でした。
curl -q -sS --noproxy '' -x http://127.0.0.1:PROXY_PORT --proxy-user lab-user:lab-pass --cacert ca.pem https://localhost:ORIGIN_HTTPS_PORT/identity

--cacert は、いま動いているフィクスチャのCAにしてください。一度きりのランチャーが終了したあとの残り evidence/ca.pem を指さないでください。記録した実行の削除済み一時パスも再利用しないでください。

信頼した実験CAで、HTTPプロキシ越しに実行したHTTPS CONNECT

CONNECTでのプロキシ資格情報なしは、HTTP 407とexit 0の経路には見えませんでした。フィクスチャはCONNECTでも407を返しました。curl 8.7.1はexit 56で、write-outのHTTPコードは000でした。間違った資格情報も同じでした。CONNECTの失敗は転送として扱ってください。あとで解析できる静かなHTML 407ではありません。

実験CA付きの直接HTTPSは200を返しました。無しの直接HTTPSはexit 60を返しました。その組がTLSの基準です。プロキシとは独立です。

ブラウザの自分のIPタブは、このトンネルを示しません。ブラウザが欲しかったなら、ブラウザを設定することになります。

05環境のプロキシと、意図した迂回を理解する

curlは http_proxy、https_proxy、all_proxy、NO_PROXY を読みます。プロキシの環境変数は、CGIの罠をはっきり書いています。入ってきた Proxy: ヘッダーは、大文字の HTTP_PROXY になります。そのためcurlは、HTTPについては小文字の http_proxy だけを受け付けます。大文字の HTTPS_PROXY と ALL_PROXY は、それぞれのスキームでは有効なままです。

実験は、すべての子プロセスをきれいな環境から始めました。プロキシ変数の大文字小文字、CGIの REQUEST_METHOD の残り、CURL_CA_BUNDLE、SSL_CERT_FILE、SSL_CERT_DIR、SSLKEYLOGFILE、REQUESTS_CA_BUNDLE を剥がしました。それから、名前の付いたダミーを一つずつ注入しました。curlに trust_env= スイッチはありません。Requestsの trust_env=False は、CAとnetrcの検索も変えます。そのフラグをcurlへ写さないでください。-q ときれいな子環境が、同等の隔離です。

  1. 小文字の http_proxy をalphaにし、--proxy-user を渡し、--noproxy '' を足してください。オリジンはalphaを指名しました。それが環境だけの経路です。
  2. 大文字の HTTP_PROXY を同じalpha URLにし、-x を省略してください。オリジンは直接返りました。alphaのイベント数は動きませんでした。それが文書化されたセキュリティの約束で、このバイナリで測りました。
  3. http_proxy をalphaにし、明示的な -x betaを渡してください。オリジンはbetaを指名しました。alphaは選ばれたホップではありませんでした。二つのプロキシ識別は、「どこかからの200」の推測に勝ちます。
  4. http_proxy をalphaにし、--noproxy '' なしで NO_PROXY=127.0.0.1 を付けてください。オリジンは直接で、alphaはアイドルのままでした。それが迂回のケースで、意図して実行しました。
  5. NO_PROXY=127.0.0.1 を保ち、--noproxy '' を足してください。空の一覧が変数を上書きします。8.7.1のマニュアルは7.53.0からそう書いています。オリジンは再びalphaを指名しました。
明示的な -x beta が、環境の http_proxy alpha に勝った実行

HTTP 200からホップを推論しないでください。直接の成功とプロキシ越しの成功は、経路を刻印しない限り本文では同じに見えます。フィクスチャは、転送したHTTPに X-Lab-Proxy を刻印しました。CONNECTはTLSの内側のオリジンへ刻印できないので、証拠はCONNECTのログです。

06ハンドシェイクの証拠でSOCKS5とSOCKS5hを比べる

SOCKSはHTTP転送ではなく、CONNECTでもありません。everything curlのSOCKSの章は表を短く保っています。SOCKS5はローカルで解決します。SOCKS5hはホスト名をプロキシへ送ります。--socks5 と --socks5-hostname がフラグの形です。-x の socks5:// と socks5h:// がURLの形です。

Appleのcurl 8.7.1は、プロトコル一覧から socks を省きつつ、SOCKSプロキシのオプションは載せています。成功したSOCKSリクエストは、DNSがどこで起きたかの証明ではありません。ハンドシェイクのATYPが証明です。

  1. --socks5 127.0.0.1:PORT から http://127.0.0.1:ORIGIN/identity はHTTP 200で完了しました。フィクスチャはATYP ipv4とアドレス 127.0.0.1 を記録しました。
  2. --socks5-hostname 127.0.0.1:PORT から http://lab.curl-fixture.test:ORIGIN/identity はHTTP 200で完了しました。フィクスチャはATYP domainとアドレス lab.curl-fixture.test を記録しました。プロキシはその実験ホスト名をループバックへ写しました。その写しはフィクスチャ側の処理であり、公開DNSへの漏れを測ったものではありません。
  3. そこで止めてください。この記事は、外部リゾルバの捕捉を主張しません。
curl -q -sS --noproxy '' --socks5-hostname 127.0.0.1:SOCKS_PORT http://lab.curl-fixture.test:ORIGIN_PORT/identity
実験ホスト名に対するATYP domainの、実行したSOCKS5hハンドシェイク

供給元の文書も同じ分け方です。Oxylabsのレジデンシャルプロトコルは、ホスト名を渡す socks5h://pr.oxylabs.io:7777 と、解決済みIPを渡す socks5:// を書いています。Decodoのレジデンシャルプロトコルは、カタログではまだSmartproxyとして載っており、gate.decodo.com:7000 の socks5h:// を書き、us.decodo.com のような国ホストはSOCKS5では動かないと述べています。それらは文書上の適合のメモです。このループバック実行ではありません。

プロトコルはIPの種類ではありません。モバイルとレジデンシャルのページは、出口プールを説明しています。SOCKS5対HTTPは、クライアントのハンドシェイクです。レジデンシャルのHTTPホップも、データセンターのSOCKSホップもあります。それらのつまみを一つに潰さないでください。

07接続失敗と転送タイムアウトを区別する

--connect-timeout は、DNSとTCP、TLSならハンドシェイクまでを区切ります。--max-time は転送全体を区切ります。everything curlのタイムアウトは、データが動いているあいだも --max-time が発火すると書いています。exit 28がそのタイマーです。Requests風のreadタイムアウトではありません。

この実験は接続タイムアウトを測っておらず、パケットも捕捉していません。exit 7は、UDPソケットが所有する一時的なループバックポートへのTCP接続から来ました。curlは Couldn't connect to server を出し、HTTPコードは000でした。それが接続エラーです。exit 28ではありません。

遅延本文の経路が、もう一つの形です。/slow-body は完全なヘッダーをすぐに送り、最初の本文バイト H をフラッシュし、残りより先に --max-time 1.5 を越えました。curlはHTTP 200を報告し、000ではなく、exit 28で終わりました。オリジンのfirst-byteイベントは立っていました。alphaは GET .../slow-body を転送していました。それが、本文が始まったあとの転送タイムアウトです。

  1. 死んだホップでは、接続エラーを期待してください。ここでは、所有されたループバックポートに対するexit 7でした。
  2. 遅い本文では、ヘッダーと最初のバイト、それから --max-time、それから本物のHTTP 200付きのexit 28を要求してください。コード000なら、その断言は失敗していたはずです。
  3. ハンドシェイクを実際に止めていないなら、--connect-timeout は文書どおりに残してください。この実行では測っていません。
curl -q -sS --noproxy '' -x http://127.0.0.1:PROXY_PORT --proxy-user lab-user:lab-pass --max-time 1.5 http://127.0.0.1:ORIGIN_PORT/slow-body
遅延本文の転送タイムアウトを実行。HTTP 200のあとcurl exit 28

再試行は別のスイッチです。--retry は、8.7.1では試行ごとに --max-time のカウンタをリセットします。付けるなら、再試行の窓は --retry-max-time で区切ってください。再試行フラグをPOSTの冪等性として扱わないでください。

08文書化されたプロトコルと認証の適合で端点を選ぶ

ホップは、供給元が文書化しているとおりに選び、自分が所有するフィクスチャでcurlを証明してください。有料ゲートウェイは呼んでいません。国の指定、ボット対策の言い伝え、「最良のサービス」の順位は範囲外です。

Oxylabsのレジデンシャルプロトコルは、2026年10月14日に取得し、HTTPを pr.oxylabs.io:7777 に置き、-U customer-USERNAME:PASSWORD を使います。同じページは、ゲートウェイへのTLSが欲しいときの https://pr.oxylabs.io:7777 と、プロキシにホスト名を見せたいときの socks5h://pr.oxylabs.io:7777 を足しています。そのページでは、SOCKS5は国別の入口ホストを使いません。

Decodoのレジデンシャルプロトコルは同じ日で、HTTPを gate.decodo.com:7000 に置き、SOCKS5hも同じホストです。生きている英語カードのOxylabsとSmartproxy / Decodoで、それらの文書化されたスキームを比べてください。それはカタログの適合であり、ゲートウェイの試験ではありません。

  1. スキームをクライアントの対応に合わせてください。ここでのcurl 8.7.1は、HTTP転送、CONNECT、SOCKS5、SOCKS5hを話しました。HTTPSプロキシへのTLSは、文書だけの行のままです。
  2. 認証は -U に合わせ、供給元が文書化するユーザー名の接頭辞を使ってください。オリジンの -u はその文字列から外してください。
  3. ホストのHTTP対SOCKSだけが要るなら、プロキシチェッカーでホップを確認してください。出口IPはブラウザのタブではなく、curlで確認してください。有料端点へcurlを向ける前に、自分が所有する生きたプロキシでホップを証明してください。
OxylabsとDecodoの文書上のcurl端点適合。供給元の性能試験ではない
Oxylabs — レジデンシャルとデータセンタープロキシ
Oxylabs — レジデンシャルとデータセンタープロキシ4.0771

Oxylabsはレジデンシャル、モバイル、ISP、データセンタープロキシを、月$30からのひとつの月次契約で売っています。支払いはカード、電信送金、AliPay、PayPalです。

10か国
$0.45
1GBあたり
Decodo(Smartproxy) — レジデンシャルとデータセンタープロキシ
Decodo(Smartproxy) — レジデンシャルとデータセンタープロキシ4.22118

Decodo(旧Smartproxy)はレジデンシャルとデータセンタープロキシを売っています。レジデンシャルは月次プランなしで1GBあたり$4、または3 GBから1GBあたり$3.75の月次パックです。支払いはカード、PayPal、Alipay、Google/Apple Pay、暗号資産(制限あり)です。

83か国
$0.38
1GBあたり
ループバックcurl実験から実行した、コンパクトな結果表
観察HTTPステータスCONNECTステータスcurlのexit変えること
HTTPプロキシ、正しいダミーユーザー200n/a0プロキシの識別が一致するときだけ、経路は証明されます
HTTPプロキシ、無いまたは間違ったユーザー407n/a-f なしで0。8.7.1の -f 付きで22-U を直してください。すべての407が22になると思わないでください
HTTPプロキシ経由のHTTPS、信頼したCA200200 Connection Established0オリジンに --cacert を残してください。-k は足さないでください
HTTPプロキシ経由のHTTPS、プロキシユーザーなし00040756このビルドでは、CONNECT 407は転送の失敗です
HTTPS、CONNECTは成功、信頼しないオリジン00020060CAを直してください。トンネルはすでに動いていました
大文字の HTTP_PROXY だけ200 直接n/a0小文字の http_proxy か、明示的な -x を使ってください
所有ポートでのTCP接続拒否000n/a7接続エラーです。タイムアウトではありません
ヘッダーと最初のバイト、そのあと --max-time200n/a28転送の予算です。接続失敗ではありません

curlでプロキシを設定するには?

curl -q から始め、次に -x host:port を付け、ホップがBasic認証を必要とするなら --proxy-user を足してください。ループバック試験では --noproxy '' を付け、シェルの NO_PROXY がプロキシを飛ばせないようにします。ホップは HTTP 200 だけでなく、ログまたはオリジンの刻印で確かめてください。

HTTPSはHTTPプロキシを使えますか?

使えます。curlはCONNECTを送り、そのトンネル越しにオリジンへTLSを走らせます。そのために https:// のプロキシURLは要りません。https:// のプロキシURLはプロキシへのTLSであり、この実験では測っていません。

-U と -u はどう違いますか?

-U はプロキシへ認証します。-u はオリジンへ認証します。プロキシは Proxy-Authorization を消費しました。オリジンは自分の Authorization 資格情報を受け、プロキシヘッダーは見ませんでした。二つの資格情報を混ぜるのが、よくある漏れです。

curlは大文字の HTTP_PROXY をなぜ無視しますか?

CGIサーバーはリクエストヘッダーを HTTP_ 変数へ写します。Proxy ヘッダーは HTTP_PROXY になります。curlはHTTPについて小文字の http_proxy だけを受け、CGIスクリプトがオープンプロキシのクライアントにされないようにします。大文字の HTTPS_PROXY は、HTTPSではまだ有効です。

socks5h はホスト名をどこで解決しますか?

プロキシ上です。--socks5-hostname と socks5h:// は ATYP domain を送ります。--socks5 と socks5:// はローカルで解決し、この実験では 127.0.0.1 へ ATYP ipv4 を送りました。成功したSOCKSの本文は、DNSの位置を示しません。

--connect-timeout と --max-time は何を制限しますか?

--connect-timeout は接続の準備を区切ります。--max-time は転送全体を区切り、ヘッダーのあとも含みます。この実行の遅延本文は HTTP 200 と curl exit 28 を返しました。拒否されたTCP接続は exit 7 であり、28ではありませんでした。