1. 程式人生 > >LNMP架構負載均衡及HTTPS相關配置

LNMP架構負載均衡及HTTPS相關配置

11月29日任務

12.17 Nginx負載均衡

12.18 ssl原理

12.19 生成ssl金鑰對

12.20 Nginx配置ssl

 

Nginx負載均衡

負載均衡原理上就是代理,只不過通過設定多個代理伺服器來實現多使用者訪問時的負載均衡。同時也可以在某個代理伺服器無法訪問時,切換到另外的代理伺服器,從而實現訪問不間斷的目的。

下面以qq.com為例,配置負載均衡

  1. 先通過dig命令檢視域名及其ip
# dig命令由bind-utils包安裝
[root@localhost ~]# yum install -y bind-utils
[root@localhost ~]# dig qq.com

; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7_4.1 <<>> qq.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65328
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;qq.com.				IN	A

;; ANSWER SECTION:
qq.com.			404	IN	A	61.135.157.156
qq.com.			404	IN	A	125.39.240.113

;; Query time: 40 msec
;; SERVER: 119.29.29.29#53(119.29.29.29)
;; WHEN: 四 1月 04 22:02:25 CST 2018
;; MSG SIZE  rcvd: 67
  1. 配置虛擬主機配置檔案
[root@localhost ~]# mv /usr/local/nginx/conf/vhost/load.conf
# 通過upstream來指定多個web伺服器
upstream qq_com
{
    # ip_hash的目的是讓同一個使用者始終保持在同一個機器上
    ip_hash;
    
    # 這裡是負載均衡時使用的多個server的ip
    # server http://61.135.157.157:80;
    # 上述表示也行,對應的server塊內的proxy_pass內直接寫qq_com即可,不需要寫http://
    server 61.135.157.157:80;
    server 125.39.240.113:80;
}
server
{
    listen 80;
    server_name www.qq.com;
    location /
    {
        # 這裡使用的是upstream名即qq_com
        proxy_pass http://qq_com;
        proxy_set_header Host               $host;
        proxy_set_header X_Real_IP          $remote_addr;
        proxy_set_header X-Forwarded_For    $proxy_add_x_forwarded_for;
    }
}

驗證效果

配置未生效時,本地訪問www.qq.com,得到的將是預設主機的內容

[root@localhost ~]# curl -x127.0.0.1:80 www.qq.com
this is default web server

重啟服務後,獲取到了www.qq.com網頁的原始碼

[root@localhost ~]# /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
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
[root@localhost ~]# curl -x127.0.0.1:80 www.qq.com
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta content="text/html; charset=gb2312" http-equiv="Content-Type">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="baidu-site-verification" content="cNitg6enc2">
<title><CC><DA>Ѷ<CA><D7>ҳ</title>
<script type="text/javascript">
if(window.location.toString().indexOf('pref=padindex') != -1){
}else{
        if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || /\(Android.*Mobile.+\).+Gecko.+Firefox/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){  
      if(window.location.href.indexOf("?mobile")<0){
                try{
                        if(/Android|Windows Phone|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
                                window.location.href="http://xw.qq.com/index.htm";
                        }else if(/iPad/i.test(navigator.userAgent)){
              //window.location.href="http://www.qq.com/pad/"
                        }else{
...

nginx不支援代理https,即server語句內的埠無法使用443。


ssl原理

  1. 客戶端向伺服器傳送https請求;
  2. 伺服器上儲存了一套數字證書,其實質為一對公私鑰。數字證書可以自己製作,也可以向組織申請。前者在客戶端訪問時需要驗證才能繼續訪問;後者不會彈出驗證提示;
  3. 伺服器將公鑰傳輸給客戶端;
  4. 客戶端驗證公鑰是否合法:無效(自己製作的)會彈出警告,有效的則生成一串隨機數,用此隨機數加密公鑰;
  5. 客戶端將加密後的字串傳輸給伺服器
  6. 伺服器收到字串後,先使用私鑰進行解密,獲取加密使用的隨機數,並以此隨機數加密傳輸的資料(對稱機密);
  7. 伺服器將加密後的資料傳輸給客戶端;
  8. 客戶端收到資料後,使用自己的私鑰(即隨機字串)進行解密。

對稱加密:將資料和私鑰(隨機字串)通過某種演算法混合在一起,除非知道私鑰,否則無法解密。


生成SSL金鑰對

  • 建立私鑰key
[root@localhost ~]# cd /usr/local/nginx/conf

# 建立私鑰key檔案,必須輸入密碼,否則無法生成key檔案
[root@localhost conf]# openssl genrsa -des3 -out tmp.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:
  • 轉換key,取消密碼
[root@localhost conf]# openssl rsa -in tmp.key -out test.key
Enter pass phrase for tmp.key:
writing RSA key

[root@localhost conf]# rm -f tmp.key 
  • 生成證書
[root@localhost conf]# openssl req -new -key test.key -out test.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) []:ZheJiang
Locality Name (eg, city) [Default City]:QuZhou
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

# 需要使用csr檔案與私鑰一起生成.crt檔案
[root@localhost conf]# openssl x509 -req -days 365 -in test.csr -signkey test.key -out test.crt
Signature ok
subject=/C=CN/ST=ZheJiang/L=QuZhou/O=Default Company Ltd
Getting Private key

Nginx配置SSL

  • 建立新虛擬主機配置檔案
[root@localhost conf]#vim /usr/local/nginx/conf/vhost/ssl.conf
server
{
    listen 443;
    server_name test.com;
    index index.html index.php;
    root /data/www/test.com;
    ssl on;
    ssl_certificate test.crt;
    ssl_certificate_key test.key;
    ssl_protocols TLSv1 TLS1.1 TLS1.2;
}
  • 建立對應目錄及檔案
[root@localhost conf]# mkdir -p /data/www/test.com
[root@localhost conf]# vim /data/www/test.com/index.php
ssl test page.
  • 重啟服務
/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload

設定時報錯 -- unknown directive “ssl”

這時由於一開始編譯時未將http_ssl_module模組編譯進nginx,需要重新編譯安裝

[root@localhost conf]# cd /usr/local/src/nginx-1.12.2/
[root@localhost nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module
[root@localhost nginx-1.12.2]# make && make install

重新編譯後將導致之前配置的虛擬主機配置檔案丟失,最後在重新編譯前對有用的nginx虛擬主機檔案進行備份


  • 編譯完成後檢視
[root@localhost conf]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.12.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) 
built with OpenSSL 1.0.2k-fips  ...
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx/ --with-http_ssl_module
  • 重啟nginx服務
# 重新編譯後的nginx必須使用/etc/init.d/nginx指令碼進行重啟
[root@localhost conf]# /etc/init.d/nginx restart
Restarting nginx (via systemctl):                          [  確定  ]

# 檢視443埠是否開放
[root@localhost conf]# netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1354/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      2116/master         
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      4953/nginx: master  
tcp6       0      0 :::3306                 :::*                    LISTEN      2156/mysqld         
tcp6       0      0 :::22                   :::*                    LISTEN      1354/sshd           
tcp6       0      0 ::1:25                  :::*                    LISTEN      2116/master         
  • 效果驗證
  1. curl驗證
# 如果不想使用-x指定ip,可以在/etc/hosts內新增如下程式碼
[root@localhost conf]# vim /etc/hosts
127.0.0.1 test.com

# curl測試
[root@localhost conf]# curl https://test.com
curl: (60) Peer's certificate issuer has been marked as not trusted by the user.
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
  1. 瀏覽器驗證 同樣的要修改客戶端上的hosts檔案,新增一行程式碼如下:
192.168.65.133 test.com

同時要檢查伺服器端的防火牆是否開放443埠,這裡為了測試方便,直接清空了iptables規則表

[root@localhost conf]# iptables -F

在瀏覽器內輸入https://test.com,測試效果如下:

點選“仍要繼續”,頁面內容顯示如下:

網頁說明描述,證書不合法