wasmpac

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 2, 2024 License: MPL-2.0 Imports: 16 Imported by: 0

README

wasmpac

wasmpac is an experimental sandboxed evaluator for Proxy Auto-Config (PAC) files.

A Proxy Auto-Configuration (PAC) file is a JavaScript function that determines whether web browser requests (HTTP, HTTPS, and FTP) go directly to the destination or are forwarded to a web proxy server.

Since PAC files are JavaScript, the evaluation of a PAC file requires a full JS runtime, which can be dangerous if not properly sandboxed. WinHTTP supports PAC files and the WPAD protocol, however in other platforms we are not that lucky. One example case is Zscaler on macOS, which (in addition to other things to route all traffic) provides a PAC file for proxy.

wasmpac is an attempt to isolate the JS engine itself by compiling it to WASM. We use the boa_engine crate to implement the engine in Rust, which we can compile for the wasm32-wasi target. With size optimizations and wasm-opt, the compiled WASM module is less than 2.5 MB in size. We then use wazero to use the module in Go. The Rust code for the module is under pac_mod, which can be built using build_mod.sh.

PAC reference page in MDN lists the predefined functions, which we provide in builtin.js. Two functions (dnsResolve and myIpAddress) should be imported by the module; which we provide implementations for. Additionally, system time is exposed to the module for proper evaluation of new Date() statements.

Example flow:

sequenceDiagram
    participant Go
    box Inside WASM module
    participant Rust
    participant JS
    end
    Go->>Rust: eval_pac(script, url, host)
    activate Rust
    Rust->>JS: register builtin functions
    Rust->>JS: register script (script)
    Rust->>JS: evaluate script (url, host)
    activate JS
    JS->>Rust: myIpAddress()
    activate Rust
    Rust->>Go: myIpAddress()
    activate Go
    Go-->>Rust: return myIP
    deactivate Go
    Rust-->>JS: return myIP
    deactivate Rust
    JS->>Rust: dnsResolve(host)
    activate Rust
    Rust->>Go: dnsResolve(host)
    activate Go
    Go-->>Rust: return ip
    deactivate Go
    Rust-->>JS: return ip
    deactivate Rust
    JS-->>Rust: return result
    deactivate JS
    Rust-->>Go: return result
    deactivate Rust
Security

wasmpac is an experiment which is not rigorously evaluated for security concerns, therefore it is not advised for professional usage.

Installation
go get github.com/kubuzetto/wasmpac

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrURLParse       = errors.New("cannot parse url")
	ErrHostModuleInit = errors.New("cannot instantiate the host module")
	ErrWASIModuleInit = errors.New("cannot instantiate the WASI module")
	ErrPACModuleInit  = errors.New("cannot instantiate the PAC module")
	ErrPACEvaluation  = errors.New("cannot evaluate the PAC script")
)

Functions

func DNSResolver added in v0.3.0

func DNSResolver(host string) (string, error)

DNSResolver resolves a given hostname to the corresponding IP address. Adapted from https://github.com/darren/gpac/blob/master/builtin_natives.go

func EvalPAC

func EvalPAC(ctx context.Context, script, url string) (string, error)

EvalPAC evaluates a given PAC script for the given url, and returns the output string. The evaluation is done in the Boa JavaScript engine, which itself is compiled into a WASM module and run by the Wazero WASM engine. Note that stdin, stdout and stderr are not connected to the wasm module, therefore console commands will not work inside the PAC scripts.

func MyIPAddr added in v0.3.0

func MyIPAddr() (string, error)

MyIPAddr returns the ip address of the machine. The meaning of this is vague for machines with multiple NICs and even in the presence of IPv6; so the usage of this function is generally discouraged in PAC files. See: https://findproxyforurl.com/pac-functions/ Adapted from https://github.com/darren/gpac/blob/master/builtin_natives.go

func Nanosleep added in v0.3.0

func Nanosleep(ns int64)

func Nanotime added in v0.3.0

func Nanotime() int64

func Walltime added in v0.3.0

func Walltime() (sec int64, nsec int32)

Types

type DNSResolverFn added in v0.3.0

type DNSResolverFn func(host string) (ip string, err error)

type Evaluator added in v0.3.0

type Evaluator struct {
	// Logger can be nil, to disable logging from the Evaluator altogether.
	// Default value is slog.Default().
	Logger *slog.Logger

	// host functions
	DNSResolver DNSResolverFn
	MyIPAddr    MyIPAddrFn

	RandSource         io.Reader
	Nanosleep          sys.Nanosleep
	Nanotime           sys.Nanotime
	NanotimeResolution sys.ClockResolution
	Walltime           sys.Walltime
	WalltimeResolution sys.ClockResolution
}

func New added in v0.3.0

func New() *Evaluator

func (*Evaluator) EvalPAC added in v0.3.0

func (e *Evaluator) EvalPAC(ctx context.Context, pacScript, urlStr string) (res string, err error)

type MyIPAddrFn added in v0.3.0

type MyIPAddrFn func() (ip string, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL