1. 程式人生 > 程式設計 >使用 Apache 搭建 VPC 伺服器代理

使用 Apache 搭建 VPC 伺服器代理

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要註明來源。 署名 4.0 國際 (CC BY 4.0)

本文作者: 蘇洋

建立時間: 2019年08月10日 統計字數: 2779字 閱讀時間: 6分鐘閱讀 本文連結: soulteary.com/2019/08/10/…


使用 Apache 搭建 VPC 伺服器代理

有的小夥伴或許沒有使用過 VPC 網路下的伺服器,在該網路環境下,伺服器預設沒有公網 IP ,所以使用者無法訪問到伺服器。一般策略是使用 SLB 進行入網流量代理,這樣使用者就能從公網訪問伺服器上的應用了。

但是這樣只能解決流量進入的問題,並解決不了 VPC 環境下的內網機器訪問公網資源的問題,給每一臺機器單獨分配 IP 顯然不是最優解,這時我們一般會選擇使用某一臺伺服器作為出口,搭建代理伺服器。

使用容器配置 Apache 代理伺服器

為內網環境伺服器搭建代理伺服器,我們一般會優先選擇 Apache Traffic Server ,但是其實使用 Apache 也可以簡單的解決問題。

相比較 Traffic Server,使用 Apache 作為代理伺服器非常簡單。容器編排檔案 docker-compose.yml 只需要 22 行:

version: "3.6"

services:

  proxy:
    image: httpd:2.4.39-alpine
    restart: always
    container_name: network-proxy
    ports:
      - 1080:80
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./httpd.conf:/usr/local
/apache2/conf/httpd.conf healthcheck: test: ["CMD-SHELL","httpd -T"] interval: 5s retries: 12 logging: driver: "json-file" options: max-size: "10m" 複製程式碼

Apache 配置檔案 httpd.conf也無需像網上配置那麼複雜,只需要下面這30來行就行:

ServerName localhost
Listen 80

LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_http2_module modules/mod_proxy_http2.so
LoadModule unixd_module modules/mod_unixd.so

User daemon
Group daemon

ErrorLog /proc/self/fd/2
LogLevel warn

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
combined LogFormat "%h %l %u %t \"%r\" %>s %b" common CustomLog /proc/self/fd/1 common ProxyRequests On ProxyVia On <Proxy *> Order deny,allow Deny from all Allow from 192.168.0.0/24 </Proxy> 複製程式碼

如果你和我一樣,明確代理伺服器的服務目標,可以在 <Proxy> 配置中將其宣告,避免服務被盜用,當然,推薦搭配防火牆安全策略一起使用,萬無一失。

使用 docker-compose up 啟動應用,會看到類似下面的日誌:

network-proxy | [Sat Aug 10 15:32:06.652264 2019] [mpm_event:notice] [pid 1:tid 140135351733576] AH00489: Apache/2.4.39 (Unix) configured -- resuming normal operations
network-proxy | [Sat Aug 10 15:32:06.652318 2019] [core:notice] [pid 1:tid 140135351733576] AH00094: Command line: 'httpd -D FOREGROUND'
複製程式碼

看日誌服務確實是啟動起來了,但是是否有效不得而知,所以我們要進行測試。

測試服務

在另外一臺伺服器上使用 curl 測試代理伺服器是否正常工作,如果能否正常使用,結果會類似下面這樣:

# http_proxy=http://192.168.0.50:1080 curl http://cip.cc/
IP	: 39.xxx.xxx.xxx
地址	: 中國  北京
運營商	: 阿里雲/電信/聯通/移動/鐵通/教育網
資料二	: 香港 | 特別行政區
資料三	: 中國北京北京市 | 阿里雲

URL	: http://www.cip.cc/39.xxx.xxx.xxx
複製程式碼

配置伺服器

讓伺服器預設出公網的流量走代理伺服器很簡單,只需要在 /etc/profile 配置檔案中新增兩行即可:

export http_proxy=http://192.168.0.50:1080
export https_proxy=http://192.168.0.50:1080
複製程式碼

對 profile 檔案進行修改後,需要手動過載檔案:

source /etc/profile
複製程式碼

或者斷開當前的終端連線,重新連線伺服器,也可以讓配置生效。再次使用 curl 對代理伺服器進行驗證,會看到預設出公網的流量會先經過代理伺服器。

# curl -v https://www.baidu.com
* Rebuilt URL to: https://www.baidu.com/
*   Trying 192.168.0.50...
* TCP_NODELAY set
* Connected to 192.168.0.50 (192.168.0.50) port 1080 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to www.baidu.com:443
> CONNECT www.baidu.com:443 HTTP/1.1
> Host: www.baidu.com:443
> User-Agent: curl/7.58.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection Established
< Proxy-agent: Apache/2.4.39 (Unix)
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* ALPN,offering h2
* ALPN,offering http/1.1
複製程式碼

配置容器服務

Docker 官方檔案中有提過 ,如果想要 Docker Daemon 使用系統代理配置,需要在其啟動之前進行配置,所以配置 daemon.json 大法在此處就不適用啦。

解決方法是覆蓋預設的 docker.service 配置檔案,先建立一個服務配置目錄:

sudo mkdir -p /etc/systemd/system/docker.service.d
複製程式碼

然後建立一個檔案並編輯檔案內容 /etc/systemd/system/docker.service.d/http-proxy.conf ,新增環境變數:

[Service]

Environment="HTTP_PROXY=http://192.168.0.50:1080"
Environment="HTTPS_PROXY=http://192.168.0.50:1080"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.0.0/24,*.domain.ltd"
複製程式碼

接著重啟服務:

sudo systemctl daemon-reload && sudo systemctl restart docker
複製程式碼

最後,使用 docker pull 命令驗證配置是否正常:

# docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
050382585609: Already exists
Digest: sha256:6a92cd1fcdc8d8cdec60f33dda4db2cb1fcdcacf3410a8e05b3741f44a9b5998
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
複製程式碼

配置容器內部環境

如果不進行容器內部網路配置,使用容器訪問公網服務,基本會遇到網路超時:

docker run --rm -it alpine

/ # apk update
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.10/main: network error (check Internet connection and firewall)
WARNING: Ignoring APKINDEX.00740ba1.tar.gz: No such file or directory
複製程式碼

Docker 官方檔案其實也有提過 ,解決方案的原理是:通過編輯 ~/.docker/config.json Docker 客戶端配置檔案,來為容器自動注入 PROXY 環境變數。

{
    "proxies": {
        "default": {
            "httpProxy": "http://192.168.0.50:1080","httpsProxy": "http://192.168.0.50:1080","noProxy": "127.0.0.1,localhost,*.domain.ltd"
        }
    }
}
複製程式碼

將上述配置新增好之後,無須重啟容器服務,直接再次執行命令即可:

# docker run --rm -it alpine

/ # apk update
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
v3.10.1-62-g89778c626e [http://dl-cdn.alpinelinux.org/alpine/v3.10/main]
v3.10.1-60-gb0081284ea [http://dl-cdn.alpinelinux.org/alpine/v3.10/community]
OK: 10337 distinct packages available
複製程式碼

至此,VPC 環境下的伺服器和容器訪問外網就設定完畢啦。

最後

別忘記設定防火牆規則,伺服器訪問公網的 IP 不允許入網流量,減少伺服器對外安全隱患。

—EOF


我現在有一個小小的折騰群,裡面聚集了一些喜歡折騰的小夥伴。

在不發廣告的情況下,我們在裡面會一起聊聊軟體、HomeLab、程式設計上的一些問題,也會在群裡不定期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼新增好友。(請註明來源和目的,否則不會通過稽核)

關於折騰群入群的那些事