作者:沈豪,上海财经大学,Datawhale成员
centos服务器上能配置多网站多证书啦!再也不愁网站配置问题了!!
前言: 作为一名大四的本科生,我的梦想是拥有自己的个人网站,向所有人分享我的所思所想。在大三的时候,我完成了这一梦想,基于Hexo框架我完成了个人网站的搭建并购买服务器实现了网站的发布!不过随着项目经历的丰富,我打算为自己的AI项目再配置一个网站!那一台主机如何同时部署两个web服务呢,本文将讲述在实际配置过程中遇到的各类坑以及解决方案。
本文适用于以下人群:
- 想要实现自己个人网站的发布的小白站长!
- 想理解apache、nginx反向代理的原理的learner!
- 想解决web服务器配置过程中的端口冲突问题(80 or 443)的部署者!
环境(centos):nginx:1.14.1,apache:2.4.37
初步思考
看到这个问题我的第一个反映是用不同的端口去部署网站不就好了吗,但是记录IP地址和端口号是个费脑的活,有没有一种方案能输入不同的域名,就能对应到同一台IP主机上相应的端口呢,并且是以https协议进行访问呢?
首先我们要明白域名访问网站的流程:
例如:我们在浏览器地址栏键入URL,按下回车后是怎么在浏览器上得到目标网站的内容呢:
- 浏览器向DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
- 解析出 IP 地址后,根据该IP 地址和默认的 80 端口,和服务器建立 TCP 连接;
- 浏览器发出读取文件的HTTP 请求后,服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
- 释放 TCP 连接;
- 浏览器将html文件进行渲染展示。
HTTP协议
在这个流程中,我们关注到域名首先会被解析为IP地址,最后实际我们访问的是地址是IP:80。那么在这个时候我们考虑到一个很重要的问题,如果我们打算在同一台IP主机上部署两个域名网站,比如a.com以及b.com。如果按照上述所说,那么a.com和b.com都将指向同一个ip和端口,那怎么才能呈现出两个网站呢?
在这里我们先介绍一下nginx反向代理的原理!!
正向代理和反向代理
正向代理
我们常说的代理服务器(多指 VPN),一般就是正向代理。它能隐藏真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都由代理服务器代替来请求。
举个例子,国内的用户想要访问 Github 时,往往无法正常访问,或者速度过慢。所以这个时候VPN的作用就是把我们的访问请求先发送到另外一个代理服务器(可以访问 Github 的服务器)上,由其代为转发请求和接收响应内容,在发送回我们的本地浏览器。
当出现多个客户端时,正向代理 Server 就对应于多个Clients,而目标服务器并不知道真实发起请求的客户端是哪一个,如下所示:
反向代理
反向代理恰好跟正向代理相反。同时反向代理一般是负载均衡的一个原理。按照上面所说,正向代理是一对一或多对一,那么反向代理就是一对多,画图说明:
反向代理
举个例子:我们都知道百度域名背后有成百上千台服务器为客户端服务,而这就是反向代理的具体体现。
如果我们访问www.baidu.com,1.首先会有一个类似于”总机“的反向代理服务器监听80端口,接收请求;2.”总机“服务器存有好多其他服务器的ip地址,会根据每个服务器目前能处理请求的能力进行请求转发的分配;3.较为空闲的服务器会接收到”总机“的请求转发,将响应的html文件传给”总机“;4.”总机“再将响应返回给客户端。
和正向代理一样,在实际访问中,我们也无法知道究竟是哪台服务器为我们进行服务。而proxy将请求合理分配给不同的服务器的过程也就是负载均衡的思想。
改进方案
那么理解了什么是”反向代理“,我们就可以对之前的方案进行一些改进:
不同于大企业所拥有的成百上千台服务器,个人用户往往可能只拥有一台Linux服务器。那么如何在只有一台服务器的情况下,进行反向代理呢?下图为改进方案的具体流程:
以下的ip和域名都并非真实
并存方案图解
当客户端想要通域名 datawhale.ml 或者 deeplearning.ml 访问网站时,由于我们将两个网站同时部署在同一个IP地址的服务器上,因此通过DNS域名解析出来的ip地址将会是同一个,在上图的案例中即为127.1.1.1。比如,当用户具体访问datawhale.ml时,通过DNS域名解析出 IP 地址后,根据该 IP 地址和默认的 80 端口,向反向代理服务器(ip地址127.1.1.1)发送请求。由于proxy的Nginx服务监听80端口,因此代理服务器可以根据请求中域名server name的值,将请求进行转发。而datawhale.ml网站是部署在Apache的web服务上,监听端口为81,因此proxy会把请求datawhale.ml最后映射到127.1.1.1:81上。访问deeplearning.ml的流程也是同理,只不过它的网页是部署在Nginx的web服务商,监听端口为82。
Nginx和Apache的具体配置
Nginx网站部署
前提须知:
- http监听端口为81
- https监听端口为441
- 防火墙中打开81和441端口
修改nginx配置文件
vim /etc/nginx/nginx.conf
# http
server {
listen 81; # http协议时,监听81端口
server_name datawhale.ml;
#root /usr/share/nginx/html;
#重定向,将http访问改为https访问
rewrite ^(.*) https://$server_name$1 permanent;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
# 个人网站index.html的根目录
root /home/git/projects/blog;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# https
server {
listen 441 ssl; # ssl不能少
server_name datawhale.ml;
#root /usr/share/nginx/html;
ssl_certificate "/etc/nginx/ssl/datawhale.ml.pem"; # ssl证书路径必须写
ssl_certificate_key "/etc/nginx/ssl/datawhale.ml.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
root /home/git/projects/blog;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
生效nginx配置文件
systemctl restart nginx.service
Apache网站配置
准备工作:
将含有index.html的根目录文件cp到/var/www/html/目录下,此时就可以通过访问ip:80进行网址查看。(前提80端口没有被其他服务如nginx占用)
修改nginx配置文件(端口更改)
vim /etc/httpd/conf/httpd.conf
Listen 82
<Directory "/var/www/html">
Options Indexes FollowSymLinks # 允许Apache 显示目录列表呢
# 允许.htaccess文件进行覆盖加载配置
Options FollowSymLinks MultiViews Includes
AllowOverride All
Require all granted
</Directory>
配置证书和HTTP 自动跳转 HTTPS 的安全配置
配置证书:
1. 在 /etc/httpd/conf
目录下的 httpd.conf 配置文件找到 Include conf.modules.d/*.conf
(用于加载配置 SSL 的配置目录)配置语句,并确认该配置语句未被注释。若已注释,请去掉首行的注释符号(#
),保存配置文件。
2. 在 /etc/httpd/conf.modules.d
目录下的 00-ssl.conf 配置文件找到 LoadModule ssl_module modules/mod_ssl.so
(用于加载 SSL 模块)配置语句,并确认该配置语句未被注释,若已注释,请去掉首行的注释符号(#
),保存配置文件。
由于操作系统的版本不同,目录结构也不同,请根据实际操作系统版本进行查找。若以上配置文件中均未找到 LoadModule ssl_module modules/mod_ssl.so 和 Include conf.modules.d/*.conf 配置语句,请确认是否已经安装 mod_ssl.so 模块。若未安装 mod_ssl.so 模块,您可通过执行yum install mod_ssl 命令进行安装。
3. 编辑 /etc/httpd/conf.d
目录下的 ssl.conf 配置文件。修改如下内容:
Listen 442 https
<VirtualHost 0.0.0.0:442>
#网站文件根目录
DocumentRoot "/var/www/html"
#填写证书名称
ServerName deeplearning.ml
#启用 SSL 功能
SSLEngine on
#证书文件的路径
SSLCertificateFile /etc/httpd/ssl/2_deeplearning.ml.crt
#私钥文件的路径
SSLCertificateKeyFile /etc/httpd/ssl/3_deeplearning.ml.key
#证书链文件的路径
SSLCertificateChainFile /etc/httpd/ssl/1_root_bundle.crt
</VirtualHost>
HTTP 自动跳转 HTTPS 的安全配置:
vim /var/www/html/.htaccess
RewriteEngine on
RewriteBase /
RewriteCond %{SERVER_PORT} !^442$
RewriteRule ^.*$ https://%{SERVER_NAME}:442%{REQUEST_URI} [L,R]
deeplearning.ml 自动变为https://deeplearning.ml:442,但是这并不是我们所希望的,我们希望能直接访问https://deeplearning.ml
生效nginx配置文件
systemctl restart httpd.service
Nginx 反向代理实现域名转发
http反向代理的配置
# test.conf 为反向代理的配置vim /etc/nginx/conf.d/test.conf
server { listen 80; server_name datawhale.ml; location / { proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:81/; }}server { listen 80; server_name deeplearning.ml; location / { proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:82/; }}
https反向代理的配置
# test.conf 为反向代理的配置vim /etc/nginx/conf.d/test.conf
server { listen 443 ssl; server_name deeplearning.ml; ssl on; ssl_certificate "/etc/httpd/ssl/2_deeplearning.ml.crt"; ssl_certificate_key "/etc/httpd/ssl/3_deeplearning.ml.key"; location / { proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass https://deeplearning.ml:442/; }}server { listen 443 ssl; server_name datawhale.ml; ssl on; ssl_certificate "/etc/nginx/ssl/datawhale.ml.pem"; ssl_certificate_key "/etc/nginx/ssl/datawhale.ml.key"; location / { proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass https://datawhale.ml:441/; }}
大坑!!!
注意,此时如果访问deeplearning.ml将会重定向到https://deeplearning.ml:442 ,但是这违背了我们设计的初衷。因为我们需要它能重定向到https://deeplearning.ml:443端口,即https://deeplearning.ml。因此可以通过修改.htaccess文件,改变重定向的规则。
第一次修改
RewriteEngine onRewriteBase /RewriteCond %{SERVER_PORT} !^443$RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
这种修改会造成重定向过多,死循环的问题。
80访问的时候,重定向到443,443通过nginx反向代理到442,442又会重定向搭配443造成死循环。
第二次修改
RewriteEngine onRewriteBase /RewriteCond %{SERVER_PORT} 80$RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
现在访问deeplearning.ml会重定向到https://deeplearning.ml,通过443端口的监听和反向代理,转发请求到 https://deeplearning.ml:442/端口,实现访问。
另一种重定向的修改方式
不适用.htaccess
文件,直接修改/etc/httpd/conf/httpd.conf
<Directory "/var/www/html"> Options Indexes FollowSymLinks # 允许Apache 显示目录列表呢 # 不允许/var/www/html/.htaccess文件配置的导入 AllowOverride None # 允许/var/www/html/.htaccess文件配置的导入 #Options FollowSymLinks MultiViews Includes #AllowOverride All # 新增 RewriteEngine on RewriteCond %{SERVER_PORT} 80$ RewriteRule ^(.*)?$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R] Require all granted</Directory>
总结:
在配置个人网站的过程中,我真实的踩到了各种各样的坑,但是通过不断踩坑填坑的过程,我对于http原理,web服务反向代理的机制更加的了解,进一步促进了个人的提升。同时,填坑成功的喜悦真的是无与伦比的,以上的配置是我通过自己个人学习的理解,以及结合Apache,Nginx网站的基础配置,对于新问题的创新型配置。(PS:毕竟企业都有好多台服务器,不会存在我这类的需求!!)
参考:
https://cloud.tencent.com/document/product/400/35243
https://zhuanlan.zhihu.com/p/25707362
https://zhuanlan.zhihu.com/p/425024640
沈豪
上海财经大学,Datawhale成员
github:https://github.com/shenhao-stu