如何用 Nginx 配置透明 HTTP 和 HTTPS 代理?

簡單的
server{
proxy_pass http://$1
}
配置無法支持HTTPS。


作為 web server nginx 當然是可以處理 ssl 的,但作為 proxy 則是不行的。
因為 nginx 不支持 CONNECT,收到 「CONNECT /:443 HTTP/1.1」 後會報一個包含「client sent invalid request while reading client request line,」 的錯誤。
因為 CONNECT 是正向代理的特性,據官方說(https://forum.nginx.org/read.php?2,15124,15256)也沒有計劃支持(見下圖)。

如果覺得 squid 比較難上手,也不夠輕量,可以試試類似的。

以下都支持 http/https,
trafficserver Apache Traffic Server Manual
tinyproxy Tinyproxy

基於 Python 的:
exaproxy http://code.google.com/p/exaproxy/
mitmproxy http://mitmproxy.org/
tinyhttpproxy Tiny HTTP Proxy in Python 就一個文件,06年以後就沒有更新了

還有跨平台且有GUI的 Charles Charles Web Debugging Proxy ? HTTP Monitor / HTTP Proxy / HTTPS SSL Proxy / Reverse Proxy

Charles 實在是太棒了!但還是不如fiddler方便,前者還是更側重 抓包而不是代理,還是 fiddler 更強大些。如果有條件還是在 windows 上開 fiddler 的代理吧。

2017/10/3 更:

如果就想用 nginx 做正向代理,可以參考評論中的選擇 https://github.com/chobits/ngx_http_proxy_connect_module


HTTP代理存在兩種。

一種是基於RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing以及其他相關RFC文檔中描述的普通代理,代理伺服器充當的是一個中間的組件,通過在請求URI設置的對應authority來指定目標伺服器。

另一種是基於RFC 2817 - Upgrading to TLS Within HTTP/1.1的5.2 Requesting a Tunnel with CONNECT(draft-luotonen-web-proxy-tunneling-01原草案)實現的TCP隧道代理。與上面的區別就在於「TCP隧道」,這種代理可以以HTTP協議的方式來實現理論上任意TCP之上的應用層協議代理,兩端之間的通訊都是在HTTP的body部分完成的。因此就可以完成基於TLS的HTTPS通訊,被加密過的數據直接在body中傳輸。

Nginx不支持第二種代理,因此不能完成https代理。Nginx的作者對於這個功能有明確的回復(http://forum.nginx.org/read.php?2,15124,15256),表示不會在近期實現,並且推薦使用Squid。

Not in near future: there is alreay good forward proxy Squid.

搭建Squid代理可以參考我寫的教程:使用Squid搭建HTTPS代理伺服器。


A. 把SSL證書和中級根證書拷貝到Apache存放證書的目錄中,如: /etc/httpd/conf/ssl.crt/
a. Copy the certificate and Intermediate CA Certificate to the Apache directory in which you plan to store your certificates (example: /etc/httpd/conf/ssl.key/ or /etc/httpd/conf/ssl.crt/).

B.使用文本編輯器打開http.conf文件,添加如下3行參數(如果沒有的話)
b. Open the Apache httpd.conf file in a text editor (notepad/vi). Locate the SSL VirtualHost associated with your certificate. Verify that you have the following 3 directives within this virtual host. Please add them if they are not present:

SSLCertificateKeyFile /where/the/key/is/located/http://www.mydomain.com.key
SSLCertificateFile
/where/the/certificate/is/located/http://www.mydomain.com.crt
SSLCACertificateFile /where/the/certificate/is/located/intermediate.crt

請注意: Apache中含有https.conf和ssl.conf兩個功能相同的文件,請只修改其中一個文件,否則會有衝突而使得Apache不能正常啟動。
Note that some instances of Apache contain both a httpd.conf and ssl.conf file. Please enter or amend the httpd.conf or the ssl.conf with the above directives. Do not enter the information in both as there will be a conflict and Apache will not start.

c. 保存修改。 Save the changes and exit the editor.

d. 使用如下命令停止Apache後再啟動Apache,以便Apache daemon能註冊修改的參數。
Stop and start the Apache daemon which will register the changes that have been made in the config file. You can use the following commands:
/usr/sbin/apachectl stop /usr/sbin/apachectl startssl
or:
/usr/sbin/httpd -k stop /usr/sbin/httpd -DSSL


[08/Jul/2014:12:58:31 +0800] "CONNECT http://www.alipay.com:443 HTTP/1.1" 400 571 "-" "-"

嗯嗯.正向代理.不支持https


server{
listen 80;
listen 443 default ssl;
...
ssl on;
ssl_certificate /path/to/crt;

ssl_certificate_key /path/to/key;

...
}
nginx接受https請求,與後端無關.


通過Nginx配置https確實麻煩,而且很多時候還是Apache方便。我就從Apache方面談下我的認識吧。

這個問題折騰我好幾天,最後發現配置下來也不過如此。總的來說,有三個步驟:

1. 申請CA證書。我用的是阿里雲上的免費證書,申請後通過審核就可以打包下載,下載後解壓內容到Apache下的cert目錄,沒有的話新建一個。2. 修改Apache的httpd.conf文件。httpd中查找並修改兩條內容:

LoadModule ssl_module modules/mod_ssl.so
Include conf/extra/httpd-ssl.conf

3. 修改conf/extra/httpd-ssl.conf文件。網上好多文章都沒有提到要修改 & 節點的內容,而如果沒有修改該節點那麼你是不能配置成功的。主要需要修改SSLProtocol、SSLCipherSuite、SSLCertificateFile、SSLCertificateKeyFile、SSLCertificateChainFile幾項內容。修改完成後重啟,然後就能使用了https協議了,不多說上圖吧。

還有不清楚的地方可以看這篇文章:互聯網工作者 intnetworker, 進行查看。


推薦閱讀:

Epoll的EPOLLOUT事件的一些疑問?
運維工程師必須掌握的基礎技能有哪些?
Linux 如何才能吸引軟體廠商為之開發軟體?

TAG:Linux | HTTPS | Nginx | HTTP |