pac-maker
v4.0.0
Published
Proxy Auto-Configuration (PAC) file generator & loader, support proxy Node's `fetch` with PAC
Downloads
37
Readme
pac-maker
Proxy Auto Configuration (PAC) file generator & maintenance tool.
Features:
- Generate PAC files from various hostname sources.
- Load a PAC file in Node.
- Serve the PAC with http and watch for source change.
- Show what hosts in your browser history will be proxied by the PAC.
- Proxy Node's
fetch
with PAC
Usage
PAC files
Pre-generated PAC files at /dist
can be used to bypass GFW:
- blacklist.pac forward GFW blocked hostnames to the proxy server, other hostnames will connect directly.
- whitelist.pac forward all but China hostnames to the proxy server.
By default, the proxy is SOCKS5 localhost:2080
, you can change the value to your proxy server address.
Performance:
| file | Load time (ms) | Memory usage (MB) | FindProxyForURL (μs/op) | |--------------------------------------------------------|----------------|-------------------|-------------------------| | blacklist.pac | 3.53 | 0.65 | 0.74 | | whitelist.pac | 35.72 | 6.06 | 1.77 | | gfwlist2pac | 4.22 | 0.20 | 3355.43 |
Install
This package is pure ESM, it cannot be require()
'd from CommonJS.
npm install pac-maker
Generate PAC files
pac-maker loads config file from working directory, default is pac.config.js
, it can be specified by --config=<path>
.
config file should export a configuration object:
import { builtinList, gfwlist, ofArray } from "pac-maker";
export default {
/**
* Location of the generated PAC file, default is "proxy.pac".
*/
path: "proxy.pac",
/**
* Fallback route when no rule matching in `sources`, default is "DIRECT".
*/
fallback: "DIRECT",
/**
* Proxy source map, the key is a proxy sorting, value is an array of HostnameSource.
* pac-maker will get hostnames from all sources and route them to the corresponding key.
*/
sources: {
"SOCKS5 localhost:2080": [
gfwlist(),
builtinList("default"),
builtinList("forbidden"),
ofArray(["google.com"]),
],
},
};
There are some built-in sources in pac-maker:
gfwlist
Fetch hostnames from gfwlist.hostnameFile
Read hostnames from a file, for hostname file example, see the list directory.builtinList
Read hostnames from a file in the list directory.ofArray
Just use an array of hostnames.
CLI commands
generate
Generate a PAC file:
pac-maker generate [--config=<path>] [--watch]
--watch
After the initial build, pac-maker will continue to watch for updates in any of the sources.
analyze
Find what hosts will be proxied by the PAC in browser history, support Chrome, Firefox, and Edge:
pac-maker analyze [--config=<path>] [--json=<path>]
--json
Save matched rules to this file, default ismatches.json
.
bench
Benchmark PAC files, show load time, memory usage, and FindProxyForURL
performance.
pac-maker bench <path/to/file.pac> [morefiles...] [--host=example.com] [--loadCount=<number>] [--workCount=<number>]
--host
Thehost
parameter passed toFindProxyForURL
, default is "www.google.com".--iterations
Time or the number of load iterations to platform, default is "1s".
serve
Serve the PAC file with http, and update when source have changes:
pac-maker serve [--config=<file>] [--host=<host>] [--port=<port>]
--host
By default, the server will accept connections from all addresses, It is possible to listen to just one selected interface using thehost
parameter.--port
The port number that http server to listened on, default is7568
.
JavaScript API
pac-maker exports some useful functions that allows you to play with PAC inside your own JavaScript program.
PACDispatcher
The undici dispatcher that dispatch requests based on rule described by the PAC.
It is designed to be used with the built-in fetch
function. To proxy the requests with the http
module, we recommend to use node-pac-proxy-agent.
import { readFileSync } from "fs";
import { PACDispatcher } from "pac-maker";
const pac = readFileSync("proxy.pac", "utf8");
const dispatcher = new PACDispatcher(pac);
const response = await fetch("https://example.com", { dispatcher });
buildPAC
Create a PAC script from rules, use the built-in template template/default.js
.
The function takes two parameters, first is a rules object which key is
a proxy string
, and value is a hostname array. the second parameter will be returned from FindProxyForURL
if no hostname matched,
default is DIRECT
.
import { writeFileSync } from "fs";
import { buildPAC } from "pac-maker";
const rules = {
"HTTP 192.168.0.1:80": ["foo.com", "bar.com"],
"SOCKS5 localhost:1080": ["example.com"],
};
writeFileSync("proxy.pac", buildPAC(rules));
loadPAC
Load and execute a PAC script, return an object includes all global variables defined in the PAC.
import { readFileSync } from "fs";
import { loadPAC } from "pac-maker";
const pac = loadPAC(readFileSync("proxy.pac", "utf8"));
console.log(pac.FindProxyForURL("", "example.com"));
parseProxies
Parse the return value of FindProxyForURL()
.
import { parseProxies } from "pac-maker";
console.log(parseProxies("HTTP localhost:80; DIRECT"));
output:
[
{ protocol: "HTTP", host: "localhost:80", port: 80, hostname: "localhost" },
{ protocol: "DIRECT", host: "", port: NaN, hostname: "" }
]
HostBlockVerifier
A tool to check which hostnames are blocked by your ISP.
This class is only support HTTP protocol, it cannot be used for hosts running non-HTTP services.
import { HostBlockVerifier } from "pac-maker";
const hosts = ["google.com", "github.com" /* ... */];
const verifier = new HostBlockVerifier("SOCKS5 localhost:1080");
(await verifier.verifyAll(hosts)).print();
Test a single hostname and return block type:
const reason = await verifier.verify("google.com");
if (reason === "DNS") {
console.log("DNS cache pollution");
} else if (reason === "TCP") {
console.log("TCP blocking");
} else if (reason === "Unavailable") {
console.log("Site may be down");
} else {
console.log("The host is not blocked");
}
commands
All commands supported by pac-maker
can also be called in JavaScript code.
import { commands } from "pac-maker";
import config from "./pac.config.js";
commands.serve({ host: "localhost", port: 12345 }, config);
Run Tests
To run unit tests, you need to enable experimental vm modules.
NODE_OPTIONS=--experimental-vm-modules
pnpm test