- サーバー
- ネットワーク
プロキシサーバーとは|仕組み・種類と開発ツールの設定・407対処
結論
プロキシサーバーは、PCとWebサーバーの間に入り、通信を代わりに取り次ぐサーバーです。利用者側の出口に置くものと、サーバー側の入口に置くものがあります。
この記事でわかること
- フォワード・リバース・透過の3種類と実際のログ
- curl・git・npm・pipなど8ツールのプロキシ設定表
- 407・証明書エラーなどエラー原文22種と直し方
同じ「プロキシ」でも、利用者を代表して外へ出るものと、サーバーを代表して外から受けるものでは、置き場所も目的も逆です。
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.comNO_PROXY=.corp.example.comcurl・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:8080http://hanako:p%40ss%3Aw0rd@proxy:8080curl は「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実例つき」で扱っています。
プロキシでつながらないときの切り分け手順
そのツールが、どのプロキシ設定を読んでいるかを見る
env | grep -i proxy で環境変数を、git config --get http.proxy・npm config get https-proxy・pip config list でツールの設定を見ます。大文字だけ・小文字だけになっていないかも確かめます。
curl -v で、プロキシに届いているかを見る
curl -v -x http://proxy:8080 https://example.com/ で、CONNECT の行と、その返事(200・403・407)を見ます。プロキシにつながらなければ Failed to connect です。
407 なら、認証情報と記号のエンコードを見る
パスワードの @・: を %エンコードしているか、パスワードの期限が切れていないかを確かめます。Java だけ HTTPS で 407 なら、Basic が無効になっていないかを見ます。
証明書エラーなら、発行者の名前を見る
curl -v の issuer: が、開いたサイトの証明書会社ではなく社内の名前なら、復号するプロキシです。社内 CA をツールに登録します。
社内のサーバーだけ失敗するなら、NO_PROXY を見る
社内のサーバーまでプロキシに送ると、403・503 になったり、名前が引けなかったりします。.corp.example.com のように先頭にドットを付けて NO_PROXY に入れます。
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期連続の黒字決算。