Я пытаюсь настроить обратный прокси-сервер nginx для хранилища BLOB-объектов Azure. Я использую nginx:1.13.9-alpine
изображение, и у меня есть простой proxy_pass, настроенный следующим образом:
location /container {
proxy_pass https://account.blob.core.windows.net/container;
proxy_set_header Host account.blob.core.windows.net
}
Однако это не совсем так. Прямой запрос к учетной записи хранения работает, поэтому я знаю, что токен SAS хорош:
curl -v "https://account.blob.core.windows.net/container/file?st=2018-04-02T01%3A57%3A00Z&se=2018-04-11T01%3A57%3A00Z&sp=rl&sv=2015-12-11&sr=b&sig=<sig>"
Но использование того же токена через прокси всегда возвращает 403:
curl -v "https://proxy.mydomain.com/container/file?st=2018-04-02T01%3A57%3A00Z&se=2018-04-11T01%3A57%3A00Z&sp=rl&sv=2015-12-11&sr=b&sig=<sig>"
...snip...
< HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
В журналах сервера я просто вижу:
10.240.0.4 - - [06/Apr/2018:04:07:30 +0000] "GET /container/file?st=2018-04-02T01%3A57%3A00Z&se=2018-04-11T01%3A57%3A00Z&sp=rl&sv=2015-12-11&sr=b&sig=<sig> HTTP/1.1" 403 621 "-" "curl/7.54.0" "-"
Я видел несколько противоречивых советов о необходимости включения $is_args
и т. д., но ничего из этого не работает. Тот же экземпляр nginx проксирует несколько других ресурсов по другим путям, и все они работают должным образом. Что мне не хватает?
редактировать
Я считаю, что это связано с закодированными символами, такими как %2f
в пути URL. Хранилище Azure в этом случае используется в качестве серверной части для реестра Docker, и ему нравится давать имена BLOB-объектов, например %2fdocker/registry/v2/blobs/sha256/e7/e7c1ef..ced394/data
. Если я добавлю в контейнер образец капли без ведущего %2f
, все работает как положено.
В файле конфигурации по умолчанию или в файле конфигурации сайта. укажите URL-адрес контейнера больших двоичных объектов как proxy_pass
и установите базовый URL вашего контейнера как proxy_set_header Host
location /images {
proxy_pass https://YOURACCOUNT.blob.core.windows.net/images;
proxy_set_header Host YOURACCOUNT.blob.core.windows.net;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
Вот что в итоге сработало:
location /files/ {
resolver 8.8.8.8;
if ($request_uri ~* "/files/(.*)") {
proxy_pass https://account.blob.core.windows.net/container/$1;
}
}
Я понятия не имею, зачем нужен резолвер, учитывая, что другие места разрешают ОК. Это становится обязательным только тогда, когда proxy_pass
команда содержит переменную.