HTTP协议及其实现httpd

HTTP协议及其实现httpd

WEB浏览器,WEB服务器,WEB相关应用程序都是通过HTTP(HyperText Transfer Protocol)相互通信,HTTP是现代全球因特网中使用的公共语言。

http脑图

HTTP协议

HTTP协议版本

目前http协议主要有以下几个版本

  • HTTP/0.9
    HTTP的1991原型版称为HTTP/0.9,该版本有严重的设计缺陷,只支持GET请求方法。
  • HTTP/1.0
    第一个得到广泛使用的HTTP版本
  • HTTP/1.1
    目前使用的HTTP版本
  • HTTP/2.0
    下一代HTTP版本,由互联网工程任务组(IETF)的Hypertext Transfer Protocol Bis(httpbis)工作小组进行开发。该组织于2014年12月将HTTP/2标准提议递交至IESG进行讨论,于2015年2月17日被批准。HTTP/2标准于2015年5月以RFC 7540正式发表。目前主流的浏览器均支持该版本。

URL

URL(Uniform Resource Locator)统一资源定位符是因特网上标准的资源的地址,通过URL我们或我们手机上的APP才能在茫茫网络世界中找到所需的资源。

URL语法
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

Alt text

Alt text


WEB服务器请求处理步骤

  1. 建立连接
    接收客户端连接,如果不希望客户端连接,就将其关闭
  2. 接收请求
    不同的WEB服务器处理请求的连接方式不同,主要有以下几种服务模式

    • 单进程I/O模型
      只启动一个进程,一个进程处理一个请求。
    • 多进程I/O模型
      并行启动多个进程,一个进程处理一个请求
    • 复用I/O结构
      • 多线程模型
        一个进程生成多个线程,一个线程处理一个请求。
      • 事件驱动
        一个进程处理多个请求
    • 复用多进程I/O模型
      启动多个进程,每个进程生成多个线程,一个线程处理一个请求
  3. 处理请求
    分析客户端的请求报文,取请求资源,请求方法等信息

  4. 访问资源
  5. 构建响应
  6. 发送响应
  7. 记录事务处理过程

Alt text


HTTP报文

HTTP报文组成

  • 起始行
  • 首部
  • 主体

HTTP请求报文结构

<method> <request-URL> <version>
<headers>
<entity-body>

HTTP响应报文结构

<version> <status> <resaon-phrase>
<headers>
<entity-body>

httpd

安装httpd

通过rpm包安装

yum -y install httpd httpd-tools httpd-manual

编译安装

httpd2.2

httpd2.2相关文件路径

  • 配置文件路径
# 主配置文件
/etc/httpd/conf/httpd.conf
# 其它配置文件路径
/etc/httpd/conf.d/*.conf
  • 主程序文件路径
# Profork工作模式主程序文件
/usr/sbin/httpd
# event工作模式主程序文件
/usr/sbin/httpd.event
# worker工作模式主程序文件
/usr/sbin/httpd.worker
  • 主进程文件路径
# 符号链接路径
/etc/httpd/run/httpd.pid
# 实际路径
/var/run/httpd/httpd.pid
  • 服务脚本
/etc/init.d/httpd
  • 模块文件路径
# 符号链接路径
/etc/httpd/modules/mod_*.so
# 实际文件路径
/usr/lib64/httpd/modules/mod_*.so
  • 日志文件路径
# 符号链接路径
/etc/httpd/logs/*_log
# 实际路径
/var/log/httpd/*_log
  • 默认主站点文件路径
/var/www/html/
  • 帮助文档
    安装了http-manual就可以通过当前web服务器查看帮助文档,URL路径如下:
http://localhost/manual

httpd2.2设置开机启动(CentOS6)

  1. 关闭防火墙和SElinux
  2. 设置开机自动启动服务
chkconfig httpd on
service httpd start

httpd2.2配置

解决启动时的错误提示
当我们启动httpd服务时,总是有如下的错误提示,虽然该提示并不影响系统的正常启动,但总是不那么令人愉快。

[root@zhubiao ~]# service httpd start
Starting httpd: httpd: apr_sockaddr_info_get() failed for zhubiao
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
[ OK ]

修改主配置文件 /etc/httpd/conf/httpd.conf 中的ServerName

ServerName www.zhubiaook.com:80

显示的版本信息
默认配置好的httpd服务,响应头部信息中会列出Apache的详细版本信息,这未免过于招摇,容易被攻击

[root@zhubiao ~]# curl -I http://127.0.0.1
HTTP/1.1 200 OK
Date: Fri, 18 Aug 2017 14:03:00 GMT
Server: Apache/2.2.15 (CentOS) <=Apache版本信息
Last-Modified: Fri, 18 Aug 2017 14:01:39 GMT
ETag: "a0b15-15-557079164308e"
Accept-Ranges: bytes
Content-Length: 21
Connection: close
Content-Type: text/html; charset=UTF-8

修改主配置文件 /etc/httpd/conf/httpd.conf 中的ServerToken

# 语法
ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full
#举例
ServerTokens Prod[uctOnly]
Server sends (e.g.): Server: Apache
ServerTokens Major
Server sends (e.g.): Server: Apache/2
ServerTokens Minor
Server sends (e.g.): Server: Apache/2.0
ServerTokens Min[imal]
Server sends (e.g.): Server: Apache/2.0.41
ServerTokens OS
Server sends (e.g.): Server: Apache/2.0.41 (Unix)
ServerTokens Full (or not specified)
Server sends (e.g.): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2
# 修改为显示信息最少的 Prod
ServerTokens Prod

监听IP和端口
默认httpd服务监听所有IP地址的80端口,我们自行修改所监听的IP和端口
修改主配置文件 /etc/httpd/conf/httpd.conf 中的Listen

语法:
Listen [IP-address:]portnumber [protocol]
e.g
#监听所有IP地址的指定端口
Listen 80
Listen 8008
#监听指定IP的端口
Listen 172.18.17.101:8008
#监听https协议
Listen 172.18.17.101:8000 https

持久链接
默认httpd服务未开启持久连接,若遇到游戏类的服务,那将是无法忍受的修改主配置文件 /etc/httpd/conf/httpd.conf 中的KeepAlive开启持久连接

语法
# 开启|关闭持久连接
KeepAlive On|Off
# 最大允许的持久连接数量
MaxKeepAliveRequests number
# 持久连接的秒数
KeepAliveTimeout seconds
e.g
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 60

MPM(Multi-Processing Module)
httpd有三种处理连接I/O模型

  • prefork:多进程I/O模型
  • worker:复用的多进程I/O模型,多进程多线程
  • event:事件驱动模型(worker模型的变种),httpd2.2还处于测试中

这三种中模式只能有一种处于工作状态,httpd2.2中通过修改/etc/sysconfig/httpd 配置文件来切换,由于event模式还处于测试中,不建议切换为event模式

# prefork模式
HTTPD=/usr/sbin/httpd
# work模式
HTTPD=/usr/sbin/httpd.worker

这些模式相应的配置如下
修改主配置文件 /etc/httpd/conf/httpd.conf

# prefork配置
<IfModule prefork.c>
StartServers 8 <=服务启动时开启的进程数
MinSpareServers 5 <=最少空闲进程数
MaxSpareServers 20 <=最大空闲进程数
ServerLimit 256 <=启动的最多进程数
MaxClients 256 <=最多客户连接数
MaxRequestsPerChild 4000 <=每个进程生命周期中处理的最大请求数,超过此值后将被杀死
</IfModule>
# worker配置
<IfModule worker.c>
StartServers 4
MaxClients 300
MinSpareThreads 25 <=最少空闲线程数
MaxSpareThreads 75 <=最多空闲线程数
ThreadsPerChild 25 <=每个进程开启的线程数
MaxRequestsPerChild 0 <=每个进程处理的最大请求数,0为不限制
</IfModule>

动态模块加载 DSO(Dynamic Shared Object)
httpd是高度模块化的软件,由core加modules共同构成。刚开始我们可以只启动内核,需要增加相应功能再动态加载模块,添加动态模块方法如下
在主配置文件/etc/httpd/conf/httpd.conf
或子配置文件/etc/httpd/conf.d/*.conf 添加动态模块配置

#语法
LoadModule module-name module-path
e.g
LoadModule auth_basic_module modules/mod_auth_basic.so

修改默认主站点
httpd默认主站点路径为/var/www/html,我们可以将其修改为其它路径
在主配置文件/etc/httpd/conf/httpd.conf中修改

#语法
DocumentRoot path
e.g
DocumentRoot /app/web

站点访问控制
httpd服务可以设置对服务器上的特定资源的访问权限,设置对客户端的访问控制。

  1. 服务器资源的访问控制
    设定资源区域,然后对该区域做访问控制。
    设定资源区域的形式有以下几种
# 文件系统路径方式
# 目录
<Directory "directory-path">
...
</Directory>
# 文件名
<Files filename>
...
</Files>
# 正则匹配文件
<FilesMath regex>
...
</FilesMath>
# URL路径方式
<Location URL>
</Location>
<LocationMatch>

对区域做访问控制的方式

# Options
Options [+|-]option [[+|-]option] ...
All 全部允许
None 全部禁止
Indexes 索引
FollowSymLinks 符号链接
# AllowOvrride options
AllowOverride All|None|directive-type [directive-type] ...
directive-type
AuthConfig 身份验证
Indexes 索引
Limit #Allow Deny Order
  1. 客户端的访问控制
    • 通过IP地址控制
Order {Deny,Allow|Allow,Deny}
{Allow|Deny} from {All|host}
# host 包括IP地址和NETWORK两种方式
NETWORK
172.16
172.16.0.0
172.16.0.0/16
172.16.0.0/255.255.0.0
  • 通过用户身份控制
基于用户身份
创建账户和密码
htpasswd [options] PATH UserName
-c 创建存储密码的文件,第一次创建使用
-m md5加密
-s sha加密
-D 删除用户
实现方法
<Directory directory-path>
AuthType [Basic|digest]
AuthName String
AuthUserFile PATH
Require [user user1,user2]|[valid-user]
<Directory>
基于组账户
创建组文件
GropFile
group1:user1 user2
group2:user3 user4
<Directory directory-path>
AuthType [Basic|digest]
AuthName String
AuthUserFile PATH
AuthGroupFile PATH
Require group group1,group2,...
<Directory>
基于IP和用户的控制
<Directory directory-path>
基于IP的控制配置
基于用户的控制配置
Satisfy All|Any
</Directory>
# All 两者都需要验证
# Any 验证任意一种

日志的设定
日志主要有访问日志和错误日志

  1. 访问日志
    主配置文件中设定访问日志路径和使用的格式
CustomLog logs/access_log Nickname
  1. 错误日志
    主配置文件中设定错误日志路径和使用的格式
ErrorLog logs/error_log
  1. 日志格式
    主配置文件中设定日志格式
LogFormat format name
%h Remote host
%l Remote logname
%u Remoe user
%t Time the request was received
%r First line of request
%s Status of response
%b Size of response in bytes
%{Foobar}i
Referer
User-Agent

设定字符集
设定WEB服务器的字符集

# 语法
AddDefaultCharset {On|Off|charset}

字符集定义
https://www.iana.org/assignments/character-sets/character-sets.xhtml

定义路径别名

Alias URL-path file-path

虚拟主机
主站点/etc/httpd/conf/httpd.conf 中DocumentRoot不注释仍然有效,不用可禁用(#DocumentRoot)

基于IP设定虚拟机

<VirtualHost 172.18.17.101:80>
ServerAdmin zb@zhubiaook.com 管理员邮箱,可不写
DocumentRoot /var/www/web1
ServerName www.zhubiaook.com
ErrorLog logs/web1_error_log
CustomLog logs/web1_access_log common
</VirtualHost>
<VirtualHost 172.18.17.102:80>
DocumentRoot /var/www/web2
ServerName www.zhubiaook.com
ErrorLog logs/web2_error_log
CustomLog logs/web2_access_log common
</VirtualHost>
<VirtualHost 172.18.17.103:80>
DocumentRoot /var/www/web3
ServerName www.zhubiaook.com
ErrorLog logs/web3_error_log
CustomLog logs/web3_access_log common
</VirtualHost>

基于端口设定虚拟主机

增加监听的端口
Listen [IP:Port]|Port
Listen [IP:Port]|Port
Listen [IP:Port]|Port
<VirtualHost 172.18.17.101:8001>
DocumentRoot /var/www/web1
ServerName www.zhubiaook.com
ErrorLog logs/web1_error_log
CustomLog logs/web1_access_log common
</VirtualHost>
<VirtualHost 172.18.17.101:8002>
DocumentRoot /var/www/web2
ServerName www.zhubiaook.com
ErrorLog logs/web2_error_log
CustomLog logs/web2_access_log common
</VirtualHost>
<VirtualHost 172.18.17.101:8003>
DocumentRoot /var/www/web3
ServerName www.zhubiaook.com
ErrorLog logs/web3_error_log
CustomLog logs/web3_access_log common
</VirtualHost>

基于FQDN设定虚拟主机

注意:基于FQDN的访问原主站点将失效,默认站点为第一个虚拟主机(比如未指定首部host:...返回的是第一个虚拟主机的站点)的
NameVirtualHost *:80
<VirtualHost *:80>
DocumentRoot /var/www/web1
ServerName www.a.com
ErrorLog logs/web1_error_log
CustomLog logs/web1_access_log common
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/web2
ServerName www.b.com
ErrorLog logs/web2_error_log
CustomLog logs/web2_access_log common
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/web3
ServerName www.c.com
ErrorLog logs/web3_error_log
CustomLog logs/web3_access_log common
</VirtualHost>

status页面

#1. 添加status模块
LoadModule status_module modules/mod_status.so
#2. 通过虚拟URL server-status访问
<Location /URL-path>
SetHandler server-status
Order deny,allow
Allow from all
</Location>
ExtendedStatus On #显示更详细的信息

httpd2.2配置文件语法检查

httpd2.4

与httpd2.2相同的路径,配置此处不再重复叙述。

httpd2.4相关文件路径

httpd2.4模块路径

  • 模块配置文件路径
    httpd2.4将模块的配置文件从主配置文件中独立出来,分成了多个子配置文件,存放于单独的一个目录下,在主配置文件中使用 Include 命令导入模块配置文件。
# 模块配置文件
/etc/httpd/conf.modules.d/*.conf
# 使用Include导入主配置文件中
[root@localhost ~]# grep 'conf.modules.d' /etc/httpd/conf/httpd.conf
Include conf.modules.d/*.conf
  • 模块文件路径
# 符号链接路径
/etc/httpd/modules/mod_*.so
# 实际路径
/usr/lib64/httpd/modules/mod_*.so

主程序文件路径
httpd2.4中三种处理连接的I/O模式只使用一个主程序文件,不同的模式切换通过模块的动态加载来实现。

/usr/sbin/httpd

httpd2.4设置开机启动(CentOS7)

systemctl enable|disable httpd.service
systemctl {start|stop|restart} httpd.service

httpd2.4配置

MPM(Multi-Processing Module)
httpd2.4中I/O处理模型的切换方式是通过动态模块的加载来实现

# 加载不同I/O模型的模块
/etc/httpd/conf.modules.d/00-mpm.conf
# prefork
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
# worker
LoadModule mpm_worker_module modules/mod_mpm_worker.so
# event
LoadModule mpm_event_module modules/mod_mpm_event.so

修改默认主站点
httpd2.4中除了修改DocumentRoot,还需对目录授权。

# 修改主配置文件中的DocumentRoot
/etc/httpd/conf/httpd.cof
DocumentRoot directory-path
# 对目录授权
<directory directory-path>
Reuqire all granted
</directory>

访问控制
httpd2.4中的访问控制与httpd2.2大不相同,对站点资源的控制使用<RequireAll>..</RequireAll><RequireAny>..</RequireAny> 两种语句块,然后将控制语句放入到这两个语句块中。

# <RequireAll> 语法
# 匹配<RequireAll>中的所有行才允许访问directory-path中的资源
<directory directory-path>
<RequireAll>
Require [not] entity-name [entity-name] ...
Require [not] entity-name [entity-name] ...
...
</RequireAll>
</directory>
# <RequireAny> 语法
# 匹配<RequireAny>中的任意一行就允许访问directory-path中的资源
<directory directory-path>
<RequireAny>
Require [not] entity-name [entity-name] ...
Require [not] entity-name [entity-name] ...
...
</RequireAny>
</directory>
# 控制语句语法
Require [not] entity-name [entity-name] ...
e.g
Require all granted 所有都允许
Require all denied 所有都静止
Require user userid [userid] ... 允许用户列表
Require group group-name [group-name] ... 允许组列表
Require valid-user 允许所有有效用户
Require ip [ip] ... 允许的IP
Require host [hostname] [hostname] ... 允许的主机

虚拟主机
httpd2.4中基于FQDN方式设定虚拟主机不再需要声明NameVirtualHost IP:Port语句,但设定虚拟主机需要给站点目录授权。

# 基于FQDN设定虚拟主机举例
<VirtualHost *:80>
ServerName www.a.com
DocumentRoot /app/web/a
<Directory /app/web/a>
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName www.b.com
DocumentRoot /app/web/b
<Directory /app/web/b>
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName www.c.com
DocumentRoot /app/web/c
<Directory /app/web/c>
Require all granted
</Directory>
</VirtualHost>

实验

实验介绍

本实验以httpd2.2为例,在CentOS6上演示一个简单的WEB服务器是如何提供服务的。实验中涉及到DNS的搭建及证书的相关内容。重点在于演示httpd2.2的配置。

实验大概步骤如下:

  • 配置DNS服务器
  • 搭建CA,申请证书,颁发证书
  • 配置WEB服务器
    • 解决默认启动错误
    • 配置证书
    • 修改版本信息
    • 主站点配置
    • 站点访问控制
    • 日志设定
    • 虚拟主机
    • HTTPS实现
    • HSTS

实验拓扑图

Alt text

实验步骤

  1. 配置DNS服务器
    我们计划在DNS上配置三个解析区域 zhubiaook.comzhubiaook.eduzhubiaook.org 为后面实验提供域名解析,此处对于配置DNS只做简要叙述,关于DNS详细配置的知识请看我的另外一篇博客 DNS 及 bind

添加解析区域
配置 /etc/named.conf 使 named服务监听本地所有端口,为所有其它主机提供域名解析服务。

然后在 /etc/named.rfc1912.zones 中添加以下三个解析区域
172.18.17.12上的配置

[root@zhubiao named]# cat /etc/named.rfc1912.zones
zone "zhubiaook.com" IN {
type master;
file "zhubiaook.com.zone";
};
zone "zhubiaook.edu" IN {
type master;
file "zhubiaook.edu.zone";
};
zone "zhubiaook.org" IN {
type master;
file "zhubiaook.org.zone";
};

添加解析库文件
新建三个解析库文件 zhubiaook.com.zonezhubiaook.edu.zonezhubiaook.org.zone ,注意文件的属主,属组为named。
172.18.17.12上的配置

# zhubiaook.com.zone
[root@zhubiao named]# cat /var/named/zhubiaook.com.zone
$TTL 3H
IN SOA dns1 www.zhubiaook.com. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS dns1
dns1 A 172.18.17.12
www A 172.18.17.101
# zhubiaook.edu.zone
[root@zhubiao named]# cat /var/named/zhubiaook.edu.zone
$TTL 3H
@ IN SOA dns1 www.zhubiaook.com. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS dns1
dns1 A 172.18.17.12
www A 172.18.17.101
# zhubiaook.org.zone
[root@zhubiao named]# cat /var/named/zhubiaook.org.zone
$TTL 3H
@ IN SOA dns1 www.zhubiaook.com. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS dns1
dns1 A 172.18.17.12
www A 172.18.17.101

将客户端的网卡DNS的地址改为DNS服务器的地址
172.18.17.11上的配置

# 修改网卡配置的DNS地址
[root@zhubiao network-scripts]# tail -1 /etc/sysconfig/network-scripts/ifcfg-eth0
DNS1=172.18.17.12
# 重启网络服务
service network restart
  1. 搭建CA,申请证书,颁发证书
    我们将CA配置为根CA,即CA的证书是自我颁发的,然后为WEB服务器提供颁发证书的服务。关于CA的详细配置请看我的另外一篇博客 openssl 及 CA

CA服务器生成私钥
创建数据库文件和序列号文件
172.18.17.13上的配置

[root@zhubiao CA]# touch /etc/pki/CA/index.txt
[root@zhubiao CA]# echo 00 > /etc/pki/CA/serial

生成私钥
172.18.17.13上的配置

[root@zhubiao CA]# (umask 066;openssl genrsa -out /etc/pki/CA/private/cakey.pem 1024)
Generating RSA private key, 1024 bit long modulus
......++++++
..++++++
e is 65537 (0x10001)

CA服务器自签名证书
CA给自己颁发证书
172.18.17.13上的配置

[root@zhubiao CA]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:yunnan
Locality Name (eg, city) [Default City]:xuanwei
Organization Name (eg, company) [Default Company Ltd]:zhubiaook.com
Organizational Unit Name (eg, section) []:opt
Common Name (eg, your name or your server's hostname) []:ca.zhubiaook.com
Email Address []:

WEB服务器申请证书
WEB服务器(172.18.17.101) 向CA(172.18.17.13)申请证书
WEB服务器生成私钥
172.18.17.101上的配置

# 创建目录用于存放web服务器的私钥、证书申请、证书、CA证书文件
[root@zhubiao ~]# mkdir -p /etc/httpd/conf.d/ssl/
# 生成私钥文件
[root@zhubiao ~]# (umask 066;openssl genrsa -out /etc/httpd/conf.d/ssl/web.key 1024)
Generating RSA private key, 1024 bit long modulus
................................................................++++++
.......++++++
e is 65537 (0x10001)

WEB服务器创建证书申请文件
172.18.17.101上的配置

[root@zhubiao ~]# openssl req -new -key /etc/httpd/conf.d/ssl/web.key -out /etc/httpd/conf.d/ssl/web.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:yunnan
Locality Name (eg, city) [Default City]:xuanwei
Organization Name (eg, company) [Default Company Ltd]:zhubiaook.com
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:www.zhubiaook.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

将证书申请文件传到CA上

CA服务器颁发证书

[root@zhubiao CA]# openssl ca -in /etc/pki/CA/web.csr -out /etc/pki/CA/certs/web.crt -days 365
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 0 (0x0)
Validity
Not Before: Aug 18 15:24:39 2017 GMT
Not After : Aug 18 15:24:39 2018 GMT
Subject:
countryName = CN
stateOrProvinceName = yunnan
organizationName = zhubiaook.com
organizationalUnitName = IT
commonName = www.zhubiaook.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
95:CD:19:79:FF:6F:C5:E7:27:36:B5:78:06:A6:46:C9:23:06:56:16
X509v3 Authority Key Identifier:
keyid:65:14:37:AC:3E:6A:6A:72:20:6D:2C:27:0F:7F:59:4B:F1:56:D3:7F
Certificate is to be certified until Aug 18 15:24:39 2018 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

将CA自己的证书,及颁发给WEB服务器的证书传到WEB服务器上,当前WEB服务器上有四个文件,如下:

[root@zhubiao ssl]# ls /etc/httpd/conf.d/ssl/
cacert.pem web.crt web.csr web.key
  1. 配置WEB服务器
    安装httpd,并做初始化配置

安装httpd

yum -y install httpd

修改主配置文件 /etc/httpd/conf/httpd.confServerName 避免启动服务时提示抱错信息

ServerName www.zhubiaook.com:80

配置虚拟主机
配置三个虚拟主机,分别提供www.zhubiaook.comwww.zhubiaook.eduwww.zhubiaook.org三个站点的WEB服务

首先创建三个站点的主目录

# 创建三个目录
mkdir /app/{web_com,web_edu,web_org}
# 目录如下所示:
[root@zhubiao app]# ls /app/{web_com,web_edu,web_org} -d
/app/web_com /app/web_edu /app/web_org

创建三个站点的首页

echo '<p>Welcome to www.zhubiaook.com<p>' > /app/web_com/index.html
echo '<p>Welcome to www.zhubiaook.edu<p>' > /app/web_edu/index.html
echo '<p>Welcome to www.zhubiaook.org<p>' > /app/web_org/index.html

创建三个基于FQDN虚拟主机

[root@zhubiao app]# cat /etc/httpd/conf.d/virtual-host.conf
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin zhubiaook@gmail.com
DocumentRoot /app/web_com
ServerName www.zhubiaook.com
ErrorLog logs/web_com-error_log
CustomLog logs/web_com-access_log combined
</VirtualHost>
<VirtualHost *:80>
ServerAdmin zhubiaook@gmail.com
DocumentRoot /app/web_edu
ServerName www.zhubiaook.edu
ErrorLog logs/web_edu-error_log
CustomLog logs/web_edu-access_log combined
</VirtualHost>
<VirtualHost *:80>
ServerAdmin zhubiaook@gmail.com
DocumentRoot /app/web_org
ServerName www.zhubiaook.org
ErrorLog logs/web_org-error_log
CustomLog logs/web_org-access_log combined
</VirtualHost>

重启httpd服务,使配置文件生效

测试客户端是否能够访问

# 访问 www.zhubiaook.com
[root@zhubiao ~]# curl www.zhubiaook.com
<p>Welcome to www.zhubiaook.com<p>
# 访问 www.zhubiaook.deu
[root@zhubiao ~]# curl www.zhubiaook.edu
<p>Welcome to www.zhubiaook.edu<p>
# 访问 www.zhubiaook.org
[root@zhubiao ~]# curl www.zhubiaook.org
<p>Welcome to www.zhubiaook.org<p>

上面的实验步骤已经实现了一台WEB服务器上创建了三个站点,客户端通过域名访问WEB服务器,下面我们将网站 www.zhubiaook.com 实现通过HTTPS访问,并且当用户访问 http://www.zhubiaook.com 时自动跳转到 https://www.zhubiaook.com

注意:SSL是基于IP地址实现,单IP的主机仅可以使用一个https虚拟主机

https的实现

安装模块 mod_ssl

yum -y install mod_ssl

修改配置文件/etc/httpd/conf.d/ssl.conf 针对WEB服务器私钥及证书路径,CA证书路径,及主站点。

# CA证书路径
SSLCACertificateFile /etc/httpd/conf.d/ssl/cacert.pem
# WEB服务器证书路径
SSLCertificateFile /etc/httpd/conf.d/ssl/web.crt
# WEB服务器私钥
SSLCertificateKeyFile /etc/httpd/conf.d/ssl/web.key
# 主站点
DocumentRoot "/app/web_com"

将CA证书导入客户端浏览器中,测试能否通过https访问

  • IE浏览器导入证书
    设置–>Internet 选项–>内容–>证书,将CA证书导入受信任的根证书颁发机构

Alt text

  • 火狐浏览器导入证书
    选项–>高级–>证书–>查看证书–>导入,将CA证书导入受信任的根证书颁发机构

Alt text

测试

Alt text


配置实现自动跳转HTTPS
使用HSTS实现浏览器自动跳转为HTTPS访问网站

HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。非加密传输时设置的HSTS字段无效。比如,https://example.com/ 的响应头含有Strict-Transport-Security: max-age=31536000; includeSubDomains。这意味着两点:
在接下来的一年(即31536000秒)中,浏览器只要向example.com或其子域名发送HTTP请求时,必须采用HTTPS来发起连接。比如,用户点击超链接或在地址栏输入 http://www.example.com/ ,浏览器应当自动将 http 转写成 https,然后直接向 https://www.example.com/ 发送请求。
在接下来的一年中,如果 example.com 服务器发送的TLS证书无效,用户不能忽略浏览器警告继续访问网站。

配置WEB服务器 /etc/httpd/conf.d/virtual-host.conf 站点 www.zhubiaook.com,强制客户端使用HTTPS与该站点进行连接。

<VirtualHost *:80>
ServerAdmin zhubiaook@gmail.com
DocumentRoot /app/web_com
ServerName www.zhubiaook.com
ErrorLog logs/web_com-error_log
CustomLog logs/web_com-access_log combined
Header always set Strict-Transport-Security "max-age=15768000"
RewriteEngine on
RewriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=301]
</VirtualHost>

https://highlightjs.org/static/demo/
https://github.com/isagalaev/highlight.js/tree/master/src/styles