web-dev-qa-db-ja.com

既存のキャッシングNginxプロキシで別のプロキシを使用してファイアウォールをバイパスする方法

私の質問は、Nginxを別のプロキシの背後にあるプロキシとして使用することです。 (やや混乱します。)

Nginxがnpmミラーのキャッシュプロキシサーバーとして機能するように設定します。ここにリンクがあります: http://eng.yammer.com/a-private-npm-cache/

ファイアウォールで制限されていないローカルマシンでは、次の構成で問題なく動作します。

proxy_cache_path /var/cache/npm/data levels=1:2 keys_zone=npm:20m max_size=1000m
inactive=365d;
proxy_temp_path /var/cache/npm/tmp;

server {
   listen 80;
   server_name classen.abc.lan;
   location / {
      proxy_pass http://registry.npmjs.org/;
      proxy_cache npm;
      proxy_cache_valid 200 302 365d;
      proxy_cache_valid 404 1m;
      sub_filter 'registry.npmjs.org' 'classen.abc.lan';
      sub_filter_once off;
      sub_filter_types application/json;
   }
}

次に、追加のファイアウォールの背後にあるサーバーに適用します。ログで、正しいアップストリームIPにアクセスしていることを確認できますが、内部ファイアウォールのためにリクエストは失敗します。

ファイアウォールをバイパスするために使用できる内部プロキシが1つあります。次に例を示します。

$ curl http://registry.npmjs.org
curl: (7) couldn't connect to Host
$ http_proxy=http://proxy.abc.lan:1234/ curl http://registry.npmjs.org
... succeeds ...

このトリックはhttp_proxy環境変数を無視するため、Nginxでは機能しません。ドキュメントを読んだ後でも、構成を変更する方法がわからなかったため、内部でプロキシを使用できます。

両方のソリューションを組み合わせることが可能ですか?キャッシングが引き続き機能することが重要です。それ以外の場合は、外部ミラーregistry.npmjs.orgを直接使用できます。

たぶん、Nginxは内部プロキシ(proxy.abc.lan)をproxy_passとして使用する必要がありますが、内部プロキシはどのようにしてリクエストが外部npmミラーに送信される必要があることを認識します( http:// registry.npmjs.org )?

Lukas回答の更新

私はルーカスの解決策を試しました:

rewrite ^(.*)$ "http://registry.npmjs.org$1" break;
proxy_pass http://proxy.abc.lan:1234;

ログはURLが書き換えられたことを示していますが、リダイレクトが発生しています(curl classen.abc.lan/test-urlによってトリガーされます):

2014/03/24 11:31:16 [notice] 13827#0: *2 rewritten redirect: "http://registry.npmjs.org/test-url", client: 172.18.40.33, server: classen.abc.lan, request: "GET /test-url HTTP/1.1", Host: "classen.abc.lan"

Curl呼び出しの結果は http://registry.npmjs.org からの予期されるJSON文字列ではなく、Nginxによって生成されたhtmlページです。

$ curl classen.abc.lan/test-url
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.4.7</center>
</body>
</html>
5
Philipp Claßen

Lukasのソリューションの問題は HttpRewriteModule です。これにより、先頭のhttp(s)のすべてが302に自動的に変換されます。

代わりに2段階で書き換えを行う場合-2番目の段階は「中断」-機能するはずです。例えば.

rewrite ^(.*)$ "://registry.npmjs.org$1";
rewrite ^(.*)$ "http$1" break;
proxy_pass http://proxy.abc.lan:1234;

これを行うにはもっと良い方法があると思いますが、うまくいくようです。

4
james.haggerty

RFC 2616、セクション5.1.2 状態

リクエストがプロキシに対して行われている場合、absoluteURI形式が必要です。
[...]
リクエストラインの例は:

  GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

だからあなたがすることになっているのはそれらの変更されたディレクティブでプロキシにリクエストを渡すことです:

rewrite ^(.*)$ "http://registry.npmjs.org$1" break;
proxy_pass http://proxy.abc.lan:1234;

nginx docs によると、rewrite ... break;を使用すると、nginxが書き換えられたURI(現在は絶対URI)を使用するように強制されますプロトコルが要求するように)proxy_passディレクティブからビルドする代わりに。

2
Lukas

上記のどちらの例よりも簡単かもしれません。彼らはrewriteを使用してURLを書き換えていますが、proxy_passを使用できますが、URLをプロキシに渡して、ホストヘッダーパラメータを目的の場所に設定します。例えば.

http {

  upstream corporate_proxy  {
      server web-proxy.mycorp.com:8080;
  }

server {
   listen 80;
   server_name classen.abc.lan;
   location / {
      proxy_pass_header on;
      proxy_set_header Host "registry.npmjs.org";
      proxy_pass http://corporate_proxy;
      proxy_cache npm;
      proxy_cache_valid 200 302 365d;
      proxy_cache_valid 404 1m;
      sub_filter 'registry.npmjs.org' 'classen.abc.lan';
      sub_filter_once off;
      sub_filter_types application/json;
   }
}
1
Mark D