在 Linux 伺服器上,我們常會遇到 curl 訪問失敗、git clone 過慢、dnf/apt/pip 下載緩慢、程式只支援 HTTP 代理而你有 SOCKS5、Docker 拉取映像失敗,甚至希望所有流量自動走代理等問題。這些問題雖然都被稱作“設定代理”,但實際上涉及完全不同的網路層。

核心認知:Linux 不存在一個能讓所有程式自動走代理的統一開關。你設定的可能是某個程式的參數、Shell 環境變數、通過 LD_PRELOAD 攔截 socket,或是路由層的 TUN/TPROXY。理解這一點,才能真正掌握代理設定。


1. 基礎概念:代理型別與環境變數

1.1 常見代理協定

HTTP Proxy

  • 埠通常為 8080 或 3128。
  • 可代理 HTTP 和 HTTPS 流量。對於 HTTPS,用戶端先傳送 CONNECT example.com:443 建立 TCP 隧道,隨後 TLS 在用戶端與目標之間直接協商,代理只負責轉發加密位元組流。
  • 需要用戶端顯式設定,不支援 UDP。

HTTPS Proxy(HTTP over TLS)

  • 指的是用戶端與代理伺服器之間的通訊使用 TLS 加密,即代理地址為 https://proxy.example.com:8080
  • 底層協定仍然是 HTTP Proxy(CONNECT 方法),但連線代理時經過 TLS 握手,防止中間人窺探。
  • 許多 CLI 工具(如 curl)支援 https_proxy 變數指向 https://... 地址。

SOCKS5 Proxy

  • 埠通常為 1080。
  • 更通用,支援 TCP 和 UDP,不關心應用層協定,適合任意 TCP/UDP 流量(如 SSH、資料庫、遊戲)。
  • 關鍵 DNS 區分
    • socks5://:DNS 解析在本地進行。
    • socks5h://:DNS 解析交給代理伺服器h 表示 hostname)。推薦使用此方式避免本地 DNS 洩露或汙染。

Shadowsocks

  • 一種基於 SOCKS5 的輕量級安全代理協定,廣泛用於穿越防火牆。
  • Linux 用戶端 ss-local 會在本機建立一個標準的 SOCKS5 代理(預設 127.0.0.1:1080):
    ss-local -s server.example.com -p 8388 -l 1080 -k your_password -m aes-256-gcm
  • 之後所有支援 SOCKS5 的程式都可使用 127.0.0.1:1080
  • 相關工具還包括 ss-redir(透明代理)和 ss-tunnel(埠轉發)。

1.2 環境變數詳解(大小寫與 no_proxy

Linux 下大量 CLI 工具(curl、Git、pip、apt、wget 等)遵循以下環境變數,但不同程式的支援程度和大小寫敏感度不同

變數名(小寫)變數名(大寫)作用
http_proxyHTTP_PROXY訪問 HTTP 網址時使用的代理
https_proxyHTTPS_PROXY訪問 HTTPS 網址時使用的代理(值可為 http://https://
all_proxyALL_PROXY訪問任意協定時使用的代理(通常設為 SOCKS5)
no_proxyNO_PROXY不走代理的地址列表(逗號分隔)

大小寫陷阱

  • 優先使用小寫curl 出於安全考慮,會忽略大寫 HTTP_PROXY(防止子行程意外繼承),因此建議至少保證小寫變數存在。
  • 為了相容更多程式(如某些 Java 工具、舊版軟體),可以同時匯出大寫版本:
    export http_proxy="http://127.0.0.1:8080"
    export HTTP_PROXY="$http_proxy"
    export https_proxy="http://127.0.0.1:8080"
    export HTTPS_PROXY="$https_proxy"
    export all_proxy="socks5h://127.0.0.1:1080"
    export ALL_PROXY="$all_proxy"

關於 https_proxy=http://...:這不是寫錯。https_proxy 表示“訪問 HTTPS URL 時使用的代理”,而後面的 http://127.0.0.1:8080 表示與代理通訊時使用 HTTP Proxy 協定(而非 SOCKS),兩者完全合理。

no_proxy 匹配規則

  • 示例:no_proxy="localhost,127.0.0.1,.example.com,192.168.0.0/16"
  • 不同程式匹配規則可能不一致(是否支援萬用字元、CIDR、域名字尾)。例如,.example.com 是否匹配 foo.example.com,需查閱具體說明文件,不要想當然。

2. 搭建代理伺服器

在使用代理之前,你首先需要“擁有”一個代理伺服器。以下介紹三種常見搭建方式,覆蓋從極簡到生產級的需求。

2.1 極簡方案:SSH 動態埠轉發(SOCKS5)

如果你已有一臺可 SSH 登入的遠端伺服器,無需安裝任何額外軟體,直接利用 SSH 自帶功能即可建立一個 SOCKS5 代理。

ssh -N -D 127.0.0.1:1080 [email protected]
  • -D:動態埠轉發,建立 SOCKS5。
  • -N:不執行遠端命令,僅建立隧道。

保持穩定(增加 keepalive):

ssh -N -D 127.0.0.1:1080 \
    -o ServerAliveInterval=30 \
    -o ServerAliveCountMax=3 \
    -o ExitOnForwardFailure=yes \
    [email protected]

也可寫入 ~/.ssh/config

Host my-proxy
    HostName server.example.com
    User user
    DynamicForward 127.0.0.1:1080
    ServerAliveInterval 30
    ServerAliveCountMax 3
    ExitOnForwardFailure yes

之後執行 ssh -N my-proxy 即可。

2.2 標準 HTTP 代理:Squid

Squid 是 Linux 下最經典的 HTTP 代理伺服器,適合為區域網或本機提供穩定的 HTTP/HTTPS 代理。

安裝

sudo apt install squid
sudo dnf install squid

基本設定/etc/squid/squid.conf):

  • 監聽埠(預設 3128):
    http_port 3128
  • 允許本機訪問(若僅本地使用):
    acl localnet src 127.0.0.0/8
    http_access allow localnet
    http_access deny all
  • 若需允許內網其他機器,新增 acl localnet src 192.168.1.0/24

啟動並設定開機自啟:

sudo systemctl start squid
sudo systemctl enable squid

現在你就擁有了一個 http://127.0.0.1:3128 的 HTTP 代理。

2.3 全能瑞士軍刀:GOST 快速搭建多協定代理

GOST 是一個輕量級的代理轉發工具,一條命令即可建立 HTTP、SOCKS5 或任意協定轉換。

  • 建立 HTTP 代理gost -L http://127.0.0.1:8080
  • 建立 SOCKS5 代理gost -L socks5://127.0.0.1:1080
  • 同時開啟兩個協定
    gost -L http://127.0.0.1:8080 -L socks5://127.0.0.1:1080

安全提醒:除非你需要對外提供服務,否則務必繫結 127.0.0.1 而非 0.0.0.0,避免意外暴露代理到公網。


3. 用戶端設定:常用工具與實戰

有了代理伺服器後,接下來就是讓各種用戶端工具使用它。

3.1 臨時使用(不汙染 Shell)

適用於單次命令,不會改變當前 Shell 環境:

https_proxy=http://127.0.0.1:8080 curl https://example.com
ALL_PROXY=socks5h://127.0.0.1:1080 git clone ...

3.2 持久化切換(Shell 函式)

放入 ~/.bashrc~/.zshrc

proxy_on() {
    export http_proxy="http://127.0.0.1:8080"
    export https_proxy="http://127.0.0.1:8080"
    export all_proxy="socks5h://127.0.0.1:1080"
    export HTTP_PROXY="$http_proxy" HTTPS_PROXY="$https_proxy" ALL_PROXY="$all_proxy"
    export no_proxy="localhost,127.0.0.1"
    export NO_PROXY="$no_proxy"
    echo "Proxy enabled"
}
proxy_off() {
    unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY no_proxy NO_PROXY
    echo "Proxy disabled"
}

3.3 各 CLI 工具設定速覽

工具設定方式
curl-x http://...-x socks5h://...
Git繼承環境變數;或 git config --global http.proxy http://127.0.0.1:8080
pippip install --proxy http://127.0.0.1:8080 pkg 或直接使用環境變數
npmnpm config set proxy http://127.0.0.1:8080
npm config set https-proxy http://127.0.0.1:8080
DNF編輯 /etc/dnf/dnf.conf 新增 proxy=http://127.0.0.1:8080
sudo https_proxy=... dnf update(注意 sudo 可能清環境,建議用 sudo -E 保留)
APT新建 /etc/apt/apt.conf.d/80proxy
Acquire::http::Proxy "http://127.0.0.1:8080";
Acquire::https::Proxy "http://127.0.0.1:8080";

3.4 為 Claude Code / Codex 打通代理:SSH 動態轉發 + GOST + 環境變數

如果本機(或某臺無法直連 Anthropic / OpenAI 的伺服器)只有一臺可以正常訪問外網的伺服器能 SSH 登入,可以用三步把 claudecodex 接到那臺伺服器的網路出口。

第一步:SSH 動態埠轉發,拿到本地 SOCKS5(做法同 2.1 節):

ssh -N -D 127.0.0.1:1080 \
    -o ServerAliveInterval=30 \
    -o ServerAliveCountMax=3 \
    -o ExitOnForwardFailure=yes \
    [email protected]

如果手頭還沒有這樣一臺伺服器,可以先參考《Linux 安裝 OCserv:搭建 OpenConnect VPN 伺服器》搭建一臺,再對它執行上面的命令。建議放進單獨的終端或 tmux 視窗長期保持連線。

第二步:用 GOST 把 SOCKS5 轉成 HTTP 代理。Claude Code 和 Codex 讀的是 HTTP_PROXY / HTTPS_PROXY,不是 SOCKS5,所以要再轉一層(同 4.2 節的轉換方式):

gost -L http://127.0.0.1:8080 -F socks5://127.0.0.1:1080

同樣建議常駐在獨立終端裡。此時 http://127.0.0.1:8080 就是一個轉發到遠端出口的 HTTP 代理。

第三步:匯出環境變數,啟動 CLI

export http_proxy="http://127.0.0.1:8080"
export https_proxy="http://127.0.0.1:8080"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"

claude
# 或
codex

只想臨時用一次,也可以不改當前 Shell,直接在命令前指定:

HTTPS_PROXY=http://127.0.0.1:8080 HTTP_PROXY=http://127.0.0.1:8080 claude

ssh -Dgostclaude/codex 這三個行程需要同時存活:前兩個中的任意一個退出,代理鏈路都會跟著斷開。

若你想將 API 請求轉發到自定義後端而非僅僅轉發協定,也可以讓 GOST 直接反向代理到目標地址:

gost -L http://127.0.0.1:8080 -F http://target-api.example.com

3.5 systemd 服務:環境變數不繼承

Shell 中 export 的變數不會影響 systemd 啟動的 daemon。正確做法是建立 drop-in 目錄:

sudo mkdir -p /etc/systemd/system/example.service.d

寫入 proxy.conf

[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8080"
Environment="HTTPS_PROXY=http://127.0.0.1:8080"
Environment="NO_PROXY=localhost,127.0.0.1"

然後 sudo systemctl daemon-reload && sudo systemctl restart example

3.6 Docker 代理的三層混淆

“Docker 配代理”至少指三種不同情況:

  1. dockerd 拉取映像:設定 /etc/docker/daemon.json
    {
      "proxies": {
        "http-proxy": "http://127.0.0.1:8080",
        "https-proxy": "http://127.0.0.1:8080",
        "no-proxy": "localhost,127.0.0.1"
      }
    }
    或通過 systemd drop-in 設定環境變數(同 3.5)。
  2. 容器內應用程式:通過 -e 傳遞變數:
    docker run --rm -e http_proxy=http://proxy:8080 ubuntu env
  3. docker build 構建過程:需通過 --build-arg 傳入。

關鍵陷阱:容器內的 127.0.0.1 指向容器自身,而非宿主機。若代理監聽在宿主機 127.0.0.1,容器內需使用宿主機在容器網路中的 IP(如 172.17.0.1)或 host.docker.internal(Mac/Windows)。


4. 程式不支援代理?ProxyChains 與 GOST 轉換

4.1 ProxyChains:劫持 libc 網路函式

對於完全不支援代理、也不讀環境變數的程式,可用 ProxyChains 強制其走代理。它通過 LD_PRELOAD 攔截 connect() 等呼叫。

設定/etc/proxychains4.conf):

strict_chain
proxy_dns          # 让 DNS 也走代理,避免泄露
[ProxyList]
socks5 127.0.0.1 1080

使用:

proxychains4 curl https://example.com

侷限性

  • 僅處理 TCP(UDP/ICMP 如 ping 無效)。
  • 對靜態連結、Go/Rust/Java 等不走標準 libc 的程式可能失效。
  • 不適用於 daemon 或容器場景。

它只是一個“相容性補丁”,而非透明代理。

4.2 GOST 協定轉換:SOCKS5 ↔ HTTP

若你只有 SOCKS5,但某個程式只支援 HTTP Proxy,可用 GOST 原地轉換:

gost -L http://127.0.0.1:8080 -F socks5://127.0.0.1:1080

現在 127.0.0.1:8080 即為 HTTP 代理,所有請求經 GOST 轉發給 SOCKS5。反之亦可(將 HTTP 轉為 SOCKS5)。


5. 透明代理:從應用層到網路層(TUN/TPROXY)

當需求上升到“所有程式無感知地走代理”,就需要從網路層接管流量。常見方案:

  • REDIRECT:iptables/nftables 將流量重定向到本地代理埠。
  • TPROXY:更靈活,保留原始目標地址,需配合策略路由。
  • TUN:建立虛擬網路卡,應用程式的 IP 包被路由到該網路卡,由代理程式處理。

5.1 推薦工具:sing-box

sing-box 是 SagerNet 推出的通用代理平臺,用 Go 編寫。它繼承了 Clash Premium 的 TUN 入站功能,是實現透明代理最現代、最合理的方式之一。

核心特點

  • TUN 模式:在網路層(L3)捕獲 IP 包,轉換為 L4 連線(TCP/UDP),再交由路由系統處理。與依賴 iptables 的 TPROXY 不同,TUN 僅修改路由表,不易與 Docker 等網路衝突。
  • auto_redirect:在 Linux 上推薦啟用,可提供更好的路由支援,並自動處理 nftables 規則。
  • 模組化設定:結構清晰,支援靈活的 DNS 和路由規則。

最小 TUN 設定示例/etc/sing-box/config.json):

{
  "inbounds": [
    {
      "type": "tun",
      "tag": "tun-in",
      "interface_name": "tun0",
      "address": ["172.19.0.1/30"],
      "auto_route": true,
      "auto_redirect": true
    }
  ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "direct"
    }
  ]
}

啟動:

sudo systemctl start sing-box

之後所有系統流量將被路由到 tun0 虛擬網路卡,由 sing-box 根據規則處理(可將流量轉發到 SOCKS5/HTTP 出站)。

5.2 何時使用透明代理?

  • 只有當你不想逐個設定程式,且願意接受額外複雜性(DNS、路由迴環、Docker 網路、IPv6、MTU 等需要處理)時,再考慮 TUN/TPROXY。
  • 否則,環境變數或 ProxyChains 更輕量。

6. 除錯排障與速查表

6.1 標準排查流程

  1. 確認代理監聽ss -lntp | grep -E '1080|8080',注意是 127.0.0.1 還是 0.0.0.0
  2. 直接測試代理curl -v -x socks5h://127.0.0.1:1080 https://example.com,觀察輸出中的 CONNECT 或 TLS 握手。
  3. 檢查環境變數env | grep -i proxy,確保大小寫都存在且值正確。
  4. 排查 DNSgetent hosts example.com,或用 tcpdump -ni any port 53 觀察 DNS 查詢是否如預期經過代理。
  5. 抓包驗證tcpdump -ni any host TARGET_IP 看流量實際走向。

誤區ping 使用 ICMP,不適用於測試 HTTP/SOCKS 代理,始終用 curlnc

6.2 決策速查表

需求推薦方案
單次 curl 或臨時測試curl -x
常規 CLI 工具(Git/pip/npm)http_proxy / https_proxy 環境變數
已有 SSH 伺服器,快速獲得代理ssh -D
搭建穩定的 HTTP 代理Squid
輕量級多協定代理GOST
程式不支援代理ProxyChains(有侷限)
SOCKS5 ↔ HTTP 轉換GOST
為 Claude Code 等 AI 工具代理環境變數或 GOST 反向代理
systemd 服務systemd Environment=
Docker 拉取映像設定 dockerd(daemon.json)
容器內應用傳遞環境變數 -e
所有程式透明代理sing-box TUN(謹慎評估)

6.3 Cheat Sheet(速查命令)

# HTTP 代理测试
curl -x http://127.0.0.1:8080 https://example.com

# SOCKS5(远端 DNS)
curl -x socks5h://127.0.0.1:1080 https://example.com

# SSH 建立 SOCKS5
ssh -N -D 127.0.0.1:1080 user@server

# 环境变量一键设置(大小写兼有)
export http_proxy=http://127.0.0.1:8080 https_proxy=http://127.0.0.1:8080 all_proxy=socks5h://127.0.0.1:1080
export HTTP_PROXY="$http_proxy" HTTPS_PROXY="$https_proxy" ALL_PROXY="$all_proxy"

# 查看代理变量
env | grep -i proxy

# 清除所有代理变量
unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY no_proxy NO_PROXY

# ProxyChains 使用
proxychains4 curl https://example.com

# GOST 转换 SOCKS5 → HTTP
gost -L http://127.0.0.1:8080 -F socks5://127.0.0.1:1080

# 查看监听端口
ss -lntp | grep -E '1080|8080'

# 详细调试
curl -v -x socks5h://127.0.0.1:1080 https://example.com

結語

Linux 代理設定的本質是選擇正確的層級。從應用層的 -x 參數,到環境變數,再到庫函式劫持(ProxyChains),最後到網路層的 TUN/TPROXY,每一層都有其適用邊界。不要一上來就追求“全域代理”,大多數情況下,環境變數或 SSH 隧道已經足夠。只有當你確實需要“所有程式無感知”時,再謹慎引入透明代理方案。