Nginx反向代理HTTPS配置

在我们的项目中需要部署多个Web服务,如果部署在同一台机器上,可以根据域名来区分,从而使这些Web服务都能通过80端口访问。而当每个服务都用Docker来部署后,宿主机的80端口只能转发到一个Docker容器,这样就需要引入一个新的容器做为各Web服务的反向代理,这个反向代理就是一个Nginx容器,它监听80和443端口,然后根据域名转发到后端不同的服务容器中,后端服务容器监听的端口没有要求,只要在这个反向代理容器里面正确配置转发端口就可以了。这种部署的结构图大致如下:

 

 

在具体的部署中,我们要求使用HTTPS访问,需要监听443端口,那么如果不监听80端口,用户输入HTTP的网址,就会出错让用户误以为网站不正常而放弃使用,因此同样需要监听80端口,然后在用户以HTTP方式访问时自动转为HTTPS方式访问即可。

假设上图中各服务使用的域名如下:

Nginx反向代理: www.domain.com

Http Server1:    server1.domain.com

Http Server2:    server2.domain.com

 

首先我们需要给域名server1.domain.com和server2.domain.com购买SSL证书(我们购买阿里云的证书,不支持通配符域名),购买后可以下载到证书文件,每个域名有两个文件,我们分别重命名为server1.key、server1.pem、server2.key、server2.pem,然后在Nginx反向代理容器的/etc/nginx目录下新建一个名为cert的目录,将这些证书文件拷贝到该目录下。我们在Nginx反向代理容器的/etc/nginx/conf.d目录下添加一个文件default.conf,内容如下:

 

server {

listen 80;

server_name  server1.domain.com;

return 301 https://$server_name$request_uri;

}

server {

listen 80;

server_name  server2.domain.com;

return 301 https://$server_name$request_uri;

}

server {

listen       443;

server_name  server1.domain.com;

ssl on;

ssl_certificate           cert/server1.pem;

ssl_certificate_key   cert/server1.key;

ssl_session_timeout 5m;

ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_prefer_server_ciphers on;

location / {

resolver 127.0.0.11;

set $target http://api;

proxy_pass  $target;

proxy_set_header Host   $http_host;

proxy_set_header X-Real-IP   $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

}

server {

listen       443;

server_name  server2.domain.com;

ssl on;

ssl_certificate           cert/server2.pem;

ssl_certificate_key   cert/server2.key;

ssl_session_timeout 5m;

ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_prefer_server_ciphers on;

location / {

resolver 127.0.0.11;

set $target http://cms;

proxy_pass  $target;

proxy_set_header Host   $http_host;

proxy_set_header X-Real-IP   $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

}

转发配置中有“set $target http://api;”这样的写法,这是因为这些Docker容器都连到一个自定义的网桥上,启动容器Http Server1时将其主机名设置为“api”,反向代理容器通过主机名“api”就能找到对应的IP地址从而能进行正确的转发。如果这里写IP,每次重新部署Http Server1时都需要更新反向代理服务的转发地址,或者需要指定Http Server1使用某个固定IP,会麻烦一些。

从上面配置可以看到,反向代理将443端口的请求以HTTP方式转发到后端服务器,因此后端的Http Server1和Http Server2只需要监听80端口即可,不需要配置443端口和HTTPS证书。

在实际项目中,由于后端服务器使用Laravel-admin框架开发,在使用HTTPS访问时,后端自动生成的css、js的路径却是HTTP开头的,这样浏览器会阻止这些内容的加载使得网站无法正常访问。找到项目的根目录,里面有个config目录,将该目录下的admin.php文件的secure值设置为true,问题得到解决。

发表评论

电子邮件地址不会被公开。