不指定主机的反向图像代理
Reverse image proxy without specifying host
我的配置中有以下内容作为图像的反向代理:
location ~ ^/image/(.+) {
proxy_pass http://example.com/;
}
问题是并非所有图像都是 example.com 图像,因此我们需要传入完整的 url。如果我尝试:
location ~ ^/image/(.+) {
proxy_pass ;
}
我收到一个错误:
invalid URL prefix in "https:/somethingelse.com/someimage.png"
这个问题很模糊,但是,根据错误消息,您要做的是完全根据用户输入执行 proxy_pass
,使用完整的 URL在 URI 的 /image/
前缀之后指定。
基本上,这是一个非常糟糕的主意,因为您正在开放自己成为一个开放的代理人。但是,它在您提供的 conf 中不起作用的原因是 URL 规范化,在您的情况下,将 http://example
压缩为 http:/example
(双斜杠变为单斜杠),这在 proxy_pass
.
的上下文中是不同的
如果您不关心安全性,您可以将 merge_slashes
从默认的 on
更改为 off
:
merge_slashes off;
location …
另一种可能与nginx proxy_pass and URL decoding
有些相关
location ~ ^/image/.+ {
rewrite ^ $request_uri;
rewrite ^/image/(.*) break;
return 400;
proxy_pass $uri; # will result in an open-proxy, don't try at home
}
正确的解决方案是实施白名单,可能借助 map
甚至基于前缀的位置指令:
location ~ ^/image/(http):/(upload.example.org)/(.*) {
proxy_pass :///;
}
请注意,根据开头的解释,上面的位置受 merge_slash
设置的影响,因此默认情况下它永远不会有双重 //
,因此需要在 proxy_pass
阶段手动添加双 //
。
在这种情况下我会使用地图
map $request_uri $proxied_url {
# if you don't care about domain and file extension
~*/image/(https?)://?(.*) ://;
# if you want to limit file extension
~*/image/(https?)://?(.*\.(png|jpg|jpeg|ico))$ ://;
# if you want to limit file extension and domain
~*/image/(https?)://?(abc\.xyz\.com/)(.*\.(png|jpg|jpeg|ico))$ ://;
default "/404";
}
然后在您的代理传递部分,您将使用如下所示的东西
location /image/ {
proxy_pass $proxied_url;
}
我已经给出了三个不同的例子,具体取决于你想如何处理它
我的配置中有以下内容作为图像的反向代理:
location ~ ^/image/(.+) {
proxy_pass http://example.com/;
}
问题是并非所有图像都是 example.com 图像,因此我们需要传入完整的 url。如果我尝试:
location ~ ^/image/(.+) {
proxy_pass ;
}
我收到一个错误:
invalid URL prefix in "https:/somethingelse.com/someimage.png"
这个问题很模糊,但是,根据错误消息,您要做的是完全根据用户输入执行 proxy_pass
,使用完整的 URL在 URI 的 /image/
前缀之后指定。
基本上,这是一个非常糟糕的主意,因为您正在开放自己成为一个开放的代理人。但是,它在您提供的 conf 中不起作用的原因是 URL 规范化,在您的情况下,将 http://example
压缩为 http:/example
(双斜杠变为单斜杠),这在 proxy_pass
.
如果您不关心安全性,您可以将 merge_slashes
从默认的 on
更改为 off
:
merge_slashes off;
location …
另一种可能与nginx proxy_pass and URL decoding
有些相关location ~ ^/image/.+ {
rewrite ^ $request_uri;
rewrite ^/image/(.*) break;
return 400;
proxy_pass $uri; # will result in an open-proxy, don't try at home
}
正确的解决方案是实施白名单,可能借助 map
甚至基于前缀的位置指令:
location ~ ^/image/(http):/(upload.example.org)/(.*) {
proxy_pass :///;
}
请注意,根据开头的解释,上面的位置受 merge_slash
设置的影响,因此默认情况下它永远不会有双重 //
,因此需要在 proxy_pass
阶段手动添加双 //
。
在这种情况下我会使用地图
map $request_uri $proxied_url {
# if you don't care about domain and file extension
~*/image/(https?)://?(.*) ://;
# if you want to limit file extension
~*/image/(https?)://?(.*\.(png|jpg|jpeg|ico))$ ://;
# if you want to limit file extension and domain
~*/image/(https?)://?(abc\.xyz\.com/)(.*\.(png|jpg|jpeg|ico))$ ://;
default "/404";
}
然后在您的代理传递部分,您将使用如下所示的东西
location /image/ {
proxy_pass $proxied_url;
}
我已经给出了三个不同的例子,具体取决于你想如何处理它