在日常上網和企業網絡環境中,我們經常需要配置代理服務器來訪問特定資源、增強安全性或管理網絡流量。Windows和macOS系統自帶的代理配置通常提供全局代理或簡單的排除列表,這在某些復雜場景下顯得不夠靈活。例如,我們可能只想代理某個特定的IP網段,而其他所有流量都直接連接。這時,PAC (Proxy Auto-Configuration) 文件 就派上了大用場。
什么是PAC文件?
PAC文件本質上是一個包含特定JavaScript函數的文本文件。這個核心函數通常命名為 FindProxyForURL(url, host)
。當瀏覽器或操作系統配置為使用PAC文件時,每當需要發起一個網絡請求(例如,訪問一個網頁或API),系統會首先調用這個 FindProxyForURL
函數,并將目標URL和主機名作為參數傳遞給它。
函數執行后,會根據其內部的邏輯返回一個字符串,告訴系統應該如何處理這個請求:
- 是通過某個特定的代理服務器?
- 是通過多個代理服務器(用于故障轉移或負載均衡)?
- 還是直接連接,不經過任何代理?
PAC文件是如何工作的?
- 配置: 用戶在操作系統或瀏覽器的網絡設置中,指定一個PAC文件的URL地址。這個URL可以是指向本地文件系統中的文件 (如
file:///C:/path/to/proxy.pac
),也可以是指向一個網絡服務器上的文件 (如http://internal.server/proxy.pac
)。 - 請求觸發: 當應用程序(如瀏覽器)嘗試訪問一個URL時,它會將該URL和從中提取的主機名傳遞給
FindProxyForURL
函數。 - JavaScript邏輯執行: PAC文件中的JavaScript代碼被執行。開發者可以在這個函數內部編寫各種條件判斷邏輯,例如:
- 判斷目標主機名是否屬于某個域名 (e.g.,
*.example.com
) - 判斷目標主機的IP地址是否屬于某個IP網段 (e.g.,
192.168.1.0/24
) - 判斷目標URL是否包含特定路徑或協議 (e.g.,
https://*
,*admin*
) - 判斷當前時間或日期 (e.g., 只在工作時間使用代理)
- 判斷目標主機名是否屬于某個域名 (e.g.,
- 返回代理指令:
FindProxyForURL
函數必須返回一個特定格式的字符串,指示代理行為。
FindProxyForURL(url, host)
函數詳解
url
: 完整的目標URL,例如 “http://www.example.com/index.html”。host
: 從URL中提取的主機名,例如 “www.example.com”。如果URL直接使用IP地址,則host就是該IP地址。
常見的返回值格式:
"DIRECT"
:
表示直接連接到目標服務器,不使用任何代理。return "DIRECT";
"PROXY proxy_host:proxy_port"
:
表示通過指定的HTTP代理服務器連接。例如:return "PROXY 192.168.1.100:8080";
"SOCKS proxy_host:proxy_port"
或"SOCKS5 proxy_host:proxy_port"
:
表示通過指定的SOCKS代理服務器連接。SOCKS5是更常用的版本。例如:return "SOCKS5 10.0.0.5:1080";
- 多個代理 (故障轉移/負載均衡):
可以返回一個由分號分隔的代理列表。系統會嘗試第一個,如果失敗則嘗試第二個,以此類推。DIRECT
也可以作為列表中的最后一項。return "PROXY proxy1.example.com:8080; PROXY proxy2.example.com:8081; DIRECT";
PAC文件中的實用JavaScript輔助函數
為了方便編寫判斷邏輯,PAC規范提供了一些內置的JavaScript輔助函數,可以在 FindProxyForURL
中使用:
isInNet(host, pattern, mask)
:
判斷host
(可以是主機名或IP地址) 解析后的IP地址是否在由pattern
(網絡地址) 和mask
(子網掩碼) 定義的IP網段內。
例如:isInNet(host, "172.31.0.0", "255.255.0.0")
判斷主機是否在172.31.0.0/16
網段。dnsResolve(host)
:
將主機名解析為其IP地址。如果解析失敗,返回null
。
例如:var ip = dnsResolve("www.example.com");
shExpMatch(str, shexp)
:
判斷字符串str
是否匹配shexp
(shell表達式,類似通配符)。
例如:shExpMatch(url, "*.example.com/*")
或shExpMatch(host, "intranet.*")
。isPlainHostName(host)
:
判斷主機名是否為簡單主機名 (即不包含任何點.
,例如 “localhost”, “mycomputer”)。dnsDomainIs(host, domain)
:
判斷host
是否屬于指定的domain
。
例如:dnsDomainIs("www.example.com", ".example.com")
返回true
。isResolvable(host)
:
判斷主機名是否可以被DNS解析。weekdayRange()
,dateRange()
,timeRange()
:
用于基于日期和時間的條件判斷。
創建PAC文件:一個實例(只代理特定網段)
回到最初的問題:只代理 172.31.0.0/16
網段,其他都不走代理。
下面是實現這個需求的PAC文件 (proxy.pac
) 內容:
function FindProxyForURL(url, host) {// 替換為代理服務器IP地址和端口var proxy_server = "YOUR_PROXY_IP_OR_HOSTNAME:YOUR_PROXY_PORT";// 判斷目標主機是否在 172.31.0.0/16 網段// "172.31.0.0/16" 的網絡地址是 "172.31.0.0",子網掩碼是 "255.255.0.0"if (isInNet(host, "172.31.0.0", "255.255.0.0")) {// 如果目標在指定網段,則通過代理服務器return "PROXY " + proxy_server;}// 對于其他所有流量,都直接連接return "DIRECT";
}
使用步驟:
-
將上述代碼保存到一個文本文件中,例如
proxy.pac
。 務必將YOUR_PROXY_IP_OR_HOSTNAME:YOUR_PROXY_PORT
替換成實際的代理服務器地址和端口 (例如10.0.0.1:8888
或myproxy.internal:3128
)。 -
在Windows上配置使用PAC文件:
- 打開 “設置” -> “網絡和 Internet” -> “代理”。
- 關閉 “自動檢測設置”。
- 打開 “使用設置腳本”。
- 在 “腳本地址” 處填入PAC文件的本地路徑,格式為
file:///C:/path/to/your/proxy.pac
(請將C:/path/to/your/proxy.pac
替換為實際的文件路徑,注意是三個斜杠///
和正斜杠/
)。 - 點擊 “保存”。
-
在macOS上配置使用PAC文件:
- 打開 “系統設置” (System Settings) -> “網絡” (Network)。
- 選擇正在使用的網絡連接(例如 Wi-Fi 或以太網)。
- 點擊右下角的 “詳細信息…” (Details…) 按鈕。
- 在左側選擇 “代理” (Proxies)。
- 選擇 “自動代理配置” (Automatic Proxy Configuration)。
- 在 “URL” 字段中填入PAC文件的本地路徑,格式為
file:///Users/yourusername/path/to/your/proxy.pac
(請將/Users/yourusername/path/to/your/proxy.pac
替換為實際的文件路徑,注意是三個斜杠///
)。 - 點擊 “好” (OK),然后點擊 “應用” (Apply)。
PAC文件的優勢
- 靈活性高: 可以通過JavaScript編寫復雜的邏輯,實現非常精細的代理規則。
- 集中管理: 如果將PAC文件部署在Web服務器上,所有客戶端可以指向同一個URL。修改PAC文件即可統一更新所有客戶端的代理行為,無需逐個修改客戶端配置。
- 跨平臺: Windows, macOS, Linux以及主流瀏覽器都支持PAC文件。
- 無需額外軟件: 這是操作系統和瀏覽器內置的功能。
注意事項和調試技巧
- 語法錯誤: PAC文件是JavaScript,任何語法錯誤都會導致其失效。仔細檢查括號、分號、引號等。
- 路徑問題: 使用本地PAC文件時,
file:///
協議和正確的路徑格式非常重要。 - 路徑格式: file:/// 后面跟的是文件的絕對路徑。Windows下盤符后的冒號要去掉,或者直接用正斜杠。例如 C:\Users\MyUser\Documents\proxy.pac 應該寫成 file:///C:/Users/MyUser/Documents/proxy.pac。
- DNS依賴: 很多判斷(如
isInNet
)依賴于DNS解析。如果DNS解析有問題,PAC規則可能不會按預期工作。 - 緩存: 瀏覽器和操作系統可能會緩存PAC文件。修改后,可能需要清除緩存、重啟瀏覽器或網絡服務,甚至重啟系統才能使更改生效。
- 調試:
- 在PAC文件中使用
alert()
函數 (例如alert("Host: " + host + " is going DIRECT");
) 可以幫助調試。但請注意,這些彈窗會打斷正常瀏覽,調試完成后務必移除。 - 某些瀏覽器開發者工具(如Firefox)提供PAC文件調試功能。
- 檢查代理服務器的日志,看請求是否如預期那樣通過代理。
- 在PAC文件中使用
總結
PAC文件是一個強大而靈活的工具,它通過簡單的JavaScript腳本實現了智能化的代理路由決策。對于需要根據目標URL、主機名、IP網段等條件動態選擇代理方式的場景,PAC文件提供了一個輕量級且無需額外軟件的解決方案。理解了它的基本原理和常用函數后,就可以根據自己的需求定制出各種復雜的代理規則了。