結論

プロキシサーバーは、PCとWebサーバーの間に入り、通信を代わりに取り次ぐサーバーです。利用者側の出口に置くものと、サーバー側の入口に置くものがあります。

この記事でわかること

  • フォワード・リバース・透過の3種類と実際のログ
  • curl・git・npm・pipなど8ツールのプロキシ設定表
  • 407・証明書エラーなどエラー原文22種と直し方

2026年10月17日更新|Squid 6.14・curl 8.5.0 で実行確認

同じ「プロキシ」でも、利用者を代表して外へ出るものと、サーバーを代表して外から受けるものでは、置き場所も目的も逆です。

flowchart TD
    PC[社内のPC] --> FP[フォワードプロキシ<br>利用者側の出口]
    FP --> NET[インターネット]
    NET --> RP[リバースプロキシ<br>サーバー側の入口]
    RP --> WEB[Webサーバー・アプリ]

社内プロキシの環境で、開発ツールを通すための設定は次のとおりです(詳しい書き方と、実際に試した結果は本文にあります)。

やりたいこと・困りごと 設定・コマンド 詳しくは
ターミナルのツールをまとめて通す export http_proxy=… と https_proxy=… 環境変数の節
社内のサーバーだけ直接つなぐ NO_PROXY=.corp.example.com,localhost NO_PROXYの書き方
407 Proxy Authentication Required URL に ユーザー:パスワード@(記号は%で書く) 407の節
証明書エラー(自己署名・PKIX) 社内のルート証明書を各ツールに登録する 証明書エラーの節
git だけ通す git config --global http.proxy URL ツール別の設定
npm だけ通す npm config set proxy URL と https-proxy ツール別の設定
pip だけ通す pip install --proxy URL パッケージ ツール別の設定
Java・Maven・Gradle -Dhttps.proxyHost・settings.xml・gradle.properties ツール別の設定

確認環境:Ubuntu 24.04・Squid 6.14・curl 8.5.0・git 2.43.0・npm 10.9.7(Node.js 22.22.2)・Node.js 24.21.0・pip 26.2.1(Python 3.11.15)・OpenJDK 21.0.10・nginx 1.24.0・pac-resolver 9.0.1。Squid でフォワードプロキシ(認証なし・Basic 認証あり・HTTPS を復号するもの)と透過プロキシ(Linux の network namespace と iptables)を立て、手元に置いた HTTP・HTTPS のサーバーへ各ツールから通して、プロキシのログ・サーバーが受け取ったヘッダー・エラー文を載せています。HTTP の仕様は MDN と RFC 9110、各ツールの設定名は curl・Git・npm(v12 の文書)・pip(26.2.1 の文書)・Oracle Java SE 25・Maven・Gradle 9.8.1・Node.js の公式ドキュメント、Windows の画面と netsh は Microsoft サポートと Microsoft Learn で確かめました(確認日 2026年10月17日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「プロキシサーバーとは|仕組み・種類と開発ツールの設定・407対処」

プロキシサーバーとは

プロキシ(proxy)は「代理」という意味で、プロキシサーバーは、クライアント(PC やスマホ)の代わりに相手のサーバーへリクエストを送り、返ってきた応答をクライアントへ渡すサーバーです。 クライアントは相手のサーバーと直接つながらず、プロキシとだけ通信します。

プロキシを置く主な目的は次の4つです。

目的 何をするか 例
アクセスの制御 行き先・利用者ごとに通す・止めるを決める 業務に関係ないサイトを止める、社員だけ外へ出す
記録(ログ) だれが、いつ、どこへアクセスしたかを残す 情報漏えいの調査、利用状況の把握
キャッシュ 一度取ったファイルを覚えて、次から自分で返す 同じファイルを何百台もが取りに行く通信を減らす
中継・保護 中の機器を外から見えなくする、入口を1か所にまとめる 社内のPCの IP アドレスを外に出さない

実際に通すと何が変わるか

手元に Squid 6.14 を立て(ポート 26600)、curl でプロキシ経由のリクエストを送りました。-x はプロキシを指定するオプションです。

curl -v -x http://127.0.0.1:26600 http://intra.example.test:26610/echo

curl がプロキシへ送った最初の行と、受け取った応答のヘッダーです。

> GET http://intra.example.test:26610/echo HTTP/1.1
> Host: intra.example.test:26610
> Proxy-Connection: Keep-Alive

< HTTP/1.1 200 OK
< Server: SimpleHTTP/0.6 Python/3.11.15
< Cache-Status: proxy.s266.test;detail=mismatch
< Via: 1.1 proxy.s266.test (squid/6.14)

Web サーバー側で、受け取ったリクエストをそのまま返すようにしておくと、次のように見えました。

{
  "request_line": "GET /echo HTTP/1.1",
  "client": "127.0.0.1",
  "headers": {
    "Host": "intra.example.test:26610",
    "Via": "1.1 proxy.s266.test (squid/6.14)",
    "X-Forwarded-For": "127.0.0.1",
    "Cache-Control": "max-age=259200"
  }
}

読み取れることは次の4つです。

  • プロキシへのリクエストは、1行目に URL 全体(http://…)が入ります。 直接つなぐときは GET /echo のようにパスだけです。この形を、HTTP の仕様では absolute-form と呼びます。
  • 名前を引く(DNS で IP アドレスに変える)のはプロキシです。 同じ URL をプロキシなしで開くと curl: (6) Could not resolve host: intra.example.test になりました。社内で「プロキシ経由だと開けるのに、直接だと名前が引けない」ことがあるのはこのためです。
  • プロキシは Via(通ったプロキシの名前)と X-Forwarded-For(元のクライアントの IP)を足します。 MDN は、Via はフォワードプロキシ・リバースプロキシのどちらも付けるヘッダーだと説明しています。
  • Web サーバーから見た接続元は、プロキシの IP アドレスです。 元の IP は X-Forwarded-For を見ないと分かりません。

キャッシュ:2回目はプロキシが返す

同じファイル(/hello.txt)を2回取りに行ったときの、Squid のアクセスログと Web サーバーのログです。

# Squid のアクセスログ
21:09:29 127.0.0.1 TCP_MISS/200 GET http://intra.example.test:26610/hello.txt
21:09:29 127.0.0.1 TCP_REFRESH_UNMODIFIED/200 GET http://intra.example.test:26610/hello.txt

# Web サーバーのログ
"GET /hello.txt HTTP/1.1" 200 -
"GET /hello.txt HTTP/1.1" 304 -

1回目は TCP_MISS(手元に無いので取りに行った)、2回目は TCP_REFRESH_UNMODIFIED です。2回目は、プロキシが「変わっていないか」だけを Web サーバーに問い合わせ、304 Not Modified(変わっていない)を受け取って、中身は自分のキャッシュから返しました。2回目の応答には Cache-Status: proxy.s266.test;hit;detail=match が付いていました。

フォワードプロキシとリバースプロキシの違い

フォワードプロキシは「利用者の代わり」、リバースプロキシは「サーバーの代わり」です。 MDN は、フォワードプロキシはクライアントの身元を隠すことができ、リバースプロキシはサーバーの身元を隠すことができる、と説明しています。

1フォワードプロキシ

社内や学校のネットワークの出口に置きます。PC 側にプロキシの設定をして使います。社内プロキシと呼ばれるのはこれです。

2リバースプロキシ

Web サーバーの手前に置きます。利用者は普通の Web サイトだと思ってつなぎ、設定は要りません。nginx・ロードバランサー・CDN が代表です。

3透過プロキシ

ネットワークの途中で通信を横取りしてプロキシに渡します。PC 側に設定が無くても、知らないうちに通っています。

比べる点 フォワードプロキシ リバースプロキシ
置き場所 利用者側(社内の出口) サーバー側(Web サーバーの手前)
代わりをする相手 クライアント Web サーバー
クライアントの設定 要る(OS・ブラウザー・ツールに設定) 要らない(URL を開くだけ)
リクエストの1行目 GET http://host/path(URL 全体) GET /path(パスだけ)
主な目的 アクセス制御・ログ・キャッシュ 負荷分散・TLS の終端・キャッシュ・圧縮
代表的なソフト・サービス Squid・社内のプロキシ装置 nginx・Apache・ALB・CloudFront

リバースプロキシの例として、nginx 1.24.0 を同じ Web サーバーの手前に置き(ポート 26620)、curl でつなぎました。curl はただ http://127.0.0.1:26620/echo を開いただけです。

> GET /echo HTTP/1.1
< HTTP/1.1 200 OK
< Server: nginx/1.24.0 (Ubuntu)
  "request_line": "GET /echo HTTP/1.0",
    "Host": "www.example.test",
    "X-Forwarded-For": "127.0.0.1",
    "X-Forwarded-Proto": "http",

クライアントが送ったのはパスだけの1行目で、応答の Server は奥の Python ではなく nginx でした。利用者からは nginx が Web サーバーそのものに見え、奥のサーバーは見えません。 nginx での書き方は、関連記事「Nginxリバースプロキシ設定|proxy_passの書き方と502/504対処」で扱っています。

透過プロキシとは

透過プロキシ(トランスペアレントプロキシ)は、クライアントに設定をさせず、ルーターやファイアウォールで通信の向きを変えて、プロキシに通す方式です。 Squid のドキュメントでは、http_port の intercept モードが「IP 層の NAT で横取りした通信を、この Squid のポートに渡す」ための設定です。

Linux の network namespace(1台の中に独立したネットワークを作る仕組み)で、「PC(10.66.0.2)→ ゲートウェイ兼プロキシ(10.66.0.1)→ Web サーバー(10.66.1.10)」を作りました。ゲートウェイでは、PC から来た 80 番ポート宛ての通信を、iptables で Squid の 26603 番に向けます。

iptables -t nat -A PREROUTING -i s266g -p tcp --dport 80 -j REDIRECT --to-ports 26603
# squid-tp.conf(要部)
http_port 127.0.0.1:26604
http_port 26603 intercept
acl lan src 10.66.0.0/24
http_access allow lan
http_access deny all

PC 側にはプロキシの設定を一切せず、Web サーバーを直接開きました。

$ curl -v http://10.66.1.10/hello.txt
> GET /hello.txt HTTP/1.1
> Host: 10.66.1.10
< HTTP/1.1 200 OK
< Via: 1.1 tproxy.s266.test (squid/6.14)
hello from origin
# ゲートウェイの Squid のアクセスログ
10.66.0.2 TCP_MISS/200 GET http://10.66.1.10/hello.txt ORIGINAL_DST/10.66.1.10

curl は直接つないだつもりで、1行目もパスだけです。それでも応答には Via が付き、Squid のログには PC(10.66.0.2)のアクセスが残りました。ORIGINAL_DST は「横取りする前の本来の宛先へ送った」という意味です。Squid の起動ログには Disabling Authentication on port 0.0.0.0:26603 (interception enabled) と出ていました。ドキュメントのとおり、intercept のポートではプロキシ認証が使えません。

HTTPS(443 番)は暗号化されているため、透過プロキシで横取りしても、そのままでは中の URL は読めません。中まで見るには、後の節の「HTTPS を復号するプロキシ」と同じ仕組みが要ります。

HTTPSがプロキシを通る仕組み(CONNECT)

HTTPS のときは、クライアントはまずプロキシに CONNECT ホスト:ポート を送り、「その相手までのトンネルを作ってほしい」と頼みます。 MDN は、CONNECT は宛先までの HTTP トンネルを作り、成功すればトンネルが閉じるまで両方向のデータをそのまま中継する、と説明しています。

flowchart TD
    C[PC] -->|1 CONNECT ホスト:443| P[プロキシ]
    P -->|2 TCPで接続| S[Webサーバー]
    P -->|3 200 Connection established| T[トンネルができる]
    T -->|4 TLSの通信を中継するだけ| S

curl で HTTPS のサーバー(ポート 26611)をプロキシ経由で開いたときの出力です。

* Establish HTTP proxy tunnel to api.example.test:26611
> CONNECT api.example.test:26611 HTTP/1.1
> Host: api.example.test:26611
> User-Agent: curl/8.5.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
<
* CONNECT phase completed
* CONNECT tunnel established, response 200
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  issuer: CN=S266 Origin Root CA
*  SSL certificate verify ok.
> GET /echo HTTP/1.1

このとき、3か所で見えたものを並べます。

見る場所 見えたもの 意味
プロキシのログ TCP_TUNNEL/200 CONNECT api.example.test:26611 行き先のホストとポートだけ。パス(/echo)は見えない
Web サーバーが受けたヘッダー Host・User-Agent・Accept だけ Via・X-Forwarded-For は付かない
curl が見た証明書 発行者 S266 Origin Root CA Web サーバー自身の証明書がそのまま届いた

トンネルの中は暗号化されているので、プロキシはヘッダーを足すことも、URL を読むこともできません。 HTTP のときに付いていた Via と X-Forwarded-For が、HTTPS では付きませんでした。

プロキシが CONNECT を断るとき

MDN は、CONNECT を受け付けるプロキシは、つないでよいポートを決まったものに限るよう勧めています(何でも通すと、メールの不正な中継などに悪用されるため)。Squid の設定例も、CONNECT を 443 番などの SSL_ports に限っています。

acl SSL_ports port 443 26611
acl CONNECT method CONNECT
http_access deny CONNECT !SSL_ports

許していないポート(26610)へトンネルを頼むと、403 で断られました。

> CONNECT intra.example.test:26610 HTTP/1.1
< HTTP/1.1 403 Forbidden
curl: (56) CONNECT tunnel failed, response 403

Node.js の fetch() は、http:// の URL でもプロキシに CONNECT を送りました。 Node.js 24.21.0 で NODE_USE_ENV_PROXY=1 を付けて http://intra.example.test:26610/ を開くと、Squid のログは TCP_DENIED/403 CONNECT intra.example.test:26610 で、Node.js 側のエラーは Request was cancelled. だけでした。curl・git・npm・Java は、http:// の URL では GET http://… の形で送っていました。HTTP のサイトが Node.js からだけ開けないときは、プロキシのログで CONNECT が断られていないかを見ます。

HTTPSを復号するプロキシと証明書エラー

会社によっては、プロキシが HTTPS の中身を検査するため、通信をいったん復号して、社内の認証局(CA)で作り直した証明書を PC に見せます。 SSL インスペクション(TLS インスペクション)などと呼ばれます。PC がその社内 CA を信頼していないと、ツールは「知らない発行者の証明書だ」と判断して止まります。

Squid の ssl-bump で、この形のプロキシ(ポート 26602)を作りました。社内 CA の名前は Example Corp Inspection CA にしています。

http_port 127.0.0.1:26602 ssl-bump generate-host-certificates=on tls-cert=/path/corpCA.pem
sslcrtd_program /usr/lib/squid/security_file_certgen -s /path/ssl_db -M 4MB
ssl_bump bump all

社内 CA を curl に渡して開くと、証明書の発行者が Web サーバーの CA から社内 CA に変わり、Web サーバーには Via と X-Forwarded-For が届きました。プロキシのログには、HTTPS なのにパスまで残っています。

*  subject: CN=api.example.test
*  issuer: O=Example Corp; CN=Example Corp Inspection CA
*  SSL certificate verify ok.
# Squid のアクセスログ
NONE_NONE/200 CONNECT api.example.test:26611
TCP_REFRESH_MODIFIED/200 GET https://api.example.test:26611/echo

社内 CA を入れていないときのエラー原文

社内 CA を各ツールに入れずに、同じ HTTPS のサーバーを開いたときのエラーです。

ツール 出たエラー(原文)
curl 8.5.0 curl: (60) SSL certificate problem: self-signed certificate in certificate chain
git 2.43.0 fatal: unable to access 'https://…/repo.git/': server certificate verification failed. CAfile: none CRLfile: none
npm 10.9.7 npm error code SELF_SIGNED_CERT_IN_CHAIN
Node.js 24.21.0(fetch) SELF_SIGNED_CERT_IN_CHAIN self-signed certificate in certificate chain
pip 26.2.1 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain
Java 21 javax.net.ssl.SSLHandshakeException: (certificate_unknown) PKIX path building failed

どれも「証明書の鎖の中に、信頼していない自己署名の証明書がある」という意味で、原因は同じです。 直し方は、社内の情報システム部門から社内 CA の証明書(PEM 形式のファイル)をもらい、ツールに登録することです。証明書の検証を切る(curl の -k、git の http.sslVerify false、npm の strict-ssl false)と通りますが、通信相手の確認をやめることになるため、登録で直すのが筋です。

ツールごとの社内 CA の登録方法

次の書き方で、どれもエラーが消えて 200 や結果が返りました(Java は keytool で作ったトラストストアで確かめています)。

ツール 一時的に指定 ずっと使う設定
curl curl --cacert corpCA.crt URL 環境変数 CURL_CA_BUNDLE
git git -c http.sslCAInfo=corpCA.crt clone URL git config --global http.sslCAInfo パス
npm npm --cafile corpCA.crt view パッケージ npm config set cafile パス
Node.js 環境変数 NODE_EXTRA_CA_CERTS=corpCA.crt 同左、または --use-system-ca
pip pip install --cert corpCA.crt パッケージ 環境変数 PIP_CERT、pip.conf の cert
Java -Djavax.net.ssl.trustStore=ファイル keytool -importcert でトラストストアに追加

Node.js の「社内ネットワークの設定」の公式ページには、NODE_EXTRA_CA_CERTS に1つ以上の PEM の証明書を入れたファイルを指定すること、Node.js 22.19.0・24.6.0 以降は NODE_USE_SYSTEM_CA=1(または --use-system-ca)で OS の証明書ストアも信頼できることが書かれています。

エラーごとの詳しい直し方は、関連記事「CERTIFICATE_VERIFY_FAILEDの直し方|pip・Node」と関連記事「PKIX path building failedの原因と直し方|Java証明書」で扱っています。

PACファイル(プロキシ自動構成スクリプト)

PAC(Proxy Auto-Configuration)ファイルは、URL ごとに「直接つなぐか、どのプロキシを使うか」を決める JavaScript のファイルです。 社内では、ブラウザーや OS に PAC の URL(http://…/proxy.pac など)を設定して配ることがよくあります。MDN では、FindProxyForURL(url, host) という関数を書き、拡張子は .pac、MIME タイプは application/x-ns-proxy-autoconfig で配るとされています。

function FindProxyForURL(url, host) {
  // 1. 社内の短い名前(ドットなし)は直接
  if (isPlainHostName(host)) return "DIRECT";
  // 2. 社内ドメインは直接
  if (dnsDomainIs(host, ".corp.example.test")) return "DIRECT";
  // 3. 社内のアドレス帯(10.0.0.0/8)は直接
  if (isInNet(host, "10.0.0.0", "255.0.0.0")) return "DIRECT";
  // 4. パッケージ配布サイトは専用のプロキシ、落ちていたら通常のプロキシ
  if (shExpMatch(host, "*.npmjs.org") || shExpMatch(host, "pypi.org"))
    return "PROXY pkgproxy.example.test:8080; PROXY proxy.example.test:8080";
  // 5. それ以外はすべて通常のプロキシ。落ちていたら直接
  return "PROXY proxy.example.test:8080; DIRECT";
}

この PAC を、Node.js 向けの proxy-agents(pac-proxy-agent)で使われているライブラリ pac-resolver 9.0.1 で評価した結果です。

http://wiki/                         -> DIRECT
https://git.corp.example.test/repo   -> DIRECT
http://10.1.2.3/                     -> DIRECT
https://registry.npmjs.org/react     -> PROXY pkgproxy.example.test:8080; PROXY proxy.example.test:8080
https://pypi.org/simple/             -> PROXY pkgproxy.example.test:8080; PROXY proxy.example.test:8080
https://github.com/                  -> PROXY proxy.example.test:8080; DIRECT
返す値・関数 意味
DIRECT プロキシを使わず直接つなぐ
PROXY host:port そのプロキシを使う
SOCKS host:port その SOCKS サーバーを使う
; で区切って複数 左から順に試し、つながらなければ次へ
isPlainHostName(host) ホスト名にドットが無いか
dnsDomainIs(host, ".例") ホスト名がそのドメインで終わるか
shExpMatch(文字列, "*.例") * を使ったパターンに合うか
isInNet(host, IP, マスク) ホストの IP がその範囲に入るか

PAC を読むのは主にブラウザーと OS です。 curl・git・npm・pip の設定項目に PAC の URL を指定するものは無く、curl 8.5.0 のマニュアルにも PAC は出てきません。社内が PAC で配っているときは、PAC の中身を開いて、開発ツールで使う宛先がどの PROXY になるかを読み、その値を環境変数やツールの設定に書きます。

Windows・Mac でのプロキシの設定場所

Microsoft サポートの手順では、Windows は「設定」→「ネットワーク & インターネット」→「プロキシ」です。

項目 内容
自動プロキシセットアップ「設定の自動検出」 オンにすると、プロキシの設定を自動で検出する
「セットアップ スクリプトを使用」 PAC の URL(スクリプトのアドレス)を入れる
手動プロキシ セットアップ「プロキシ サーバーを使用」 「プロキシ IP アドレス」と「ポート」を入れる
例外 .contoso.com; *.adatum.com のように ; で区切る

この画面の設定は、コマンドラインの curl・git・npm・pip には効きません(それぞれ環境変数か自分の設定を読みます)。Windows のサービスなどが使う WinHTTP の設定は別で、Microsoft Learn では netsh winhttp show proxy は非推奨になり、netsh winhttp show advproxy を使うよう書かれています。

社内プロキシで開発ツールを通す設定(環境変数)

多くのコマンドラインのツールは、環境変数 http_proxy・https_proxy・no_proxy を読みます。 Linux・Mac のシェルなら次のように書きます(Windows の PowerShell は $env:https_proxy = "http://proxy.example.com:8080")。

export http_proxy=http://proxy.example.com:8080
export https_proxy=http://proxy.example.com:8080
export no_proxy=localhost,127.0.0.1,.corp.example.com
# 大文字しか読まないツールのために、同じ値を大文字でも入れておく
export HTTP_PROXY=$http_proxy HTTPS_PROXY=$https_proxy NO_PROXY=$no_proxy
変数 使われる場面 値の例
http_proxy http:// の URL を開くとき http://proxy.example.com:8080
https_proxy https:// の URL を開くとき http://proxy.example.com:8080
no_proxy プロキシを通さない宛先 localhost,127.0.0.1,.corp.example.com
all_proxy 上の2つが無いときの共通の値(curl・git) http://proxy.example.com:8080

https_proxy の値も「http://」で始める

https_proxy は「HTTPS のサイトを開くときに使うプロキシ」で、プロキシとの間の通信は普通の HTTP(http://)です。 値を https:// で始めると、ツールはプロキシと TLS でつなごうとして失敗しました。

ツール 値を https:// で始めたときのエラー
curl curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
pip SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1016)')
npm npm error code EPROTO … packet length too long

プロキシ自体が TLS で待ち受けている(HTTPS プロキシ)ときだけ https:// を使います。curl のマニュアルでは、-x に https:// を付けると HTTPS プロキシとして扱う(7.52.0 から)とあります。

大文字・小文字と NO_PROXY の書き方は、ツールで違う

同じ環境変数でも、読むかどうか、NO_PROXY をどう解釈するかがツールで違いました。Web サーバーの名前を intra.example.test にして、NO_PROXY の書き方を変えて試した結果です(「直接」は NO_PROXY に当たってプロキシを通らなかったもの)。

ツール example.test .example.test *.example.test 大文字の HTTP_PROXY
curl 8.5.0 直接 直接 プロキシ経由 読まない
git 2.43.0 直接 直接 プロキシ経由 読まない
Python 3.11(urllib) 直接 直接 プロキシ経由 読む
npm 10.9.7 直接 直接 プロキシ経由 読む
Node.js 24.21.0(fetch) 直接 直接 直接 読む

社内ドメインをまとめてプロキシから外したい

効かないツールがあるNO_PROXY=*.corp.example.com
→
5ツールで効いたNO_PROXY=.corp.example.com

curl・git・Python・npm は * 付きを文字どおりに扱い、プロキシへ送った

表から分かることは次のとおりです。

  • http_proxy は小文字で書きます。 curl のマニュアルには、環境変数は大文字・小文字のどちらでもよいが、http_proxy だけは小文字しか使えない、と書かれています。大文字の HTTP_PROXY だけを入れた状態では、curl と git はプロキシを使わず、Could not resolve host になりました。
  • ドメインの指定は、先頭にドットを付けた .example.test が5つのツールで同じように効きました。 curl のマニュアルでは、local.com は local.com と www.local.com に合い、www.notlocal.com には合わない、とされています。
  • * は、curl のマニュアルでは「* 1文字だけ」のときにすべての宛先に合う特別な値です。 *.example.test のような書き方は、curl・git・Python・npm では効きませんでした。
  • IP アドレスの範囲(127.0.0.0/8 など)は、URL が IP アドレスのときだけ当たります。 名前(intra.example.test)で開いたときは、名前が 127.0.0.1 を指していても、curl も Python もプロキシを通しました。curl は CIDR の書き方に 7.86.0 から対応しています。
  • Node.js 22.22.2 では、example.test(ドットなし)はサブドメインに当たらず、プロキシへ送りました。同じ Node.js でも版で結果が変わりました。

Node.js は、環境変数を設定しただけではプロキシを使いません。 環境変数だけでは fetch() が直接つなぎにいき ENOTFOUND になり、NODE_USE_ENV_PROXY=1 を付けるとプロキシを通りました。Node.js の公式ページでは、node:http・node:https は v22.21.0・v24.5.0 以降、fetch() は v22.21.0・v24.0.0 以降でこの設定に対応しています。

ツール別のプロキシ設定(git・npm・pip・curl・Java)

環境変数を使わず、ツールごとに設定することもできます。ツールの設定は、そのツールにだけ効きます。

ツール 設定するコマンド・ファイル 確認・解除
curl curl -x http://proxy:8080 URL、~/.curlrc に proxy = "http://proxy:8080" --noproxy '*' で一時的に外す
git git config --global http.proxy http://proxy:8080 git config --global --unset http.proxy
npm npm config set proxy … と npm config set https-proxy …、noproxy npm config get https-proxy、npm config delete proxy
pip pip install --proxy http://proxy:8080 パッケージ、pip.conf の proxy pip config list
Java -Dhttp.proxyHost・-Dhttp.proxyPort・-Dhttps.proxyHost・-Dhttps.proxyPort -Dhttp.nonProxyHosts で除外(縦棒区切り)
Maven ~/.m2/settings.xml の <proxies> <nonProxyHosts> で除外(縦棒区切り)
Gradle gradle.properties の systemProp.https.proxyHost など systemProp.http.nonProxyHosts
Node.js NODE_USE_ENV_PROXY=1 か --use-env-proxy と環境変数 NO_PROXY

git

git config --global http.proxy http://proxy.example.com:8080
# 社内の Git サーバーだけプロキシを使わない(空の値にする)
git config --global http.https://git.corp.example.com.proxy ''

~/.gitconfig には次のように書かれます。

[http]
    proxy = http://proxy.example.com:8080
[http "https://git.corp.example.com"]
    proxy =

Git のドキュメントでは、http.proxy は環境変数 http_proxy・https_proxy・all_proxy の設定を上書きするもので、http.<url>.* を使うと http の設定を特定の URL にだけ当てられます。全体の http.proxy を認証の要るプロキシ(407 を返す)にし、特定の URL だけ空の値にすると、その URL では 407 ではなく Could not resolve host(直接つなぎにいった)に変わりました。

npm

npm config set proxy http://proxy.example.com:8080
npm config set https-proxy http://proxy.example.com:8080
npm config set noproxy ".corp.example.com,localhost"

~/.npmrc には proxy=・https-proxy=・noproxy= の3行が入りました。npm のドキュメント(v12.2.0)では、proxy と https-proxy の既定値は null で、HTTP_PROXY・http_proxy(https-proxy は HTTPS_PROXY・https_proxy も)が設定されていればそれを使い、noproxy の既定値は NO_PROXY の値です。

npm は応答をキャッシュするため、一度プロキシ経由で取れたパッケージの情報は、プロキシを外しても返ってきました。設定が効いているかを確かめるときは、キャッシュの影響に気をつけます(--prefer-online を付ける、別のキャッシュ先を使うなど)。

pip

pip install --proxy http://proxy.example.com:8080 requests
pip config --user set global.proxy http://proxy.example.com:8080

pip のドキュメント(26.2.1)では、--proxy の形は scheme://[user:passwd@]proxy.server:port で、設定ファイルの proxy、または環境変数 http_proxy・https_proxy・no_proxy でも指定できます。pip config set を実行すると、Writing to …/.config/pip/pip.conf と出て、[global] の下に proxy = … が書かれました。

pip.conf の proxy は、環境変数 https_proxy より優先されました。 pip.conf に存在しないプロキシ(proxy.example.test:8080)を書いたまま、https_proxy に正しいプロキシを入れて実行すると、pip は pip.conf の方へつなぎにいき、proxy connection error: ('Unable to connect to proxy', NameResolutionError(…)) で失敗しました。環境変数を直しても変わらないときは、pip config list で設定ファイルを見ます。

Java・Maven・Gradle

Java は http_proxy などの環境変数を読みません。 環境変数だけを設定して HttpURLConnection で開くと java.net.UnknownHostException: intra.example.test(直接つなぎにいった)になり、システムプロパティを付けると Via 付きの 200 が返りました。

java -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080 \
     -Dhttps.proxyHost=proxy.example.com -Dhttps.proxyPort=8080 \
     -Dhttp.nonProxyHosts="*.corp.example.com|localhost" \
     -jar app.jar

Oracle の Java SE 25 のドキュメントでは、http.proxyPort の既定は 80、https.proxyPort の既定は 443、http.nonProxyHosts は | 区切りで * が使え、既定値は localhost|127.*|[::1] です。java.net.useSystemProxies=true にすると、Windows・macOS・Gnome では OS のプロキシ設定を使います(既定は false)。Java の nonProxyHosts は環境変数の NO_PROXY と違い、*.example.test の形で効きました。

Maven は ~/.m2/settings.xml、Gradle は gradle.properties に書きます(どちらも公式ドキュメントの例と同じ形)。

<settings>
  <proxies>
    <proxy>
      <id>corp-proxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.example.com</host>
      <port>8080</port>
      <nonProxyHosts>localhost|*.corp.example.com</nonProxyHosts>
    </proxy>
  </proxies>
</settings>
systemProp.http.proxyHost=proxy.example.com
systemProp.http.proxyPort=8080
systemProp.https.proxyHost=proxy.example.com
systemProp.https.proxyPort=8080
systemProp.http.nonProxyHosts=*.corp.example.com|localhost

Gradle のドキュメント(9.8.1)の例では、HTTPS 用でも nonProxyHosts は systemProp.http.nonProxyHosts と書き、「誤字ではない」と注記されています。Maven のドキュメントには、NTLM のプロキシは対応していない(試験されていない)と書かれています。

407 Proxy Authentication Requiredの原因と直し方

407 は「プロキシに通るための認証(ユーザー名・パスワード)が無い、または間違っている」というエラーです。 MDN では、407 は Proxy-Authenticate ヘッダー(認証の方式)とともに返され、クライアントは Proxy-Authorization ヘッダーを付けて送り直せる、とされています。サイトにログインするときの 401 とは、相手がプロキシである点が違います。

Basic 認証を付けた Squid(ポート 26601)に、認証なしで送ったときの応答です。

HTTP/1.1 407 Proxy Authentication Required
Server: squid/6.14
Content-Type: text/html;charset=utf-8
X-Squid-Error: ERR_CACHE_ACCESS_DENIED 0
Proxy-Authenticate: Basic realm="S266 Proxy"
Via: 1.1 proxy.s266.test (squid/6.14)

ツールごとの 407 の出方

ツール 出たエラー(原文)
curl(http) 407 の HTML がそのまま表示される(-i で HTTP/1.1 407 が見える)
curl(https) curl: (56) CONNECT tunnel failed, response 407
git(http) fatal: unable to access '…': The requested URL returned error: 407
git(https) fatal: unable to access '…': CONNECT tunnel failed, response 407
npm npm error code E407 と 407 Proxy Authentication Required - GET http://…
pip WARNING: Retrying … 'OSError('Tunnel connection failed: 407 Proxy Authentication Required')'
Java(http) java.io.IOException: Server returned HTTP response code: 407 for URL: …
Java(https) java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"

pip は、407 の警告のあとに ERROR: No matching distribution found for … で終わります。 --retries 0 にすると警告が出ず、最後のエラーだけが残りました。「パッケージが見つからない」と出ても、本当の原因がプロキシの認証のことがあります。関連記事「pip No matching distribution foundの直し方」で扱っています。

認証情報の渡し方

curl -U 'taro:パスワード' -x http://proxy.example.com:8080 https://example.com/
export https_proxy='http://taro:パスワード@proxy.example.com:8080'
git config --global http.proxy 'http://taro:パスワード@proxy.example.com:8080'

これで curl・git・npm・pip のどれも通りました(curl は 200、git は clone、npm と pip はパッケージの取得まで)。curl に間違ったパスワードを渡すと、また 407 になりました。

パスワードに @・:・# などの記号があるときは、URL の中ではパーセントエンコードします。 @ は %40、: は %3A です。

パスワードが p@ss:w0rd のとき

エラーhttp://hanako:p@ss:w0rd@proxy:8080
→
200で通ったhttp://hanako:p%40ss%3Aw0rd@proxy:8080

curl は「Unsupported proxy syntax … Port number was not a decimal number between 0 and 65535」で止まった

Basic 認証のパスワードは、そのままプロキシへ流れる

curl の -v で見ると、送ったヘッダーは次のとおりで、HTTPS のサイトでも、CONNECT の段階で同じヘッダーが送られていました。

> CONNECT api.example.test:26611 HTTP/1.1
> Host: api.example.test:26611
> Proxy-Authorization: Basic dGFybzpzMjY2LVBhc3M=

dGFybzpzMjY2LVBhc3M= を Base64 で戻すと taro:s266-Pass です。Basic 認証は暗号化ではなく、PC とプロキシの間が HTTP なら、経路上で読み取れます。 パスワードをシェルの履歴や .gitconfig・.npmrc に平文で残すことにもなるため、ファイルの権限に気をつけ、共有のリポジトリには入れないようにします。社内で Kerberos・NTLM の認証を使っている場合、curl には --proxy-negotiate・--proxy-ntlm・--proxy-anyauth があります(curl のマニュアル)。

Java は HTTPS のときだけ Basic 認証を使わない

Java は既定で、HTTPS のトンネル(CONNECT)での Basic 認証を無効にしています。 JDK 21 の conf/net.properties には次の行があります。

jdk.http.auth.tunneling.disabledSchemes=Basic

Authenticator で正しいユーザー名とパスワードを渡しても、結果は次のとおりでした。

宛先 既定のまま disabledSchemes を空にしたとき
http:// の URL 200 200
https:// の URL 407(Unable to tunnel through proxy) 200

表の右の列は -Djdk.http.auth.tunneling.disabledSchemes=(空の値)を付けて起動した結果です。Java のアプリだけが HTTPS で 407 になるときは、この設定を疑います。空の値にすると Basic が使えるようになりますが、パスワードが平文に近い形で流れることは上の節のとおりです。

プロキシのよくあるエラー一覧(原文と直し方)

この記事で実際に出たエラーを、原因ごとにまとめます。

出たもの(原文) ツール 原因 直し方
Could not resolve host: … curl・git プロキシを使わず直接つなぎ、名前が引けない 小文字の http_proxy・https_proxy を設定。NO_PROXY に当たっていないか見る
getaddrinfo ENOTFOUND … npm・Node.js 同上 npm は proxy・https-proxy、Node.js は NODE_USE_ENV_PROXY=1
java.net.UnknownHostException: … Java 環境変数を読まない -Dhttps.proxyHost などのシステムプロパティ
Failed to connect to … port 1080 curl プロキシのポートを書いていない(curl の既定は 1080) http://proxy:8080 のようにポートまで書く
wrong version number・WRONG_VERSION_NUMBER curl・pip https_proxy を https:// で始めた http:// で始める
EPROTO … packet length too long npm 同上 同上
CONNECT tunnel failed, response 407 curl・git 認証が無い・間違い ユーザー:パスワード@ を付ける。記号は%エンコード
The requested URL returned error: 407 git 同上(http の URL) 同上
npm error code E407 npm 同上 同上
Tunnel connection failed: 407 pip 同上(最後は No matching distribution) --proxy に認証情報を付ける
Unable to tunnel through proxy. … 407 Java 認証が無い、または Basic が無効 Authenticator と jdk.http.auth.tunneling.disabledSchemes
Unsupported proxy syntax … Port number was not a decimal number curl パスワードの @・: を URL にそのまま書いた %40・%3A にする
CONNECT tunnel failed, response 403 curl プロキシが許していないポート・宛先 443 以外は管理者に通してもらう
Request was cancelled. Node.js fetch http:// でも CONNECT を送り、断られた プロキシのログを見る。宛先を NO_PROXY に入れる
HTTP/1.1 403 Forbidden(ERR_ACCESS_DENIED) 共通 プロキシの規則で止められた宛先 業務で要る宛先なら管理者に申請する
HTTP/1.1 503(ERR_CONNECT_FAIL 111) 共通 プロキシから相手につながらない 相手のサーバー・ポートを確かめる
HTTP/1.1 503(ERR_DNS_FAIL) 共通 プロキシが名前を引けない ホスト名の綴りを確かめる
SSL certificate problem: self-signed certificate in certificate chain curl 復号するプロキシの社内 CA を信頼していない --cacert か CURL_CA_BUNDLE
server certificate verification failed. CAfile: none git 同上 http.sslCAInfo
SELF_SIGNED_CERT_IN_CHAIN npm・Node.js 同上 cafile、NODE_EXTRA_CA_CERTS
CERTIFICATE_VERIFY_FAILED pip 同上 --cert か PIP_CERT
PKIX path building failed Java 同上 keytool でトラストストアに追加

プロキシが返した 403・503 は、応答の X-Squid-Error ヘッダーや Via で「プロキシが返したもの」だと分かります(社内のプロキシ製品によってヘッダー名は変わります)。ステータスコードごとの意味は、関連記事「HTTPステータスコード 一覧|全コードの原因と対処・curl実例つき」で扱っています。

プロキシでつながらないときの切り分け手順

1

そのツールが、どのプロキシ設定を読んでいるかを見る

env | grep -i proxy で環境変数を、git config --get http.proxy・npm config get https-proxy・pip config list でツールの設定を見ます。大文字だけ・小文字だけになっていないかも確かめます。

症状:Could not resolve host/ENOTFOUND/UnknownHostException

2

curl -v で、プロキシに届いているかを見る

curl -v -x http://proxy:8080 https://example.com/ で、CONNECT の行と、その返事(200・403・407)を見ます。プロキシにつながらなければ Failed to connect です。

症状:Failed to connect/タイムアウト

3

407 なら、認証情報と記号のエンコードを見る

パスワードの @・: を %エンコードしているか、パスワードの期限が切れていないかを確かめます。Java だけ HTTPS で 407 なら、Basic が無効になっていないかを見ます。

症状:407 Proxy Authentication Required

4

証明書エラーなら、発行者の名前を見る

curl -v の issuer: が、開いたサイトの証明書会社ではなく社内の名前なら、復号するプロキシです。社内 CA をツールに登録します。

症状:self-signed certificate in certificate chain/PKIX

5

社内のサーバーだけ失敗するなら、NO_PROXY を見る

社内のサーバーまでプロキシに送ると、403・503 になったり、名前が引けなかったりします。.corp.example.com のように先頭にドットを付けて NO_PROXY に入れます。

症状:社内の URL だけ 403・503

curl の使い方全般は、関連記事「curlコマンドの使い方|よく使うオプションとAPIの確認方法」で扱っています。

プロキシとVPNの違い

どちらも「通信を別の場所を経由させる」点は同じですが、範囲と暗号化が違います。

比べる点 プロキシ(HTTP プロキシ) VPN
対象 設定したアプリ・ツールの通信(主に HTTP・HTTPS) 端末の通信全体(設定しだいで一部)
設定する場所 OS・ブラウザー・ツールごと VPN のソフト・OS
PC とプロキシの間の暗号化 HTTP プロキシ自体は暗号化しない(HTTPS のサイトは TLS で守られる) VPN の区間を暗号化する
主な使い道 社内からインターネットへの出口の管理 社外から社内ネットワークへ入る

VPN をつないでいるときに、社内プロキシの設定が別に要る構成もあります。どちらの設定が効いているかは、上の切り分け手順の1と2で確かめられます。

よくある質問

Q. プロキシサーバーとは何ですか? A. PC と Web サーバーの間に入り、通信を代わりに取り次ぐサーバーです。アクセスの制御・記録・キャッシュなどのために置かれます。「プロキシサーバーとは」の節に、実際に通したときのヘッダーの変化を載せています。

Q. フォワードプロキシとリバースプロキシの違いは何ですか? A. フォワードプロキシは利用者側の出口で、PC に設定して使います。リバースプロキシは Web サーバーの手前に置く入口で、利用者は設定せずにつなぎます。「フォワードプロキシとリバースプロキシの違い」の表にまとめています。

Q. 透過プロキシとは何ですか? A. PC にプロキシの設定をさせず、ルーターなどで通信の向きを変えてプロキシに通す方式です。PC から見ると直接つないでいるのに、応答に Via が付き、プロキシのログに残ります。

Q. HTTPS の通信はプロキシでどう扱われますか? A. クライアントが CONNECT ホスト:ポート でトンネルを作り、中の暗号化された通信をプロキシはそのまま中継します。プロキシのログに残るのはホストとポートだけです。社内 CA で復号するプロキシの場合は、URL まで見えます。

Q. 407 Proxy Authentication Required はどう直しますか? A. プロキシの URL に ユーザー:パスワード@ を付けるか、curl の -U などで認証情報を渡します。記号は %エンコードします。Java の HTTPS では、既定で Basic 認証が無効になっています。

Q. HTTP_PROXY と http_proxy はどちらを設定しますか? A. 小文字の http_proxy を設定し、必要なら大文字にも同じ値を入れます。curl と git は大文字の HTTP_PROXY を読みませんでした。

まとめ

  • プロキシサーバーは、通信を代わりに取り次ぐサーバー。利用者側の出口がフォワード、サーバー側の入口がリバース、設定なしで横取りするのが透過プロキシ。
  • HTTP はプロキシに URL 全体を送り、プロキシが Via・X-Forwarded-For を足す。HTTPS は CONNECT のトンネルで、プロキシに見えるのはホストとポートだけ。
  • 環境変数は小文字の http_proxy・https_proxy・no_proxy。https_proxy の値も http:// で始め、NO_PROXY は .corp.example.com の形がツールをまたいで効いた。
  • Java は環境変数を読まず、-Dhttps.proxyHost などで指定する。HTTPS のトンネルでは既定で Basic 認証を使わない。
  • 407 は認証情報の不足。証明書エラーは、復号するプロキシの社内 CA を各ツールに登録して直す。
  • PAC は主にブラウザーと OS が読む。開発ツールには、PAC の中の値を環境変数や設定に書き写す。

参考・出典

確認日はいずれも 2026年10月17日です。

  • MDN「Proxy servers and tunneling」:https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Proxy_servers_and_tunneling
  • MDN「Proxy Auto-Configuration (PAC) file」:https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file
  • MDN「CONNECT request method」:https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/CONNECT
  • MDN「407 Proxy Authentication Required」:https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/407
  • RFC 9110 HTTP Semantics:https://www.rfc-editor.org/rfc/rfc9110
  • Squid「http_port」:https://www.squid-cache.org/Doc/config/http_port/
  • curl「curl.1 the man page」:https://curl.se/docs/manpage.html
  • Git「http.* の設定(Documentation/config/http.adoc)」:https://git-scm.com/docs/git-config
  • npm Docs「config」(v12):https://docs.npmjs.com/cli/v12/using-npm/config
  • pip documentation「User Guide - Using a Proxy Server」:https://pip.pypa.io/en/stable/user_guide/
  • Oracle「Networking Properties(Java SE 25)」:https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/net/doc-files/net-properties.html
  • Apache Maven「Configuring a proxy」:https://maven.apache.org/guides/mini/guide-proxies.html
  • Gradle User Manual「Networking」:https://docs.gradle.org/current/userguide/networking.html
  • Node.js「Enterprise Network Configuration」:https://nodejs.org/en/learn/http/enterprise-network-configuration
  • Microsoft サポート「Windows でプロキシ サーバーを使用する」:https://support.microsoft.com/ja-jp/windows/windows-%E3%81%A7%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B-03096c53-0554-4ffe-b6ab-8b1deee8dae1
  • Microsoft Learn「WinHTTP の Netsh コマンド」:https://learn.microsoft.com/ja-jp/windows/win32/winhttp/netsh-exe-commands

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「プロキシサーバーとは|仕組み・種類と開発ツールの設定・407対処」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?