目錄
文章目錄
- 目錄
- Nginx
- Nginx 的安裝
- Nginx 的基礎配置
- 配置虛擬主機
- 配置反向代理
- 配置負載均衡
- 配置 HTTPS
Nginx
Nginx 是俄羅斯人 Igor Sysoev 開發的一個開源的、輕量級的、高性能的、高可靠的 Web 和反向代理服務器,同時也是一個 IMAP/POP3/SMTP 代理服務器,在微服務的體系之下,Nginx 正在被越來越多的專案采用作為 APIGW 的底座,
- Nginx 中文檔案:https://www.nginx.cn/doc/
截至 2019 年 12 月,差不多世界上每 3 個網站中就有 1 個使用了 Nginx,

值得注意的是,所謂 Web(HTTP)服務器,只是一個靜態檔案服務器或者 HTTP 請求轉發器,它可以把靜態檔案的請求直接回傳靜態檔案資源,把動態檔案的請求轉發給后臺的處理程式,例如:php-fpm、apache、tomcat、jetty 等,另外,這些后臺服務即使沒有 Nginx 的情況下也是可以直接訪問的,只是更多的情況下這些后臺服務器被放置在防火墻的后面,不直接對外暴露,所以通過 Nginx 來作為轉換,

Nginx 的安裝
- 安裝:
$ yum install epel-release -y
$ yum install nginx -y
$ nginx -v
nginx version: nginx/1.16.1
-
關鍵檔案或目錄:
- /etc/nginx/nginx.conf:主組態檔;
- /usr/share/nginx/html/:存放靜態檔案;
- /var/log/nginx:存放日志檔案,
-
啟動 Nginx:默認占有 0.0.0.0:80 埠,
systemctl enable nginx
systemctl start nginx
systemctl status nginx
- 常用指令:
nginx -s reload # 向主行程發送信號,重新加載組態檔,熱重啟,
nginx -s reopen # 重啟 Nginx,
nginx -s stop # 快速關閉,
nginx -s quit # 優雅關閉,
nginx -T # 查看當前 Nginx 的配置,
nginx -t -c <組態檔路徑> # 檢查配置是否有問題,
- 瀏覽器訪問 Nginx:http://localhost:80

Nginx 的基礎配置
nginx.conf 的核心結構樹如下:
main # 全域配置,
├── events # 配置 HTTP 服務器的基礎引數,例如:I/O 模型、行程最大并發數等,
├── http # 配置代理,快取,日志等大多數功能,以及配置第三方模塊,
│ ├── upstream # 配置后端服務器的具體地址,
│ ├── server # 配置虛擬主機的相關引數,可以存在多個 server 指令塊,作為 HTTP 虛擬主機,
│ ├── server
│ │ ├── location # 配置 URI paths 對應的檔案系統目錄路徑,一個 server 指令塊可以包含多個 location 指令塊,
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...
組態檔的語法規則:
- 組態檔由指令與指令塊構成;
- 每條指令以 “;” 分號結尾,指令與引數間以空格號分隔;
- 指令塊以 {} 大括號將多條指令組織在一起;
- include 陳述句允許組合多個組態檔以提升可維護性;
- 使用 # 符號添加注釋,提高可讀性;
- 使用 $ 符號使用變數;
- 部分指令的引數支持正則運算式;
全域變數:可以在配置的任何位置使用它們,

配置虛擬主機
在 HTTP/1.0 中會為每臺 HTTP Server 都系結一個唯一的 IP 地址,因此,請求訊息中的 URL 并沒有傳遞主機名(Hostname),但隨著虛擬主機技術的發展,在一臺物理服務器上可以存在多個虛擬主機(Multi-homed Web Servers),并且它們共享一個 IP 地址,HTTP/1.1 的請求訊息和回應訊息都應支持 Host 頭域,且請求訊息中如果沒有 Host 頭域會報告一個錯誤(400 Bad Request),
通常的,我們可以實作:
- 基于 IP 的虛擬主機,
- 基于 Port 的虛擬主機,
- 基于 Domain Name 的虛擬主機,
配置:
$ cat /etc/nginx/nginx.conf
...
http {
...
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name nginx1.com;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
root /usr/share/nginx/html;
index index.html;
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
server {
listen 80;
server_name fanguiju.com;
location / {
root /usr/share/nginx/html/fanguiju;
index index.html;
}
}
}
$ mkdir /usr/share/nginx/html/fanguiju
$ cat /usr/share/nginx/html/fanguiju/index.html
fanguiju.com
$ nginx -s reload
測驗:
$ curl -X GET http://127.0.0.1:80/
nginx1.com
$ curl -X GET http://127.0.0.1:80 -H "host: fanguiju.com"
fanguiju.com
配置反向代理

反向代理可以將一類(對特定 URL 的)請求轉發到指定的 URL 上,
配置:將 http://fanguiju.com/ 反向代理到 http://www.baidu.com/,注意 “/” 可以是任意路徑,
server {
listen 80;
server_name fanguiju.com;
location / {
proxy_pass http://www.baidu.com;
}
}
測驗:
$ curl -X GET http://127.0.0.1:80/ -H "host: fanguiju.com"
...
<title>百度一下,你就知道</title>
反向代理的關鍵指令:
- proxy_set_header:指定在將客戶端請求發送給后端服務器之前,更改來自客戶端的請求頭資訊;
- proxy_connect_timeout:指定與后端代理服務器的連接超時時間;
- proxy_read_timeout:指定與后端服務器的 Read 超時時間;
- proxy_send_timeout:指定與后端服務器組的 Write 超時時間;
- proxy_redirect:指定用于修改后端服務器回傳的回應頭中的 Location 和 Refresh,
配置負載均衡

Nginx 提供了幾種負載均衡方式,默認為輪詢:
- 輪詢:按時間順序將請求逐一分配到不同的后端服務器,如果后端服務器掛了,可以自動剔除;
- weight(權重分配):指定輪詢幾率,權重越高,被訪問的概率越大,用于后端服務器性能不均的情況;
- ip_hash:每個請求按訪問 IP 的 hash 結果分配,這樣可以保證每個客戶端固定訪問到一個后端服務器,應用與 Session 等有狀態訪問的場景,
- fair(第三方):按后端服務器的回應時間分配,回應時間短的優先分配,依賴第三方插件 nginx-upstream-fair,需要先安裝;
配置:
http {
upstream server-hostname {
# ip_hash;
# fair;
server 127.0.0.1:8081;
server 127.0.0.1:8080;
server 127.0.0.1:8082 weight=10;
}
server {
listen 80;
server_name fanguiju.com;
location / {
proxy_pass http://server-hostname; # Server 的反向代理目標和 Upstream 通過 {server-hostname} 進行匹配,
proxy_connect_timeout 10;
}
}
}
配置 HTTPS
HTTPS 是在 HTTP 和 TCP 之間加上一層 TLS 加密層,
- 客戶端向服務端發送訊息時:本質上是客戶端使用服務端的公鑰來加密資訊,服務端使用自己的私鑰進行解密,
- 客戶端從服務端獲取訊息時:服務端使用自己私鑰加密,客戶端使用服務端的公鑰來解密資訊,
因為,在這個程序中,需要保證服務端發送給客戶端的公鑰不是假冒的,而證明服務端公鑰安全性的機構是 CA(數字認證中心),
可以簡單理解為:如果想證明一個人的身份是真的,就只需要證明這個人的身份證是真的,而充當 CA 就是部門機構,數字證書就相當于物理世界中的身份證,
HTTPS 證書認證流程:
- 服務端生產自己的公鑰和私鑰,并將自己的數字證書(包括:公鑰、域名、其他資訊)請求 CA 進行簽名,CA 使用自己的私鑰對數字證書進行加密,以此簽發 Server 證書,只有 CA 的公鑰(CA 證書)才能解開,
- 服務端將自己的 Server 證書發送給瀏覽器,
- 瀏覽器的 “證書管理器” 中有 “受信任的根證書頒發機構” 串列,客戶端在接收到服務端的回應后,會在這個串列里查看是否存在解開該 Server 證書的 CA 證書,有兩種錯誤情況:1)如果 CA 證書在這個串列里,但是解碼后的內容不匹配,說明 Server 證書被冒用了;如果 CA 證書不在這個串列里,說明這張 Server 證書不是受信任的機構所頒發,其真實性無法確定,
- 只要 Server 證書(證書里有服務端的公鑰)是可信的,那么 Server 公鑰就是可信的,如果一切都沒問題,瀏覽器就可以使用 CA 證書解密 Server 證書,得到 Server 的公鑰,并使用 Server 公鑰對資訊內容進行加密,然后與服務器交換資訊(已加密),
+--------------+ +------------------+
| 服務端 |---------->| 數字認證中心 (CA) |
+------+-------+ 1 X +------------------+
| / /
| / /
| / /
| / /
|2 3 / / 4
| / /
| / /
| / /
X / /
+--------------+ /
| 瀏覽器 |X
+--------------+
制作證書:詳見《互聯網協議 — TLS — 使用 OpenSSL 自建 CA中心》
配置:
# Settings for a TLS enabled server.
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name nginx1.com;
ssl_certificate "/root/nginx-cert/web.apigw.com/server.pem";
ssl_certificate_key "/root/nginx-cert/web.apigw.com/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
測驗:
$ nginx -s reload
$ netstat -lpntu | grep 443
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2996/nginx: master
tcp6 0 0 :::443 :::* LISTEN 2996/nginx: master
# 忽略 TLS 認證進行訪問
$ curl -vvv -k -X GET https://127.0.0.1:443/
nginx1.com
# 攜帶 CA 證書進行訪問,這里會報錯,因為簽發證書時系結的域名不一致,
$ curl --cacert /root/nginx-cert/ca_01.pem -X GET https://127.0.0.1:443/
curl: (51) Unable to communicate securely with peer: requested domain name does not match the servers certificate.
可見,Server 證書是簽發給某個 Domain Name 的,如果 Web Server 不是這個 Domain Name,那么就算拿到了 Server 證書也無法正常使用,這個很好理解,因為 Server 證書是簽發給某個本地設備的,其他設備無法盜用,
# 攜帶 CA 證書和 Host 進行訪問,還會報錯,說明 TLS 認證只看 URL 中的 Domain Name,
$ curl -vvv --cacert /root/nginx-cert/ca_01.pem -X GET "https://127.0.0.1:443/" -H "host: web.apigw.com"
* About to connect() to 127.0.0.1 port 443 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /root/nginx-cert/ca_01.pem
CApath: none
* Server certificate:
* subject: CN=web.apigw.com,O=Dis,ST=Denial,C=US
* start date: 1月 05 07:31:30 2021 GMT
* expire date: 1月 05 07:31:30 2022 GMT
* common name: web.apigw.com
* issuer: CN=web.apigw.com,O=Dis,L=Springfield,ST=Denial,C=US
* NSS error -12276 (SSL_ERROR_BAD_CERT_DOMAIN)
* Unable to communicate securely with peer: requested domain name does not match the servers certificate.
* Closing connection 0
curl: (51) Unable to communicate securely with peer: requested domain name does not match the server's certificate.
# 攜帶 CA 證書和 Host 進行訪問,需要將 Domain Name 切實的寫入到 URL 中才生效,
$ curl -vvv --cacert /root/nginx-cert/ca_01.pem -X GET "https://web.apigw.com:443/"
* About to connect() to web.apigw.com port 443 (#0)
* Trying 127.0.0.1...
* Connected to web.apigw.com (127.0.0.1) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /root/nginx-cert/ca_01.pem
CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=web.apigw.com,O=Dis,ST=Denial,C=US
* start date: 1月 05 07:31:30 2021 GMT
* expire date: 1月 05 07:31:30 2022 GMT
* common name: web.apigw.com
* issuer: CN=web.apigw.com,O=Dis,L=Springfield,ST=Denial,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: web.apigw.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.16.1
< Date: Tue, 05 Jan 2021 13:47:03 GMT
< Content-Type: text/html
< Content-Length: 11
< Last-Modified: Mon, 04 Jan 2021 15:28:32 GMT
< Connection: keep-alive
< ETag: "5ff33420-b"
< Accept-Ranges: bytes
<
nginx1.com
* Connection #0 to host web.apigw.com left intact
這是另外一個有趣的現象,為什么顯示的指定了 HTTP Header "host: web.apigw.com" 依舊無法建立 TLS 連接呢?這是因為 TLS 握手會發生在客戶端通過 HTTP Header host 來指示連接到某個具體的網站之前,也就是說還沒有到識別 HTTP Header host 的時候,TLS 就已經判別為 requested domain name does not match the server’s certificate. 了,所以需要在 URL 里面顯示的寫入與 Server 證書一致的 Domain Name,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/245178.html
標籤:其他
上一篇:liunx 的Centos7 NAT模式連接網路并連接到Xshell和Xftp
下一篇:介紹專案詳細開發流程:
