基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

boborz發表於2019-03-01

實際環境

  • 系統環境 macOS Sierra(10.12.5)
  • Apache Apache/2.4.25 (Unix)
  • OpenSSL OpenSSL 1.0.2l

引言

Mac系統預設安裝了Apache伺服器,你只需要在終端裡輸入sudo apachectl start命令,然後開啟瀏覽器,輸入網址http://localhost/index,顯示如下圖:

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

恭喜你,一個HTTP伺服器已經搭建成功了!是不是很簡單?接下來介紹如何具體定製化配置Apache伺服器。

搭建HTTP伺服器

  • 修改伺服器預設根路徑
    開啟配置檔案/private/etc/apache2/httpd.conf,更改系統預設的根路徑DocumentRoot為自定義路徑(因為系統預設的根路徑要求管理員許可權,更改比較繁瑣,如果需要用系統預設的根路徑,可以跳過此步驟)。
DocumentRoot "/Users/libo/apache_server"
<Directory "/Users/libo/apache_server">
複製程式碼
  • 設定虛擬主機
    通過設定多個虛擬主機可以支援一臺物理伺服器訪問多個域名,就好像有多個伺服器一樣。開啟配置檔案/private/etc/apache2/httpd.conf,去掉#Include /private/etc/apache2/extra/httpd-vhosts.conf前面的#,儲存並退出。然後開啟/private/etc/apache2/extra/httpd-vhosts.conf,註釋掉以下程式碼:
#<VirtualHost *:80>
#    ServerAdmin webmaster@dummy-host.example.com
#    DocumentRoot "/usr/docs/dummy-host.example.com"
#    ServerName dummy-host.example.com
#    ServerAlias www.dummy-host.example.com
#    ErrorLog "/private/var/log/apache2/dummy-host.example.com-error_log"
#    CustomLog "/private/var/log/apache2/dummy-host.example.com-access_log" common
#</VirtualHost>

#<VirtualHost *:80>
#    ServerAdmin webmaster@dummy-host2.example.com
#    DocumentRoot "/usr/docs/dummy-host2.example.com"
#    ServerName dummy-host2.example.com
#    ErrorLog "/private/var/log/apache2/dummy-host2.example.com-error_log"
#    CustomLog "/private/var/log/apache2/dummy-host2.example.com-access_log" common
#</VirtualHost>
複製程式碼

然後加入以下程式碼:

<VirtualHost *:80>
    # ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "/Users/libo/apache_server/mywebsite"
    ServerName mywebsite.com
    ErrorLog "/private/var/log/apache2/mywebsite.com-error_log"
    CustomLog "/private/var/log/apache2/mywebsite.com-access_log" common

    <Directory />
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order deny,allow
                Allow from all
    </Directory>

</VirtualHost>

<VirtualHost *:80>
    # ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "/Users/libo/apache_server/mywebsite2"
    ServerName mywebsite2.com
    ErrorLog "/private/var/log/apache2/mywebsite2.com-error_log"
    CustomLog "/private/var/log/apache2/mywebsite2.com-access_log" common

    <Directory />
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order deny,allow
                Allow from all
    </Directory>
   
</VirtualHost>
複製程式碼

我們也配置兩個虛擬主機,因為HTTP不顯式指定訪問埠號時預設為80號埠,為了訪問方便,我們設定伺服器訪問埠號為80,當然你也可以設定其它埠號,比如8080,這時還需要配置httpd.conf,加入Listen 8080。但有些埠有特殊意義,不能隨便設定,比如443埠號預設是HTTPS訪問埠。
<Directory /></Directory>之間的配置是一些比較細化的伺服器配置選項,AllowOverride all是允許覆蓋所有的檔案,Order deny,allow是命令的兩種型別,Allow from all是允許所有的客戶端(或代理)訪問本伺服器,你也可以配置
Allow from #IPDeny from #IP來控制允許或者禁止特定的IP訪問伺服器。

注意:兩個虛擬主機的根路徑必須在伺服器根路徑下。

  • 更改本地DNS配置檔案
    開啟配置檔案/private/etc/hosts,把我們的伺服器域名對應到回送地址127.0.0.1上,這樣就可以直接本地進行域名訪問。檔案前3行配置是系統預設配置,我們平時訪問的localhost就是通過該檔案直接解析成對應的IP地址進行本地訪問的,其中127.0.0.1IPv4標準,::1IPv6標準。其實我們平時通過域名訪問網址時,都會首先訪問這個本地的hosts檔案來查詢IP地址,如果找不到對應的結果才會訪問DNS伺服器進行DNS解析來進行後續的步驟。
    配置程式碼如下:
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost
127.0.0.1       mywebsite.com
127.0.0.1       mywebsite2.com
複製程式碼
  • 驗證
    最後我們在配置的伺服器根路徑下加入測試的HTML檔案來進行測試,結果如下:
基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器
基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

說明我們的HTTP伺服器已經配置成功了!

搭建HTTPS伺服器

我們只需要在HTTP伺服器的基礎上配置HTTPS就可以了。

  • 建立自簽名SSL/TLS證照
    首先使用OpenSSL建立私鑰檔案
openssl genrsa -out mywebsite.key 2048
複製程式碼

然後利用私鑰建立自簽名證照

openssl req -new -x509 -key mywebsite.key -out mywebsite.cer
複製程式碼

需要自己填寫一些證照資訊,如下圖:

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

紅框標註選項最好填寫虛擬主機域名,如果不按要求填寫也可以使用,同理我們建立另一個虛擬主機mywebsite2.com證照。

  • 修改伺服器配置
    去掉#Include /private/etc/apache2/extra/httpd-ssl.conf前面的#,
    去掉#LoadModule ssl_module libexec/apache2/mod_ssl.so前面的#,
    去掉#LoadModule socache_shmcb_module libexec/apache2/mod_socache_shmcb.so前面的#

  • 修改httpd-ssl.conf配置
    開啟/private/etc/apache2/extra/httpd-ssl.conf檔案,找到對應的SSLCertificateFileSSLCertificateKeyFile欄位,加入如下程式碼:

SSLCertificateFile "/Users/libo/apache_server/mywebsite/mywebsite.cer"
SSLCertificateFile "/Users/libo/apache_server/mywebsite2/mywebsite2.cer"
複製程式碼
SSLCertificateKeyFile "/Users/libo/apache_server/mywebsite/mywebsite.key"
SSLCertificateKeyFile "/Users/libo/apache_server/mywebsite2/mywebsite2.key"
複製程式碼
  • 修改虛擬主機配置
    更改虛擬主機預設埠號為443,配置伺服器證照SSLCertificateFile和私鑰SSLCertificateKeyFile,如下:
<VirtualHost *:443>
    # ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "/Users/libo/apache_server/mywebsite"
    ServerName mywebsite.com
    ErrorLog "/private/var/log/apache2/mywebsite.com-error_log"
    CustomLog "/private/var/log/apache2/mywebsite.com-access_log" common

    SSLCertificateFile    "/Users/libo/apache_server/mywebsite/mywebsite.cer"
    SSLCertificateKeyFile "/Users/libo/apache_server/mywebsite/mywebsite.key"

    <Directory />
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order deny,allow
                Allow from all
    </Directory>

</VirtualHost>

<VirtualHost *:443>
    # ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "/Users/libo/apache_server/mywebsite2"
    ServerName mywebsite2.com
    ErrorLog "/private/var/log/apache2/mywebsite2.com-error_log"
    CustomLog "/private/var/log/apache2/mywebsite2.com-access_log" common

    SSLCertificateFile    "/Users/libo/apache_server/mywebsite2/mywebsite2.cer"
    SSLCertificateKeyFile "/Users/libo/apache_server/mywebsite2/mywebsite2.key"

    <Directory />
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order deny,allow
                Allow from all
    </Directory>

</VirtualHost>
複製程式碼
  • 驗證
    重啟伺服器sudo apachectl restart,瀏覽器訪問,如下圖:
基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器
基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

可以看到我們的HTTPS伺服器已經搭建成功了,儘管不是“安全”的訪問!接下來我們要進行一些操作使訪問變得“安全”。

  • 建立安全的HTTPS訪問
    所謂建立安全的HTTPS訪問,就是讓瀏覽器信任伺服器頒發的公鑰證照,因為我們的證照沒有新增到瀏覽器信任列表,所以瀏覽器會提示我們“不安全”。廢話不多說,首先建立CA根證照:

建立CA私鑰:

openssl genrsa -des3 -out Apache_CA.key 2048
複製程式碼

這裡使用-des3進行加密,需要4~1023位密碼。

建立CA證照:

openssl req -new -x509 -days 365 -key Apache_CA.key  -out Apache_CA.cer
複製程式碼

這裡需要輸入剛才設定的CA私鑰密碼並填寫一些證照資訊。

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

建立伺服器證照私鑰:

openssl genrsa -out mywebsite.key 2048
複製程式碼

生成證照請求檔案CSR:

openssl req -new -key mywebsite.key -out mywebsite.csr
複製程式碼

這裡同樣需要填寫一些證照資訊,同樣,紅框標註選項最好填寫虛擬主機域名

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

生成證照配置檔案v3.ext:

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = mywebsite.com
複製程式碼

DNS.1要寫配置證照的伺服器域名。

用自己的CA簽發證照:

openssl x509 -req -in mywebsite.csr -CA Apache_CA.cer -CAkey Apache_CA.key -CAcreateserial -out mywebsite.cer  -days 365 -sha256 -extfile v3.ext
複製程式碼

然後需要輸入生成Apache_CA.key時設定的密碼。

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

恭喜你,證照已經建立成功!然後我們按照前面提到的步驟替換掉伺服器的證照,重啟伺服器sudo apachectl restart

設定系統始終信任CA證照:
雙擊點開Apache_CA.cer ,然後在鑰匙串中找到該證照,右鍵->顯示簡介->信任,設定為始終信任。然後分別再次訪問網址https://mywebsite.com/indexhttps://mywebsite2.com/index。訪問結果如下:

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器
基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

恭喜你!mywebsite.com伺服器的訪問已經變成“安全”的了,同理可以配置mywebsite2.com伺服器。但是,你要注意一點,這種“安全”只是相對的安全,或者說是一種假象,因為你的CA證照是自己建立頒發的,別人也可以通過竊取你的CA私鑰或者其他方式來偽造證照。更為穩妥的辦法還是要向正規的證照頒發機構去申請私鑰和證照,這點一定要注意。

搭建正向代理伺服器

在搭建正向代理伺服器之前,我們先說下正向代理和反向代理的區別。我們平時訪問網上的資源,絕大多數情況是要經過各種(正向或反向或其他)代理的,只是這對使用者來說是無感知的。正向代理可以理解為一層跳板,我們訪問資源的目的IP地址是伺服器,只是經過正向代理這個節點。而反向代理是我們訪問資源的目的IP地址就是反向代理伺服器,反向代理伺服器和最終的伺服器進行互動,獲取資源。下圖可以很清晰的展示這兩種關係:

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器
基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

下面我們開始配置正向代理伺服器。

  • 修改伺服器配置
    開啟配置檔案/private/etc/apache2/httpd.conf,去掉以下module前面的#
#LoadModule proxy_module libexec/apache2/mod_proxy.so
#LoadModule proxy_connect_module libexec/apache2/mod_proxy_connect.so
#LoadModule proxy_ftp_module libexec/apache2/mod_proxy_ftp.so
#LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so
複製程式碼

通過以上module的命名我們可以瞭解到mod_proxy.so是基礎的代理配置,mod_proxy_http.so支援HTTP請求,mod_proxy_ftp.so支援FTP請求,mod_proxy_connect.so支援HTTPS請求(HTTPS請求頭和報文是加密的,代理伺服器不能通過識別請求頭來獲取目的伺服器的地址,所以在最開始建立連線時代理伺服器需要開啟一條從客戶端到伺服器的端到端connect通道)。

  • 修改虛擬主機配置
    將虛擬主機埠號改為80,加入正向代理設定。
<VirtualHost *:80>
    # ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot "/Users/libo/apache_server/mywebsite"
    ServerName mywebsite.com
    ErrorLog "/private/var/log/apache2/mywebsite.com-error_log"
    CustomLog "/private/var/log/apache2/mywebsite.com-access_log" common

    SSLCertificateFile    "/Users/libo/apache_server/mywebsite/mywebsite.cer"
    SSLCertificateKeyFile "/Users/libo/apache_server/mywebsite/mywebsite.key"

    <Directory />
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order deny,allow
                Allow from all
    </Directory>

    #正向代理設定
    ProxyRequests On
    ProxyVia Full

    <Proxy *>
        Order deny,allow
        #Deny from all
        Allow from all
    </Proxy>

</VirtualHost>
複製程式碼

ProxyVia Full可以為我們打出最詳細的代理伺服器資訊。

  • 建立自動代理配置
    為了方便測試,我們建立mywebsite.pac檔案來配置代理。
function FindProxyForURL(url, host) {
    if (host == "www.jianshu.com") {
        return "PROXY 127.0.0.1:80";
    }
    return `DIRECT;`;
}
複製程式碼

我們有選擇的只要求訪問簡書www.jianshu.com域名時經過我們的代理伺服器,其他域名進行DIRECT直連。

  • 配置代理配置
    開啟系統偏好設定**->網路->高階->代理,選中自動代理配置,配置mywebsite.pac檔案的路徑地址,然後點選好->**應用。

  • 驗證
    瀏覽器開啟簡書首頁http://www.jianshu.com/,開啟開發者模式:

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

通過Via欄位,我們發現這次請求經過了我們的代理伺服器,說明我們的配置成功了!

搭建反向代理伺服器

  • 修改伺服器配置
    我們需要用PHP指令碼來測試反向代理,Apache伺服器自身支援PHP,只需要開啟配置檔案/private/etc/apache2/httpd.conf,去掉#LoadModule php5_module libexec/apache2/libphp5.so前面的#

  • 修改虛擬主機配置
    我們把mywebsite.commywebsite2.com的預設埠號改為80,讓mywebsite2.com作為反向代理伺服器,mywebsite.com作為原始伺服器,通過訪問反向代理伺服器間接訪問原始伺服器資源。配置程式碼如下:

<VirtualHost *:80>
    # ServerAdmin webmaster@dummy-host2.example.com
    DocumentRoot "/Users/libo/apache_server/mywebsite2"
    ServerName mywebsite2.com
    ErrorLog "/private/var/log/apache2/mywebsite2.com-error_log"
    CustomLog "/private/var/log/apache2/mywebsite2.com-access_log" common

    SSLCertificateFile    "/Users/libo/apache_server/mywebsite2/mywebsite2.cer"
    SSLCertificateKeyFile "/Users/libo/apache_server/mywebsite2/mywebsite2.key"

    <Directory />
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order deny,allow
                Allow from all
    </Directory>

    #反向代理設定
    ProxyPass / http://mywebsite.com/
    ProxyPassReverse / http://mywebsite.com/

</VirtualHost>
複製程式碼

ProxyPass / http://mywebsite.com/是把所有訪問當前主機http://mywebsite2.com/的請求轉發給http://mywebsite.com/主機,至於ProxyPassReverse / http://mywebsite.com/的作用,我們稍後再說。

  • 驗證
    我們在"/Users/libo/apache_server/mywebsite"路徑下建立兩個PHP檔案:

redirect.php

<?php

	 function redirect($url)
	 {
    	header("Location: $url");
   	exit();
    }

    $url = "http://mywebsite.com/test.php";
    redirect($url);
   
?>
複製程式碼

test.php

<?php

phpinfo();
   
?>
複製程式碼

重啟伺服器,訪問http://mywebsite2.com/redirect.php

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

可以看到請求的Request URLhost還是mywebsite2.com,但是它確實是由 mywebsite.com來處理的,通過訪問mywebsite.com資源redirect.php檔案,進而重定向到test.php檔案。說明我們反向代理伺服器已經搭建成功了!

現在我們介紹下ProxyPassReverse的作用,我們把配置檔案的這一項配置去掉,重啟伺服器再次訪問http://mywebsite2.com/redirect.php

基於Apache搭建HTTP HTTPS 正向代理 反向代理伺服器

和上圖對比可以看到請求的Request URLhostmywebsite.com而不是 mywebsite2.com,這是因為配置了ProxyPassReverse後,mywebsite.com/redirect.php在重定向到mywebsite.com/test.php時,Apache會將它調整回 mywebsite2.com/test.php, 然後Apache再將mywebsite2.com/test.php 轉發給mywebsite.com/test.php。所以說配置了ProxyPassReverse後,即使在請求過程中發生了重定向,Apache也會幫你擦去這些痕跡

總結

以上都是我對Apache伺服器的基礎配置,簡單的實現了預期功能。伺服器配置很細碎繁瑣,能根據不同程式碼實現更為複雜精細的配置,更為詳細的功能具體請參考官方文件,本人沒有做深入研究。本文如有錯誤,希望指正,一起學習,共同進步,不勝感激!

參考連結

www.liuchungui.com/blog/2015/0…
beyondvincent.com/2014/03/17/…
www.cnblogs.com/zemliu/arch…
httpd.apache.org/docs/2.4/

相關文章