У меня вопрос об использовании 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-адресу восходящего потока, но запрос не выполняется из-за внутреннего брандмауэра.
У нас есть один внутренний прокси, который я могу использовать для обхода межсетевого экрана, например:
$ 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 ...
Этот трюк не работает с Nginx, поскольку он игнорирует http_proxy
переменная окружения. Прочитав документацию, я все еще не мог понять, как изменить конфигурацию, чтобы он мог использовать прокси внутри.
Можно ли совместить оба решения? Важно, чтобы кеширование по-прежнему работало, в противном случае вы можете просто использовать внешнее зеркало registry.npmjs.org напрямую.
Возможно, Nginx должен использовать внутренний прокси (proxy.abc.lan) как proxy_pass
, но тогда как внутренний прокси узнает, что запрос должен быть отправлен на внешнее зеркало npm (http://registry.npmjs.org)?
Обновление ответа Лукаса
Я попробовал решение Лукаса:
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 не является ожидаемая строка JSON от http://registry.npmjs.org но html-страница, созданная Nginx:
$ 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>
Проблема с решением Лукаса заключается в HttpRewriteModule , который автоматически превращает все, что содержит http (s) в начале, в 302.
Если вместо этого вы выполните переписывание в два этапа - второй «обрыв» - он должен работать. например
rewrite ^(.*)$ "://registry.npmjs.org$1";
rewrite ^(.*)$ "http$1" break;
proxy_pass http://proxy.abc.lan:1234;
Я подозреваю, что есть способ сделать это лучше, но, похоже, он работает.
Я думаю, что это может быть проще, чем любой из приведенных выше примеров. Они используют 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;
}
}
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, с помощью rewrite ... break;
заставит nginx использовать переписанный URI (теперь абсолютный URI, как того требует протокол) вместо того, чтобы пытаться построить его из proxy_pass
директива.