IdentityServer 部署踩坑记
Intro
周末终于部署了 IdentityServer
以及 IdentityServerAdmin
项目,踩了几个坑,在此记录分享一下。
部署架构
项目是基于 IdentityServerAdmin 项目修改的,感谢作者的开源付出,有需要 IdentityServer 管理需求的可以关注一下,觉得好用的可以给个 star 支持一下 https://github.com/skoruba/IdentityServer4.Admin
实际部署的有两个服务,一个是 IdentityServer 项目(https://id.weihanli.xyz),一个是 IdentityAdmin 项目(<https://id-admin.weihanli.xyz>)。
两个服务都是部署在一台服务器上,这一台服务器上部署一个单节点的 kubernetes,两个服务都是部署在 k8s 上并通过 NortPort 的方式对外提供服务,外面有一层 nginx 做了请求转发同时提供对外 https 的支持。
最初的 nginx 配置如下
server {
listen 443;
ssl_certificate /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.cer;
ssl_certificate_key /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.key;
server_name id.weihanli.xyz;
location / {
proxy_pass http://172.17.0.2:31210;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 443;
ssl_certificate /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.cer;
ssl_certificate_key /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.key;
server_name id-admin.weihanli.xyz;
location / {
proxy_pass http://172.17.0.2:31211;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
IdentityServer重定向到内网地址
部署起来之后,IdentityServer 可以访问,但是 IdentityAdmin 访问的时候会重定向到 IdentityServer 去登录,在发生重定向的时候会重定向到内网地址,重定向到了 172.17.0.1:31210
这个内网地址,这个地址是一个内网地址,公网肯定是没有办法访问的,在网上 Google 了半天发现有个类似的问题 网络回流(NAT Loopback/ Hairpin NAT),大概就是在同一网段的内网中的两个服务通信的时候通过公网域名没有办法访问,会转换成内网IP访问,所以发生重定向的时候会出现原本是域名重定向但是却变成了内网IP(不确定我的这种情况是不是属于网络回流的情况,有网络大佬的话可以帮忙分析一下,万分感谢)
因为使用了 nginx 并且转发后的内网 IP 地址是 nginx 转发到的请求地址,所以又 Google 了 nginx proxy redirect 关键词,最后找到一个解决方案 https://unix.stackexchange.com/questions/290141/nginx-reverse-proxy-redirection
最后生效的 nginx 完整配置如下:
server {
listen 443 http2;
ssl_certificate /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.cer;
ssl_certificate_key /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.key;
server_name id-admin.weihanli.xyz;
location / {
proxy_pass http://172.17.0.2:31211;
proxy_redirect http://172.17.0.2:31210/ https://id.weihanli.xyz/;
proxy_set_header Host $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
增加了上面的配置之后再发生重定向的时候地址就是正确的了,不再是一个内网IP 了
Invalid Token
Identity Server 重定向的问题解决之后,马上就出现了新的问题。。。
首先在 Identity Server 登录成功之后返回到 IdentityAdmin 的时候会报错,查看日志可以看到是 token 不合法的问题,起初是 issuer 不对的问题,我想可能是 issuer 可能 http/https 不一致的问题,于是增加了一个配置,直接在注册 IdentityServer 的时候使用指定的 issuer ,想着这样就不会有 http/https 的问题,于是重新部署,重新尝试之后,token 还是有问题,日志显示是token 签名验证错误,这时不经意之间看了一眼 IdentityServer 的 发现文档,打开之后发现里面的各种 endpoint 都是 http 的,后来发现 IdentityServer 有一个 PublicOrigin
的配置,把这个配置配置成 https://id.weihanli.xyz
之后就没有 invalid token 之类的错误了,再看发现文档的时候,endpoint 也是基于 https 的了。
Identity-Admin 502
在 IdentityServer
登录成功之后重定向到 IdentityAdmin 的时候 502,但是服务是存在的 在日志里只找到下面这样的错误日志
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_grant' , error_description: 'error_description is null', error_uri: 'error_uri is null'
在网上 Google 之后找到了这个issue:https://github.com/IdentityServer/IdentityServer4/issues/1670,尝试了下面这个解决方案解决了,是因为重定向的时候请求信息太大了
nginx 中 IdentityAdmin 项目增加配置:
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
修改之后,执行 sudo nginx-s reload
重新加载配置之后就正常了
More
最后现在在用的有效的完整的 nginx 配置如下:
server {
listen 443 http2;
ssl_certificate /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.cer;
ssl_certificate_key /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.key;
server_name id.weihanli.xyz;
location / {
proxy_pass http://172.17.0.2:31210;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 443 http2;
ssl_certificate /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.cer;
ssl_certificate_key /home/pipeline/.acme.sh/*.weihanli.xyz/*.weihanli.xyz.key;
server_name id-admin.weihanli.xyz;
location / {
proxy_pass http://172.17.0.2:31211;
proxy_redirect http://172.17.0.2:31210/ https://id.weihanli.xyz/;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_set_header Host $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Reference
https://github.com/IdentityServer/IdentityServer4
https://github.com/skoruba/IdentityServer4.Admin
https://unix.stackexchange.com/questions/290141/nginx-reverse-proxy-redirection
https://github.com/IdentityServer/IdentityServer4/issues/1670
http://docs.identityserver.io/en/latest/topics/deployment.html#typical-architecture
http://docs.identityserver.io/en/latest/reference/options.html
https://github.com/OpenReservation/Identity