目前,使用HTTPS
通信已经成为主流,相对于HTTP,HTTPS更加安全,因为它就是加密的HTTP协议,使用HTTPS通信,即使数据包被截获,我们也无法破译里面的内容。
HTTPS通信的过程大致如下:
- 浏览器发送一个HTTPS请求给服务器
- 服务器要有一套数字证书,可以自己制作,也可以向相关组织申请。区别就是自己的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书就是一对公钥和私钥
- 服务器会把公钥传输给客户端
- 客户端(浏览器)收到公钥后,会验证其是否合法有效,无效会有警告提醒,有效则会生成一串随机字符串,并用收到的公钥加密
- 客户端把加密后的随机字符串传输给服务器
- 服务器收到加密随机字符串后,先用私钥解密(公钥用来加密,私钥用来解密),获取到这一串随机字符串后,再用这串随机字符串加密传输的数据(这种加密就是“对称加密”)
- 服务器把加密后的数据传输给客户端
- 客户端收到数据后,再用自己的私钥(也就是那串随机字符串)解密
通过上面过程我们可以知道,我们可以确定服务器上必须要有一对公钥和私钥,这就是SSL证书,如果网站对外提供服务,则需要购买被各大浏览器厂商认可的SSL证书,自己制作的SSL证书无法使用在真实生产环境中。
要想弄明白SSL认证原理,首先要对CA有有所了解,它在SSL认证过程中有非常重要的作用。说白了,CA就是一个组织,专门为网络服务器颁发证书的,国际知名的CA机构有VeriSign、Symantec,国内的有GlobalSign。每一家CA都有自己的根证书(根证书就是处于认证树顶端的证书),用来对它所签发过的服务器端证书进行验证。
如果服务器提供方想为自己的服务器申请证书,它就需要向CA机构提出申请。服务器提供方向CA提供自己的身份信息,CA判明申请者的身份后,就为它分配一个公钥,
并且CA将该公钥和服务器身份绑定在一起,并为之签字,这就形成了一个服务器端证书。
如果一个用户想鉴别另一个证书的真伪,他就用CA的公钥对那个证书上的签字进行验证,一旦验证通过,该证书就被认为是有效的。证书实际是由证书签证机关(CA)签发的对用户的公钥的认证。
证书的内容包括:电子签证机关的信息、公钥用户信息、公钥、权威机构的签字和有效期等等。目前,证书的格式和验证方法普遍遵循X.509国际标准。
首先要有一个CA根证书,然后用CA根证书来签发用户证书。
用户进行证书申请:
- 先生成一个私钥
- 用私钥生成证书请求(证书请求里应含有公钥信息)
- 利用证书服务器的CA根证书来签发证书
这样最终拿到一个由CA根证书签发的证书,其实证书里仅有公钥,而私钥是在用户手里的。
SSL的工作流程分为两种——单向认证和双向认证:
1.客户端say hello 服务端
2.服务端将证书、公钥等发给客户端
3.客户端CA验证证书,成功继续、不成功弹出选择页面
4.客户端告知服务端所支持的加密算法
5.服务端选择最高级别加密算法明文通知客户端
6.客户端生成随机对称密钥key,使用服务端公钥加密发送给服务端
7.服务端使用私钥解密,获取对称密钥key
8.后续客户端与服务端使用该密钥key进行加密通信
单向认证,仅仅是客户端需要检验服务端证书是否是正确的,而服务端不会检验客户端证书是否是正确的。双向认证,指客户端验证服务器端证书,而服务器也需要通过CA的公钥证书来验证客户端证书(类似于网上银行的数字证书,使用U盾才能成功交易)。
Nginx配置SSL的具体配置过程如下:
# cd /usr/local/nginx/conf/
# openssl genrsa -des3 -out tmp.key 2048 #openssl命令生成key文件(私钥),2048为加密字符串长度
Generating RSA private key, 2048 bit long modulus
.................................+++
.......................+++
e is 65537 (0x10001)
Enter pass phrase for tmp.key: #这里让我们输入密码,不能太短
Verifying - Enter pass phrase for tmp.key: #这里再输入一遍
# openssl rsa -in tmp.key -out lzx.key #把刚刚生成的tmp.key再转换成lzx.key,目的是删除刚刚设置的密码,如果key文件有密码,Nginx在加载它时必须每次都输入密码,会很不方便
Enter pass phrase for tmp.key: //这里输入之前输入的密码
writing RSA key
# rm -f tmp.key
# openssl req -new -key lzx.key -out lzx.csr #生成证书请求文件,key文件和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) []:zhengjiang
Locality Name (eg, city) [Default City]:hangzhou
Organization Name (eg, company) [Default Company Ltd]:1
Organizational Unit Name (eg, section) []:1
Common Name (eg, your name or your server's hostname) []:lzx.com #这里可以填你的名字或服务器名字
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
# openssl x509 -req -days 365 -in lzx.csr -signkey lzx.key -out lzx.crt #生成了crt证书文件——公钥
Signature ok
subject=/C=CN/ST=zhengjiang/L=hangzhou/O=1/OU=1/CN=lzx #这里是上面填写的资料内容
Getting Private key
上面操作的目的就是生成lzx.key
和lzx.crt
两个文件,其实购买SSL证书主要是得到这两个文件。
# vim /usr/local/nginx/conf/vhost/ssl.conf
server
{
listen 443;
server_name lzx.com;
index index.html index.php;
root /data/nginx/lzx.com;
ssl on;
ssl_certificate lzx.crt;
ssl_certificate_key lzx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location ~ \.php$
{
include fastcgi_params;
fastcgi_pass unix:/tmp/php-fcgi.sock;
fastcgi_index index.php;;
fastcgi_param SCRIPT_FILENAME /data/nginx/lzx.com$fastcgi_script_name;
}
access_log /tmp/1.log combined_realip;
}
# /usr/local/nginx/sbin/nginx -t
nginx: [emerg] unknown directive "ssl" in /usr/local/nginx/conf/vhost/ssl.conf:8 #出现报错,这是因为当前Nginx不支持SSL,需要重新编译Nginx,配置支持SSL参数
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
# cd /usr/local/src/nginx-1.12.1
# ./configure --prefix=/usr/local/nginx --with-http_ssl_module #这里增加配置SSL参数
# make
# make install
# /usr/local/nginx/sbin/nginx -t #编译完成后,再来检查一次
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful #这里没有问题
# /usr/local/nginx/sbin/nginx -s reload
# mkdir -p /data/nginx/lzx.com
# echo "" > /data/nginx/lzx.com/1.php
# /etc/init.d/nginx restart #重启Nginx服务
Restarting nginx (via systemctl): [ 确定 ]
192.168.100.150 lzx.com
# iptables -I INPUT -p tcp --dport 80 -j ACCEPT
# iptables -I INPUT -p tcp --dport 443 -j ACCEPT #防止浏览器访问不了lzx.com
https://lzx.com/1.php
:点击高级
这里可以点击继续前往lzx.com(不安全)
,进入lzx.com/1.php
。
和LAMP不同,在LNMP架构中,php-fpm作为一个独立的服务存在,php-fpm的配置文件为/usr/local/php-fpm/etc/php-fpm.conf
,它同样支持include语句。
Nginx可以配置多个虚拟主机,php-fpm同样也支持配置多个pool,每一个pool可以监听一个窗口,也可以监听一个socket。
# vim /usr/local/php-fpm/etc/php-fpm.conf
[global]
pid = /usr/local/php-fpm/var/run/php-fpm.pid
error_log = /usr/local/php-fpm/var/log/php-fpm.log
include = etc/php-fpm.d/*.conf #新增这一行,必须写上etc目录,注意等号后面路径
# mkdir /usr/local/php-fpm/etc/php-fpm.d
# cd /usr/local/php-fpm/etc/php-fpm.d
# vim www.conf #写入下面内容
[www]
listen = /tmp/www.sock
listen.mode = 666
user = php-fpm
group = php-fpm
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
rlimit_files = 1024
# vim lzx.conf
[lzx]
listen = /tmp/lzx.sock
listen.mode = 666
user = php-fpm
group = php-fpm
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
rlimit_files = 1024
这样就有了两个pool了,第一个pool监听/tmp/www.sock
,第二个pool监听/tmp/lzx.sock
。这样,就可以在Nginx不同的虚拟主机中调用不同的pool,从而达到相互隔离的目的,两个pool互不影响。
# /usr/local/php-fpm/sbin/php-fpm -t
[08-Jul-2018 21:08:33] NOTICE: configuration file /usr/local/php-fpm/etc/php-fpm.conf test is successful #说明配置没有问题
# /etc/init.d/php-fpm restart #重启php-fpm服务
Gracefully shutting down php-fpm . done
Starting php-fpm done
# ls /tmp/*.sock
/tmp/lzx.sock /tmp/mysql.sock /tmp/php-fcgi.sock #除了默认自带的pool,也有刚刚创建的两个pool
php-fpm的慢执行日志,可以看到php的脚本哪里执行时间长,它可以定位到具体的行。通过php-fpm的慢执行日志,我们有时可以解决PHP的网站php-fpm进程占用资源过多而导致网站很卡的问题。
# vim /usr/local/php-fpm/etc/php-fpm.d/www.conf #在最后面加入下面内容
request_slowlog_timeout = 1 #定义超时时间,即PHP的脚本执行时间超过1秒就会记录日志
slowlog = /usr/local/php-fpm/var/www-slow.log #定义慢执行日志的路径和名字
open_basedir
定义open-basedir的目的就是为了安全,httpd可以针对每个虚拟主机设置一个open-basedir,php-fpm也可以针对每个pool设置不同的open_basedir。
# vim /usr/local/php-fpm/etc/php-fpm.d/lzx.conf #在最后面加入下面内容
php_admin_value[open_basedir]=/data/www/:/tmp/
只要在对应的Nginx虚拟主机配置文件中调用对应的pool,就可以使用open_basedir来物理隔离多个站点,从而达到安全目的。
pm = dynamic 定义php-fpm的子进程启动模式,dynamic为动态模式,根据实际需求,动态地增加或减少子进程,最多不超过pm.max_children定义的数值
pm.max_children = 50 另外一种是static,这种模式下子进程数量由pm.max_children决定,一次性启动这么多,不增加也不减少
pm.start_servers = 20 针对dynamic模式,定义在启动服务时产生的子进程的数量
pm.min_spare_servers = 5 针对dynamic模式,定义空闲时段子进程数的最小值
pm.max_spare_servers = 35 针对dynamic模式,定义空闲时段子进程数的最大值
pm.max_requests = 500 针对dynamic模式,定义一个子进程最多处理的请求数,达到这个数值时,它会自动退出
更多资料参考:
nginx算法分析
nginx中的root和alias区别