Proxy IPFS in path style
为什么使用代理方式,而不是运行 ipfs daemon
,为了省内存!
使用 nginx 就可以轻松实现了。
Proxy IPFS in subdomain style
DNS
Cloudflare 支持泛域名解析
HTTPS 证书
acme.sh
安装简单(相比 certbot
),使用简单。
curl https://get.acme.sh | sh -s email=[email protected]
# 关掉nginx释放443、80端口
# 安装
~/.acme.sh/acme.sh --issue --standalone -d ipfs.drink.cafe -d '*.ipns.ipfs.drink.cafe' -d '*.ipfs.ipfs.drink.cafe' --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
# 添加 DNS TXT 记录后,验证 wildcard 域名
~/.acme.sh/acme.sh --issue --standalone -d ipfs.drink.cafe -d '*.ipns.ipfs.drink.cafe' -d '*.ipfs.ipfs.drink.cafe' --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force --renew
正确代理上游的内容(过时)
- weaming/proxyany: HTTP(S) reverse proxy with domain replaced
- 泛域名代理问题:proxyany 阴差阳错地已经支持了。
- 上游连接数的问题(未解决)
[
{"from": "ipfs.ipfs.drink.cafe", "to": "https://ipfs.dweb.link"},
{"from": "ipfs.drink.cafe", "to": "https://ipfs.dweb.link"}
]
正确代理上游内容 2
proxy_pass 到 ipfs.dweb.link 的时候出现 502 问题。
阅读 How to Use NGINX as an HTTPS Forward Proxy Server 后发现不应该 nginx 反向代理不成功啊。
查看 /var/log/nginx/error.log
发现问题是 no resolver defined to resolve ipfs.dweb.link
。
在 nginx 的 location
内添加 resolver 1.1.1.1;
就好了。
location / {
add_header x-source https://$subdomain.ipfs.dweb.link$uri;
#return 302 https://$subdomain.ipfs.dweb.link$uri;
resolver 1.1.1.1;
proxy_pass https://$subdomain.ipfs.dweb.link;
proxy_set_header Host $subdomain.ipfs.dweb.link;
# proxy_cache_bypass $http_upgrade;
proxy_pass_request_headers on;
client_max_body_size 50M;
}
跳转 path style 的请求
查看 gateway checker 的 JS 源码,可以看到必须实现跳转。
function expectSubdomainRedirect(url) {
// Detecting redirects on remote Origins is extra tricky,
// but we seem to be able to access xhr.responseURL which is enough to see
// if paths are redirected to subdomains.
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onload = function () {
// expect to be redirected to subdomain where first DNS label is CID
if (new URL(xhr.responseURL).hostname.startsWith(IMG_HASH)) {
resolve()
} else {
reject()
}
}
xhr.onerror = function (err) {
console.error(url, err)
reject()
}
xhr.send(null)
})
}
通过 nginx 的 location 正则匹配即可实现。
不支持 CIDv0
访问 https://QmfEw63k5VZP2ffAiGZTvZfUgkRfzuKddLWi8SC78cuS4R.ipfs.dweb.link 报错
invalid CID: selected encoding not supported (possible lowercased CIDv0; consider converting to a case-agnostic CIDv1, such as base32)
解决方式 1:转化为 CIDv1
$ ipfs cid base32 QmfEw63k5VZP2ffAiGZTvZfUgkRfzuKddLWi8SC78cuS4R
bafybeih3d63d53eggrlibuhwdpofajzvrbjw2ounv55uo755smzpr2h57i
解决方式 2:不跳转 CIDv0
https://ipfs.drink.cafe/ipfs/QmfEw63k5VZP2ffAiGZTvZfUgkRfzuKddLWi8SC78cuS4R
最终 nginx 配置结果
server {
include requestid.conf;
include https.conf;
server_name ipfs.drink.cafe;
ssl_certificate /etc/letsencrypt/live/drink.cafe/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/drink.cafe/privkey.pem;
ssl_dhparam /usr/local/nginx/dhparams.pem;
location ~ ^/ipfs/(?<cid>[0-9a-z]+)(?<extra>(.|/)*)$ {
client_max_body_size 5M;
add_header access-control-allow-origin '*';
return 302 'https://$cid.ipfs.ipfs.drink.cafe$extra';
}
location / {
client_max_body_size 5M;
add_header access-control-allow-origin '*';
proxy_pass https://ipfs.io;
proxy_set_header Host 'ipfs.io';
proxy_cache_bypass $http_upgrade;
}
location = / {
return 302 '/ipfs/bafybeih3d63d53eggrlibuhwdpofajzvrbjw2ounv55uo755smzpr2h57i';
}
}
server {
include requestid.conf;
include https.conf;
server_name ~^(?<subdomain>.+)\.ipfs\.ipfs\.drink\.cafe$;
ssl_certificate /root/.acme.sh/ipfs.drink.cafe/ipfs.drink.cafe.cer;
ssl_certificate_key /root/.acme.sh/ipfs.drink.cafe/ipfs.drink.cafe.key;
ssl_dhparam /usr/local/nginx/dhparams.pem;
location / {
client_max_body_size 50M;
# proxy_cache_bypass $http_upgrade;
proxy_pass_request_headers on;
add_header x-source https://$subdomain.ipfs.dweb.link$uri;
resolver 1.1.1.1;
proxy_pass https://$subdomain.ipfs.dweb.link;
proxy_set_header Host $subdomain.ipfs.dweb.link;
}
}