前一篇提到 HiNet 連不到百度 CDN,除了在客戶端開 VPN,另個解法是在雲端找台海外 VPS 裝 HTTP Proxy 當跳板。想到就做,我把它當練習題目,學會一點新東西,簡單筆記。

上回介紹過 .NET 寫的 Titanium Web Proxy,優點是擴充彈性無窮,但這回我只需要標準 HTTP Proxy 功能,追求盡可能簡單輕巧,它不是最佳人選。評估後我選中 Tinyproxy,一個用 C 撰寫的開源超輕量級 HTTP/HTTPS 代理伺服器,適用所有 POSIX 系統,資源需求極低,甚至可在嵌入式裝置上跑。其支援 CONNECT 轉送 HTTPS、透明代理、上游代理串接、網域過濾與存取控制等功能。以 Alpine 3.x 最新版當基底,映像檔可縮小到 5MB 左右,符合我愛的極簡輕巧。

問了 AI 大神,建議的 docker-compose.yml 寫法如下:

services:
  tinyproxy:
    build:
      context: .
      dockerfile_inline: |
        FROM alpine:3
        RUN apk add --no-cache tinyproxy
        EXPOSE 8888
        CMD ["tinyproxy", "-d", "-c", "/etc/tinyproxy/tinyproxy.conf"]
    image: local/tinyproxy
    container_name: tinyproxy
    restart: unless-stopped
    ports:
      - "8888:8888"
    volumes:
      - ./tinyproxy.conf:/etc/tinyproxy/tinyproxy.conf:ro
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

跟著學到現場 Build Docker 映像檔的技巧,AI 的理由是 Docker Hub 上的 tinyproxy 映像多是個人維護,更新頻率和可信度存疑,用 Alpine 官方映像和官方套件庫現點現做更安心。

第一次 docker compose up 時 Compose 發現本機沒有 local/tinyproxy 映像會用 dockerfile_inline 內容現場製作 - 拉取 alpine:3,執行 apk add tinyproxy,大約十幾秒便可完成。

之後再執行 up 會直接沿用建好的 local/tinyproxy,不需重新重置。想更新則可用 docker compose up -d --build,抓取最新的 Alpine 基底和 tinyproxy 套件。

(若不介意拉取網友做的映像,可試試 vimagick/tinyproxy,但要先確認其設定檔路徑和啟動參數自行調整)

Tinyproxy 設定寫在 tinyproxy.conf,應用時建議仔細確認 IP 管控與身分認證有設好,我的 VPS 外層已有防火牆限定家中對外 IP,故 Tinyproxy 可設 0.0.0.0/0,若沒有這層,建議用白名單列舉存取來源 IP 或設帳號密碼,以免主機被駭客當跳板。

Port 8888
Listen 0.0.0.0
Timeout 600

# 日誌輸出到 stdout(docker logs 可看)
LogLevel Info

MaxClients 100

# 策略一 雲端或 Reverse Proxy 已設防火牆 (注意:務必確認設定以防惡意利用)
Allow 0.0.0.0/0

# 策略二 由 TinyProxy 限定可存存來源 IP ──
# Allow 127.0.0.1
# Allow 192.168.0.0/16
# Allow 10.0.0.0/8
#Allow 172.16.0.0/12
# Allow 1.2.3.4          # 合法客戶端的對外 IP

# ── 帳號認證(架在公網時建議開啟)──
# BasicAuth myuser mypassword

# HTTPS 走 CONNECT,只放行 443
ConnectPort 443

# 不洩漏代理資訊
DisableViaHeader Yes

然後,過去我只會在從瀏覽器設 HTTP Proxy 跟排除網站名單,Chrome/Edge/Firefox/手機需個別設定,若要修改就煩了(例如增加排除網站)。又跟 AI 偷學一招:.pac 代理自動設定檔,概念是用 proxy.pac 檔寫 JavaScript 函式 FindProxyForURL(url, host),依網址或主機回傳 PROXY host:port、SOCKS 或 DIRECT,決定連線走代理或直連,多個值以分號分隔可作備援。將這個檔案放在用戶端可連到的 HTTPS 網址,在瀏覽器設定 PAC 網址即可。

function FindProxyForURL(url, host) {
  if (isPlainHostName(host) || dnsDomainIs(host, ".corp.local"))
    return "DIRECT";
  return "PROXY 192.168.1.10:8888; DIRECT";
}

以下是 Windows Edge/Chrome 的設定方式:

而針對本次案例,我設定只針對百度 CDN 改走代理,其餘直接,proxy.pac 寫法如下。未來若需增加,只需修改一個地方,所有客戶端一次更新,這才是優雅的管理方式,又學到新東西囉~

// 只讓百度靜態資源、下載走 proxy,其餘直連
function FindProxyForURL(url, host) {
  var PROXY = "PROXY <tiny-proxy-ip>:8888";

  if (dnsDomainIs(host, ".bdstatic.com") ||
      dnsDomainIs(host, ".bcebos.com") ||
      dnsDomainIs(host, ".baidupcs.com") ||
      dnsDomainIs(host, ".bdimg.com")) {
    return PROXY + "; DIRECT";
  }
  return "DIRECT";
}


Comments

Be the first to post a comment

Post a comment