garden/content/articles/20240622204025-对象存储反代设置.md
SouthFox 12506255f0
All checks were successful
/ deploy (push) Successful in 49s
[post] new post
2024-06-22 22:41:32 +08:00

274 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

+++
title = "对象存储反代设置"
author = ["SouthFox"]
date = 2024-06-22T20:40:00+08:00
lastmod = 2024-06-22T22:40:55+08:00
tags = ["publish"]
draft = false
+++
## 为什么要为对象存储做一层反代? {#为什么要为对象存储做一层反代}
在对象存储商前面挂一层[反向代理]({{< relref "../main/nw_反向代理.md" >}})做一层[缓存]({{< relref "../main/nw_缓存.md" >}})是一个好主意,可以压缩请求数和流量,节省消费开支。同时挡下一些恶意请求。
对象存储很多服务商都是有着「请求数」和「流量」的计费项目,如果被有心之人大量恶意请求那么就有可能产生高额账单。
## 对策 {#对策}
- 创建桶名时为其添加随机后缀
- 最好不要直接使用服务商提供的链接
- 设置为公开读的桶最好做一层反代
## Nginx 反代配置 {#nginx-反代配置}
这里以我所用的 mastadon 所用的配置来举例:
```cfg
proxy_cache_path /tmp/nginx_mstdn_media levels=1:2 keys_zone=mastodon_media:100m max_size=1g inactive=24h;
server {
listen 80;
listen [::]:80;
server_name [media-host];
return 301 https://[media-host]$request_uri;
access_log /dev/null;
error_log /dev/null;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name [media-host];
ssl_certificate /etc/letsencrypt/live/[media-host]/fullchain.pem; # ma>
ssl_certificate_key /etc/letsencrypt/live/[media-host]/privkey.pem; # >
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
access_log /var/log/nginx/mstdn-media-access.log;
error_log /var/log/nginx/mstdn-media-error.log;
location = / {
return 418;
}
location / {
limit_except GET {
deny all;
}
proxy_cache mastodon_media;
proxy_cache_revalidate on;
proxy_buffering on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_valid 30d;
proxy_cache_valid 404 1h;
proxy_hide_header 'Access-Control-Allow-Origin';
proxy_hide_header 'Access-Control-Allow-Methods';
proxy_hide_header 'Access-Control-Allow-Headers';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header x-amz-bucket-region;
proxy_hide_header x-amzn-requestid;
proxy_hide_header x-amz-version-id;
proxy_ignore_headers Set-Cookie;
proxy_ignore_headers Cache-Control;
add_header X-Cached $upstream_cache_status;
add_header 'Access-Control-Allow-Origin' '*';
expires 1y;
proxy_pass [s3-url];
}
proxy_intercept_errors on;
error_page 400 403 404 = @fallback;
location @fallback {
return 404;
}
}
```
```cfg
location = / {
return 418;
}
```
如果设置为公开读的桶,那么访问域名主页会列出当下桶前面一些数量的对象,这可能会带来一些风险,所以针对直接访问主页的请求直接拒绝并返回。
```cfg
limit_except GET {
deny all;
}
```
只允许 HTTP GET 方法,毕竟很多对象存储服务是连失败的请求也要计入费用的。
```cfg
proxy_cache_path /tmp/nginx_mstdn_media levels=1:2 keys_zone=mastodon_media:100m max_size=1g inactive=24h;
...
proxy_cache mastodon_media;
proxy_cache_revalidate on;
proxy_buffering on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_valid 30d;
proxy_cache_valid 404 1h;
```
`nginx` 缓存设置,缓存到服务器本地并设置为 30 天有效期
```cfg
add_header 'Access-Control-Allow-Origin' '*';
expires 1y;
proxy_pass [s3-url];
```
`add_header` 放行跨域设置,对于联邦宇宙而言有些实例会直接让用户读取源站媒体,所以不能做限制。
`expires` 设置客户端的缓存失效时间为一年。
`proxy_pass` 服务商给的桶公开链接。
```cfg
proxy_intercept_errors on;
error_page 400 403 404 = @fallback;
location @fallback {
return 404;
}
```
一些服务商的 404 页面里会包含桶名信息,这是一个会被知晓桶名的点。
`proxy_intercept_errors` 开启后将允许自定义设置错误,将其定位为 `nginx` 的默认 404 页面。
## 设置迁移 {#设置迁移}
有时候对一个服务商感到不满准备迁移,例如使用 [Rclone](https://rclone.org/) 工具将原来的桶拷贝到另一个服务商的桶,对于一个几十上千万的对象的桶来说迁移将是一个漫长的过程。而在迁移时也不可能完全停止服务,但可以在反代层设置一个策略,当找不到对象时可以导向原来的桶,这样对于用户来说也是无感的。具体来说:
- 更改应用程序配置 s3 设置为新服务商,让新写入数据导向新桶
- 编辑 `nginx` 配置,设置反代为新服务商
- 当新服务商报 404 时,往旧服务商的地址再进行反代
- 运行迁移,将旧服务商的桶对象拷贝到新服务商的桶内
具体配置:
```cfg
proxy_cache_path /tmp/nginx_mstdn_media levels=1:2 keys_zone=mastodon_media:100m max_size=1g inactive=24h;
server {
listen 80;
listen [::]:80;
server_name [media-host];
return 301 https://[media-host]$request_uri;
access_log /dev/null;
error_log /dev/null;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name [media-host];
ssl_certificate /etc/letsencrypt/live/[media-host]/fullchain.pem; # ma>
ssl_certificate_key /etc/letsencrypt/live/[media-host]/privkey.pem; # >
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
access_log /var/log/nginx/mstdn-media-access.log;
error_log /var/log/nginx/mstdn-media-error.log;
location / {
limit_except GET {
deny all;
}
proxy_cache mastodon_media;
proxy_cache_revalidate on;
proxy_buffering on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_valid 30d;
proxy_cache_valid 404 1h;
proxy_hide_header 'Access-Control-Allow-Origin';
proxy_hide_header 'Access-Control-Allow-Methods';
proxy_hide_header 'Access-Control-Allow-Headers';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header x-amz-bucket-region;
proxy_hide_header x-amzn-requestid;
proxy_hide_header x-amz-version-id;
proxy_ignore_headers Set-Cookie;
proxy_ignore_headers Cache-Control;
add_header X-Cached $upstream_cache_status;
add_header 'Access-Control-Allow-Origin' '*';
expires 1y;
proxy_pass [new-s3-url];
}
proxy_intercept_errors on;
recursive_error_pages on;
error_page 400 403 404 = @404;
location @404 {
proxy_pass [old-s3-url];
proxy_hide_header 'Access-Control-Allow-Origin';
proxy_hide_header 'Access-Control-Allow-Methods';
proxy_hide_header 'Access-Control-Allow-Headers';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header x-amz-bucket-region;
proxy_hide_header x-amzn-requestid;
proxy_hide_header x-amz-version-id;
proxy_ignore_headers Set-Cookie;
proxy_ignore_headers Cache-Control;
error_page 400 403 404 = @fallback;
}
location @fallback {
return 418;
}
}
```
其中新增加内容并不多:
`recursive_error_pages` 允许多次定义错误页。
```cfg
location @fallback {
return 418;
}
```
不能再返回 404 了否则会陷入循环,可以另选一个其它错误,这里我选择 418 。
## 免责声明 {#免责声明}
安全无小事,我也无法保证上面的设置是没有漏洞的或者完全安全的,对使用相关配置带来的后果也不负任何责任。
## 参考 {#参考}
[Proxying object storage through nginx | Mastodon Docs](https://docs.joinmastodon.org/admin/optional/object-storage-proxy/)
[云上黑暗森林打爆云账单只需要S3桶名 | Pigsty](https://pigsty.io/zh/blog/cloud/s3-scam/)