我正在尝试将我的网站从http迁移到https。该架构是:在Nginx服务器上运行的angularJS webapp前端(侦听端口80),它将请求发送到在Puma服务器上运行的Rails API应用程序(侦听端口8080)。两台服务器都在Amazon EC2实例中共存。
这是我第一次迁移到HTTPS并且我根本不熟练。读了很多,我取得了一些进展,但现在我被卡住了。
我想确认我是否采用了正确的方法,或者我的方法是错误的。
目前:
现在(这只是在开发中工作,而不是AWS实例)试图保护后端Puma服务器我采用了一种非常简单的方法:由于Rails API是私有的,我创建了一个自签名的SSL证书,只是用它来启动Puma服务器,如下所示:
捆绑exec puma -b'sssl://127.0.0.1:3000?key = puma.server.key& cert = puma.server.crt'-e development -S~ / puma -C config / puma / development .RB
如上所述,这是在开发中。我的Nginx服务器正在443中监听,并向Puma监听端口3000发送请求。
所以,在这一点上,我想知道我是否采用正确的方法,但我只是遗漏了一些东西,否则,对于EC2实例来说这是一种错误的方法,我需要做一些与众不同的事情。注意:我已经阅读了有关如何配置Nginx服务器以代理https的内容,但目前还不太了解。我应该这样走吗?
@ffeast回答后的评论和问题:
我理解你的方法。我建议,它阻碍了第二种方法。但是,我有一些问题:
我会解决使用此方法遇到的阻止:混合内容错误吗?为什么?我的意思是,Rails API请求是否会发生变化?注意:目前,在Angular中,我有资源发送请求,例如:// domain-name:8080 / action,Puma服务器正在侦听该端口中的请求。我目前没有任何代理通行证。
我认为你包括连接到Puma套接字的de Nginx配置,我想我需要创建这个Puma套接字,我需要检查一下。如果你知道如何包含一个例子会有所帮助。如果我用这个套接字配置Puma,我是否需要在特定端口启动Puma?
我试着理解整个画面,但我仍然感到困惑: 3.1对API(来自Angular Nginx)的请求应该如何? 3.2如果我应该在特定端口启动Puma?我不知道是否需要套接字方法...... 3.3代理传递配置应该如何匹配这些请求。
您能澄清一下可能更新您的示例吗?我们假设此时请求类似于//域名:8080 / action
更新 我正在尝试配置Ningx代理将请求传递给PUMA套接字(目前处于开发阶段)。我收到错误,请参阅新帖子以保持清洁:Nginx proxy pass to Rails API
更新2 它工作!我的网站安全无误!这是我的配置。
upstream api.development {
# Path to Puma SOCK file, as defined previously
server unix:/tmp/puma.sock fail_timeout=0;
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /keys/ssl/development.server.crt;
ssl_certificate_key /keys/ssl/development.server.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
location / {
root /path-to-app;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
# Proxy pass requests to Yanpy API
location /api {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
#proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
rewrite ^/api(.*) /$1 break;
proxy_pass http://api.development;
}
}
我唯一的问题是:如果我评论所有的proxy_set_header指令:
location /api {
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Host $host;
#proxy_set_header X-Forwarded-Proto https;
#proxy_redirect off;
rewrite ^/api(.*) /$1 break;
proxy_pass http://api.development;
}
它也有效。我知道他们不是强制性的工作,应该包括在内,因为他们有一些好处吗?
同样:
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
答案 0 :(得分:4)
你走错了路。
在大多数情况下,您无需保护后端应用,这就是原因:
因此,任务归结为在nginx中配置https并通过与HTTP感知后端服务器的不安全连接执行proxy_pass(https://nginx.ru/en/docs/http/ngx_http_proxy_module.html#proxy_pass)。
问题是如何处理以下问题:
http
或https
网址以下是它通常如何解决的问题:
Host
标头通过proxy_set_header传递并由后端服务器接收X-Forwarded-Proto
标头已被传递并且通常受后端服务器的尊重X-Forwarded-For
标头包含原始用户的IP 我搜索了与puma
相关的设置,这与它最终的样子非常接近(从这里借来https://gist.github.com/rkjha/d898e225266f6bbe75d8),@myapp_puma
部分对你的案例特别感兴趣:
upstream myapp_puma {
server 127.0.0.1:8080 fail_timeout=0;
}
server {
listen 443 default ssl;
server_name example.com;
root /home/username/example.com/current/public;
ssl on;
ssl_certificate /home/username/.comodo_certs/example.com.crt;
ssl_certificate_key /home/username/.comodo_certs/example.com.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
try_files $uri/index.html $uri @myapp_puma;
location @myapp_puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_pass http://myapp_puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
现在关于你的角度应用程序。 它需要知道它应该用于API请求的URL。 它可以通过多种方式解决,但重点是NO URL应该在代码中进行硬编码,您可以使用环境变量代替。这是其中一种方法described - 它使用角度应用之前包含的 env.js 文件,然后依赖于整个代码中定义的常量。在您的情况下,apiUrl应指向所需的https端点
(function (window) {
window.__env = window.__env || {};
// API url
window.__env.apiUrl = 'http://dev.your-api.com';
// Base url
window.__env.baseUrl = '/';
// Whether or not to enable debug mode
// Setting this to false will disable console output
window.__env.enableDebug = true;
}(this));
增加: 因为你的后端似乎正在处理没有API前缀的URL, 你可以使用nginx的以下技巧:
location /api/ {
...
proxy_pass http://api.development/;
...
}
注意到proxy_pass之后的尾部斜杠 - 在这种情况下,将删除位置前缀。来自here:
如果使用URI指定了proxy_pass指令,那么当a。时 请求被传递给服务器,这是规范化请求URI的一部分 匹配该位置将被指令
中指定的URI替换
答案 1 :(得分:1)
听起来整个考验都是关于你在某个地方收到的blocked:mixed-content
错误:
是否在浏览器中?无论好坏,浏览器实际上都不会知道前端服务器与后端服务器之间的连接是否超过{{1} }或http
。换句话说,更有可能的是,错误是由网页某处仍在https
上提取内容的内容引起的,无论是来自您自己的域,还是来自第三方,而不是任何事情后端通过http
上的前端服务器代理。例如,您可能希望在前端代码中将http
更改为src="http://cdn.example.org/….js"
,以使所有JavaScript脚本都满意。
它在后端吗?一般来说,为了告诉"在连接安全的后端,前端代理必须添加适当的src="//cdn.example.org/….js"
标头。
否则,http://nginx.org/r/proxy_pass确实在最新版本的nginx中支持经过验证的https,您可以使用X-Forwarded-Proto
指令的组合来配置安全策略,例如proxy_ssl_…
与公共版本您的自签名证书和/或CA,以及proxy_ssl_trusted_certificate
。
P.S。实际上,我不同意关于后端和前端服务器之间加密性能影响的优点的其他答案。如果你有理由相信这种联系可能会被破坏(甚至谷歌发现他们的数据中心之间的专用光纤线已被政府利用),那么,确实在后端之间使用自签名的proxy_ssl_verify on;
和前端服务器
在性能方面,https
的主要成本来自建立连接;但是在服务器场景中,那个连接可以重新用于服务多个客户端(例如,可能通过https
控制);即使连接无法重用,后端和前端服务器之间的延迟通常也足够小,能够在没有性能影响的情况下维持一些额外的往返(特别是考虑到最终用户的延迟通常在订单上比那更大的数量。)
话虽如此,https
address scheme如今被高度滥用 - 大多数公共网站都没有被强制使用proxy_ssl_session_reuse
的好处,因为它只会减少可以访问这些网站的人数(请参阅HTTP/2.0: The IETF Is Phoning It In仅列出基于策略的问题列表,并且还存在许多TLS不兼容的技术问题),而且面向客户的https
确实会因为需要额外的往返行程而降低性能因此,如果您不从https
获得任何额外的好处,那么它通常只是一种责任。总而言之,如果没有它,偶尔拍摄猫图片的博客可能会更好。