简体   繁体   English

为了将域切换到HTTPS,是否需要更改Apache或Node.js应用程序?

[英]In order to switch my domain to HTTPS, do I need to change Apache or my Node.js app?

I have a web app that runs on my domain. 我有一个在我的域上运行的Web应用程序。 First I had regular HTTP site, which was running on port 8082 on my server, while an Apache server (using virtual hosts) was redirecting requests from port 80 to localhost:8082 . 首先,我有一个常规的HTTP站点,该站点运行在服务器的8082端口上,而Apache服务器(使用虚拟主机)将请求从80端口重定向到localhost:8082

Now I got an SSL certificate that I tried to install with my site. 现在,我获得了一个SSL证书,该证书试图与我的网站一起安装。 I made an HTTPS server in Node, and on https://localhost:8082 everything worked as it should. 我在Node中制作了一个HTTPS服务器,并在https://localhost:8082所有工作。

But then I tried serving my domain over HTTPS. 但是后来我尝试通过HTTPS为我的域提供服务。 I tried editing my virtual host file to use the certificate, but I think I haven't written it correctly. 我尝试编辑我的虚拟主机文件以使用证书,但我认为我没有正确编写它。 Also, I tried to make it redirect HTTP to HTTPS, but it didn't work. 另外,我尝试使它将HTTP重定向到HTTPS,但没有用。

What should I do? 我该怎么办? Should I run an HTTP or HTTPS server in Node, and what should I put in my Apache virtual host configuration? 我应该在Node中运行HTTP还是HTTPS服务器,我应该在Apache虚拟主机配置中添加什么?

Here's my virtual host file: 这是我的虚拟主机文件:

<VirtualHost *:80>
        ServerName www.domain.com
        Redirect permanent / https://www.domain.com
</VirtualHost>

<VirtualHost *:443>

        ServerName domain.com
        ServerAlias www.domain.com

        SSLEngine On
        SSLProxyEngine On
        SSLCertificateFile "/home/USERNAME/Projects/NODEAPP/chained.pem"
        SSLCertificateKeyFile "/home/USERNAME/Projects/NODEAPP/domain.key"

        ProxyPreserveHost On
        ProxyRequests off

        <Proxy *>
                Order deny,allow
                Allow from all
        </Proxy>

        <Location />
                ProxyPass http://localhost:8082/

                ProxyPassReverse http://localhost:8082/
        </Location>

</VirtualHost>

(Fair warning: my understanding of your question is that you want https://www.domain.com to appear in the browser's URL bar, not https://www.domain.com:8082 . If that's not the case a lot of the below is wrong, but will probably still help you understand your problem better.) (警告:我对您的问题的理解是,您希望https://www.domain.com出现在浏览器的网址栏中,而不是https://www.domain.com:8082 。如果不是这样的话以下内容是错误的,但可能仍将帮助您更好地理解问题。)

Background 背景

(aka, HTTP design crash course because I think you don't quite understand what's going on, but feel free to skip if you do:) (aka,HTTP设计速成课程,因为我认为您不太了解正在发生的事情,但是如果您这样做,请随时跳过:)

I think you have a misconception as to what Apache's doing - mostly because you're saying that it's "redirecting" requests. 我认为您对Apache的操作有一个误解-主要是因为您是在说它正在“重定向”请求。

An HTTP redirect is any(?) response with a status code in the 3xx range, and it tells your browser that the resource it's requested has moved somewhere else. HTTP重定向是状态代码在3xx范围内的任何(?)响应,它告诉您的浏览器所请求的资源已移动到其他地方。 For example, let's say that http://example.com/foo used to exist, but has since been moved to http://example.org/bar (note the .com and .org difference). 例如,假设http://example.com/foo曾经存在,但此后已移至http://example.org/bar (请注意.com.org区别)。 If you type in http://example.com/foo into your URL bar, your browser will request /foo (specifically it will send an HTTP GET request) to example.com . 如果您在URL栏中输入http://example.com/foo ,则浏览器将向example.com请求/foo (特别是它将发送HTTP GET请求)。 example.com will then send an HTTP response back to the browser redirecting it to http://example.org/bar . 然后example.com将HTTP响应发送回浏览器, 重定向http://example.org/bar Then the browser will send an HTTP GET request for /bar to example.org and get back a response containing the resource. 然后,浏览器将/bar的HTTP GET请求发送到example.org并获取包含该资源的响应。

Here's a diagram: 这是一个图:

Step 1:

-------------                                   --------------------------
|           |                                   |                        |
|  Browser  | -------- HTTP GET /foo ---------> | example.com web server |
|           | <-- HTTP 301 Moved Permanently -- |                        |
-------------                                   --------------------------

Step 2:

-------------                        --------------------------
|           |                        |                        |
|  Browser  | --- HTTP GET /bar ---> | example.org web server |
|           | <---- HTTP 200 OK ---- |                        |
-------------                        --------------------------

Now, here's the thing. 现在,这是事情。 That's not what you're doing, nor probably what you want to be doing. 不是你在做什么,也可能不是你想做什么。 What you're doing is called reverse proxying, which is where whenever the web server (in your case Apache) receives a request, it just forwards it somewhere else. 您正在做的事情称为反向代理,这是每当Web服务器(在您的情况下为Apache)接收到请求时,它将转发到其他地方的请求。 In your original (all-HTTP) setup, the web browser would request www.domain.com from Apache, then Apache would simply forward that request, with little to no modification, to http://localhost:8082 . 在您的原始(全HTTP)设置中,Web浏览器将向Apache请求www.domain.com ,然后Apache只需将该请求(几乎没有修改)转发到http://localhost:8082 Here's the diagram: 如下图:

Step 1:

-------------                        ----------                        ------------------
|           |                        |        |                        |                |
|           | ----- HTTP GET / ----> |        |                        |                |
|  Browser  |                        | Apache | ----- HTTP GET / ----> | localhost:8082 |
|           |                        |        | <---- HTTP 200 OK ---- |                |
|           | <---- HTTP 200 OK ---- |        |                        |                |
-------------                        ----------                        ------------------

Step 2:

There is no step 2. BOOM.

The really important thing to note here is that the browser doesn't "see" Node.js, it sees Apache on the other end. 这里要注意的真正重要的事情是浏览器没有“看到” Node.js,而是看到了另一端的Apache。 Likewise Node.js doesn't "see" the browser, it sees Apache (although typically Apache will augment the request with details about the browser connection - see for example the X-Forwarded-For header). 同样,Node.js不会“看到”浏览器,而是看到Apache(尽管通常Apache会使用有关浏览器连接的详细信息来扩充请求-例如,参见X-Forwarded-For标头)。

This is an intentional part of the design of HTTP - HTTP request and response semantics don't imply anything about the internal implementation details of how requests are processed. 这是HTTP设计的故意部分-HTTP请求和响应语义并不暗示有关如何处理请求的内部实现细节。 That's why HTTP is so powerful. 这就是HTTP如此强大的原因。 It lets you create really complex setups - think what you're doing but on a much bigger scale and with even more components - and then abstract over that complication with a simple, uniform interface that's shown to the external world: your URL hierarchy combined with the HTTP request/response cycle. 它使您可以创建非常复杂的设置-思考您正在做的事情,但是要更大的规模并使用更多的组件-然后通过向外界显示的简单,统一的界面抽象出这种复杂性:URL层次结构与HTTP请求/响应周期。

How to solve your actual problem 如何解决您的实际问题

Now that we've established what you're trying to do, here's what your problem is: you're conflating what protocol Node.js is speaking with what protocol Apache is speaking (and thus what the external world is seeing). 既然我们已经确定您要尝试做的事情,这就是您的问题所在:您正在将Node.js在说什么协议与Apache在说什么协议(以及外界在看什么)混为一谈。

Your end goal is for people to connect to your website over HTTPS, right? 您的最终目标是让人们通过HTTPS连接到您的网站,对吗? In that case, you don't need Node.js to speak HTTPS, because the only thing that directly talks to Node.js is Apache. 在那种情况下,您不需要Node.js讲HTTPS,因为直接与Node.js对话的唯一东西就是Apache。 Apache is the thing that speaks to browsers, so Apache is what you need to use HTTPS. Apache是​​与浏览器对话的东西,因此Apache是​​使用HTTPS所需要的。 Ideally, you'd have Apache speak HTTPS to browsers and HTTP to Node.js - it doesn't matter if Apache encrypts traffic to Node because Node is on localhost. 理想情况下,您应该让Apache对浏览器讲HTTPS,对HTTP.Node.js讲HTTP-Apache是​​否加密到Node的流量并不重要,因为Node在本地主机上。 In diagram form: 以图表形式:

-------------                         ----------                        ------------------
|           |                         |        |                        |                |
|           | ----- HTTPS GET / ----> |        |                        |                |
|  Browser  |                         | Apache | ----- HTTP GET / ----> | localhost:8082 |
|           |                         |        | <---- HTTP 200 OK ---- |                |
|           | <---- HTTPS 200 OK ---- |        |                        |                |
-------------                         ----------                        ------------------

So make your Node app listen for HTTP requests, then fix your Apache config to serve stuff with HTTPS, but speak HTTP to the Node backend. 因此,请让您的Node应用程序侦听HTTP请求,然后修复您的Apache配置,以使用HTTPS来提供服务,但要向Node后端讲HTTP。

I think what's wrong with your configuration is that you need quotes around the path, ie <Location "/"> . 我认为您的配置有问题,您需要在路径两边加上引号,即<Location "/"> Alternately in the reverse proxy configs that I have, I have ProxyPass directives set up without a <Location> block, like so: 或者,在我具有的反向代理配置中,我设置了ProxyPass指令,而没有<Location>块,如下所示:

ProxyPass / http://localhost:8082/
ProxyPassReverse / http://localhost:8082/

so you could try that too. 因此您也可以尝试。

If it still doesn't work, try removing the <Proxy> / </Proxy> block - I'm not really sure what that does, but I don't have anything like that in my reverse proxy configurations (which work) - so it might be interfering with something. 如果仍然无法正常运行,请尝试删除<Proxy> / </Proxy>块-我不确定是否可以这样做,但是我的反向代理配置中没有类似的功能(可以正常工作)-因此它可能会干扰某些事情。

As for your HTTP to HTTPS redirect, I don't really see anything wrong with it. 至于您的HTTP到HTTPS重定向,我没有发现任何问题。 Are you sure you're connecting to www.domain.com instead of domain.com ? 您确定要连接到www.domain.com而不是domain.com吗? The second VirtualHost serves both, but the first serves only the former. 第二台VirtualHost可以同时为两者提供服务,但第一台VirtualHost只能为前者提供服务。

From your description I'm going to summarize your problem as follows: 根据您的描述,我将总结您的问题,如下所示:

  1. You've configured node.js to accept TLS connections 您已将node.js配置为接受TLS连接

  2. You want Apache to accept TLS connections 您希望Apache接受TLS连接

OK. 好。 So first question. 所以第一个问题。 You said: 你说:

I made https server in Node, and on https://localhost:8082 everything worked as it should. 我在Node中制作了https服务器,并在https:// localhost:8082上使一切正常运行。

Without changing anything, what happens when you try to access http://localhost:8082 ? 在不进行任何更改的情况下,尝试访问http://localhost:8082什么? I can tell you what happens (no guesses, no "should", I can definitely tell you) but you should at least try it in order to see for yourself what happens. 我可以告诉您发生了什么(没有猜测,没有“应该”,我可以肯定地告诉您),但是您至少应该尝试一下,以便自己了解发生了什么。

SPOILERS: HTTP does not support listening for both TLS and unencrypted connections on a single port. SPOILERS:HTTP不支持在单个端口上同时侦听TLS和未加密的连接。 It's just the way the protocol was specified. 这只是协议的指定方式。 Other protocols like POP3, SMTP, FTP etc have the capability to do this but not HTTP. 其他协议(例如POP3,SMTP,FTP等)也可以执行此操作,但HTTP无法执行。 So what happens is trying to access http://localhost:8082 will fail. 因此,尝试访问http://localhost:8082会失败。

Now, look carefully at your Apache config: 现在,仔细查看您的Apache配置:

# THIS is the problematic part:
ProxyPass         http://localhost:8082/
ProxyPassReverse  http://localhost:8082/
#                   ^
#                   |______ notice this?

So the problem is you are proxying to a url that does not work. 因此,问题在于您正在代理无法使用的网址。

You have two options here. 您在这里有两个选择。 Both of them valid depending on how you want to design your architecture. 两者均有效,具体取决于您要如何设计体系结构。

  1. Proxy to https instead of http . 代理https而不是http

     ProxyPass https://localhost:8082/ ProxyPassReverse https://localhost:8082/ 

    The advantage of this is that you get end-to-end encryption. 这样做的好处是您可以获得端到端加密。 Even if someone manage to login to your server they can't listen in to the connection. 即使有人设法登录到您的服务器,他们也无法收听连接。 The disadvantage of this is you're encrypting twice which mean you're using much more CPU time to serve a request. 这样做的缺点是您要加密两次,这意味着您将花费更多的CPU时间来处理请求。

  2. Remove TLS from node.js. 从node.js删除TLS。

    The advantage of this is that you're letting Apache handle all encryption so your web app does not need to spend any CPU time handling encryption itself. 这样做的好处是让Apache处理所有加密,因此您的Web应用程序无需花费任何CPU时间来处理加密本身。 For very large services like Google or Facebook they can even offload the encryption to another front-end server (or more likely servers) so that the server running your web app won't be busy encrypting and decrypting HTTP connections. 对于Google或Facebook这样的大型服务,他们甚至可以将加密工作转移到另一台前端服务器(或更可能的服务器),这样运行您的Web应用程序的服务器就不会忙于加密和解密HTTP连接。 The disadvantage is that anyone who can login to your server can easily listen in to the connection. 缺点是任何可以登录到您的服务器的人都可以轻松收听连接。

There is a third way that some people do but it's getting less and less popular. 有些人可以采用第三种方法,但是这种方法越来越不受欢迎。 Run node.js listening on two ports. 运行node.js在两个端口上侦听。 For example, configure one to listen to 8082 for http and also listen to 8084 for https then you can proxy http pages to 8082 and https pages to 8084. However, looking at your Apache config I can tell this is not what you want to do. 例如,配置一个可以监听8082的HTTP,也可以监听8084的https,然后可以将HTTP页面代理到8082,将https页面代理到8084。但是,查看您的Apache配置,我可以知道这不是您想要做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM