15 KiB
GUI Documentation
Software for which this article applies
Programmable
Brook GUI will pass different global variables to the script at different times, and the script only needs to assign the processing result to the global variable out
- address: We call it address which includes both host and port. For example, an ip address contains an ip and a port; a domain address contains a domain and a port.
- Fake DNS: Fake DNS can allow you to obtain domain address on
in_addressstep. How Fake DNS works
Variables
| variable | type | condition | timing | description | out type |
|---|---|---|---|---|---|
| in_brooklinks | map | / | Before connecting | Predefine multiple brook links, and then programmatically specify which one to connect to | map |
| in_dnsquery | map | FakeDNS: On | When a DNS query occurs | Script can decide how to handle this request | map |
| in_address | map | / | When connecting to an address | script can decide how to connect | map |
| in_httprequest | map | / | When an HTTP(S) request comes in | the script can decide how to handle this request | map |
| in_httprequest,in_httpresponse | map | / | when an HTTP(S) response comes in | the script can decide how to handle this response | map |
in_brooklinks
| Key | Type | Description | Example |
|---|---|---|---|
| _ | bool | meaningless | true |
out, ignored if not of type map
| Key | Type | Description | Example |
|---|---|---|---|
| ... | ... | ... | ... |
| custom name | string | brook link | brook://... |
| ... | ... | ... | ... |
in_dnsquery
| Key | Type | Description | Example |
|---|---|---|---|
| domain | string | domain name | google.com |
| type | string | query type | A |
| appid | string | App ID or path | com.google.Chrome.helper |
| interface | string | network interface. Mac only | en0 |
out, if it is error type will be recorded in the log. Ignored if not of type map
| Key | Type | Description | Example |
|---|---|---|---|
| block | bool | Whether Block, default false |
false |
| ip | string | Specify IP directly, only valid when type is A/AAAA |
1.2.3.4 |
| system | bool | Resolve by System DNS, default false |
false |
| bypass | bool | Resolve by Bypass DNS, default false |
false |
| brooklinkkey | string | When need to connect the Server,instead, connect to the Server specified by the key in_brooklinks | custom name |
in_address
| Key | Type | Description | Example |
|---|---|---|---|
| network | string | Network type, the value tcp/udp |
tcp |
| ipaddress | string | IP type address. There is only of ipaddress and domainaddress. Note that there is no relationship between these two | 1.2.3.4:443 |
| domainaddress | string | Domain type address, because of FakeDNS we can get the domain name address here | google.com:443 |
| appid | string | App ID or path | com.google.Chrome.helper |
| interface | string | network interface. Mac only | en0 |
out, if it is error type will be recorded in the log. Ignored if not of type map
| Key | Type | Description | Example |
|---|---|---|---|
| block | bool | Whether Block, default false |
false |
| ipaddress | string | IP type address, rewrite destination | 1.2.3.4:443 |
| ipaddressfrombypassdns | string | Use Bypass DNS to obtain A or AAAA IP and rewrite the destination, only valid when domainaddress exists, the value A/AAAA |
A |
| bypass | bool | Bypass, default false. If true and domainaddress, then ipaddress or ipaddressfrombypassdns must be specified |
false |
| mitm | bool | Whether to perform MITM, default false. Only valid when network is tcp. Need to install CA, see below |
false |
| mitmprotocol | string | MITM protocol needs to be specified explicitly, the value is http/https |
https |
| mitmcertdomain | string | The MITM certificate domain name, which is taken from domainaddress by default. If ipaddress and mitm is true and mitmprotocol is https then must be must be specified explicitly |
example.com |
| mitmwithbody | bool | Whether to manipulate the http body, default false. will read the body of the request and response into the memory and interact with the script. iOS 50M total memory limit may kill process |
false |
| mitmautohandlecompress | bool | Whether to automatically decompress the http body when interacting with the script, default false |
false |
| mitmclienttimeout | int | Timeout for MITM talk to server, second, default 0 | 0 |
| mitmserverreadtimeout | int | Timeout for MITM read from client, second, default 0 | 0 |
| mitmserverwritetimeout | int | Timeout for MITM write to client, second, default 0 | 0 |
| brooklinkkey | string | When need to connect the Server,instead, connect to the Server specified by the key in_brooklinks | custom name |
in_httprequest
| Key | Type | Description | Example |
|---|---|---|---|
| URL | string | URL | https://example.com/hello |
| Method | string | HTTP method | GET |
| Body | bytes | HTTP request body | / |
| ... | string | other fields are HTTP headers | / |
out, must be set to a request or response
in_httpresponse
| Key | Type | Description | Example |
|---|---|---|---|
| StatusCode | int | HTTP status code | 200 |
| Body | bytes | HTTP response body | / |
| ... | string | other fields are HTTP headers | / |
out, must be set to a response
Module
There are already some modules: https://github.com/txthinking/brook/blob/master/programmable/modules/
Brook GUI
In Brook GUI, scripts are abstracted into modules, and it will automatically combine _header.tengo and _footer.tengo, so you only need to write the module itself.
modules = append(modules, {
// If you want to predefine multiple brook links, and then programmatically specify which one to connect to, then define `brooklinks` key a function
brooklinks: func(m) {
// Please refer to the example in `brooklinks.tengo`
},
// If you want to intercept and handle a DNS query, then define `dnsquery` key a function, `m` is the `in_dnsquery`
dnsquery: func(m) {
// Please refer to the example in `block_aaaa.tengo`
},
// If you want to intercept and handle an address, then define `address` key a function, `m` is the `in_address`
address: func(m) {
// Please refer to the example in `block_google_secure_dns.tengo`
},
// If you want to intercept and handle a http request, then define `httprequest` key a function, `request` is the `in_httprequest`
httprequest: func(request) {
// Please refer to the example in `ios_app_downgrade.tengo` or `redirect_google_cn.tengo`
},
// If you want to intercept and handle a http response, then define `httpresponse` key a function, `request` is the `in_httprequest`, `response` is the `in_httpresponse`
httpresponse: func(request, response) {
// Please refer to the example in `response_sample.tengo`
}
})
tun2brook
If you are using tun2brook, you can combine multiple modules into a complete script in the following way. For example:
cat _header.tengo > my.tengo
cat block_google_secure_dns.tengo >> my.tengo
cat block_aaaa.tengo >> my.tengo
cat _footer.tengo >> my.tengo
Syntax
Library
-
text: regular expressions, string conversion, and manipulation
-
math: mathematical constants and functions
-
times: time-related functions
-
rand: random functions
-
fmt: formatting functions
-
json: JSON functions
-
enum: Enumeration functions
-
hex: hex encoding and decoding functions
-
base64: base64 encoding and decoding functions
-
brook: brook moduleConstants * os: string, linux/darwin/windows/ios/android Functions * splithostport(address string) => map/error: splits a network address of the form "host:port" to { "host": "xxx", "port": "xxx" } * country(ip string) => string/error: get country code from ip * cidrcontainsip(cidr string, ip string) => bool/error: reports whether the network includes ip * parseurl(url string) => map/error: parses a raw url into a map, keys: scheme/host/path/rawpath/rawquery * parsequery(query string) => map/error: parses a raw query into a kv map * map2query(kv map) => string/error: convert map{string:string} into a query string * bytes2ints(b bytes) => array/error: convert bytes into [int] * ints2bytes(ints array) => bytes/error: convert [int] into bytes * bytescompare(a bytes, b bytes) => int/error: returns an integer comparing two bytes lexicographically. The result will be 0 if a == b, -1 if a < b, and +1 if a > b * bytescontains(b bytes, sub bytes) => bool/error: reports whether sub is within b * byteshasprefix(s bytes, prefix bytes) => bool/error: tests whether the bytes s begins with prefix * byteshassuffix(s bytes, suffix bytes) => bool/error: tests whether the bytes s ends with suffix * bytesindex(s bytes, sep bytes) => int/error: returns the index of the first instance of sep in s, or -1 if sep is not present in s * byteslastindex(s bytes, sep bytes) => int/error: returns the index of the last instance of sep in s, or -1 if sep is not present in s * bytesreplace(s bytes, old bytes, new bytes, n int) => bytes/error: returns a copy of the s with the first n non-overlapping instances of old replaced by new. If n < 0, there is no limit on the number of replacements * pathescape(s string) => string/error: escapes the string so it can be safely placed inside a URL path segment, replacing special characters (including /) with %XX sequences as needed * pathunescape(s string) => string/error: does the inverse transformation of pathescape * queryescape(s string) => string/error: escapes the string so it can be safely placed inside a URL query * queryunescape(s string) => string/error: does the inverse transformation of queryescape * hexdecode(s string) => bytes/error: returns the bytes represented by the hexadecimal string s * hexencode(s string) => string/error: returns the hexadecimal encoding of src
Debug
If you are writing complex scripts, the GUI may not be convenient for debugging. It is recommended to use tun2brook on desktop to debug with fmt.println
Install CA
https://txthinking.github.io/ca/ca.pem
| OS | How |
|---|---|
| iOS | https://www.youtube.com/watch?v=HSGPC2vpDGk |
| Android | Android has user CA and system CA, must be installed in the system CA after ROOT |
| macOS | nami install mad ca.txthinking, sudo mad install --ca ~/.nami/bin/ca.pem |
| Windows | nami install mad ca.txthinking, Admin: mad install --ca ~/.nami/bin/ca.pem |
Some software may not read the system CA,you can use
curl --cacert ~/.nami/bin/ca.pemto debug