Skip to content

Latest commit

 

History

History
1152 lines (788 loc) · 49.2 KB

3.20_20170525_HTTP.md

File metadata and controls

1152 lines (788 loc) · 49.2 KB

HTTP

计算机网络通信模型有OSI参考模型和当前正在使用TCP/IP模型

从linux的角度看计算机网络的通信模型,物理层是通过硬件实现的,数据链路层是通过相关硬件的驱动程序实现的,网络层和传输层在内核中实现,应用层在用户空间实现。

应用层的重点是不同的程序实现特有的一些功能,TCP/IP的下三层更通用,重点是数据的传送

物理层提供设备到设备的通信,网络层提供主机到主机的通信,传输层为进程提供端到端的通信服务,传输层使用端口来区分各个进程,传输层使用的协议常用的有两种,TCP和UDP

网络通信实际上也是两个进程之间的通信,套接字(Socket)是进程通信的一种方式,允许位于不同主机的不同进程进行通信,套接字是进程间数据流的端点,以IP协议为通信基础的套接字称为网络套接字,以本地文件系统通信的套接字称为Unix Socket。

套接字有三种类型,一种是以TCP为基础的SOCK_STREAM,一种是以UDP为基础的SOCK_DGRAM,还有一种直接以IP为基础的raw socket

IANA将0-1023的端口已经永久分配给固定的应用使用,叫做特权端口;1024-41951范围内的端口也是由IANA进行注册的端口,但要求不严格,可分配给开发者注册为某应用使用;41952之后的端口是客户端随机使用的端口,也叫做动态端口或私有端口,其范围由/proc/sys/ipv4/ip_local_port_range文件定义。

客户端和服务端组成一组套接字,服务端使用固定的端口监听,客户端使用随机端口。

Socket Domain根据所使用的地址不同,Socket分为AF_INET、AF_INET6、AF_UNIX。

  • AF_INET
  • AF_INET6
  • AF_UNIX:同一主机上不同的进程通信时使用

每类套接字都至少提供了两种Socket数据传输机制:流和数据报。流可以可靠地传递并且是面向连接的,而且是无边界的;数据报是不可靠地传递,报文有边界、无连接。

与套接字相关的系统调用有

  • socket():创建套接字
  • bind():绑定套接字
  • listen():监听套接字
  • accept():接受请求
  • connect():请求连接建立
  • write():发送
  • read():接收

HTTP协议

超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是互联网上广泛使用的协议,提供了一种发布和接收HTML页面的方法。通过HTTP或HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

C/S架构是一种网络架构,分为客户端和服务端,客户端和服务端要使用相同的协议才可以正常的通信,C/S架构最常见的就是在互联网所浏览的网页,使用的http协议,监听在tcp80端口,用来传输使用html标记的文件,http的客户端多数是浏览器(browser),服务端是http server。

多用途互联网邮件扩展MIMEMultipurpose Internet Mail Extensions)的引入使html可以支持多媒体,服务端将非文本格式的数据编码为文本数据,客户端将文本数据还原为非文本格式的数据。

HTTP请求对象的内容叫做web资源(web resource),静态文件是最基本的资源,如文本、音频、视频。web资源也有动态资源,如php、jsp。一个页面中展示的资源可能有多个;每个资源都需要单独请求。

资源(媒体)有类型,又称为MIME类型,有主类型和次类型major/minor,如text/html、text/plain、image/gif、video/mpeg。

每个资源的唯一标识符叫做URL,URL是统一资源定位符,是URI的子集,URI是统一资源标识符。URL用于描述某服务器特定资源的位置

URL(Uniform Resource Locator),由三部分组成:URL方案scheme、服务器地址ip:port、资源路径。

URL一般格式:<scheme>://<user>:<password>@<host>:<port>/<path>;<params=>?<query=>#<frag>

URL分为绝对URL和相对URL

http协议的版本

  • HTTP/0.9:原型版本
  • HTTP/1.0:第一个广泛使用的版本,支持MIME,有缓存缺陷,支持keep-alive
  • HTTP/1.1:广泛使用的版本,更多的请求方法,更精细的缓存控制,支持持久连接
  • HTTP/2.0:与2015年5月作为互联网标准正式发布

一次完整的HTTP请求处理过程

1、建立或处理连接:接收或拒绝请求

2、接收请求:接收来自于来自于网络请求报文中对某一资源的一次请求过程

3、处理请求:对请求报文进行解析,并获得请求的资源及请求方法等相关信息。请求报文的首部有请求方法、url、请求主机名称、Connection等

4、访问资源:获取请求报文中请求的资源。web服务器即存放了web资源的服务器,负责像请求者提供对方请求的静态资源或动态运行后生成的资源,这些资源放置于本地文件系统某路径下,此路径通常称为DocRoot

5、构建响应报文:

​ 标记资源的MIME类型:显示分类、魔法分类、协商分类

​ web服务器构建的响应并非客户端请求的资源,而是向客户端提供资源的另外一个访问路径,这叫做URL重定向

6、发送响应报文

7、记录日志

web服务端接收请求时的并发访问模型(web i/o)

  • 单进程IO结构:启动一个进程处理用户请求,而且一次只处理一个;多个请求被串行响应;
  • 多进程IO结构:启动多个进程,每个进程响应一个请求
  • 复用IO结构:一个进程响应多个请求
    • 多线程模型:一个进程生成多个线程,每个线程响应一个用户请求;对于Linux而言进程和线程响应量级相似
    • event-driven:事件驱动,一个进程直接响应N个请求
  • 复用多线程IO结构:启动多个线程,每个线程响应多个请求

服务端资源映射方式

  • Docroot
  • 路径别名
  • 虚拟主机Docroot映射
  • 用户家目录docroot映射

HTTP报文

一次请求以及与其对应的响应被称为http的事务,http一种无状态(stateless)协议,一次http事务结束后,连接断开,服务器无法持续追踪客访问者来源,所以引入了cookie和session机制来追踪同一个用户

每请求一个资源都需要tcp三次握手,效率十分低下,使用并行请求或保持连接来提高效率。保持连接有两个条件触发断开保持连接,限制时间或请求资源数。

http方法:GET、put、head、post、delete

http请求:request请求报文

<method> <request-url> <version> #起始行(请求行)
<headers>

<entity-body>

http响应:response响应报文

<vsesion> <status> <reson-phrase> #起始行(响应行)
<headers>

<entity-body>

<method>:请求方法,标明客户端希望服务器对资源执行的动作。常用的有GET、HEAD、POST

  • GET:请求从服务器获取一个资源,安全方法
  • HEAD:只从服务器获取文档的响应首部,不需要发送资源,安全方法
  • POST:向服务器发送要处理的数据,支持html表单提交
  • PUT:将请求的主体部分存储在服务器上
  • DELETE:请求删除服务器上指定的文档
  • TRACE:追踪请求到达服务器中间经过的代理服务器
  • OPTIONS:请求服务器返回对指定资源支持使用的请求方法

<request-url>:请求的资源,可以使相对路径,也可以是完整的URL

<version>:协议版本,格式为HTTP/<major>.<minor>,如http/1.1

<headers>:每个请求或响应报文可包含多个首部,每个首部都有首部名称,后面跟一个冒号,而后跟上一个可选空格,接着是一个值

  • 通用首部:请求和相应都可以使用
    • Connection:定义C/S之间关于请求/响应的有关选项,如在http/1.0中,Connection:keep-alive
    • Via:显示了报文经过的中间节点
    • Cache-Control:缓存控制
    • Date:报文的创建时间
  • 请求首部
    • Client-IP:客户端IP。下四层的信息由内核处理,IP被拆掉,实际上也有其他方法获取客户端IP
    • Host:请求的主机名和端口号。虚拟主机环境下用于标识不同的虚拟主机
    • Referer:指明了当前请求的资源是从何处来的,包含当前正在请求的资源的上一级资源。如防盗链,投放广告效果分析
    • User-Agent:用户代理,使用什么工具发出的请求
    • Accept:通知服务器自己可以接受的媒体类型,标明客户端更倾向于使用的方式
      • Accept:指明服务器能发送的媒体类型
      • Accept-Charset:支持使用的字符集
      • Accept-Encoding:支持使用的编码方式,如gzip
      • Accept-Language:支持使用的语言
    • 条件请求
      • Expect
      • If-Modified-Since:是否在指定的时间后修改过此资源
      • If-None-Match:本地缓存中存储的文档的ETag标签是否与服务器文档的Etag不匹配
    • 安全相关
      • Authorization:客户端提交给服务端的认证数据,如账号和密码
      • Cookie/Cookie2:客户端发送给服务端的身份标识
    • 代理请求首部
      • Proxy-Authorization:向代理服务器认证
  • 响应首部
    • 信息性首部
      • Age:响应持续的时间
      • Server:向客户端标明服务器程序名称、版本
    • 协商首部:某资源有多种表示方法时使用
      • Accept-Ranges:对当前资源来讲,服务器能够接受的范围类型
      • Vary:首部列表,服务器会根据列表中的内容,挑选出适合的版本发送给客户端
    • 安全相关
      • Set-Cookie/Cookie2:在客户端第一次请求时,服务端发送的令牌
      • WWW-Authentication:质询,要求客户端提供账号和密码
  • 实体首部:用于指定实体部分的属性
    • Location:资源的新位置
    • Allow:允许对此资源使用的请求方法
    • 内容首部
      • Content-Encoding
      • Content-Language
      • Content-Lentgth
      • Content-Location
      • Content-Type
    • 缓存首部
      • ETag:实体标签
      • Expires:过期期限
      • Last-Modified:上一次的修改时间
  • 扩展首部:非标准 首部,可能由程序开发者创建的。

<status>:状态码,三位数字,如200、404、502,标记请求处理过程中发生情况

  • 1xx:100-101, 信息提示状态码
  • 2xx:200-206, 成功状态码
    • 200:成功,请求的所有数据通过响应报文的entity-body部分发送。简要描述为OK
  • 3xx:300-305(?307), 重定向状态码
    • 301:请求URL指向的资源已被删除,在响应报文中通过首部location指明了资源现在所处的位置。简要描述为Move permanently
    • 302:与301相似,在响应报文中通过location指明了资源现在所处的临时位置。简要描述为Found
    • 304:客户端发出了条件式请求,但服务器上的资源未曾发生改变,则通过此状态码告知客户端。简要描述为Not Modified
  • 4xx:400-415, 错误类信息,客户端错误
    • 401:需要输入帐号和密码认证,方能访问资源。简要描述为unauthorized
    • 403:请求被禁止。简要描述为Forbidden
    • 404:服务器无法找到客户端请求的资源。简要描述为Not Found
    • 405:Method Not Allowed
  • 5xx:500-505, 错误类信息,服务器端错误
    • 500:服务器内部错误。简要描述为internal Server Error
    • 502:代理服务器从后端服务器收到了一条伪响应。简要描述为Bad Gateway
    • 503:ServiceUnavailable

<reson-phrase>:原因短语,解释状态码

<entity-body>:主体部分

http协议分析可以使用tcpdump、tshark和wireshark等抓包分析工具

httpd

常见的web服务器程序有httpd、nginx、Lighttpd,还有一些应用程序服务器(APP Server),可以返回动态内容,如ISS、tomcat、jboss、resin、webshpere、weblogic、oc4j。

美国的机构会定期统计各web服务程序在市场的占有率

httpd的版本主要有2.0、2.2、2.4,在CentOS 6默认提供的版本是2.2,CentOS 7默认提供的是2.4

httpd的特性

  • 高度模块化:由core和各种modules组成

  • DSO(Dynamic Shared Object)机制:支持模块的动态装卸载

  • MPM(Multipath-Processing Modules)机制:多路处理模块 ,非一个模块,是一种机制

    最常见的有下面三个模块:(面试必问,对三个模块形成文字总结,分析各方面的优劣)

    • prefork模块:多进程模型,每个进程响应一个请求。

      主进程负责接收请求但不处理请求,一个主进程负责生成多个子进程以及回收子进程,每个子进程处理一个用户请求,即便没有用户请求,也会预先生成多个空闲进程,随时等待请求到达,并发请求最大不会超过1024个。

    • worker:多线程模型,每个线程相应一个请求。一个主进程生成多个子进程,,每个子进程生成多个线程,每个线程响应一个请求;

    • event:事件驱动模型,单线程响应多个请求。一个主进程生成m个线程,每个线程相应n个请求;

httpd的功能特性

  • 支持虚拟主机virtual host
  • CGI(Common Gateway Interface)通用网关接口
  • 反向代理
  • 支持负载均衡
  • 支持路径别名alias
  • 丰富的用户认证机制authentication
  • 支持第三方模块。

使用httpd -l可以查看编译到server的模块,不包含DSO模块

mod_so.c表示启用DSO机制,prefork.c表示使用MPM中的prefork模式。在httpd2.2编译时,只能编译一种MPM,编译后不能修改。如果想要使用MPM中的worker机制,要使用httpd.worker来启动httpd。在服务脚本/etc/sysconfig/httpd中可以定义默认启动httpd的类型,HTTPD=/usr/sbin/httpd.worker。

httpd 2.2

在CentOS 6中,rpm包默认提供的是httpd2.2

使用rpm包安装后的http的目录结构

  • httpd主目录、网站根目录:/etc/httpd
  • 主配置文件:/etc/httpd/conf/httpd.conf
  • 补充配置文件:/etc/httpd/conf.d/
  • 服务脚本:/etc/rc.d/init.d/httpd
  • 服务脚本的配置文件:/etc/sysconfig/httpd
  • 主程序:/usr/sbin/httpd、/usr/sbin/httpd.event、/usr/sbin/httpd.worker
  • 日志文件:/var/log/httpd,日志文件有两个,一个是access_log访问日志,另外一个是error_log错误日志文件
  • DocRoot文档根目录:/var/www/html
  • CGI目录:/var/www/cgi-bin
  • httpd的模块文件:/usr/lib64/httpd/modules

启动httpd服务时,会对当前的ip地址进行反向解析,如果反向解析的结果和当前的主机名不对应是会报错。实验中可以编辑/etc/host是ip地址和主机名对应。

使用ss -tnlp检查服务的80端口是否监听

主进程的属主是root,工作进程的属主是普通用户apache,因为要在内核中注册使用小于1023的端口,只有管理员有权限, 主进程不响应请求,工作进程响应。

httpd的配置文件

httpd的主配置文件有三部分组成,分为了三个Section,第二段和第三段不要同时使用

Section 1:Global Environment

Section 2:‘Main’ server configuration #主机配置,用于仅提供一个站点时使用

Section 3:Virtual Hosts

一般格式是 directive value,directive不区分大小写,value是文件路径时取决于文件系统。

配置文件语法测试:service httpd configtest或httpd -t,绝大多数的配置修改后,可以通过service httpd reload来生效,如果修改了监听端口的地址或端口,必须要重启服务才能生效

  • Listen [IP:]PORT

    监听的地址和端口

    ip地址可以省略,表示监听所有ip地址

    可以使用多条Listen,用于指定监听多个不同的套接字

  • KeepAlive On|Off

    是否开启保持连接

    开启后,要设置 MaxKeepAliveRequest和KeepAliveTimeout的值,时间的默认单位是秒

    每个资源获取完后不会立即断开连接,而是继续等待其他资源请求 对并发访问量较大的服务器,持久连接可能会使一些访问请求得不到响应 一个折中的解决方案就是使用较短的持久连接时间,在2.4中可以支持毫秒级持久时间 使用数量限制来断开持久连接:默认为100个 使用时间限制来断开持久连接:可配置,单位是秒

    测试持久连接: telnet HOST PORT GET /URL HTTP/1.1 HOST:HOSTNAME|IP

  • MPM

    http2.2不支持同时编译多个模块,在编译时只能选择一个,rpm安装的包提供了三个二进制程序文件,分别实现了对不同mpm机制的支持。

    使用ps -aux | grep httpd,可以查看运行的httpd的类型,默认运行的是/usr/sbin/httpd,使用的是prefork

    使用ps命令查看的httpd类型加上-l 查看在核心中静态编译的模块

    使用httpd -M显示当前httpd加载的所有模块(静态编译+动态装载模块)

    更换使用的httpd程序:编辑脚本配置文件/etc/sysconfig/httpd中HTTPD=...

    在配置文件中使用<IfModule MODULE>...</IfModule>来判断运行的模块,如果匹配,参数即生效。

    • StartServers:number of server processes to start 默认启动的工作进程数
    • MinSpareServers:minimum number of server processes which are kept spare最少空闲进程数
    • MaxSpareServers:maximum number of server processes which are kept spare最大空闲进程数
    • ServerLimit:maximum value for MaxClients for the lifetime of the server最大活动进程数
    • MaxClients:maximum number of server processes allowed to start并发请求的最大数,要小于等于ServerLimit
    • MaxRequestsPerChild:maximum number of requests a server process serves每个子进程在生命周期内所能服务的最多请求个数。达到指定的数值后杀死进程,重新生成新的进程,当然如果一个子进程在重复使用没有问题的情况下,可以将数值调大。

    • StartServers: initial number of server processes to start启动的子进程数
    • MaxClients: maximum number of simultaneous client connections并发请求的最大数
    • MinSpareThreads: minimum number of worker threads which are kept spare最小空闲进程数
    • MaxSpareThreads: maximum number of worker threads which are kept spare最大空闲线程数
    • ThreadsPerChild: constant number of worker threads in each server process每个子进程生成的线程数
    • MaxRequestsPerChild: maximum number of requests a server process serves每个子进程在生命周期内所能服务的最多请求个数。0表示不限定
  • DSO

    DSO机制在配置文件中使用LoadModule来指定加载的模块

    LoadModule <mod_name> <mod_path>

    模块路径可以使用相对路径,相对路径是相当于ServerRoot(/etc/httpd)指向的路径而言。

    /etc/httpd/modules是一个符号链接指向了模块的目录

    使用httpd -M可以查看所有加载的DSO模块以及非DSO模块

  • DocumentRoot

    定义'Main' Server的文档页面根路径

    DocumentRoot指向的路径为URL路径的起始位置

    使用<Directory "/path/to/somewhere"> </Direcotry> ,可以对DocumentRoot下的目录进行属性的定义。

    也可以使用<Directory ~ "regexpress"> </Direcotry>,启用正则表达式,速度慢

    也可以使用<Location "URL"></Location>可以基于URL配置属性定义。如果某要配置其属性的URL能映射到某具体文件系统路径,建议使用Directory。

  • 页面访问属性和访问控制

    • Options Indexs|FollowSysLinks|None|All|...

      • Indexs:缺少指定的默认页面时,允许将目录中的所有文件以列表形式返回给用户。危险!

      • FollowSysLinks:允许访问符号链接所指向的原始文件

      • None:所有的选项都不启用

      • All:所有的都启用

      • ExecCGI:允许使用mod_cgi模块执行CGI脚本

      • Includes:允许使用mod_include模块实现服务器端包含(SSI)

      • Multiviews:允许使用mod_negotiation实现内容协商

      • SysLinksIfOwnerMatch:在链接文件属主属组域原始文件的属主属组相同时,允许访问符号链接所指向的原始文件

    • AllowOverride None| ALL|Options|FileInfo|Limit|...:是否允许覆盖下面的三个选项,None表示不禁用

    • Order、Allow、Deny

      Order Deny,Allow:默认Allow,除了指定Deny的--黑名单

      Order Allow,Deny:没有Allow的,都Deny--白名单

      二者都能匹配到或者都没有匹配到都以默认规则,即后者定义的行为。单个匹配到的,就按匹配的规则执行Deny或Allow

      基于主机的访问控制可以使用IP、Network Address定制规则

    • 基于用户的访问控制

      安全域:需要用户认证后方能访问的路径。每个安全域应该通过名称对其进行标识,并用于告知用户认证的原因

      用户的帐号和密码使用的虚拟账号,仅用于访问某服务时用到的认证标识。

      认证质询:WWW-Authenticate,响应码为401,拒绝客户端请求,并说明要求客户端提供帐号和密码

      认证:Authorization,客户端用户填入账号和密码后再次发送请求报文。认证通过服务端发送响应资源

      这里的用户并不是系统真正的用户,而是在获取服务端一些资源时为了验证身份而设置的虚拟用户。

      认证类型有两种,一种是basic认证,一种是digest认证。basic认证帐号和密码是明文发送的,digest认证将帐号密码hash编码后发送,但很多浏览器不支持digest认证,大部分浏览器使用的basic认证。在模块中是以auth_开头的模块,共有两个。

      认证提供者(authentication provider)是帐号和密码的存放位置,在模块中以authn_开头

      授权机制(Authorization)用来定义根据什么授权,在模块中以authz_开头

      根据用户和组进行授权,基于文件,做基本认证

      1. 在httpd的配置文件配置要认证的目录,对/var/www/html/admin目录要求进行认证登录
      <Directory "/var/www/html/admin">
      	Optinos None
      	AllowOverride AuthConfig
      	AuthType Basic #认证类型
      	AuthName "Private Area" #质询时弹出窗口的提示信息
      	AuthBasicProvider file #可省略,下面一条就说明了使用File
      	AuthUserFile /etc/httpd/conf/.htpasswd #
      	Require valid-user|tom,simon #valid-user允许账号文件中的所有用户登录访问
      </Directory>
      
      也可以基于组认证
      <Directory "">					
      	Options None
      	AllowOverride AuthConfig
      	AuthType Basic
      	AuthName "STRING"
      	AuthUserFile "/PATH/TO/HTTPD_USER_PASSWD_FILE"
      	AuthGroupFile "/PATH/TO/HTTPD_GROUP_FILE"
      	Require group GROUP1 GROUP2 ...
      </Directory>	
      
      1. 使用htpasswd命令创建AuthUserFile

        在没有密码文件时,使用htpasswd -c -m PASSWDFILE USERNAME。-c是创建文件,-m是使用md5将密码加密存放,-s 使用sha1加密用户密码,-D 删除指定用户

        组文件手动创建,每一行定义一个组。组文件的格式:组名:User1 User2 User3

  • DirectoryIndex

    定义默认主页面,页面文件可以有多个,会自左向右查找第一个找到的页面

  • Userdir disabled|public_html

    用户目录,如果期望让Linux每个用户都可以创建个人站点

    public_htm是用户家目录下的目录名称,所有位于此目录中的文件都可以通过http://Server_IP/~Username/进行访问,用户的家目录得赋予httpd进程的用户拥有执行权限。

  • CustomLog和ErrorLog

    httpd有两种日志,一个是access.log访问日志,记录的内容需要自定义,一个是error.log错误日志

    设定写入日志级别LogLevel warn

    日志级别由低到高:debug, info, notice, warn, error, crit, alert, emerg

    CustomLog定义访问日志的文件路径,需要指定日志路径和LogFormat日志格式

    定义好的日志格式,可以使用一个名称进行识别,使用CustomLog制定日志格式时使用定义的名称即可,默认使用的是combined

    LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined

    %h:Remote Host客户端IP地址
    %l: Remote logname (from identd, if supplied),远程登录名,-表示为空
    %u: Remote user,  (from auth; may be bogus if return status (%s) is 401)。认证时的远程用户名,-表示为空
    %t:Time the request was received (standard english format),服务器收到请求的时间
    %r:First line of request,请求报文的首行信息(method url version)
    %>s: 响应状态码
    %b: 响应报文的长度,单位是字节,不包括响应报文首部
    %{Referer}i:请求报文当中"referer"首部的值;当前资源的访问入口,即从哪个页面中的超链接跳转而来的
    %{Header_Name}i:记录指定请求报文首部的内容
    %{User-Agent}i:请求报文当中"User-Agent"首部的值;即发出请求用到的应用程序,通常是浏览器,也可是压力测试工具,或是爬虫工具
    官方文档:http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats 
    

    ErrorLog指定错误日志的位置

  • Alias路径别名

    使用路径别名可以访问不在DocumentRoot目录下的文件,使用Alias /目录/ "/var/www/A/"

    如:Alias /bbs/ "/forum/htdocs"

    http://www.jsp.com/bbs/index.html 使用别名后,文件在/forum/htdocs

  • AddDefaultCharset

    指定使用的默认字符集

  • ScriptAlias

    CGI脚本路径别名

    CGI是通用网关接口协议,当用户请求的是非静态资源时,httpd会使用CGI协议调用其他程序,将运行后的结果返回给用户,CGI的实现有一些问题,需要使用SUID和SGID,是危险操作。目前与前端通信时,php使用SAPI机制,pyton使用UWCGI机制。

    并非所有的CGI脚本都能被httpd识别,只有由ScriptAlias所定义的脚本别名路径下的文档才能被当作CGI,由mod_cgi、mod_alias获取后执行。

    使用CGI返回结果要使用URLhttp://hostname/cgi-bin/a_script

  • 虚拟主机

    虚拟主机可以在一台物理主机上架设多个站点

    区分虚拟主机可以基于不同的IP、不同的端口、以及FQDN

    • 基于ip:为每个虚拟机准备至少一个ip地址
    • 基于port:为每个虚拟主机准备至少一个专用port,实践中很少使用
    • 基于FQDN:为每个虚拟主机准备至少一个专用hostname。在请求首部可以看到请求的Hostname

    可混合使用上述三种方式中的任意方式

    一般虚拟主机不要和Main server混用,所以,要使用虚拟主机,先禁用中心主机:注释DocumentRoot

    在启用虚拟主机的情况下,如果客户端请求的URL是物理主机的ip地址,httpd则会将配置文件的第一虚拟主机返回给客户端,当然可以定义默认的虚拟主机。

    三种虚拟主机的方法可以混合使用,大部分用在中心主机的配置都可以在虚拟主机中使用

    基于ip

    <VirtualHost 172.16.100.6:80>
        ServerName web1.jsp.com
        DocumentRoot "/vhosts/web1/htdocs"
        <Directory " ">
        	options None
        </Directory>
        CustomLog ...... combined
    </VirtualHost>
    
    <VirtualHost 172.16.100.7:80>
        ServerName web2.jsp.com
        DocumentRoot "/vhosts/web2/htdocs"
        CustomLog ...... combined
    </VirtualHost>
    

    基于port

    <VirtualHost 172.16.100.7:80>
        ServerName web2.jsp.com
        DocumentRoot "/vhosts/web2/htdocs"
        CustomLog ...... combined
    </VirtualHost>
    
    <VirtualHost 172.16.100.7:8080>
        ServerName web3.jsp.com
        DocumentRoot "/vhosts/web3/htdocs"
        CustomLog ...... combined
    </VirtualHost>
    

    基于FQDN

    在httpd2.2中,使用FQDN方式的虚拟主机,要在配置文件中将NameVirtualHost *:80启用,并且虚拟主机的定义格式与NameVirtualHost的格式保持一致

    NameVirtualHost 172.16.100.6:80
    <VirtualHost 172.16.100.6:80>
        ServerName web1.jsp.com
        DocumentRoot "/vhosts/web1/htdocs"
        CustomLog ...... combined
    </VirtualHost>
    
    <VirtualHost 172.16.100.6:80>
        ServerName web2.jsp.com
        DocumentRoot "/vhosts/web2/htdocs"
        CustomLog ...... combined
    </VirtualHost>
    
    <VirtualHost 172.16.100.6:80>
        ServerName web3.jsp.com
        DocumentRoot "/vhosts/web3/htdocs"
        CustomLog ...... combined
    </VirtualHost>
    
    
  • 服务器status页面

    status页面可以通过web页面进行显示,status只能使用Location进行定义,因为status在文件系统中没有文件。

    在apache中有很多处理器,当文件被调用时,apache在内部的表现形式,一般来说,每种类型都有其隐式处理器。status页面信息需要指定处理器,需要加载模块status_mod,显示定义使用的处理器SetHandler

    <Location /server-status>
       SetHandler server-status
       AuthType Basic
       AuthUserFile "/etc/httpd/conf/.htpasswd"
       Require valid-user
       Order deny,allow
       Allow from all
    </Location>
    

完成水平:不看笔记独立完成所有配置,包括https。

HTTPS

http是明文传输的,要加密传输报文,需要借助于ssl/tls,对内容进行加密。

http是文本协议,https是二进制格式的协议,数据加密后是二进制编码。https监听在tcp/443端口,ssl会话是基于ip地址的,所以不支持基于FQDN的虚拟主机上实现。httpd基于mod_ssl模块实现对ssl的支持

SSL会话的简化过程

(1) 客户端发送可供选择的加密方式,并向服务器请求证书;

(2) 服务器端发送证书以及选定的加密方式给客户端;

(3) 客户端取得证书并进行证书验正:

​ 如果信任给其发证书的CA:

​ (a) 验正证书来源的合法性;用CA的公钥解密证书上数字签名; ​ (b) 验正证书的内容的合法性:完整性验正 ​ (c) 检查证书的有效期限; ​ (d) 检查证书是否被吊销; ​ (e) 证书中拥有者的名字,与访问的目标主机要一致;

(4) 客户端生成临时会话密钥(对称密钥),并使用服务器端的公钥加密此数据发送给服务器,完成密钥交换; (5) 服务用此密钥加密用户请求的资源,响应给客户端;

客户端验证服务端证书

  • 日期检测:验证证书是否在有效期内
  • 证书颁发者可信度检测:验证证书颁发者的可信度
  • 证书签名检测:验证证书的签名是否可信
  • 持有者身份检测:验证请求地址和持有者的地址是否一致

生成私有证书

[root@4fc6vm ~]# cd /etc/pki/CA
[root@4fc6vm CA]# (umask 077; openssl genrsa 2048 > private/cakey.pem)
Generating RSA private key, 2048 bit long modulus
..............................................................................+++
........................+++
e is 65537 (0x10001)
[root@4fc6vm CA]# ls -l private/
total 4
-rw-------. 1 root root 1679 Jun 13 10:12 cakey.pem

修改/etc/pki/tls/openssl.cnf文件,修改默认参数如国家省份等,生成证书时,就不需要多次填写

生成自签署证书

[root@4fc6vm CA]# openssl req -new -x509 -key private/cakey.pem -days 3655 -out cacert.pem
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) [CN]:
State or Province Name (full name) [JiangSu]:
Locality Name (eg, city) [Nanjing]:
Organization Name (eg, company) [JSP Company Ltd]:
Organizational Unit Name (eg, section) [LinuxOP]:
Common Name (eg, your name or your server's hostname) []:ca.jsp.com    
Email Address []:[email protected]

[root@4fc6vm CA]# ls
cacert.pem  certs  crl  newcerts  private

生成服务器私钥httpd.key

[root@4fc6vm ~]# cd /etc/httpd/conf
[root@4fc6vm conf]# mkdir ssl
[root@4fc6vm conf]# cd ssl
[root@4fc6vm ssl]# (umask 077;openssl genrsa 1024 > httpd.key)
Generating RSA private key, 1024 bit long modulus
..............++++++
..................................................................++++++
e is 65537 (0x10001)

生成证书签署请求httpd.csr

[root@4fc6vm ssl]# openssl req -new -key httpd.key -out httd.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) [CN]:
State or Province Name (full name) [JiangSu]:
Locality Name (eg, city) [Nanjing]:
Organization Name (eg, company) [JSP Company Ltd]:
Organizational Unit Name (eg, section) [LinuxOP]:
Common Name (eg, your name or your server's hostname) []:www.jsp.com  
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@4fc6vm ssl]# ls -l
total 8
-rw-r--r--. 1 root root 712 Jun 13 10:39 httd.csr
-rw-------. 1 root root 887 Jun 13 10:37 httpd.key

CA签署证书httpd.crt

[root@4fc6vm ssl]# cd /etc/pki/CA
[root@4fc6vm CA]# ls
[root@4fc6vm CA]# touch index.txt serial crlnumber
[root@4fc6vm CA]# echo 01 > serial
[root@4fc6vm CA]# cd /etc/httpd/conf/ssl
[root@4fc6vm ssl]# openssl ca -in httpd.csr -out httpd.crt
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Jun 13 02:49:01 2017 GMT
            Not After : Jun 13 02:49:01 2018 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = JiangSu
            organizationName          = JSP Company Ltd
            organizationalUnitName    = LinuxOP
            commonName                = www.jsp.com
            emailAddress              = [email protected]
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                EE:98:40:71:98:CF:30:DD:0A:A1:9D:69:58:66:91:A1:17:64:15:7F
            X509v3 Authority Key Identifier: 
                keyid:A6:B6:A8:F8:5E:53:0A:53:F4:EC:26:80:B8:5B:A8:8A:8C:9E:1B:80

Certificate is to be certified until Jun 13 02:49:01 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

[root@4fc6vm ssl]# ls
httpd.crt  httpd.csr  httpd.key

确认mod_ssl模块是否安装,使用yum -y install mod_ssl进行安装

[root@4fc6vm ssl]# grep mod_ssl /etc/httpd/conf/httpd.conf
# (e.g. :80) if mod_ssl is being used, due to the nature of the
[root@4fc6vm ssl]# grep mod_ssl /etc/httpd/conf.d/*
[root@4fc6vm ssl]# yum -y install mod_ssl
[root@4fc6vm ssl]# rpm -ql mod_ssl
/etc/httpd/conf.d/ssl.conf
/usr/lib64/httpd/modules/mod_ssl.so
/var/cache/mod_ssl
/var/cache/mod_ssl/scache.dir
/var/cache/mod_ssl/scache.pag
/var/cache/mod_ssl/scache.sem

修改mod_ssl的配置文件,/etc/httpd/conf.d/ssl.conf

检查语法,重启httpd

[root@4fc6vm conf.d]# httpd -t
Syntax OK
[root@4fc6vm conf.d]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[root@4fc6vm conf.d]# ss -tnl
State      Recv-Q Send-Q                               Local Address:Port                                 Peer Address:Port 
LISTEN     0      128                                             :::45411                                          :::*     
LISTEN     0      128                                              *:52068                                           *:*     
LISTEN     0      128                                             :::111                                            :::*     
LISTEN     0      128                                              *:111                                             *:*     
LISTEN     0      128                                             :::80                                             :::*     
LISTEN     0      128                                             :::22                                             :::*     
LISTEN     0      128                                              *:22                                              *:*     
LISTEN     0      128                                      127.0.0.1:631                                             *:*     
LISTEN     0      128                                            ::1:631                                            :::*     
LISTEN     0      100                                            ::1:25                                             :::*     
LISTEN     0      100                                      127.0.0.1:25                                              *:*     
LISTEN     0      128                                             :::443                                            :::*     

将证书/etc/pki/CA中的证书cacert.pem发给客户端,在windows中重命名为cacert.crt安装即可使用。使用openssl s_client -connect www.jsp.com:443 -CAfile /etc/pki/CA/cacert.pem也可以进行验证

总结

(1)准备好服务器的私钥和证书

(2)安装mod_ssl

(3)配置/etc/httpd/conf/ssl.conf,配置使用的ssl的虚拟主机的ServerName和DocumentRoot,配置证书和私钥SSLCertificateFile、SSLCertificateKeyFile

(4)重启httpd服务

(5)测试

在浏览器中如果没有明确指定使用https协议,默认都是使用80端口的http协议,在开放80的同时,使访问80端口自动跳转到443端口,这要基于URL RewriteURL重写。

curl和页面压缩

curl是基于URL语法在命令行方式下工作的文件传输工具,它支持FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE及LDAP等协议。curl支持HTTPS认证,并且支持HTTP的POST、PUT等方法, FTP上传, kerberos认证,HTTP上传,代理服务器, cookies, 用户名/密码认证, 下载文件断点续传,上载文件断点续传, http代理服务器管道( proxy tunneling), 甚至它还支持IPv6, socks5代理服务器,,通过http代理服务器上传文件到FTP服务器等等,功能十分强大。

一般使用格式:curl [options][URL...]

-I/--head 只显示响应报文首部信息
-A/--user-agent <string> 设置用户代理发送给服务器
-e/--referer <URL> 来源网址
-basic 使用HTTP基本认证
--tcp-nodelay 使用TCP_NODELAY选项
--cacert <file> CA证书 (SSL)
--compressed 要求返回是压缩的格式
-H/--header <line>自定义首部信息传递给服务器
--limit-rate <rate> 设置传输速度
-u/--user <user[:password]>设置服务器的用户和密码
-0/--http1.0 使用HTTP 1.0

另外一个工具叫elinks,一般使用格式:elinks [OPTION]... [URL]...

-dump:不进入交互模式,而直接将url的内容输出至标准输出

使用mod_deflate模块压缩页面可以优化传输速度,默认不启用。压缩要有一个过滤器,来指定压缩文件类型。

适用场景:

(1) 节约带宽,额外消耗CPU;同时,可能有些较老浏览器不支持;

(2) 压缩适于压缩的资源,例如文本文件;

如果在httpd的主配置文件中,没有关于输出过滤器的配置,可以在/etc/httpd/conf.d/目录下建立一个配置文件deflate.conf,

SetOutputFilter DEFLATE #启动输出过滤器为deflate

# mod_deflate configuration

# Restrict compression to these MIME types #对那些格式的文档进行压缩
AddOutputFilterByType DEFLATE text/plain 
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/css

# Level of compression (Highest 9 - Lowest 1) #定义压缩比
DeflateCompressionLevel 9
 
# Netscape 4.x has some problems. #指定不使用压缩的浏览器
BrowserMatch ^Mozilla/4 gzip-only-text/html
 
# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip
 
# MSIE masquerades as Netscape, but it is fine
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

httpd自带的工具程序

  • apachectl:apache自带的服务控制脚本,可以控制httpd程序,如apachectl stop,而在/etc/rc.d/init.d目录下的脚本是rpm作者提供的脚本

  • htpasswd: basic认证基于文件实现时,用到的账号密码文件生成工具;

  • apxs:由httpd-devel包提供的,扩展httpd使用第三方模块的工具;

  • rotatelogs:日志滚动工具;

    ​access.log --> ​access.log, access.1.log ​access.log, access.1.log, access.2.log

  • suexec:访问某些有特殊权限配置的资源时,临时切换至指定用户运行;

  • ab: Apache benchmark

压力测试

资源限定有软限制和硬限制。软限制可以超出限制,但仅超出一定时长,硬限制是不能超出的限制,是ulimit可以修改软限制的数值。修改硬限制在配置文件/etc/security/limits.conf,或者在扩展配置/etc/security/limits.d/*.conf中修改,修改不会立即生效,只能重启生效,可以暂时使用ulimit命令修改,立即生效,等重启后读取配置文件即可。

-n [N]:显示或限定能打开的最大的文件句柄数
-u [N]:显示或限定能够运行的最多进程数,没有数字表示显示当前数值

使用ab命令可以会httpd进行压力测试,一般使用格式ab [OPTIONS] URL

-c:模拟最大并发数。c的值要小于等于n的值
-n:总的请求数
-k:以持久连接模式测试

ab -c 100 -n 50000 http://192.168.4.208/index.html

Server Software:        Apache/2.4.6
Server Hostname:        192.168.4.208
Server Port:            80

Document Path:          /index.html
Document Length:        208 bytes

Concurrency Level:      100
Time taken for tests:   29.451 seconds
Complete requests:      50000
Failed requests:        0
Write errors:           0
Non-2xx responses:      50000
Total transferred:      20350000 bytes
HTML transferred:       10400000 bytes
Requests per second:    1697.72 [#/sec] (mean)
Time per request:       58.903 [ms] (mean)
Time per request:       0.589 [ms] (mean, across all concurrent requests)
Transfer rate:          674.78 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.6      0      20
Processing:     7   58  28.1     59    1111
Waiting:        1   58  27.7     59    1111
Total:         13   59  28.1     60    1111

Percentage of the requests served within a certain time (ms)
  50%     60
  66%     69
  75%     73
  80%     76
  90%     84
  95%     93
  98%    104
  99%    115
 100%   1111 (longest request)

除了ab可以对服务端httpd进行压力测试,还有webbench、http_load也可以做压力测试,但这些测试实际上都无法代表真正意义的流量,使用tcpcopy可以将真实的流量保存,然后使用真实的流量在架构上重放。

充分理解并解释压力测试结果

httpd 2.4

在CentOS 7中,默认提供apache的版本是2.4,使用RPM包安装httpd的默认路径是/etc/httpd,如果测试页不能正常打开,可以使用iptables或firewall-cmd来允许指定tcp端口或者允许指定的服务。

iptables -I INPUT -p tcp -dport 80 -j ACCEPT
firewall-cmd --permanent --add-service http

新特性

(1) MPM支持运行时装载模块;以模块形式按需加载; (2) 支持event MPM; (3) 支持异步读写; (4) 支持每模块及每个目录分别使用各自的日志级别; (5) 每请求配置;<If> (6) 增强版的表达式分析器; (7) 支持毫秒级的keepalive timeout; (8) 基于FQDN的虚拟主机不再需要NameVirtualHost指令; (9) 支持用户自定义变量;

新模块

(1) mod_proxy_fcgi

(2) mod_ratelimit

(3)mod_request

(4) mod_remoteip

修改了一些配置机制:不再支持使用Order, Deny, Allow来做基于IP的访问控制,统一使用require进行

编译安装httpd-2.4

httpd2.4依赖于apr-1.4+、apr-util-1.4+、apr-iconv,编译安装需要apr、apr-util、apr-icon

apr的全称是apache portable runtime,是一个用来使httpd跨平台的工具

在Cent OS 6中默认的是apr-1.3.9和apr-util-1.3.9

编译安装步骤:

在CentOS 6中要关闭httpd服务service httpd stop,并且确保httpd2.2没有开机启动chkconfig httpd off

1.4+版的apr和apr-util、安装开发环境,安装pcre-devel

(1) apr

# ./configure --prefix=/usr/local/apr
# make && make install

(2) apr-util

# ./configure --prefix=/usr/local/apr-util --with=/usr/local/apr
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr/
# make && make install

(3)编译安装httpd2.4

# groupadd -r apache
# useradd -r -g apache apahce
# ./configure --prefix=/usr/local/apache --sysconf=/etc/httpd24 --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util/ --enable-modules=most --enable-mpms-shared=all --with-mpm=prefork
# make && make install

(4)后续配置

导出头文件:ln -sv /usr/local/httpd24/include /usr/include/httpd

导出库文件和man手册

输出二进制程序:编辑/etc/profile.d/httpd.sh,添加export PATH=/usr/local/httpd24/bin$PATH

在CentOS 6中为编译的httpd2.4创建脚本

复制一个httpd2.2的脚本,命名为httpd24,修改文件内容

启动服务:apachectl 或service

CentOS 7中的httpd2.4(rpm)

主配置文件:/etc/httpd/conf/httpd.conf

模块配置文件:/etc/httpd/conf.modules.d/*.conf

辅助配置文件:/etc/httpd/conf.d/*.conf

mpm:以DSO机制提供,配置文件00-mpm.conf

服务控制:systemctl {start|stop|restart|status|reload} httpd.service

基于IP的访问控制

∂绝所有主机访问:Require all deny

控制某网络主机的访问:Require ip IPADDR | Require no ip IPADDR

IPADDR可是是具体地址、网络和子网掩码格式、网络和网络长度

基于Hostname的访问控制

Require host HOSTNAME|Require not host HOSTNAME

HOSTNAME可以是具体的主机,也可以是一个域

练习:在httpd2.4中配置CGI、虚拟主机、https、mod_deflate、mod_status

IO模型

一个进程同时需要和多个IO打交道,有磁盘IO、网络IO等。有四种机制:

  • 阻塞:当一个进程发起IO调用,调用的IO没有完成前,当前的进程会被挂起

  • 非阻塞:当一个进程发起IO调用,被调用函数完成之前不会阻塞当前进程而是立即返回结果,提示当前IO未完成

  • 同步:进程发起一个过程调用(功能、函数)后,在没得到结果之前,该调用将不会返回

  • 异步:进程发起一个过程调用后,即便调用者不能立即得到结果,但调用却会返回结果,返回是未完成状态。调用完成后,内核会通知调用者结果已经OK

    常见的有:同步阻塞、异步阻塞、异步非阻塞(真正的异步IO)

五种IO模型

  • 同步阻塞(blocking):当进程向内核发起一个对文件系统的访问时,进程阻塞,无法进行其他的任务,等待内核返回结果,而内核也不会立即对进程进行响应,而是到文件系统中将文件载入到内核内存,然后复制到进程内存中。

    进程阻塞有两个阶段,第一阶段是等待内核将数据载入到内核内存,第二阶段是等待数据复制到进程内存空间同步阻塞效率低。

  • 同步非阻塞(nonblocking):实际上同步非阻塞也是同步阻塞,在第一阶段,进程不会被挂起,而是定时向内核询问(盲等待),直到得到内核响应,此阶段进程是非阻塞,而得到内核响应后,等待数据复制到进程内存阶段,进程仍然是阻塞的。

  • IO复用(I/O multiplexing):IO复用在第一阶段和第二阶段都是阻塞的,只不过有多个IO同时都阻塞。BSD:select(),SysV:poll()

  • 信号驱动(signal-driven):第一阶段完成后,内核通知进程,第二阶段进程阻塞。只通知一次的叫做边缘触发,多次通知的叫水平触发。在linux中是epoll(),在BSD是kqueue()

  • 异步IO(asynchronous):进程发起调用后,收到通知,数据就已经在进程内存中了

内存映射(mmap)是省去了内核将数据复制到进程内存的步骤,而是进程直接访问内核内存。nginx支持异步IO、边缘触发、mmap,所以nginx性能比httpd好的原因,nginx可以一个线程响应多个请求。

httpd的prefork调用的是select(),最大的并发不超过1024,select()跨平台比较好,event调用的是epoll()