21. 多虚拟主机
多虚拟主机应用场景:
httpd支持在一台物理主机实现多个网站, 即多虚拟主机
对于访问量不是很大的网站, 可以在同一个主机配置不同的网站
网站的唯一标识:
ip相同, 但端口不同
ip不同, 但端口相同
FQDN不同, ip端口和端口都相同
多虚拟主机有三种实现方案:
1. 基于ip: 为每个虚拟主机准备至少一个ip地址, 在一台服务器上, 准备多个ip地址, 搭建多个独立的网站
2. 基于port: 为每个虚拟主机使用至少一个独立的port, 但是ip地址相同
3. 基于FQDN: 为每个虚拟主机使用至少一个FQDN, 利用请求报文首部的Host字段:www.apache.com
准备环境:
CentOS8, yum安装httpd, ip:10.0.0.84
1. 基于IP的虚拟主机
每个网站域名绑定一个公网IP, 都使用默认的80端口
主机网卡配置多个IP地址, 客户可以直接通过域名访问
缺点: 一个网站就需要一个公网IP
案例:
- 安装httpd服务, 设置默认页面
yum -y install httpd; systemctl enable --now httpd; echo default /var/www/html/index.html > /var/www/html/index.html
- 修改客户端hosts文件, 实现dns解析
10.0.0.85作为客户端, 修改其hosts文件
vim /etc/hosts
10.0.0.84 www.httpd.org
- 测试访问
[12:32:06 root@client ~]#curl www.httpd.org
default /var/www/html/index.html
- 实现基于ip地址的多虚拟主机
格式: 虚拟主机的配置文件, 建议放在独立的配置文件中
<VirtualHost IP:PORT> # 虚拟主机语句块
ServerName FQDN # 主机头, 只在利用FQDN搭建虚拟主机时才起作用
DocumentRoot "/path" #网站文件目录
</VirtualHost> # 虚拟主机语句块
案例: 实现基于ip地址的多虚拟主机, 搭建额外三个网站
添加网卡ip
10.0.0.81 第一个虚拟主机
10.0.0.82 第二个虚拟主机
10.0.0.83 第三个虚拟主机
10.0.0.84 默认站点
[12:32:54 root@apache ~]#ip a a 10.0.0.81/24 dev eth0 label eth0:1
[12:37:09 root@apache ~]#ip a a 10.0.0.82/24 dev eth0 label eth0:2
[12:37:13 root@apache ~]#ip a a 10.0.0.83/24 dev eth0 label eth0:3
[12:37:17 root@apache ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:1f:4a:0c brd ff:ff:ff:ff:ff:ff
inet 10.0.0.84/24 brd 10.0.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 10.0.0.81/24 scope global secondary eth0:1
valid_lft forever preferred_lft forever
inet 10.0.0.82/24 scope global secondary eth0:2
valid_lft forever preferred_lft forever
inet 10.0.0.83/24 scope global secondary eth0:3
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe1f:4a0c/64 scope link
valid_lft forever preferred_lft forever
没有做配置前, 通过这三个ip访问得到的都是上一步定义的默认页面
[12:38:10 root@apache ~]#curl 10.0.0.81
default /var/www/html/index.html
[12:38:14 root@apache ~]#curl 10.0.0.82
default /var/www/html/index.html
[12:38:15 root@apache ~]#curl 10.0.0.83
default /var/www/html/index.html
[12:38:16 root@apache ~]#curl 10.0.0.84
default /var/www/html/index.html
[12:38:18 root@apache ~]#curl www.httpd.org
default /var/www/html/index.html
给三个网站创建DocumentRoot, 制作默认页面
[12:38:22 root@apache ~]#mkdir /data/html/web_81 -pv
mkdir: created directory '/data/html'
mkdir: created directory '/data/html/web_81'
[12:39:09 root@apache ~]#mkdir /data/html/web_82 -pv
mkdir: created directory '/data/html/web_82'
[12:39:11 root@apache ~]#mkdir /data/html/web_83 -pv
mkdir: created directory '/data/html/web_83'
[12:39:13 root@apache ~]#echo /data/html/web_81/index.html > /data/html/web_81/index.html
[12:39:44 root@apache ~]#echo /data/html/web_82/index.html > /data/html/web_82/index.html
[12:39:49 root@apache ~]#echo /data/html/web_83/index.html > /data/html/web_83/index.html
编辑虚拟主机配置文件
[12:39:53 root@apache ~]#vim /etc/httpd/conf.d/test.conf
<VirtualHost 10.0.0.81:80>
ServerName www.web_81.org #基于ip地址的虚拟主机, 无需servername
DocumentRoot "/data/html/web_81"
<directory /data/html/web_81>
Require all granted
</directory>
</VirtualHost>`
[12:44:15 root@apache ~]#systemctl restart httpd
客户端配置本地域名解析, 为了测试
10.0.0.81 www.web_81.org www.web_82.org www.web_83.org
测试访问:
可以看到, 无论访问哪个域名, 最终访问的都是10.0.0.81对应的页面, 因此, 证明了基于ip地址的虚拟主机, servername指令是不起作用的. 真正起作用的是域名解析到的ip地址
虽然81的servername是web_81, 但是访问web_82和web_83.org都能访问到10.0.0.81虚拟主机
[12:44:28 root@client ~]#curl www.web_81.org
/data/html/web_81/index.html
[12:44:30 root@client ~]#curl www.web_82.org
/data/html/web_81/index.html
[12:44:33 root@client ~]#curl www.web_83.org
/data/html/web_81/index.html
剩余两个虚拟主机配置
[12:45:52 root@apache ~]#vim /etc/httpd/conf.d/test.conf
<VirtualHost 10.0.0.81:80>
ServerName www.web_81.org
DocumentRoot "/data/html/web_81"
<directory /data/html/web_81>
Require all granted
</directory>
</VirtualHost>
<VirtualHost 10.0.0.82:80>
#ServerName FQDN
DocumentRoot "/data/html/web_82"
<directory /data/html/web_82>
Require all granted
</directory>
</VirtualHost>
<VirtualHost 10.0.0.83:80>
#ServerName FQDN
DocumentRoot "/data/html/web_83"
<directory /data/html/web_83>
Require all granted
</directory>
</VirtualHost>
[12:45:49 root@apache ~]#systemctl restart httpd
修改客户端/etc/hosts文件, 实现域名和ip对应
10.0.0.84 www.httpd.org
10.0.0.81 www.web_81.org
10.0.0.82 www.web_82.org
10.0.0.83 www.web_83.org
测试访问:
[12:47:16 root@client ~]#curl www.httpd.org
default /var/www/html/index.html
[12:47:38 root@client ~]#curl 10.0.0.81
/data/html/web_81/index.html
[12:47:43 root@client ~]#curl 10.0.0.82
/data/html/web_82/index.html
[12:47:44 root@client ~]#curl 10.0.0.83
/data/html/web_83/index.html
[12:47:45 root@client ~]#curl 10.0.0.84
default /var/www/html/index.html
[12:47:47 root@client ~]#curl www.web_81.org
/data/html/web_81/index.html
[12:47:55 root@client ~]#curl www.web_82.org
/data/html/web_82/index.html
[12:47:57 root@client ~]#curl www.web_83.org
/data/html/web_83/index.html
2. 基于端口号的虚拟主机
所有网站共用一个IP, 但是端口号不同, 用户访问时, 根据指定的端口号来访问对应的网站页面
缺点: 客户访问时, 需要在域名后面+端口号
案例:
准备环境, 把上一步添加的网卡ip清除
#重新加载在网卡即可
nmcli conn up eth0
配置基于端口号的虚拟主机, *:81, *:82, *;83, 服务器上所有ip的81,82,83端口, 实现三个虚拟主机
10.0.0.84:80 还是作为默认的站点
配置文件:
[12:46:22 root@apache ~]#vim /etc/httpd/conf.d/test.conf
listen 81 # 需要打开监听端口
listen 82
listen 83
<VirtualHost *:81>
ServerName www.web_81.org
DocumentRoot "/data/html/web_81"
<directory /data/html/web_81>
Require all granted
</directory>
</VirtualHost>
<VirtualHost *:82>
ServerName www.web_82.org
DocumentRoot "/data/html/web_82"
<directory /data/html/web_82>
Require all granted
</directory>
</VirtualHost>
<VirtualHost *:83>
ServerName www.web_83.org
DocumentRoot "/data/html/web_83"
<directory /data/html/web_83>
Require all granted
</directory>
</VirtualHost>
重启服务, 修改客户端hosts文件, 测试访问
[12:58:49 root@apache ~]#systemctl restart httpd
[12:55:46 root@apache ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:81 *:*
LISTEN 0 128 *:82 *:*
LISTEN 0 128 *:83 *:*
LISTEN 0 128 [::]:22 [::]:*
10.0.0.84 www.httpd.org
10.0.0.84 www.web_81.org www.web_82.org www.web_83.org
[12:59:41 root@client ~]#curl www.httpd.org
default /var/www/html/index.html
[13:00:46 root@client ~]#curl 10.0.0.84
default /var/www/html/index.html
[13:00:50 root@client ~]#curl www.web_81.org:81
/data/html/web_81/index.html
[13:01:02 root@client ~]#curl www.web_82.org:82
/data/html/web_82/index.html
[13:01:09 root@client ~]#curl www.web_83.org:83
/data/html/web_83/index.html
[13:01:11 root@client ~]#curl www.web_83.org:82
/data/html/web_82/index.html
[13:02:59 root@client ~]#curl www.web_83.org:80
default /var/www/html/index.html
[13:03:05 root@client ~]#curl www.web_83.org:81
/data/html/web_81/index.html
[13:03:11 root@client ~]#curl www.web_83.org
default /var/www/html/index.html
根据以上结果可以得出, 基于端口号的多虚拟主机, 和servername无关, 起作用的是端口号
无论客户端输入那个域名, 最终都会解析成10.0.0.84的ip地址, 最终能访问到哪个虚拟主机, 就看域名后面加的端口号. 不加端口, 就是访问默认的80主站点, 81就是web_81... 和servername无关
3. 基于FQDN
http请求报文头部会封装用户访问的网站名: host(http报文字段):网站名, 因此基于FQDN的虚拟主机可以根据网站名去分辨用户访问的是哪个网站, 而不是基于IP地址或端口. 这样达到在一个物理机, 一个IP上搭建多个网站.
[13:07:16 root@client ~]#telnet 10.0.0.84 80
Trying 10.0.0.84...
Connected to 10.0.0.84.
Escape character is '^]'.
GET /index.html HTTP/1.1
host: www.web_82.org # 指定头部信息, 也就是要访问的网站域名
HTTP/1.1 200 OK
Date: Wed, 10 Mar 2021 05:08:51 GMT
Server: Apache/2.4.37 (centos)
Last-Modified: Wed, 10 Mar 2021 04:30:04 GMT
ETag: "21-5bd271ef0bd56"
Accept-Ranges: bytes
Content-Length: 33
Content-Type: text/html; charset=UTF-8
default /var/www/html/index.html
Connection closed by foreign host.
curl -v 查看详细报文.
[13:10:10 root@client ~]#curl -v www.web_82.org
* Rebuilt URL to: www.web_82.org/
* Trying 10.0.0.84...
* TCP_NODELAY set
* Connected to www.web_82.org (10.0.0.84) port 80 (#0)
> GET / HTTP/1.1
> Host: www.web_82.org
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 10 Mar 2021 05:10:41 GMT
< Server: Apache/2.4.37 (centos)
< Last-Modified: Wed, 10 Mar 2021 04:30:04 GMT
< ETag: "21-5bd271ef0bd56"
< Accept-Ranges: bytes
< Content-Length: 33
< Content-Type: text/html; charset=UTF-8
<
default /var/www/html/index.html
* Connection #0 to host www.web_82.org left intact
报文封装结构:
datalink-IP(10.0.0.84)-TCP-http(host:servername)-data
基于FQDN的虚拟主机注意事项:
设置了基于FQDN虚拟主机后, 如果还是用ip地址访问, 那么会显示排在虚拟主机第一位的网站, 而非默认页面.
用了FQDN虚拟主机后, 默认页面就失效了, 即使在服务器上访问自己的127地址, 也是显示配置文件中, 排在第一位的虚拟主机的页面. 而基于IP和端口号的, 默认页面还有效.
配置注意事项:
- 任意目录下的页面只有显示授权才能被访问
- 基于FQDN的虚拟主机, 需要做日志分离
- 三种方式的虚拟主机可以混合使用
- FQDN,公网访问只需要有多个域名即可, 在局域网内, 可以用基于IP或者端口的.
实现过程:
修改配置文件
<VirtualHost *:80>
ServerName www.web_81.org
DocumentRoot "/data/html/web_81"
<directory /data/html/web_81>
Require all granted
</directory>
</VirtualHost>
<VirtualHost *:80>
ServerName www.web_82.org
DocumentRoot "/data/html/web_82"
<directory /data/html/web_82>
Require all granted
</directory>
</VirtualHost>
<VirtualHost *:80>
ServerName www.web_83.org
DocumentRoot "/data/html/web_83"
<directory /data/html/web_83>
Require all granted
</directory>
</VirtualHost>
systemctl restart httpd
客户端dns配置
10.0.0.84 www.httpd.org www.web_81.org www.web_82.org www.web_83.org
访问测试:
[13:17:26 root@client ~]#curl www.web_81.org
/data/html/web_81/index.html
[13:17:49 root@client ~]#curl www.web_82.org
/data/html/web_82/index.html
[13:17:52 root@client ~]#curl www.web_83.org
/data/html/web_83/index.html
[13:17:54 root@client ~]#curl www.httpd.org # 基于FQDN的虚拟主机, 默认页面会失效, 访问主站点域名, 实际会访问到在配置文件中定义的第一个虚拟主机网站
/data/html/web_81/index.html
[13:18:00 root@client ~]#curl 10.0.0.84
/data/html/web_81/index.html
[13:16:12 root@apache ~]#curl localhost
/data/html/web_81/index.html
# 无论是访问ip地址, 还是在服务器本地访问localhost, 都是访问的排在第一个的虚拟主机
实现日志分离, 每个网站都有单独的日志
只需在每个VirtualHost添加日志保存路径和定义格式即可, 这里使用默认格式, 实现,每个网站的日志, 放在自己的家目录下
日志存放路径需要指定绝对路径, 否则就是相对ServerRoot安装目录下的logs. 而安装目录下的logs实际是/var/log/httpd的软连接
先创建存放日志目录
[13:32:20 root@apache ~]#mkdir /data/html/web_81/logs
[13:32:30 root@apache ~]#mkdir /data/html/web_82/logs
[13:32:32 root@apache ~]#mkdir /data/html/web_83/logs
修改配置文件, 指定日志存放路径, 使用默认的combined格式
[13:19:32 root@apache ~]#vim /etc/httpd/conf.d/test.conf
<VirtualHost *:80>
ServerName www.web_81.org
DocumentRoot "/data/html/web_81"
ErrorLog "/data/html/web_81/logs/web_81_error_log"
CustomLog "/data/html/web_81/logs/web_81_access_log" combined
<directory /data/html/web_81>
Require all granted
</directory>
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "/data/html/web_82"
ServerName www.web_82.org
ErrorLog "/data/html/web_82/logs/web_82_error_log"
CustomLog "/data/html/web_82/logs/web_82_access_log" combined
<directory /data/html/web_82>
Require all granted
</directory>
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "/data/html/web_83"
ErrorLog "/data/html/web_83/logs/web_83_error_log"
CustomLog "/data/html/web_83/logs/web_83_access_log" combined
ServerName www.web_83.org
<directory /data/html/web_83>
Require all granted
</directory>
</VirtualHost>
[13:32:34 root@apache ~]#systemctl restart httpd
查看效果
[13:32:43 root@apache ~]#tree /data/html/
/data/html/
├── web_81
│ ├── index.html
│ └── logs
│ ├── web_81_access_log
│ └── web_81_error_log
├── web_82
│ ├── index.html
│ └── logs
│ ├── web_82_access_log
│ └── web_82_error_log
└── web_83
├── index.html
└── logs
├── web_83_access_log
└── web_83_error_log
6 directories, 9 files
22. 压缩
apache默认没有开启压缩功能
服务端开启后, 传数据前会把数据进行压缩, 客户端和服务器会协商压缩算法, 客户端浏览器收到数据会自动解压缩.
注意: 在访问日志中, 显示的数据大小, 是不包括各层头部封装信息的, 只显示数据本身的大小
使用mod_deflate模块压缩页面优化传输速度
[13:38:25 root@apache ~]#ll /etc/httpd/modules/mod_deflate.so
-rwxr-xr-x 1 root root 36720 Nov 4 11:21 /etc/httpd/modules/mod_deflate.so
#将模块加载到配置文件
LoadModule deflate_module modules/mod_deflate.so
#如果是yum安装的httpd, 那么该模块是已经被加载的
00-base.conf:LoadModule deflate_module modules/mod_deflate.so
适用场景:
- 节约广域网带宽, 但额外消耗服务器端CPU; 同时, 可能有些较老浏览器不支持
- 压缩适合压缩的资源, 例如文本文件, 有些资源, 压缩效果不高, 而且压缩后很可能大小反而增加
定义压缩级别:
Deflate
案例:
开启压缩指令, 针对www.web_81.org进行压缩
<VirtualHost *:80>
ServerName www.web_81.org
DocumentRoot "/data/html/web_81"
ErrorLog "/data/html/web_81/logs/web_81_error_log"
CustomLog "/data/html/web_81/logs/web_81_access_log" combined
AddOutputFilterByType DEFLATE text/plain # 针对哪种MIME类型进行压缩, 是必须指定项
<directory /data/html/web_81>
Require all granted
</directory>
</VirtualHost>
重启服务
systemctl restart httpd
准备一个大文件, 放到web_81站点目录下
[14:58:41 root@apache ~]#ll /data/html/web_81/logs/messages.txt -h
-rw------- 1 root root 56M Mar 10 14:58 /data/html/web_81/logs/messages.txt
[14:58:48 root@apache ~]#chmod +r /data/html/web_81/logs/messages.txt #由于文件默认是只有root能读, 因此还要修改权限
先用curl命令测试结果, 默认curl命令访问是不会被压缩的. 因为curl是个命令端浏览器, 无法像图形化浏览器一样辨别出服务器端是否压缩
[15:00:00 root@client ~]#curl www.web_81.org/logs/messages.txt
10.0.0.85 - - [10/Mar/2021:14:59:59 +0800] "GET /logs/messages.txt HTTP/1.1" 200 58180114 "-" "curl/7.61.1"
如果想让curl支持压缩, 需要加--compressed 选项
[14:50:24 root@client ~]#curl www.web_81.org/testfile.txt --compressed
10.0.0.85 - - [10/Mar/2021:15:03:38 +0800] "GET /logs/messages.txt HTTP/1.1" 200 7921479 "-" "curl/7.61.1"
再用浏览器测试
10.0.0.1 - - [10/Mar/2021:15:02:59 +0800] "GET /logs/messages.txt HTTP/1.1" 200 7921479 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"
#可以看到,大小变成了7921479
23. 实现https
注意: SSL是基于IP的地址实现, 单IP的httpd主机, 只能有一个https网站,或者基于一个虚拟主机的https网站. 如果多虚拟主机,访问不同的域名是无法通过https访问的, 即使通过curl -k跳过证书验证, 也是只能访问默认页面. Nginx可以解决该问题.
https通信过程:
1. 客户端发送可供选择的加密方式, 并向服务器请求证书
2. 服务器端发送证书, 以及选定的加密方式发给客户端
3. 客户端取得证书并进行证书验证, 如果信任给其发证书的CA
a. 验证证书来源合法性: 用CA的公钥解密证书上数字签名
b. 验证证书的内容的合法性: 完整性验证
c. 检查证书的有效期限
d. 检查证书是否被吊销
e. 证书中拥有者的名字, 与访问的目标主机要一致
4. 客户端生成临时会话密钥(对沉秘钥), 并使用服务器端的公钥加密此数据发给服务器, 完成密钥交换
5. 服务器用此密钥加密用户请求的资源, 响应给客户端
实现apache基于https, 需要安装mod_ssl模块, 安装后, 重启服务, 会自动生成自签名证书和服务器私钥文件, 基于这个自签名证书和私钥, 就可以实现https访问. 但是由于是自签名证书, 因此客户端不会信任.
[16:05:07 root@apache ~]#yum -y install mod_ssl
[16:05:22 root@apache ~]#systemctl restart httpd
[16:06:03 root@apache ~]#ll /etc/pki/tls/private/
total 8
-rw------- 1 root root 1704 Mar 10 16:05 localhost.key
-rw-------. 1 root root 3243 Oct 29 18:20 postfix.key
[16:06:12 root@apache ~]#ss -ntl # httpd会自动开启
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 128 *:443 *:*
[16:06:33 root@apache ~]#openssl x509 -in /etc/pki/tls/certs/localhost.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1213888900138231549 (0x10d89985f18766fd)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, O = Unspecified, OU = ca-8641870554608572955, CN = CentOS-8-4, emailAddress = root@CentOS-8-4 # 证书发布者
Validity
Not Before: Mar 10 08:05:49 2021 GMT
Not After : Mar 15 09:45:49 2022 GMT
Subject: C = US, O = Unspecified, CN = CentOS-8-4, emailAddress = root@CentOS-8-4 # 给哪个域名用的证书, 默认有效期1年
如果是对外公网网站, 需要申请证书, 之后导入ssl.conf配置文件即可
这里用的是我在阿里云申请的免费证书
[16:20:41 root@apache ~]#ll
total 12
-rw-r--r-- 1 root root 1679 Sep 26 21:03 4555747_www.wangxiaoning.com_chain.crt # 上级CA信息
-rw-r--r-- 1 root root 1675 Sep 26 21:03 4555747_www.wangxiaoning.com.key # 私钥
-rw-r--r-- 1 root root 2013 Sep 26 21:03 4555747_www.wangxiaoning.com_public.crt # 证书
[16:20:42 root@apache ~]#mkdir /data/ssl
[16:21:16 root@apache ~]#mv 4* /data/ssl # 将证书放到/data/ssl目录下
[16:21:21 root@apache ~]#ll /data/ssl
total 20
-rw-r--r-- 1 root root 4462 Mar 10 16:19 4555747_www.wangxiaoning.com_apache.zip
-rw-r--r-- 1 root root 1679 Mar 10 16:19 4555747_www.wangxiaoning.com_chain.crt
-rw-r--r-- 1 root root 1675 Mar 10 16:19 4555747_www.wangxiaoning.com.key
-rw-r--r-- 1 root root 2013 Mar 10 16:19 4555747_www.wangxiaoning.com_public.crt
取消之前搭建的虚拟主机, 因为apache的https只能针对一个ip, 不支持虚拟主机
删除虚拟主机配置文件
重启服务测试即可
[16:21:58 root@apache ~]#rm -rf /etc/httpd/conf.d/test.conf
[16:25:31 root@apache ~]#systemctl restart httpd
apache自带默认的https证书是自签名, 因此访问会提示安全风险
- 搭建一个本地站点, www.wangxiaoning.com ; 本地dns解析 10.0.0.84 www.wangxiaoning.com
注意: 证书文件和网站域名一定要匹配
[16:21:24 root@apache ~]#echo 'www.wangxiaoning.com' > /var/www/html/index.html
#Windows /etc/hosts文件
10.0.0.84 www.wangxiaoning.com
- 修改ssl配置文件/etc/httpd/conf.d/ssl.conf, 该配置文件会在安装mod_ssl模块, 重启httpd服务后自动生成.
默认证书路径: 默认指向了安装mod_ssl模块后生成的自签名证书和私钥
修改证书路径:
SSLCertificateFile /data/ssl/4555747_www.wangxiaoning.com_public.crt
SSLCertificateKeyFile /data/ssl/4555747_www.wangxiaoning.com.key
SSLCertificateChainFile /data/ssl/4555747_www.wangxiaoning.com_chain.crt #chain.crt指的是上级CA信息
-
重启服务验证
如果是企业内部网站, 可以自己搭建CA, 自己颁发证书, 节省成本
自建CA一键脚本
#!/bin/bash
CA_SUBJECT="/O=blog/CN=ca.blog.com" #CA组织
SUBJECT="/C=CN/ST=liaoning/L=anshan/O=blog.org/CN=*.anshanblog.org" #给哪个域名颁发
SERIAL=1
EXPIRE=203009
FILE=blog
openssl req -x509 -newkey rsa:2048 -subj ${CA_SUBJECT} -keyout ca.key -nodes -days $EXPIRE -out ca.crt
openssl req -newkey rsa:2048 -nodes -keyout ${FILE}.key -subj ${SUBJECT} -out ${FILE}.csr
openssl x509 -req -in ${FILE}.csr -CA ca.crt -CAkey ca.key -set_serial $SERIAL -days ${EXPIRE} -out ${FILE}.crt
chmod 600 ${FILE}.key ca.key
Generating a RSA private key
..............................+++++
.....................................................................+++++
writing new private key to 'ca.key'
-----
Generating a RSA private key
..+++++
...........+++++
writing new private key to 'blog.key'
-----
Signature ok
subject=C = CN, ST = liaoning, L = anshan, O = blog.org, CN = *.anshanblog.org
Getting CA Private Key
[16:40:04 root@apache ~]#ll
total 24
-rw-r--r-- 1 root root 1094 Mar 10 16:39 blog.crt
-rw-r--r-- 1 root root 993 Mar 10 16:39 blog.csr
-rw------- 1 root root 1704 Mar 10 16:39 blog.key
-rw-r--r-- 1 root root 1164 Mar 10 16:39 ca.crt
-rw------- 1 root root 1704 Mar 10 16:39 ca.key
-rw-r--r-- 1 root root 909 Mar 10 16:39 ca.sh
修改ssl.conf配置文件, 指明证书和私钥存放路径
[10:02:35 root@c8prac ~]#vim /etc/httpd/conf.d/ssl.conf
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /root/blog.crt
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /root/blog.key
#SSLCertificateChainFile /data/ssl/4555747_www.wangxiaoning.com_chain.crt # ChainFile注释掉即可
#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt #如果是自建CA, 那么因为证书直接由根CA颁发, 所以没有上级CA, 那么CA证书文件可以直接写在这里, 如果是互联网申请的CA, 在apache中需要把chain上级CA证书写到ChainFile指令中
SSLCACertificateFile /root/ca.crt
分别修改Windows和Linux客户端的hosts文件, 绑定10.0.0.84本机ip到www.anshanblog.org域名和db.anshanblog.org域名, 因为申请的证书是基于域名的, 因此同域名下的网站都可以使用该证书
10.0.0.84 www.anshanblog.org db.anshanblog.org
systemctl restart httpd
测试访问结果:
#curl命令需要加-k选项才能忽略ssl的证书验证
[16:53:09 root@client ~]#curl -k https://www.anshanblog.org
www.wangxiaoning.com
[17:07:35 root@client ~]#curl -k https://db.anshanblog.org
www.wangxiaoning.com
Windows浏览器访问: 因为是自建CA, 所以客户端不会信任, 需要手动添加CA到信任站点
如何信任ca?
将ca的证书导入客户端, 安装证书到受信任的机构即可
导入后, 有可能会是显示无效, 因此并不是认可授权的的CA
24. URL重定向
URL重定向: 即将http请求的URL转发至另一个URL
https跳转参数: strict-transport-security: max-age=0 #永远跳转, 以秒为单位
用户通过浏览器访问http页面时, 如果服务器支持https, 那么服务器会回复客户端, 本地支持https, 请用https访问. 0是默认值, 永久跳转, 跟的这个数值定义了浏览器在多长时间内(以秒为单位), 再次访问网站, 如果还是用http访问, 那么浏览器会自动补https. 这样下次用户在访问该网站时, 就不用等服务器回复客户端用https访问这一步操作了
[17:07:46 root@client ~]#curl -I http://www.taobao.com
HTTP/1.1 301 Moved Permanently 301永久重定向
Server: Tengine
Date: Wed, 10 Mar 2021 13:37:51 GMT
Content-Type: text/html
Content-Length: 278
Connection: keep-alive
Location: https://www.taobao.com/ #通过客户端浏览器, http已经被重定向到了https, 下次用https访问
Via: cache2.cn1452[,0]
Timing-Allow-Origin: *
EagleId: 7488871616153834710753802e
301-永久重定向, 客户端访问某个URL, 会被重定向到另一个URL, 这个重定向是永久的, 也就是当前访问的URL之后可能不会用了
302-临时重定向, 客户端访问某个URL, 会被重定向到另一个URL, 但是这个重定向是临时的, 也许一段时间后会修改回来
根据不同规划去设置.
301,302 vs strict-transport-security: max-age=0
301,302: 客户端访问一个URL时, 服务器会回复客户端, 请访问另一个URL, 并指明是301还是302. 之后客户端再访问新的URL. 客户端要发两次请求. 整个通信过程是三次交互
strict-transport-security: max-age=0 定义了当服务器支持https时, 如果客户端用http发起请求, 那么服务器会回复客户端本地支持https, 之后客户端在发起https请求, 当下次在访问时, 直接在浏览器内部做307内部跳转, 只要不超过max-age, 从浏览器再次访问http, 会自动访问https, 不会有301/302的在客户端和服务器之间的三次交互过程.
curl 只会显示301或者302但是不会真的跳转, 需要加-L选项才可以真跳转
用URL重定向, redirect缺点: 会出现循环一直跳转到的情况, 造成跳转次数过多而无法访问页面. 这是因为只要访问的是网站的/, 那么无论是通过http还是https访问, 那么都会继续转到https, 造成无线循环, 因此, 需要配合if条件判断, 只将http的访问转发到https上.
实现重定向指令, Redirect [status] URL-path URL
status状态:
- permanent: 返回永久重定向状态码301, 此重定向信息会进行缓存到磁盘
- temp: 返回临时重定向状态码302, 此为默认值
配置案例: 实现永久重定向
实现访问当前站点的根目录, 就会被永久重定向到baidu
[21:56:29 root@apache /etc/httpd/conf.d]#vim test.conf
Redirect permanent / https://www.baidu.com
25. 实现HSTS
http strict transport security, 服务端配置支持HSTS后, 会在给浏览器返回的http首部中携带hsts字段. 浏览器获取到该信息后, 会将所有http访问请求在内部做307跳转到https. 而无需任何网络过程, 实现更高的安全性
用户第一次访问时, 服务器会告诉客户端进行跳转, 在有效期内再次访问时, 浏览器会在内部做307跳转到指定URL
案例:
Header always set Strict-Transport-Security "max-age=31536000" #回复客户端, 下次访问http时,请直接访问https
RewriteEngine on #重写访问地址, 直接在浏览器内部做307跳转
RewriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=302] #定义访问网站的根时,就跳转到https, 302临时重定向
26. sendfile机制
加速功能, 默认开启. 磁盘文件复制到内核关于磁盘的缓冲区, 再直接复制到内核网络缓冲区, 减少内核空间和用户空间的来回切换.
不适合启用sendfile的情况: 如果网站内容不是在服务器本地, 而且通过网络共享存储, 那么就不能用sendfile, 因为sendfile加速的是本地.
设置:
EnableSendfile on|off #默认开启