diff --git a/.github/update.log b/.github/update.log index b171a9225b..0295fa401f 100644 --- a/.github/update.log +++ b/.github/update.log @@ -871,3 +871,4 @@ Update On Mon Dec 30 19:34:06 CET 2024 Update On Tue Dec 31 19:31:50 CET 2024 Update On Wed Jan 1 19:33:17 CET 2025 Update On Thu Jan 2 19:33:11 CET 2025 +Update On Fri Jan 3 19:34:50 CET 2025 diff --git a/brook/README.md b/brook/README.md index c24d9f9bfb..303b0862d6 100644 --- a/brook/README.md +++ b/brook/README.md @@ -28,18 +28,137 @@ brook server -l :9999 -p hello - [macOS](https://apps.apple.com/us/app/brook-network-tool/id1216002642) - [Windows](https://github.com/txthinking/brook/releases/latest/download/Brook.msix) - [Linux](https://github.com/txthinking/brook/releases/latest/download/Brook.bin) -- [OpenWrt](https://github.com/txthinking/brook/releases) +- [OpenWrt](https://www.txthinking.com/talks/articles/brook-openwrt-en.article) > You may want to use `brook link` to customize some parameters - [About App Mode on macOS](https://www.txthinking.com/talks/articles/macos-app-mode-en.article) -- [How to install Brook on Windows?](https://www.txthinking.com/talks/articles/msix-brook-en.article) +- [How to install Brook on Windows](https://www.txthinking.com/talks/articles/msix-brook-en.article) - [How to install Brook on Linux](https://www.txthinking.com/talks/articles/linux-app-brook-en.article) - [How to install Brook on OpenWrt](https://www.txthinking.com/talks/articles/brook-openwrt-en.article) -# Client +# Server -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` +brook dnsserver, dohserver, dnsserveroverbrook, server, wsserver, wssserver, quicserver can use script to do more complex thing. brook 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` + +## Brook DNS Server + +![x](./images/brook-dns-server.svg) + +Script can do more: + +- There are [examples](https://github.com/txthinking/brook/blob/master/programmable/dnsserver/) for dns server +- In the `script: in_dnsquery` step, script can do more, read more below + +## Brook Server + +![x](./images/brook-server.svg) + +Script can do more: + +- There are [examples](https://github.com/txthinking/brook/blob/master/programmable/server/) for server +- In the `script: in_address` step, script can do more, read more below + +## Variables + +| variable | type | command | timing | description | out type | +| ------------------------------ | ---- | ----------- | --------------------------------- | ------------------------------------------------- | -------- | +| in_dnsservers | map | dnsserver/dnsserveroverbrook/dohserver/server/wsserver/wssserver/quicserver | When just running | Predefine multiple dns servers, and then programmatically specify which one to use | map | +| in_dohservers | map | dnsserver/dnsserveroverbrook/dohserver/server/wsserver/wssserver/quicserver | When just running | Predefine multiple doh servers, and then programmatically specify which one to use | map | +| in_brooklinks | map | server/wsserver/wssserver/quicserver | When just running | Predefine multiple brook links, and then programmatically specify which one to use | map | +| in_dnsquery | map | dnsserver/dnsserveroverbrook/dohserver | When a DNS query occurs | Script can decide how to handle this request | map | +| in_address | map | server/wsserver/wssserver/quicserver | When the Server connects the proxied address | Script can decide how to handle this request | map | + +## in_dnsservers + +| Key | Type | Description | Example | +| ------ | ------ | -------- | ---------- | +| _ | bool | meaningless | true | + +`out`, ignored if not of type `map` + +| Key | Type | Description | Example | +| ------------ | ------ | -------------------------------------------------------------------------------------------------- | ------- | +| ... | ... | ... | ... | +| custom name | string | dns server | 8.8.8.8:53 | +| ... | ... | ... | ... | + + +## in_dohservers + +| Key | Type | Description | Example | +| ------ | ------ | -------- | ---------- | +| _ | bool | meaningless | true | + +`out`, ignored if not of type `map` + +| Key | Type | Description | Example | +| ------------ | ------ | -------------------------------------------------------------------------------------------------- | ------- | +| ... | ... | ... | ... | +| custom name | string | dohserver | https://dns.quad9.net/dns-query?address=9.9.9.9%3A443 | +| ... | ... | ... | ... | + + +## 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 | +| ------ | ------ | ----------- | ---------- | +| fromipaddress | string | client address which send this request | 1.2.3.4:5 | +| domain | string | domain name | google.com | +| type | string | query type | A | +| ... | ... | ... | ... | +| tag_key | string | --tag specifies the key value | tag_value | +| ... | ... | ... | ... | + +`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 | +| dnsserverkey | string | Use the dnsserver specified by key to resolve | custom name | +| dohserverkey | string | Use the dohserver specified by key to resolve | custom name | + +## in_address + +| Key | Type | Description | Example | +| ------ | ------ | ----------- | ---------- | +| network | string | `tcp` or `udp` | tcp | +| fromipaddress | string | client address which send this request | 1.2.3.4:5 | +| ipaddress | string | ip address to be proxied | 1.2.3.4:443 | +| domainaddress | string | domain address to be proxied | google.com:443 | +| user | string | user ID, only available when used with --userAPI | 9 | +| ... | ... | ... | ... | +| tag_key | string | --tag specifies the key value | tag_value | +| ... | ... | ... | ... | + +`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 | +| address | string | Rewrite destination to an address | 1.2.3.4 | +| ipaddressfromdnsserverkey | string | If the destination is domain address, use the dnsserver specified by key to resolve | custom name | +| ipaddressfromdnsserverkey | string | If the destination is domain address, use the dohserver specified by key to resolve | custom name | +| aoraaaa | string | Must be used with ipaddressfromdnsserverkey or ipaddressfromdnsserverkey. Valid value is `A`/`AAAA` | A | +| speedlimit | int | Set a rate limit for this request, for example `1000000` means 1000 kb/s | 1000000 | +| brooklinkkey | string | Use the brook link specified by key to proxy | custom name | +| dialwith | string | If your server has multiple IPs or network interfaces, you can specify the IP or network interface name to initiate this request | 192.168.1.2 or 2606:4700:3030::ac43:a86a or en1 | +# Client ## CLI @@ -52,106 +171,52 @@ For the specifics of socks5 and http proxy, you can read [this article](https:// ## GUI -The GUI client does not use socks5 and http proxy mode, so there is no issue with some software not using the system proxy. Instead, it uses a virtual network card to take over the entire system's network, including UDP-based http3. Moreover, Brook allows us to control network requests programmatically, so it is necessary to have basic knowledge of network requests. +The GUI client does not use socks5 and http proxy mode, so there is no issue with some software not using the system proxy. Instead, it uses a virtual network card to take over the entire system's network, including UDP-based http3. Moreover, Brook allows us to control network requests programmatically, so it is necessary to have basic knowledge of network requests. 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` -## Without Brook: Basic Knowledge of Network Requests +## Without Brook > Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: `google.com:443`, or an IP address: `8.8.8.8:53` +![x](./images/network.svg) + 1. When an app requests a domain address, such as `google.com:443` 2. It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com` - 1. The system DNS will return the IP of `google.com`, such as `1.2.3.4`, to the app +1. The system DNS will return the IP of `google.com`, such as `1.2.3.4`, to the app 3. The app will combine the IP and port into an IP address, such as: `1.2.3.4:443` 4. The app makes a network request to this IP address `1.2.3.4:443` 5. The app receives the response data In the above process, the app actually makes two network requests: one to the IP address `8.8.8.8:53` and another to the IP address `1.2.3.4:443`. In other words, the domain name is essentially an alias for the IP, and must obtain the domain's IP to establish a connection. -## With Brook: Fake DNS On +## With Brook -Brook has a Fake DNS feature, which can parse the domain name out of the query requests that an app sends to the system DNS and decide how to respond to the app. +Brook has a Fake DNS feature default, which can parse the domain name out of the query requests that an app sends to the system DNS UDP 53 and decide how to respond to the app. + +![x](./images/brook-client.svg) 1. When an app requests a domain name address, such as `google.com:443` 2. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com` 3. The Brook client detects that an app is sending a network request to `8.8.8.8:53`. This will trigger the `in_dnsquery` variable, carrying information such as `domain` - 1. The Brook client returns a fake IP to the app, such as `240.0.0.1` +1. The Brook client returns a fake IP to the app, such as `240.0.0.1` 4. The app combines the IP and port into an IP address, such as: `240.0.0.1:443` 5. The app makes a network request to the IP address `240.0.0.1:443` 6. The Brook client detects that an app is sending a network request to `240.0.0.1:443`, discovers that this is a fake IP, and will convert the fake IP address back to the domain address `google.com:443`. This will trigger the `in_address` variable, carrying information such as `domainaddress` - 1. The Brook client sends `google.com:443` to the Brook Server - 2. The Brook Server first requests its own DNS to resolve the domain name to find out the IP of `google.com`, such as receiving `1.2.3.4` - 3. The Brook Server combines the IP and port into an IP address, such as: `1.2.3.4:443` - 4. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client - 5. The Brook client then returns the data to the app +1. The Brook client sends `google.com:443` to the Brook Server +2. The Brook Server first requests its own DNS to resolve the domain name to find out the IP of `google.com`, such as receiving `1.2.3.4` +3. The Brook Server combines the IP and port into an IP address, such as: `1.2.3.4:443` +4. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client +5. The Brook client then returns the data to the app 7. The app receives the response data -However, if the following situations occur, the domain name will not/cannot be parsed, meaning that the Brook client will not/cannot know what the domain name is and will treat it as a normal request sent to an IP address: +However, if the following situations occur, the domain name will not/cannot be parsed, meaning that the Brook client will not/cannot know what the domain name is and will treat it as a normal request sent to an IP address. To avoid the ineffectiveness of Fake DNS, please refer to [this article](https://www.txthinking.com/talks/articles/brook-fakedns-en.article): - Fake DNS not enabled: in this case, the Brook client will not attempt to parse the domain name from the request sent to the system DNS and will treat it as a normal request sent to an IP address. - Even with Fake DNS enabled, but the app uses the system's secure DNS or the app's own secure DNS: in this case, the Brook client cannot parse the domain name from the request sent to the secure DNS and will treat it as a normal request sent to an IP address. -To avoid the ineffectiveness of Fake DNS, please refer to [this article](https://www.txthinking.com/talks/articles/brook-fakedns-en.article). +Script can do more: -## With Brook: Fake DNS Off - -1. When an app requests a domain address, such as `google.com:443` -2. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com` -3. The Brook client detects that an app is sending a network request to `8.8.8.8:53`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `8.8.8.8:53` to the Brook Server - 2. The Brook Server sends a network request to `8.8.8.8:53` and returns the result, such as `1.2.3.4`, to the Brook client - 3. The Brook client then returns the result to the app -4. The app combines the IP and port into an IP address, such as: `1.2.3.4:443` -5. The app makes a network request to the IP address `1.2.3.4:443` -6. The Brook client detects that an app is sending a network request to `1.2.3.4:443`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `1.2.3.4:443` to the Brook Server - 2. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client - 3. The Brook client then returns the data to the app -7. The app receives the response data - -## With Brook: Fake DNS On, But the App Uses the System's Secure DNS or Its Own Secure DNS - -1. When an app requests a domain name address, such as `google.com:443` -2. A DNS resolution will be performed first. That is, the app will send a network request to the secure DNS, such as `8.8.8.8:443`, to inquire about the IP of `google.com` -3. The Brook client detects that an app is sending a network request to `8.8.8.8:443`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `8.8.8.8:443` to the Brook Server - 2. The Brook Server sends a network request to `8.8.8.8:443`, and returns the result, such as `1.2.3.4`, to the Brook client - 3. The Brook client then returns the result to the app -4. The app combines the IP and port into an IP address, such as: `1.2.3.4:443` -5. The app makes a network request to the IP address `1.2.3.4:443` -6. The Brook client detects that an app is sending a network request to `1.2.3.4:443`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `1.2.3.4:443` to the Brook Server - 2. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client - 3. The Brook client then returns the data to the app -7. The app receives the response data - -To avoid the ineffectiveness of Fake DNS, please refer to [this article](https://www.txthinking.com/talks/articles/brook-fakedns-en.article). - -## Handle Variable Trigger - -- When the `in_brooklinks` variable is triggered: - - This is currently the only variable that gets triggered before the Brook client starts. - - We know that Brook starts with your choice of a Brook Server, and this variable lets you specify multiple Brook Servers. - - Then during runtime, you can use one of these Brook Servers as needed. -- When the `in_dnsquery` variable is triggered, you can process as needed, such as: - - Blocking, such as to prevent ad domain names. - - Directly specifying the response IP. - - Letting the system DNS resolve this domain. - - Letting Bypass DNS resolve this domain. - - And so on. -- When the `in_address` variable is triggered, you can process as needed, such as: - - Block this connection. - - Rewrite the destination. - - If it's a domain address, you can specify that Bypass DNS is responsible for resolving the IP of this domain. - - Allow it to connect directly without going through a proxy. - - If it's HTTP/HTTPS, you can start MITM (Man-In-The-Middle), which will subsequently trigger `in_httprequest` and `in_httpresponse`. - - And so on. -- When the `in_httprequest` variable is triggered, you can process as needed, such as: - - Modifying the HTTP request. - - Returning a custom HTTP response directly. -- When the `in_httpresponse` variable is triggered, you can process as needed, such as: - - Modifying the HTTP response. - -For detailed information on the properties and responses of variables, please refer to the following content. +- In the `script: in_dnsquery` step, script can do more, read more below +- In the `script: in_address` step, script can do more, read more below ## Variables @@ -159,9 +224,9 @@ For detailed information on the properties and responses of variables, please re | ------------------------------ | ---- | ----------- | --------------------------------- | ------------------------------------------------- | -------- | | 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_address | map | / | When connecting to an address | Script can decide how to handle this request | map | +| in_httprequest | map | / | When an HTTP(S) request comes in | Script can decide how to handle this request | map | +| in_httprequest,in_httpresponse | map | / | when an HTTP(S) response comes in | Script can decide how to handle this response | map | ## in_brooklinks @@ -183,42 +248,40 @@ For detailed information on the properties and responses of variables, please re | ------ | ------ | ----------- | ---------- | | 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 | +| appid | string | macOS App Mode: this is app id; Linux and Windows: this is app path; OpenWrt: this is IP address of client device. Note: In some operating systems, the app may initiate DNS queries through the system app. | com.google.Chrome.helper | `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 | +| ip | string | Ignore fake DNS, specify IP directly, only valid when `type` is `A`/`AAAA` | 1.2.3.4 | +| system | bool | Ignore fake DNS, resolve by System DNS over brook, default `false` | false | +| bypass | bool | Ignore fake DNS, resolve by Bypass DNS, default `false` | false | +| brooklinkkey | string | When need to connect the Server, instead, perfer 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 | +| ipaddress | string | IP type address. There is only one 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 | +| appid | string | macOS App Mode: this is app id; Linux and Windows: this is app path; OpenWrt: this is IP address of client device | com.google.Chrome.helper | `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 | +| ipaddress | string | Rewrite destination to an ip address | 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 | +| bypass | bool | Bypass, default `false`. If `true` and `domainaddress` exists, 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 | +| mitmcertdomain | string | The MITM certificate domain name, which is taken from `domainaddress` by default. If `ipaddress` exists 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 | +| mitmautohandlecompress | bool | Whether to automatically decompress the http body when interacting with the script, default `false`. Usually need set this to true | 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 | @@ -233,7 +296,7 @@ For detailed information on the properties and responses of variables, please re | Body | bytes | HTTP request body | / | | ... | string | other fields are HTTP headers | / | -`out`, must be set to a request or response +`out`, must be set to an unmodified or modified request or a response ## in_httpresponse @@ -243,11 +306,11 @@ For detailed information on the properties and responses of variables, please re | Body | bytes | HTTP response body | / | | ... | string | other fields are HTTP headers | / | -`out`, must be set to a response +`out`, must be set to an unmodified or modified response ## Modules -In Brook GUI, scripts are abstracted into **Modules**. There are already [some modules](https://github.com/txthinking/brook/blob/master/programmable/modules/), and thre is no magic, it just automatically combine [_header.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_header.tengo) and [_footer.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_footer.tengo), so you only need to write the module itself. +In Brook GUI, scripts are abstracted into **Modules**. There are already [some modules](https://github.com/txthinking/brook/blob/master/programmable/modules/), and there is no magic, it just automatically combine [_header.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_header.tengo) and [_footer.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_footer.tengo), so you only need to write the module itself. ``` modules = append(modules, { @@ -274,11 +337,11 @@ modules = append(modules, { }) ``` -## tun2brook +## ipio -https://github.com/txthinking/tun2brook +https://github.com/txthinking/ipio -If you are using tun2brook, you can manually combine multiple modules into a complete script in the following way. For example: +ipio uses the same script as the GUI. If you are using ipio, you can manually combine multiple modules into a complete script in the following way. For example: ``` cat _header.tengo > my.tengo @@ -289,56 +352,24 @@ cat block_aaaa.tengo >> my.tengo cat _footer.tengo >> my.tengo ``` -## Syntax +## openwrt -[Tengo Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md) +https://www.txthinking.com/talks/articles/brook-openwrt-en.article -Library +openwrt uses the same script as the GUI. If you are using openwrt, you can manually combine multiple modules into a complete script in the following way. For example: -- [text](https://github.com/d5/tengo/blob/master/docs/stdlib-text.md): regular expressions, string conversion, and manipulation -- [math](https://github.com/d5/tengo/blob/master/docs/stdlib-math.md): mathematical constants and functions -- [times](https://github.com/d5/tengo/blob/master/docs/stdlib-times.md): time-related functions -- [rand](https://github.com/d5/tengo/blob/master/docs/stdlib-rand.md): random functions -- [fmt](https://github.com/d5/tengo/blob/master/docs/stdlib-fmt.md): formatting functions -- [json](https://github.com/d5/tengo/blob/master/docs/stdlib-json.md): JSON functions -- [enum](https://github.com/d5/tengo/blob/master/docs/stdlib-enum.md): Enumeration functions -- [hex](https://github.com/d5/tengo/blob/master/docs/stdlib-hex.md): hex encoding and decoding functions -- [base64](https://github.com/d5/tengo/blob/master/docs/stdlib-base64.md): base64 encoding and decoding functions -- `brook`: brook module +``` +cat _header.tengo > my.tengo - ``` - Constants +cat block_google_secure_dns.tengo >> my.tengo +cat block_aaaa.tengo >> my.tengo - * 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 - ``` +cat _footer.tengo >> my.tengo +``` ## Debug -If you are writing complex scripts, the GUI may not be convenient for debugging. It is recommended to use [tun2brook](https://github.com/txthinking/tun2brook) on desktop to debug with `fmt.println` +If you are writing complex scripts, the GUI may not be convenient for debugging. It is recommended to use [ipio](https://github.com/txthinking/ipio) on desktop to debug with `fmt.println` ## CA @@ -353,10 +384,6 @@ https://txthinking.github.io/ca/ca.pem > Some software may not read the system CA,you can use `curl --cacert ~/.nami/bin/ca.pem` to debug -## OpenWrt - -[Brook OpenWRT: Perfectly supports IPv4/IPv6/TCP/UDP](https://www.txthinking.com/talks/articles/brook-openwrt-en.article) - ## IPv6 Brook's stance on IPv6 is positive, if your server or local environment doesn't have an IPv6 stack, read [this article](https://www.txthinking.com/talks/articles/brook-ipv6-en.article). @@ -403,8 +430,93 @@ Brook's stance on IPv6 is positive, if your server or local environment doesn't 16. Read the [documentation](https://brook.app) 14. Submit [new issue](https://github.com/txthinking/brook/issues?q=is%3Aissue) 17. Seek help in the [group](https://t.me/txthinking) +# Other + +## Script Syntax + +I think just reading this one page is enough: [Tengo Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md) + +Library + +- [text](https://github.com/d5/tengo/blob/master/docs/stdlib-text.md): regular expressions, string conversion, and manipulation +- [math](https://github.com/d5/tengo/blob/master/docs/stdlib-math.md): mathematical constants and functions +- [times](https://github.com/d5/tengo/blob/master/docs/stdlib-times.md): time-related functions +- [rand](https://github.com/d5/tengo/blob/master/docs/stdlib-rand.md): random functions +- [fmt](https://github.com/d5/tengo/blob/master/docs/stdlib-fmt.md): formatting functions +- [json](https://github.com/d5/tengo/blob/master/docs/stdlib-json.md): JSON functions +- [enum](https://github.com/d5/tengo/blob/master/docs/stdlib-enum.md): Enumeration functions +- [hex](https://github.com/d5/tengo/blob/master/docs/stdlib-hex.md): hex encoding and decoding functions +- [base64](https://github.com/d5/tengo/blob/master/docs/stdlib-base64.md): base64 encoding and decoding functions +- `brook`: brook module + + ``` + Constants + + * 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 + ``` + +## Example + +Each `subcommand` has a `--example`, such as: + +``` +brook server --example +``` + +## Resources + +| CLI | Description | +| --- | --- | +| [nami](https://github.com/txthinking/nami) | A clean and tidy decentralized package manager | +| [joker](https://github.com/txthinking/joker) | Joker can turn process into daemon. Zero-Configuration | +| [nico](https://github.com/txthinking/nico) | Nico can work with brook wsserver together | +| [z](https://github.com/txthinking/z) | z - process manager | +| [ipio](https://github.com/txthinking/ipio) | Proxy all traffic just one line command | +| [mad](https://github.com/txthinking/mad) | Generate root CA and derivative certificate for any domains and any IPs | +| [hancock](https://github.com/txthinking/hancock) | Manage multiple remote servers and execute commands remotely | +| [sshexec](https://github.com/txthinking/sshexec) | A command-line tool to execute remote command through ssh | +| [bash](https://github.com/txthinking/bash) | Many one-click scripts | +| [docker](https://hub.docker.com/r/txthinking/brook) | `docker run txthinking/brook` | + +| Resources | Description | +| --- | --- | +| [Protocol](https://github.com/txthinking/brook/tree/master/protocol) | Brook Protocol | +| [Blog](https://www.txthinking.com/talks/) | Some articles you should read | +| [YouTube](https://www.youtube.com/txthinking) | Some videos you should watch | +| [Telegram](https://t.me/txthinking) | Ask questions here | +| [Announce](https://t.me/s/txthinking_talks) | All news you should care | +| [GitHub](https://github.com/txthinking) | Other useful repos | +| [Socks5 Configurator](https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb) | If you prefer CLI brook client | +| [IPvBar](https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj) | See domain, IP and country in browser | +| [TxThinking SSH](https://www.txthinking.com/ssh.html) | A SSH Terminal | +| [brook-store](https://github.com/txthinkinginc/brook-store) | A Brook User System | +| [TxThinking](https://www.txthinking.com) | Everything | + # CLI Documentation -Each subcommand has a `--example` parameter that can print the minimal example of usage # NAME Brook - A cross-platform programmable network tool @@ -425,69 +537,31 @@ Brook [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] # GLOBAL OPTIONS -- **--blockCIDR4List**="": One CIDR per line, https://, http:// or local file absolute path, like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr4.txt. Works with server/wsserver/wssserver/quicserver +- **--cliToken**="": The CLI Token of your Brook Plus or Brook Business account, get it from https://www.txthinking.com/brook.html -- **--blockCIDR6List**="": One CIDR per line, https://, http:// or local file absolute path, like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_cidr6.txt. Works with server/wsserver/wssserver/quicserver - -- **--blockDomainList**="": One domain per line, suffix match mode. https://, http:// or local file absolute path. Like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt. Works with server/wsserver/wssserver/quicserver - -- **--blockGeoIP**="": Block IP by Geo country code, such as US. Works with server/wsserver/wssserver/quicserver - -- **--blockListUpdateInterval**="": Update list --blockDomainList,--blockCIDR4List,--blockCIDR6List interval, second. default 0, only read one time on start (default: 0) - -- **--clientHKDFInfo**="": client HKDF info, most time you don't need to change this, if changed, all and each brook links in client side must be same, I mean each (default: "brook") - -- **--dialWithDNS**="": When a domain name needs to be resolved, use the specified DNS. Such as 8.8.8.8:53 or https://dns.google/dns-query?address=8.8.8.8%3A443, the address is required. Note that for client-side commands, this does not affect the client passing the domain address to the server - -- **--dialWithDNSPrefer**="": This is used with the dialWithDNS parameter. Prefer A record or AAAA record. Value is A or AAAA - -- **--dialWithIP4**="": When the current machine establishes a network connection to the outside IPv4, both TCP and UDP, it is used to specify the IPv4 used - -- **--dialWithIP6**="": When the current machine establishes a network connection to the outside IPv6, both TCP and UDP, it is used to specify the IPv6 used - -- **--dialWithNIC**="": When the current machine establishes a network connection to the outside, both TCP and UDP, it is used to specify the NIC used - -- **--dialWithSocks5**="": When the current machine establishes a network connection to the outside, both TCP and UDP, with your socks5 proxy, such as 127.0.0.1:1081 - -- **--dialWithSocks5Password**="": If there is - -- **--dialWithSocks5TCPTimeout**="": time (s) (default: 0) - -- **--dialWithSocks5UDPTimeout**="": time (s) (default: 60) - -- **--dialWithSocks5Username**="": If there is +- **--clientHKDFInfo**="": client HKDF info, most time you don't need to change this, if changed, all and each brook links in client side must be same (default: "brook") -- **--ipLimitInterval**="": Interval (s) for ipLimitMax (default: 0) +- **--log**="": Works with server, wsserver, wssserver, quicserver, dnsserver, dohserver, dnsserveroverbrook. A valid value is file path. If you want to debug SOCKS5 lib, set env SOCKS5_DEBUG=true -- **--ipLimitMax**="": Limit the number of client IP addresses, be careful when using this parameter, as the client may have dynamic IP. Works with server/wsserver/wssserver/quicserver (default: 0) +- **--pid**="": A file path used to store pid. Send SIGUSR1 to me to reset the --log or --userLog file on unix system -- **--ipLimitWait**="": How long (s) to wait for recovery after exceeding ipLimitMax (default: 0) +- **--script**="": [Brook Plus or Brook Business]. Works with server, wsserver, wssserver, quicserver, dnsserver, dohserver, dnsserveroverbrook. https://, http:// or /path/to/file.tengo. Get details at https://brook.app -- **--log**="": Enable log. A valid value is file path or 'console'. Send SIGUSR1 to me to reset the log file on unix system. If you want to debug SOCKS5 lib, set env SOCKS5_DEBUG=true +- **--scriptUpdateInterval**="": Works with --script. The interval (s) to re-fetch script. The default is 0, which means only fetch once on startup (default: 0) -- **--pid**="": A file path used to store pid. Send SIGUSR1 to me to reset the --serverLog file on unix system +- **--serverHKDFInfo**="": server HKDF info, most time you don't need to change this, if changed, all and each brook links in client side must be same (default: "brook") -- **--pprof**="": go http pprof listen addr, such as :6060 +- **--tag**="": Works with --log, --userAPI, --userLog, --script. Tag can be used to the process, will be append into log or userLog, such as: 'key1:value1'. And all tags will also be appended as query parameters one by one to the userAPI -- **--prometheus**="": prometheus http listen addr, such as :7070. If it is transmitted on the public network, it is recommended to use it with nico +- **--userAPI**="": [Brook Business]. Works with server, wsserver, wssserver, quicserver. When you build your own user system, Brook Server will send GET request to your userAPI to check if token is valid, for example: https://your-api-server.com/a_unpredictable_path. Yes, it is recommended to add an unpredictable path to your https API, of course, you can also use the http api for internal network communication. The request format is https://your-api-server.com/a_unpredictable_path?token=xxx. When the response is 200, the body should be the user's unique identifier, such as user ID; all other status codes are considered to represent an illegitimate user, and in these cases, the body should be a string describing the error. For more information, please read https://github.com/txthinking/brook/blob/master/protocol/user.md -- **--prometheusPath**="": prometheus http path, such as /xxx. If it is transmitted on the public network, a hard-to-guess value is recommended +- **--userAPIRateLimit**="": Works with --userAPI. Limit the request rate per token to the user API by Brook Server, this will reduce the load on the user API. This is especially important when users have expired, and the userAPIValidCacheTime will not cache the requests, resulting in continuous requests to the user API. The default is 0, which means no limitation. For example, setting it to 1 means the rate is limited to 1 request per token per second. The phrase 'per token' means that each token has its own rate limiter, and they do not interfere with each other (default: 1) -- **--serverHKDFInfo**="": server HKDF info, most time you don't need to change this, if changed, all and each brook links in client side must be same, I mean each (default: "brook") +- **--userAPIValidCacheTime**="": Works with --userAPI. Once a token is checked and valid, the userAPI will not be requested to validate again for a certain period (s). A reasonable value must be set, otherwise it will affect the performance of each incoming connection (default: 3600) -- **--serverLog**="": Enable server log, traffic and more. A valid value is file path or 'console'. Send SIGUSR1 to me to reset the log file on unix system. Mutually exclusive with the --log parameter. Works with server/wsserver/wssserver/quicserver with brook protocol - -- **--speedLimit**="": Limit speed (b), 500kb/s such as: 500000, works with server/wsserver/wssserver/quicserver (default: 0) - -- **--tag**="": Tag can be used to the process, will be append into log or serverLog, such as: 'key1:value1'. All tags will also be appended as query parameters one by one to the userAPI - -- **--userAPI**="": When you build your own user system, Brook Server will send GET request to your userAPI to check if token is valid, for example: https://your-api-server.com/a_unpredictable_path. Yes, it is recommended to add an unpredictable path to your https API, of course, you can also use the http api for internal network communication. The request format is https://your-api-server.com/a_unpredictable_path?token=xxx. When the response is 200, the body should be the user's unique identifier, such as user ID; all other status codes are considered to represent an illegitimate user, and in these cases, the body should be a string describing the error. It should be used with --serverLog and server/wsserver/wssserver/quicserver with brook protocol. For more information, please read https://github.com/txthinking/brook/blob/master/protocol/user.md - -- **--userAPIInvalidCacheTime**="": Once a token is checked and invalid, the userAPI will not be requested to validate again for a certain period (s). A reasonable value must be set, otherwise it will affect the performance of each incoming connection. Note that this may affect the user experience, when you change the user status from invalid to valid in your user system (default: 1800) - -- **--userAPIValidCacheTime**="": Once a token is checked and valid, the userAPI will not be requested to validate again for a certain period (s). A reasonable value must be set, otherwise it will affect the performance of each incoming connection (default: 3600) +- **--userLog**="": Works with --userAPI. Log, traffic and more. A valid value is file path. Send SIGUSR1 to me to reset the log file on unix system. Mutually exclusive with the --log parameter. - **--version, -v**: print the version @@ -498,14 +572,6 @@ Brook [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] Start a brook server that supports tcp and udp -- **--blockCIDR4List**="": This option will be removed in a future version, please use the global option instead - -- **--blockCIDR6List**="": This option will be removed in a future version, please use the global option instead - -- **--blockDomainList**="": This option will be removed in a future version, please use the global option instead - -- **--blockGeoIP**="": This option will be removed in a future version, please use the global option instead - - **--example**: Show a minimal example of usage - **--listen, -l**="": Listen address, like: ':9999' @@ -516,8 +582,6 @@ Start a brook server that supports tcp and udp - **--udpTimeout**="": time (s) (default: 0) -- **--updateListInterval**="": This option will be removed in a future version, please use the global option instead (default: 0) - ## client Start a brook client that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook client <-> $ brook server <-> dst] @@ -544,14 +608,6 @@ Start a brook client that supports tcp and udp. It can open a socks5 proxy, [src Start a brook wsserver that supports tcp and udp. It opens a standard http server and a websocket server -- **--blockCIDR4List**="": This option will be removed in a future version, please use the global option instead - -- **--blockCIDR6List**="": This option will be removed in a future version, please use the global option instead - -- **--blockDomainList**="": This option will be removed in a future version, please use the global option instead - -- **--blockGeoIP**="": This option will be removed in a future version, please use the global option instead - - **--example**: Show a minimal example of usage - **--listen, -l**="": Listen address, like: ':80' @@ -564,10 +620,6 @@ Start a brook wsserver that supports tcp and udp. It opens a standard http serve - **--udpTimeout**="": time (s) (default: 0) -- **--updateListInterval**="": This option will be removed in a future version, please use the global option instead (default: 0) - -- **--withoutBrookProtocol**: The data will not be encrypted with brook protocol - - **--xForwardedFor**: Replace the from field in --log, note that this may be forged ## wsclient @@ -596,14 +648,6 @@ Start a brook wsclient that supports tcp and udp. It can open a socks5 proxy, [s Start a brook wssserver that supports tcp and udp. It opens a standard https server and a websocket server -- **--blockCIDR4List**="": This option will be removed in a future version, please use the global option instead - -- **--blockCIDR6List**="": This option will be removed in a future version, please use the global option instead - -- **--blockDomainList**="": This option will be removed in a future version, please use the global option instead - -- **--blockGeoIP**="": This option will be removed in a future version, please use the global option instead - - **--cert**="": The cert file absolute path for the domain, such as /path/to/cert.pem. If cert or certkey is empty, a certificate will be issued automatically - **--certkey**="": The cert key file absolute path for the domain, such as /path/to/certkey.pem. If cert or certkey is empty, a certificate will be issued automatically @@ -620,10 +664,6 @@ Start a brook wssserver that supports tcp and udp. It opens a standard https ser - **--udpTimeout**="": time (s) (default: 0) -- **--updateListInterval**="": This option will be removed in a future version, please use the global option instead (default: 0) - -- **--withoutBrookProtocol**: The data will not be encrypted with brook protocol - ## wssclient Start a brook wssclient that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook wssclient <-> $ brook wssserver <-> dst] @@ -650,14 +690,6 @@ Start a brook wssclient that supports tcp and udp. It can open a socks5 proxy, [ Start a brook quicserver that supports tcp and udp. -- **--blockCIDR4List**="": This option will be removed in a future version, please use the global option instead - -- **--blockCIDR6List**="": This option will be removed in a future version, please use the global option instead - -- **--blockDomainList**="": This option will be removed in a future version, please use the global option instead - -- **--blockGeoIP**="": This option will be removed in a future version, please use the global option instead - - **--cert**="": The cert file absolute path for the domain, such as /path/to/cert.pem. If cert or certkey is empty, a certificate will be issued automatically - **--certkey**="": The cert key file absolute path for the domain, such as /path/to/certkey.pem. If cert or certkey is empty, a certificate will be issued automatically @@ -672,13 +704,9 @@ Start a brook quicserver that supports tcp and udp. - **--udpTimeout**="": time (s) (default: 0) -- **--updateListInterval**="": This option will be removed in a future version, please use the global option instead (default: 0) - -- **--withoutBrookProtocol**: The data will not be encrypted with brook protocol - ## quicclient -Start a brook quicclient that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook quicclient <-> $ brook quicserver <-> dst]. (The global-dial-parameter is ignored) +Start a brook quicclient that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook quicclient <-> $ brook quicserver <-> dst] - **--example**: Show a minimal example of usage @@ -716,19 +744,9 @@ Relay network traffic over brook, which supports TCP and UDP. Accessing [from ad ## dnsserveroverbrook -Run a dns server over brook, which supports TCP and UDP, [src <-> $ brook dnserversoverbrook <-> $ brook server/wsserver/wssserver/quicserver <-> dns] or [src <-> $ brook dnsserveroverbrook <-> dnsForBypass] +Run a dns server over brook, which supports TCP and UDP, [src <-> $ brook dnserversoverbrook <-> $ brook server/wsserver/wssserver/quicserver <-> dns] -- **--blockDomainList**="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt - -- **--bypassDomainList**="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt - -- **--disableA**: Disable A query - -- **--disableAAAA**: Disable AAAA query - -- **--dns**="": DNS server for resolving domains NOT in list (default: 8.8.8.8:53) - -- **--dnsForBypass**="": DNS server for resolving domains in bypass list. Such as 223.5.5.5:53 or https://dns.alidns.com/dns-query?address=223.5.5.5:443, the address is required (default: 223.5.5.5:53) +- **--dns**="": Forward to DNS server (default: 8.8.8.8:53) - **--example**: Show a minimal example of usage @@ -744,6 +762,24 @@ Run a dns server over brook, which supports TCP and UDP, [src <-> $ brook dnserv - **--udpTimeout**="": time (s) (default: 0) +## connect + +Run a client and connect with a brook link, which supports TCP and UDP. It can start a socks5 proxy, [src <-> socks5 <-> $ brook connect <-> $ brook server/wsserver/wssserver/quicserver <-> dst] + +- **--example**: Show a minimal example of usage + +- **--http**="": Where to listen for HTTP proxy connections + +- **--link, -l**="": brook link, you can get it via $ brook link + +- **--socks5**="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080) + +- **--socks5ServerIP**="": Only if your socks5 server IP is different from listen IP + +- **--tcpTimeout**="": time (s) (default: 0) + +- **--udpTimeout**="": time (s) (default: 0) + ## link Generate a brook link @@ -770,34 +806,14 @@ Generate a brook link - **--tlsfingerprint**="": When server is brook wssserver, select tls fingerprint, value can be: chrome -- **--token**="": A token represents a user's identity. A string encoded in hexadecimal. Server needs to have --userAPI enabled. Note that: Only supported by the brook GUI(except for OpenWrt) and tun2brook +- **--token**="": A token represents a user's identity. A string encoded in hexadecimal. Server needs to have --userAPI enabled -- **--udpoverstream**: When server is brook quicserver, UDP over Stream. Under normal circumstances, you need this parameter because the max datagram size for QUIC is very small. Note: only brook CLI and tun2brook suppport for now +- **--udpoverstream**: When server is brook quicserver, UDP over Stream. Under normal circumstances, you need this parameter because the max datagram size for QUIC is very small - **--udpovertcp**: When server is brook server, UDP over TCP - **--username, -u**="": Username, when server is socks5 server -- **--withoutBrookProtocol**: When server is brook wsserver or brook wssserver or brook quicserver, the data will not be encrypted with brook protocol - -## connect - -Run a client and connect with a brook link, which supports TCP and UDP. It can start a socks5 proxy, [src <-> socks5 <-> $ brook connect <-> $ brook server/wsserver/wssserver/quicserver <-> dst] - -- **--example**: Show a minimal example of usage - -- **--http**="": Where to listen for HTTP proxy connections - -- **--link, -l**="": brook link, you can get it via $ brook link - -- **--socks5**="": Where to listen for SOCKS5 connections (default: 127.0.0.1:1080) - -- **--socks5ServerIP**="": Only if your socks5 server IP is different from listen IP - -- **--tcpTimeout**="": time (s) (default: 0) - -- **--udpTimeout**="": time (s) (default: 0) - ## relay Run a standalone relay, which supports TCP and UDP. Accessing [from address] is equal to accessing [to address], [src <-> from address <-> to address] @@ -816,12 +832,6 @@ Run a standalone relay, which supports TCP and UDP. Accessing [from address] is Run a standalone dns server -- **--blockDomainList**="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt - -- **--disableA**: Disable A query - -- **--disableAAAA**: Disable AAAA query - - **--dns**="": DNS server which forward to. Such as 8.8.8.8:53 or https://dns.google/dns-query?address=8.8.8.8%3A443, the address is required (default: 8.8.8.8:53) - **--example**: Show a minimal example of usage @@ -850,16 +860,10 @@ Send a dns query Run a standalone doh server -- **--blockDomainList**="": One domain per line, suffix match mode. https://, http:// or local absolute file path. Like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt - - **--cert**="": The cert file absolute path for the domain, such as /path/to/cert.pem. If cert or certkey is empty, a certificate will be issued automatically - **--certkey**="": The cert key file absolute path for the domain, such as /path/to/certkey.pem. If cert or certkey is empty, a certificate will be issued automatically -- **--disableA**: Disable A query - -- **--disableAAAA**: Disable AAAA query - - **--dns**="": DNS server which forward to. Such as 8.8.8.8:53 or https://dns.google/dns-query?address=8.8.8.8%3A443, the address is required (default: 8.8.8.8:53) - **--domainaddress**="": Such as: domain.com:443, if you want to create a https server. If you choose to automatically issue certificates, the domain must have been resolved to the server IP and 80 port also will be used @@ -890,7 +894,7 @@ Send a dns query ## dhcpserver -Run a standalone dhcp server. Other running dhcp servers need to be stopped. +Run a standalone dhcp server. IPv4 only. Other running dhcp servers need to be stopped. - **--cache**="": Cache file, local absolute file path, default is $HOME/.brook.dhcpserver @@ -946,27 +950,11 @@ Convert a socks5 proxy to a http proxy, [src <-> listen address(http proxy) <-> - **--tcpTimeout**="": Connection tcp timeout (s) (default: 0) -## pac - -Run a PAC server or save PAC to a file - -- **--bypassDomainList, -b**="": One domain per line, suffix match mode. http(s):// or local absolute file path. Like: https://raw.githubusercontent.com/txthinking/brook/master/programmable/list/example_domain.txt - -- **--example**: Show a minimal example of usage - -- **--file, -f**="": Save PAC to file, this will ignore listen address - -- **--listen, -l**="": Listen address, like: 127.0.0.1:1980 - -- **--proxy, -p**="": Proxy, like: 'SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT' (default: SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT) - ## testsocks5 Test a socks5 server to see if it works properly -- **--dns**="": DNS server for connecting (default: 8.8.8.8:53) - -- **--domain**="": Domain for query (default: http3.ooo) +- **--dns**="": A DNS Server to connect to and send TCP DNS query to test TCP, and UDP DNS query to test UDP. (default: 8.8.8.8:53) - **--example**: Show a minimal example of usage @@ -976,24 +964,16 @@ Test a socks5 server to see if it works properly - **--username, -u**="": Socks5 username -- **-a**="": The A record of domain (default: 137.184.237.95) - ## testbrook -Test UDP and TCP of a brook server/wsserver/wssserver/quicserver connection. (The global-dial-parameter is ignored) +Test UDP and TCP of a brook server/wsserver/wssserver/quicserver connection. -- **--dns**="": DNS server for connecting (default: 8.8.8.8:53) - -- **--domain**="": Domain for query (default: http3.ooo) +- **--dns**="": A DNS Server to connect to and send TCP DNS query to test TCP, and UDP DNS query to test UDP. (default: 8.8.8.8:53) - **--example**: Show a minimal example of usage - **--link, -l**="": brook link. Get it via $ brook link -- **--socks5**="": Temporarily listening socks5 (default: 127.0.0.1:11080) - -- **-a**="": The A record of domain (default: 137.184.237.95) - ## echoserver Echo server, echo UDP and TCP address of routes @@ -1054,298 +1034,3 @@ Generate man.1 page Shows a list of commands or help for one command -# Examples - -List some examples of common scene commands, pay attention to replace the parameters such as IP, port, password, domain name, certificate path, etc. in the example by yourself - -## Run brook server - -``` -brook server --listen :9999 --password hello -``` - -then - -- server: `1.2.3.4:9999` -- password: `hello` - -or get brook link - -``` -brook link --server 1.2.3.4:9999 --password hello --name 'my brook server' -``` - -or get brook link with `--udpovertcp` - -``` -brook link --server 1.2.3.4:9999 --password hello --udpovertcp --name 'my brook server' -``` - -## Run brook wsserver - -``` -brook wsserver --listen :9999 --password hello -``` - -then - -- server: `ws://1.2.3.4:9999` -- password: `hello` - -or get brook link - -``` -brook link --server ws://1.2.3.4:9999 --password hello --name 'my brook wsserver' -``` - -or get brook link with domain, even if that's not your domain - -``` -brook link --server ws://hello.com:9999 --password hello --address 1.2.3.4:9999 --name 'my brook wsserver' -``` - -## Run brook wssserver: automatically certificate - -> Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80 - -``` -brook wssserver --domainaddress domain.com:443 --password hello -``` - -then - -- server: `wss://domain.com:443` -- password: `hello` - -or get brook link - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' -``` - -## Run brook wssserver Use a certificate issued by an existing trust authority - -> Make sure your domain has been resolved to your server IP successfully - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem -``` - -then - -- server: `wss://domain.com:443` -- password: `hello` - -or get brook link - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' -``` - -## Run brook wssserver issue untrusted certificates yourself, any domain - -Install [mad](https://github.com/txthinking/mad) - -``` -nami install mad -``` - -Generate root ca - -``` -mad ca --ca /root/ca.pem --key /root/cakey.pem -``` - -Generate domain cert by root ca - -``` -mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com -``` - -Run brook - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem -``` - -get brook link with `--insecure` - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --insecure -``` - -or get brook link with `--ca` - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --ca /root/ca.pem -``` - -## withoutBrookProtocol - -Better performance, but data is not strongly encrypted using Brook protocol. So please use certificate encryption, and it is not recommended to use --withoutBrookProtocol and --insecure together - -## withoutBrookProtocol automatically certificate - -> Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80 - -``` -brook wssserver --domainaddress domain.com:443 --password hello --withoutBrookProtocol -``` - -get brook link - -``` -brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol -``` - -## withoutBrookProtocol Use a certificate issued by an existing trust authority - -> Make sure your domain has been resolved to your server IP successfully - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol -``` - -get brook link - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --withoutBrookProtocol -``` - -## withoutBrookProtocol issue untrusted certificates yourself, any domain - -Install [mad](https://github.com/txthinking/mad) - -``` -nami install mad -``` - -Generate root ca - -``` -mad ca --ca /root/ca.pem --key /root/cakey.pem -``` - -Generate domain cert by root ca - -``` -mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com -``` - -Run brook wssserver - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol -``` - -Get brook link - -``` -brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol --address 1.2.3.4:443 --ca /root/ca.pem -``` - -## Run brook socks5, A stand-alone standard socks5 server - -``` -brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4 -``` - -then - -- server: `1.2.3.4:1080` - -or get brook link - -``` -brook link --server socks5://1.2.3.4:1080 -``` - -## Run brook socks5 with username and password. A stand-alone standard socks5 server - -``` -brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4 --username hello --password world -``` - -then - -- server: `1.2.3.4:1080` -- username: `hello` -- password: `world` - -or get brook link - -``` -brook link --server socks5://1.2.3.4:1080 --username hello --password world -``` - -## brook relayoverbrook can relay a local address to a remote address over brook, both TCP and UDP, it works with brook server wsserver wssserver. - -``` -brook relayoverbrook ... --from 127.0.0.1:5353 --to 8.8.8.8:53 -``` - -## brook dnsserveroverbrook can create a encrypted DNS server, both TCP and UDP, it works with brook server wsserver wssserver. - -``` -brook dnsserveroverbrook ... --listen 127.0.0.1:53 -``` - -## Brook OpenWRT Router: Perfectly supports IPv4/IPv6/TCP/UDP. Native IPv6 - -https://www.txthinking.com/talks/articles/brook-openwrt-en.article - -## Turn macOS into a Gateway with Brook - -https://www.txthinking.com/talks/articles/brook-macos-gateway-en.article - -## Turn Windows into a Gateway with Brook - -https://www.txthinking.com/talks/articles/brook-windows-gateway-en.article - -## Turn Linux into a Gateway with Brook - -https://www.txthinking.com/talks/articles/brook-linux-gateway-en.article - -## brook relay can relay a address to a remote address. It can relay any tcp and udp server - -``` -brook relay --from :9999 --to 1.2.3.4:9999 -``` - -## brook socks5tohttp can convert a socks5 to a http proxy - -``` -brook socks5tohttp --socks5 127.0.0.1:1080 --listen 127.0.0.1:8010 -``` - -## There are countless examples; for more feature suggestions, it's best to look at the commands and parameters in the CLI documentation one by one, and blog, YouTube... -# Resources - -| CLI | Description | -| --- | --- | -| [nami](https://github.com/txthinking/nami) | A clean and tidy decentralized package manager | -| [joker](https://github.com/txthinking/joker) | Joker can turn process into daemon. Zero-Configuration | -| [nico](https://github.com/txthinking/nico) | Nico can work with brook wsserver together | -| [z](https://github.com/txthinking/z) | z - process manager | -| [tun2brook](https://github.com/txthinking/tun2brook) | Proxy all traffic just one line command | -| [mad](https://github.com/txthinking/mad) | Generate root CA and derivative certificate for any domains and any IPs | -| [hancock](https://github.com/txthinking/hancock) | Manage multiple remote servers and execute commands remotely | -| [sshexec](https://github.com/txthinking/sshexec) | A command-line tool to execute remote command through ssh | -| [jb](https://github.com/txthinking/jb) | write script in an easier way than bash | -| [bash](https://github.com/txthinking/bash) | Many one-click scripts | -| [docker](https://hub.docker.com/r/txthinking/brook) | `docker run txthinking/brook` | - -| Resources | Description | -| --- | --- | -| [Protocol](https://github.com/txthinking/brook/tree/master/protocol) | Brook Protocol | -| [Blog](https://www.txthinking.com/talks/) | Some articles you should read | -| [YouTube](https://www.youtube.com/txthinking) | Some videos you should watch | -| [Telegram](https://t.me/txthinking) | Ask questions here | -| [Announce](https://t.me/s/txthinking_news) | All news you should care | -| [GitHub](https://github.com/txthinking) | Other useful repos | -| [Socks5 Configurator](https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb) | If you prefer CLI brook client | -| [IPvBar](https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj) | See domain, IP and country in browser | -| [TxThinking SSH](https://www.txthinking.com/ssh.html) | A SSH Terminal | -| [brook-user-system](https://github.com/txthinkinginc/brook-user-system) | A Brook User System | -| [TxThinking](https://www.txthinking.com) | Everything | - diff --git a/brook/docs/build.js b/brook/docs/build.js index 50c17fe97d..96a118880d 100755 --- a/brook/docs/build.js +++ b/brook/docs/build.js @@ -14,17 +14,16 @@ await fs.write(f.fd, '**❤️ [Shiliew - A network app designed for those who var s = await fs.readFile('getting-started.md', { encoding: 'utf8' }) await fs.write(f.fd, s) -var s = await fs.readFile('gui.md', { encoding: 'utf8' }) +var s = await fs.readFile('server.md', { encoding: 'utf8' }) +await fs.write(f.fd, s) +var s = await fs.readFile('client.md', { encoding: 'utf8' }) +await fs.write(f.fd, s) +var s = await fs.readFile('other.md', { encoding: 'utf8' }) await fs.write(f.fd, s) await fs.write(f.fd, '# CLI Documentation\n') -await fs.write(f.fd, 'Each subcommand has a `--example` parameter that can print the minimal example of usage\n') var s = await $`brook mdpage`.text() s = s.split("\n").filter(v => !v.startsWith("[")).join("\n").replace("```\n```", "```\nbrook --help\n```").split("\n").map(v => v.startsWith("**") && !v.startsWith("**Usage") ? "- " + v : v).join('\n') s = s.replace("### help, h", "").replace("Shows a list of commands or help for one command", "").replaceAll("- **--help, -h**: show help", "") await fs.write(f.fd, s) -var s = await fs.readFile('example.md', { encoding: 'utf8' }) -await fs.write(f.fd, s) -var s = await fs.readFile('resources.md', { encoding: 'utf8' }) -await fs.write(f.fd, s) await fs.close(f.fd) await $`markdown ../readme.md ./index.html` diff --git a/brook/docs/gui.md b/brook/docs/client.md similarity index 58% rename from brook/docs/gui.md rename to brook/docs/client.md index 3582f86ec1..9901073dc2 100644 --- a/brook/docs/gui.md +++ b/brook/docs/client.md @@ -1,7 +1,5 @@ # Client -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` - ## CLI Before discussing the GUI client, let's first talk about the command line client `brook`. As we know, after you have deployed the server, you can use the command line client `brook` to create a local socks5 proxy or http proxy on your machine, and then configure it in your system proxy settings or in your browser to use this proxy. However: @@ -13,106 +11,52 @@ For the specifics of socks5 and http proxy, you can read [this article](https:// ## GUI -The GUI client does not use socks5 and http proxy mode, so there is no issue with some software not using the system proxy. Instead, it uses a virtual network card to take over the entire system's network, including UDP-based http3. Moreover, Brook allows us to control network requests programmatically, so it is necessary to have basic knowledge of network requests. +The GUI client does not use socks5 and http proxy mode, so there is no issue with some software not using the system proxy. Instead, it uses a virtual network card to take over the entire system's network, including UDP-based http3. Moreover, Brook allows us to control network requests programmatically, so it is necessary to have basic knowledge of network requests. 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` -## Without Brook: Basic Knowledge of Network Requests +## Without Brook > Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: `google.com:443`, or an IP address: `8.8.8.8:53` +![x](./images/network.svg) + 1. When an app requests a domain address, such as `google.com:443` 2. It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com` - 1. The system DNS will return the IP of `google.com`, such as `1.2.3.4`, to the app +1. The system DNS will return the IP of `google.com`, such as `1.2.3.4`, to the app 3. The app will combine the IP and port into an IP address, such as: `1.2.3.4:443` 4. The app makes a network request to this IP address `1.2.3.4:443` 5. The app receives the response data In the above process, the app actually makes two network requests: one to the IP address `8.8.8.8:53` and another to the IP address `1.2.3.4:443`. In other words, the domain name is essentially an alias for the IP, and must obtain the domain's IP to establish a connection. -## With Brook: Fake DNS On +## With Brook -Brook has a Fake DNS feature, which can parse the domain name out of the query requests that an app sends to the system DNS and decide how to respond to the app. +Brook has a Fake DNS feature default, which can parse the domain name out of the query requests that an app sends to the system DNS UDP 53 and decide how to respond to the app. + +![x](./images/brook-client.svg) 1. When an app requests a domain name address, such as `google.com:443` 2. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com` 3. The Brook client detects that an app is sending a network request to `8.8.8.8:53`. This will trigger the `in_dnsquery` variable, carrying information such as `domain` - 1. The Brook client returns a fake IP to the app, such as `240.0.0.1` +1. The Brook client returns a fake IP to the app, such as `240.0.0.1` 4. The app combines the IP and port into an IP address, such as: `240.0.0.1:443` 5. The app makes a network request to the IP address `240.0.0.1:443` 6. The Brook client detects that an app is sending a network request to `240.0.0.1:443`, discovers that this is a fake IP, and will convert the fake IP address back to the domain address `google.com:443`. This will trigger the `in_address` variable, carrying information such as `domainaddress` - 1. The Brook client sends `google.com:443` to the Brook Server - 2. The Brook Server first requests its own DNS to resolve the domain name to find out the IP of `google.com`, such as receiving `1.2.3.4` - 3. The Brook Server combines the IP and port into an IP address, such as: `1.2.3.4:443` - 4. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client - 5. The Brook client then returns the data to the app +1. The Brook client sends `google.com:443` to the Brook Server +2. The Brook Server first requests its own DNS to resolve the domain name to find out the IP of `google.com`, such as receiving `1.2.3.4` +3. The Brook Server combines the IP and port into an IP address, such as: `1.2.3.4:443` +4. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client +5. The Brook client then returns the data to the app 7. The app receives the response data -However, if the following situations occur, the domain name will not/cannot be parsed, meaning that the Brook client will not/cannot know what the domain name is and will treat it as a normal request sent to an IP address: +However, if the following situations occur, the domain name will not/cannot be parsed, meaning that the Brook client will not/cannot know what the domain name is and will treat it as a normal request sent to an IP address. To avoid the ineffectiveness of Fake DNS, please refer to [this article](https://www.txthinking.com/talks/articles/brook-fakedns-en.article): - Fake DNS not enabled: in this case, the Brook client will not attempt to parse the domain name from the request sent to the system DNS and will treat it as a normal request sent to an IP address. - Even with Fake DNS enabled, but the app uses the system's secure DNS or the app's own secure DNS: in this case, the Brook client cannot parse the domain name from the request sent to the secure DNS and will treat it as a normal request sent to an IP address. -To avoid the ineffectiveness of Fake DNS, please refer to [this article](https://www.txthinking.com/talks/articles/brook-fakedns-en.article). +Script can do more: -## With Brook: Fake DNS Off - -1. When an app requests a domain address, such as `google.com:443` -2. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com` -3. The Brook client detects that an app is sending a network request to `8.8.8.8:53`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `8.8.8.8:53` to the Brook Server - 2. The Brook Server sends a network request to `8.8.8.8:53` and returns the result, such as `1.2.3.4`, to the Brook client - 3. The Brook client then returns the result to the app -4. The app combines the IP and port into an IP address, such as: `1.2.3.4:443` -5. The app makes a network request to the IP address `1.2.3.4:443` -6. The Brook client detects that an app is sending a network request to `1.2.3.4:443`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `1.2.3.4:443` to the Brook Server - 2. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client - 3. The Brook client then returns the data to the app -7. The app receives the response data - -## With Brook: Fake DNS On, But the App Uses the System's Secure DNS or Its Own Secure DNS - -1. When an app requests a domain name address, such as `google.com:443` -2. A DNS resolution will be performed first. That is, the app will send a network request to the secure DNS, such as `8.8.8.8:443`, to inquire about the IP of `google.com` -3. The Brook client detects that an app is sending a network request to `8.8.8.8:443`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `8.8.8.8:443` to the Brook Server - 2. The Brook Server sends a network request to `8.8.8.8:443`, and returns the result, such as `1.2.3.4`, to the Brook client - 3. The Brook client then returns the result to the app -4. The app combines the IP and port into an IP address, such as: `1.2.3.4:443` -5. The app makes a network request to the IP address `1.2.3.4:443` -6. The Brook client detects that an app is sending a network request to `1.2.3.4:443`. This will trigger the `in_address` variable, carrying information such as `ipaddress` - 1. The Brook client sends `1.2.3.4:443` to the Brook Server - 2. The Brook Server sends a network request to `1.2.3.4:443` and returns the data to the Brook client - 3. The Brook client then returns the data to the app -7. The app receives the response data - -To avoid the ineffectiveness of Fake DNS, please refer to [this article](https://www.txthinking.com/talks/articles/brook-fakedns-en.article). - -## Handle Variable Trigger - -- When the `in_brooklinks` variable is triggered: - - This is currently the only variable that gets triggered before the Brook client starts. - - We know that Brook starts with your choice of a Brook Server, and this variable lets you specify multiple Brook Servers. - - Then during runtime, you can use one of these Brook Servers as needed. -- When the `in_dnsquery` variable is triggered, you can process as needed, such as: - - Blocking, such as to prevent ad domain names. - - Directly specifying the response IP. - - Letting the system DNS resolve this domain. - - Letting Bypass DNS resolve this domain. - - And so on. -- When the `in_address` variable is triggered, you can process as needed, such as: - - Block this connection. - - Rewrite the destination. - - If it's a domain address, you can specify that Bypass DNS is responsible for resolving the IP of this domain. - - Allow it to connect directly without going through a proxy. - - If it's HTTP/HTTPS, you can start MITM (Man-In-The-Middle), which will subsequently trigger `in_httprequest` and `in_httpresponse`. - - And so on. -- When the `in_httprequest` variable is triggered, you can process as needed, such as: - - Modifying the HTTP request. - - Returning a custom HTTP response directly. -- When the `in_httpresponse` variable is triggered, you can process as needed, such as: - - Modifying the HTTP response. - -For detailed information on the properties and responses of variables, please refer to the following content. +- In the `script: in_dnsquery` step, script can do more, read more below +- In the `script: in_address` step, script can do more, read more below ## Variables @@ -120,9 +64,9 @@ For detailed information on the properties and responses of variables, please re | ------------------------------ | ---- | ----------- | --------------------------------- | ------------------------------------------------- | -------- | | 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_address | map | / | When connecting to an address | Script can decide how to handle this request | map | +| in_httprequest | map | / | When an HTTP(S) request comes in | Script can decide how to handle this request | map | +| in_httprequest,in_httpresponse | map | / | when an HTTP(S) response comes in | Script can decide how to handle this response | map | ## in_brooklinks @@ -144,42 +88,40 @@ For detailed information on the properties and responses of variables, please re | ------ | ------ | ----------- | ---------- | | 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 | +| appid | string | macOS App Mode: this is app id; Linux and Windows: this is app path; OpenWrt: this is IP address of client device. Note: In some operating systems, the app may initiate DNS queries through the system app. | com.google.Chrome.helper | `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 | +| ip | string | Ignore fake DNS, specify IP directly, only valid when `type` is `A`/`AAAA` | 1.2.3.4 | +| system | bool | Ignore fake DNS, resolve by System DNS over brook, default `false` | false | +| bypass | bool | Ignore fake DNS, resolve by Bypass DNS, default `false` | false | +| brooklinkkey | string | When need to connect the Server, instead, perfer 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 | +| ipaddress | string | IP type address. There is only one 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 | +| appid | string | macOS App Mode: this is app id; Linux and Windows: this is app path; OpenWrt: this is IP address of client device | com.google.Chrome.helper | `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 | +| ipaddress | string | Rewrite destination to an ip address | 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 | +| bypass | bool | Bypass, default `false`. If `true` and `domainaddress` exists, 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 | +| mitmcertdomain | string | The MITM certificate domain name, which is taken from `domainaddress` by default. If `ipaddress` exists 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 | +| mitmautohandlecompress | bool | Whether to automatically decompress the http body when interacting with the script, default `false`. Usually need set this to true | 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 | @@ -194,7 +136,7 @@ For detailed information on the properties and responses of variables, please re | Body | bytes | HTTP request body | / | | ... | string | other fields are HTTP headers | / | -`out`, must be set to a request or response +`out`, must be set to an unmodified or modified request or a response ## in_httpresponse @@ -204,11 +146,11 @@ For detailed information on the properties and responses of variables, please re | Body | bytes | HTTP response body | / | | ... | string | other fields are HTTP headers | / | -`out`, must be set to a response +`out`, must be set to an unmodified or modified response ## Modules -In Brook GUI, scripts are abstracted into **Modules**. There are already [some modules](https://github.com/txthinking/brook/blob/master/programmable/modules/), and thre is no magic, it just automatically combine [_header.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_header.tengo) and [_footer.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_footer.tengo), so you only need to write the module itself. +In Brook GUI, scripts are abstracted into **Modules**. There are already [some modules](https://github.com/txthinking/brook/blob/master/programmable/modules/), and there is no magic, it just automatically combine [_header.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_header.tengo) and [_footer.tengo](https://github.com/txthinking/brook/blob/master/programmable/modules/_footer.tengo), so you only need to write the module itself. ``` modules = append(modules, { @@ -235,11 +177,11 @@ modules = append(modules, { }) ``` -## tun2brook +## ipio -https://github.com/txthinking/tun2brook +https://github.com/txthinking/ipio -If you are using tun2brook, you can manually combine multiple modules into a complete script in the following way. For example: +ipio uses the same script as the GUI. If you are using ipio, you can manually combine multiple modules into a complete script in the following way. For example: ``` cat _header.tengo > my.tengo @@ -250,56 +192,24 @@ cat block_aaaa.tengo >> my.tengo cat _footer.tengo >> my.tengo ``` -## Syntax +## openwrt -[Tengo Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md) +https://www.txthinking.com/talks/articles/brook-openwrt-en.article -Library +openwrt uses the same script as the GUI. If you are using openwrt, you can manually combine multiple modules into a complete script in the following way. For example: -- [text](https://github.com/d5/tengo/blob/master/docs/stdlib-text.md): regular expressions, string conversion, and manipulation -- [math](https://github.com/d5/tengo/blob/master/docs/stdlib-math.md): mathematical constants and functions -- [times](https://github.com/d5/tengo/blob/master/docs/stdlib-times.md): time-related functions -- [rand](https://github.com/d5/tengo/blob/master/docs/stdlib-rand.md): random functions -- [fmt](https://github.com/d5/tengo/blob/master/docs/stdlib-fmt.md): formatting functions -- [json](https://github.com/d5/tengo/blob/master/docs/stdlib-json.md): JSON functions -- [enum](https://github.com/d5/tengo/blob/master/docs/stdlib-enum.md): Enumeration functions -- [hex](https://github.com/d5/tengo/blob/master/docs/stdlib-hex.md): hex encoding and decoding functions -- [base64](https://github.com/d5/tengo/blob/master/docs/stdlib-base64.md): base64 encoding and decoding functions -- `brook`: brook module +``` +cat _header.tengo > my.tengo - ``` - Constants +cat block_google_secure_dns.tengo >> my.tengo +cat block_aaaa.tengo >> my.tengo - * 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 - ``` +cat _footer.tengo >> my.tengo +``` ## Debug -If you are writing complex scripts, the GUI may not be convenient for debugging. It is recommended to use [tun2brook](https://github.com/txthinking/tun2brook) on desktop to debug with `fmt.println` +If you are writing complex scripts, the GUI may not be convenient for debugging. It is recommended to use [ipio](https://github.com/txthinking/ipio) on desktop to debug with `fmt.println` ## CA @@ -314,10 +224,6 @@ https://txthinking.github.io/ca/ca.pem > Some software may not read the system CA,you can use `curl --cacert ~/.nami/bin/ca.pem` to debug -## OpenWrt - -[Brook OpenWRT: Perfectly supports IPv4/IPv6/TCP/UDP](https://www.txthinking.com/talks/articles/brook-openwrt-en.article) - ## IPv6 Brook's stance on IPv6 is positive, if your server or local environment doesn't have an IPv6 stack, read [this article](https://www.txthinking.com/talks/articles/brook-ipv6-en.article). diff --git a/brook/docs/example.md b/brook/docs/example.md deleted file mode 100644 index 1ae9d00f1c..0000000000 --- a/brook/docs/example.md +++ /dev/null @@ -1,265 +0,0 @@ -# Examples - -List some examples of common scene commands, pay attention to replace the parameters such as IP, port, password, domain name, certificate path, etc. in the example by yourself - -## Run brook server - -``` -brook server --listen :9999 --password hello -``` - -then - -- server: `1.2.3.4:9999` -- password: `hello` - -or get brook link - -``` -brook link --server 1.2.3.4:9999 --password hello --name 'my brook server' -``` - -or get brook link with `--udpovertcp` - -``` -brook link --server 1.2.3.4:9999 --password hello --udpovertcp --name 'my brook server' -``` - -## Run brook wsserver - -``` -brook wsserver --listen :9999 --password hello -``` - -then - -- server: `ws://1.2.3.4:9999` -- password: `hello` - -or get brook link - -``` -brook link --server ws://1.2.3.4:9999 --password hello --name 'my brook wsserver' -``` - -or get brook link with domain, even if that's not your domain - -``` -brook link --server ws://hello.com:9999 --password hello --address 1.2.3.4:9999 --name 'my brook wsserver' -``` - -## Run brook wssserver: automatically certificate - -> Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80 - -``` -brook wssserver --domainaddress domain.com:443 --password hello -``` - -then - -- server: `wss://domain.com:443` -- password: `hello` - -or get brook link - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' -``` - -## Run brook wssserver Use a certificate issued by an existing trust authority - -> Make sure your domain has been resolved to your server IP successfully - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem -``` - -then - -- server: `wss://domain.com:443` -- password: `hello` - -or get brook link - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' -``` - -## Run brook wssserver issue untrusted certificates yourself, any domain - -Install [mad](https://github.com/txthinking/mad) - -``` -nami install mad -``` - -Generate root ca - -``` -mad ca --ca /root/ca.pem --key /root/cakey.pem -``` - -Generate domain cert by root ca - -``` -mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com -``` - -Run brook - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem -``` - -get brook link with `--insecure` - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --insecure -``` - -or get brook link with `--ca` - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --ca /root/ca.pem -``` - -## withoutBrookProtocol - -Better performance, but data is not strongly encrypted using Brook protocol. So please use certificate encryption, and it is not recommended to use --withoutBrookProtocol and --insecure together - -## withoutBrookProtocol automatically certificate - -> Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80 - -``` -brook wssserver --domainaddress domain.com:443 --password hello --withoutBrookProtocol -``` - -get brook link - -``` -brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol -``` - -## withoutBrookProtocol Use a certificate issued by an existing trust authority - -> Make sure your domain has been resolved to your server IP successfully - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol -``` - -get brook link - -``` -brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --withoutBrookProtocol -``` - -## withoutBrookProtocol issue untrusted certificates yourself, any domain - -Install [mad](https://github.com/txthinking/mad) - -``` -nami install mad -``` - -Generate root ca - -``` -mad ca --ca /root/ca.pem --key /root/cakey.pem -``` - -Generate domain cert by root ca - -``` -mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com -``` - -Run brook wssserver - -``` -brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol -``` - -Get brook link - -``` -brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol --address 1.2.3.4:443 --ca /root/ca.pem -``` - -## Run brook socks5, A stand-alone standard socks5 server - -``` -brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4 -``` - -then - -- server: `1.2.3.4:1080` - -or get brook link - -``` -brook link --server socks5://1.2.3.4:1080 -``` - -## Run brook socks5 with username and password. A stand-alone standard socks5 server - -``` -brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4 --username hello --password world -``` - -then - -- server: `1.2.3.4:1080` -- username: `hello` -- password: `world` - -or get brook link - -``` -brook link --server socks5://1.2.3.4:1080 --username hello --password world -``` - -## brook relayoverbrook can relay a local address to a remote address over brook, both TCP and UDP, it works with brook server wsserver wssserver. - -``` -brook relayoverbrook ... --from 127.0.0.1:5353 --to 8.8.8.8:53 -``` - -## brook dnsserveroverbrook can create a encrypted DNS server, both TCP and UDP, it works with brook server wsserver wssserver. - -``` -brook dnsserveroverbrook ... --listen 127.0.0.1:53 -``` - -## Brook OpenWRT Router: Perfectly supports IPv4/IPv6/TCP/UDP. Native IPv6 - -https://www.txthinking.com/talks/articles/brook-openwrt-en.article - -## Turn macOS into a Gateway with Brook - -https://www.txthinking.com/talks/articles/brook-macos-gateway-en.article - -## Turn Windows into a Gateway with Brook - -https://www.txthinking.com/talks/articles/brook-windows-gateway-en.article - -## Turn Linux into a Gateway with Brook - -https://www.txthinking.com/talks/articles/brook-linux-gateway-en.article - -## brook relay can relay a address to a remote address. It can relay any tcp and udp server - -``` -brook relay --from :9999 --to 1.2.3.4:9999 -``` - -## brook socks5tohttp can convert a socks5 to a http proxy - -``` -brook socks5tohttp --socks5 127.0.0.1:1080 --listen 127.0.0.1:8010 -``` - -## There are countless examples; for more feature suggestions, it's best to look at the commands and parameters in the CLI documentation one by one, and blog, YouTube... diff --git a/brook/docs/getting-started.md b/brook/docs/getting-started.md index 7b929673c8..d0410e382b 100644 --- a/brook/docs/getting-started.md +++ b/brook/docs/getting-started.md @@ -21,12 +21,12 @@ brook server -l :9999 -p hello - [macOS](https://apps.apple.com/us/app/brook-network-tool/id1216002642) - [Windows](https://github.com/txthinking/brook/releases/latest/download/Brook.msix) - [Linux](https://github.com/txthinking/brook/releases/latest/download/Brook.bin) -- [OpenWrt](https://github.com/txthinking/brook/releases) +- [OpenWrt](https://www.txthinking.com/talks/articles/brook-openwrt-en.article) > You may want to use `brook link` to customize some parameters - [About App Mode on macOS](https://www.txthinking.com/talks/articles/macos-app-mode-en.article) -- [How to install Brook on Windows?](https://www.txthinking.com/talks/articles/msix-brook-en.article) +- [How to install Brook on Windows](https://www.txthinking.com/talks/articles/msix-brook-en.article) - [How to install Brook on Linux](https://www.txthinking.com/talks/articles/linux-app-brook-en.article) - [How to install Brook on OpenWrt](https://www.txthinking.com/talks/articles/brook-openwrt-en.article) diff --git a/brook/docs/images/brook-client.svg b/brook/docs/images/brook-client.svg new file mode 100644 index 0000000000..6a1e81b658 --- /dev/null +++ b/brook/docs/images/brook-client.svg @@ -0,0 +1,855 @@ +

App wants to connect google.com:443

+
AppSystem DNS(8.8.8.8:53)BrookServer query IP of google.comquery IP of google.comdefault: the IP is f.a.k.ethe IP is f.a.k.econnect f.a.k.e:443default: connect google.com:443script: in_dnsqueryscript: in_address + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/brook/docs/images/brook-dns-server.svg b/brook/docs/images/brook-dns-server.svg new file mode 100644 index 0000000000..18c5b3aac9 --- /dev/null +++ b/brook/docs/images/brook-dns-server.svg @@ -0,0 +1,849 @@ +

Client wants to query google.com

+
ClientBrook DNS Server--dns I want query IP of google.comdefault: query IP of google.comscript: in_dnsquery + + + + + + + + +
\ No newline at end of file diff --git a/brook/docs/images/brook-server.svg b/brook/docs/images/brook-server.svg new file mode 100644 index 0000000000..e91cd6d0fc --- /dev/null +++ b/brook/docs/images/brook-server.svg @@ -0,0 +1,852 @@ +

Client wants to proxy google.com:443

+
Brook ClientBrook ServerServer System DNSgoogle.com:443 I want to proxy of google.com:443default: query IP of google.comthe IP is 1.2.3.4default: connect 1.2.3.4:443script: in_address + + + + + + + + + + + +
\ No newline at end of file diff --git a/brook/docs/images/network.svg b/brook/docs/images/network.svg new file mode 100644 index 0000000000..7fcdca648e --- /dev/null +++ b/brook/docs/images/network.svg @@ -0,0 +1,849 @@ +

App wants to connect google.com:443

+
AppSystem DNS(8.8.8.8:53)google.com:443 query IP of google.comthe IP is 1.2.3.4connect 1.2.3.4:443 + + + + + + + + +
\ No newline at end of file diff --git a/brook/docs/index.html b/brook/docs/index.html index 6600dbce5d..91040b6fa4 100644 --- a/brook/docs/index.html +++ b/brook/docs/index.html @@ -1160,30 +1160,43 @@
  • Client
  • -
  • Client
  • -
  • Examples -
  • -
  • Resources
  • @@ -1260,30 +1248,43 @@
  • Client
  • -
  • Client
  • -
  • Examples -
  • -
  • Resources
  • @@ -1368,171 +1344,73 @@
  • macOS
  • Windows
  • Linux
  • -
  • OpenWrt
  • +
  • OpenWrt
  • You may want to use brook link to customize some parameters

    -

    Client

    -

    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

    -

    CLI

    -

    Before discussing the GUI client, let's first talk about the command line client brook. As we know, after you have deployed the server, you can use the command line client brook to create a local socks5 proxy or http proxy on your machine, and then configure it in your system proxy settings or in your browser to use this proxy. However:

    -
      -
    1. Not all apps will use this proxy, whether they use it is up to the app itself.
    2. -
    3. Generally, all UDP protocols will not go through this proxy, such as http3.
    4. -
    -

    For the specifics of socks5 and http proxy, you can read this article.

    -

    GUI

    -

    The GUI client does not use socks5 and http proxy mode, so there is no issue with some software not using the system proxy. Instead, it uses a virtual network card to take over the entire system's network, including UDP-based http3. Moreover, Brook allows us to control network requests programmatically, so it is necessary to have basic knowledge of network requests.

    -

    Without Brook: Basic Knowledge of Network Requests

    -
    -

    Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: google.com:443, or an IP address: 8.8.8.8:53

    -
    -
      -
    1. When an app requests a domain address, such as google.com:443
    2. -
    3. It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as 8.8.8.8:53, to inquire about the IP of google.com
        -
      1. The system DNS will return the IP of google.com, such as 1.2.3.4, to the app
      2. -
      -
    4. -
    5. The app will combine the IP and port into an IP address, such as: 1.2.3.4:443
    6. -
    7. The app makes a network request to this IP address 1.2.3.4:443
    8. -
    9. The app receives the response data
    10. -
    -

    In the above process, the app actually makes two network requests: one to the IP address 8.8.8.8:53 and another to the IP address 1.2.3.4:443. In other words, the domain name is essentially an alias for the IP, and must obtain the domain's IP to establish a connection.

    -

    With Brook: Fake DNS On

    -

    Brook has a Fake DNS feature, which can parse the domain name out of the query requests that an app sends to the system DNS and decide how to respond to the app.

    -
      -
    1. When an app requests a domain name address, such as google.com:443
    2. -
    3. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as 8.8.8.8:53, to inquire about the IP of google.com
    4. -
    5. The Brook client detects that an app is sending a network request to 8.8.8.8:53. This will trigger the in_dnsquery variable, carrying information such as domain
        -
      1. The Brook client returns a fake IP to the app, such as 240.0.0.1
      2. -
      -
    6. -
    7. The app combines the IP and port into an IP address, such as: 240.0.0.1:443
    8. -
    9. The app makes a network request to the IP address 240.0.0.1:443
    10. -
    11. The Brook client detects that an app is sending a network request to 240.0.0.1:443, discovers that this is a fake IP, and will convert the fake IP address back to the domain address google.com:443. This will trigger the in_address variable, carrying information such as domainaddress
        -
      1. The Brook client sends google.com:443 to the Brook Server
      2. -
      3. The Brook Server first requests its own DNS to resolve the domain name to find out the IP of google.com, such as receiving 1.2.3.4
      4. -
      5. The Brook Server combines the IP and port into an IP address, such as: 1.2.3.4:443
      6. -
      7. The Brook Server sends a network request to 1.2.3.4:443 and returns the data to the Brook client
      8. -
      9. The Brook client then returns the data to the app
      10. -
      -
    12. -
    13. The app receives the response data
    14. -
    -

    However, if the following situations occur, the domain name will not/cannot be parsed, meaning that the Brook client will not/cannot know what the domain name is and will treat it as a normal request sent to an IP address:

    +

    Server

    +

    brook dnsserver, dohserver, dnsserveroverbrook, server, wsserver, wssserver, quicserver can use script to do more complex thing. brook 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

    +

    Brook DNS Server

    +

    x

    +

    Script can do more:

    -

    To avoid the ineffectiveness of Fake DNS, please refer to this article.

    -

    With Brook: Fake DNS Off

    -
      -
    1. When an app requests a domain address, such as google.com:443
    2. -
    3. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as 8.8.8.8:53, to inquire about the IP of google.com
    4. -
    5. The Brook client detects that an app is sending a network request to 8.8.8.8:53. This will trigger the in_address variable, carrying information such as ipaddress
        -
      1. The Brook client sends 8.8.8.8:53 to the Brook Server
      2. -
      3. The Brook Server sends a network request to 8.8.8.8:53 and returns the result, such as 1.2.3.4, to the Brook client
      4. -
      5. The Brook client then returns the result to the app
      6. -
      -
    6. -
    7. The app combines the IP and port into an IP address, such as: 1.2.3.4:443
    8. -
    9. The app makes a network request to the IP address 1.2.3.4:443
    10. -
    11. The Brook client detects that an app is sending a network request to 1.2.3.4:443. This will trigger the in_address variable, carrying information such as ipaddress
        -
      1. The Brook client sends 1.2.3.4:443 to the Brook Server
      2. -
      3. The Brook Server sends a network request to 1.2.3.4:443 and returns the data to the Brook client
      4. -
      5. The Brook client then returns the data to the app
      6. -
      -
    12. -
    13. The app receives the response data
    14. -
    -

    With Brook: Fake DNS On, But the App Uses the System's Secure DNS or Its Own Secure DNS

    -
      -
    1. When an app requests a domain name address, such as google.com:443
    2. -
    3. A DNS resolution will be performed first. That is, the app will send a network request to the secure DNS, such as 8.8.8.8:443, to inquire about the IP of google.com
    4. -
    5. The Brook client detects that an app is sending a network request to 8.8.8.8:443. This will trigger the in_address variable, carrying information such as ipaddress
        -
      1. The Brook client sends 8.8.8.8:443 to the Brook Server
      2. -
      3. The Brook Server sends a network request to 8.8.8.8:443, and returns the result, such as 1.2.3.4, to the Brook client
      4. -
      5. The Brook client then returns the result to the app
      6. -
      -
    6. -
    7. The app combines the IP and port into an IP address, such as: 1.2.3.4:443
    8. -
    9. The app makes a network request to the IP address 1.2.3.4:443
    10. -
    11. The Brook client detects that an app is sending a network request to 1.2.3.4:443. This will trigger the in_address variable, carrying information such as ipaddress
        -
      1. The Brook client sends 1.2.3.4:443 to the Brook Server
      2. -
      3. The Brook Server sends a network request to 1.2.3.4:443 and returns the data to the Brook client
      4. -
      5. The Brook client then returns the data to the app
      6. -
      -
    12. -
    13. The app receives the response data
    14. -
    -

    To avoid the ineffectiveness of Fake DNS, please refer to this article.

    -

    Handle Variable Trigger

    +

    Brook Server

    +

    x

    +

    Script can do more:

    -

    For detailed information on the properties and responses of variables, please refer to the following content.

    Variables

    - + + + + + + + + + + + + + + + + + - - - + + + - + @@ -1540,26 +1418,102 @@ - - - + + + +
    variable typeconditioncommand timing description out type
    in_dnsserversmapdnsserver/dnsserveroverbrook/dohserver/server/wsserver/wssserver/quicserverWhen just runningPredefine multiple dns servers, and then programmatically specify which one to usemap
    in_dohserversmapdnsserver/dnsserveroverbrook/dohserver/server/wsserver/wssserver/quicserverWhen just runningPredefine multiple doh servers, and then programmatically specify which one to usemap
    in_brooklinks map/Before connectingPredefine multiple brook links, and then programmatically specify which one to connect toserver/wsserver/wssserver/quicserverWhen just runningPredefine multiple brook links, and then programmatically specify which one to use map
    in_dnsquery mapFakeDNS: Ondnsserver/dnsserveroverbrook/dohserver When a DNS query occurs Script can decide how to handle this request map
    in_address map/When connecting to an addressscript can decide how to connectserver/wsserver/wssserver/quicserverWhen the Server connects the proxied addressScript can decide how to handle this request map
    +

    in_dnsservers

    + + - - - - - - + + + + + + + + + + + + +
    in_httprequestmap/When an HTTP(S) request comes inthe script can decide how to handle this requestmapKeyTypeDescriptionExample
    _boolmeaninglesstrue
    +

    out, ignored if not of type map

    + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + +
    KeyTypeDescriptionExample
    ............
    in_httprequest,in_httpresponsemap/when an HTTP(S) response comes inthe script can decide how to handle this responsemapcustom namestringdns server8.8.8.8:53
    ............
    +

    in_dohservers

    + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    _boolmeaninglesstrue
    +

    out, ignored if not of type map

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    ............
    custom namestringdohserverhttps://dns.quad9.net/dns-query?address=9.9.9.9%3A443
    ............
    @@ -1619,6 +1573,12 @@ +fromipaddress +string +client address which send this request +1.2.3.4:5 + + domain string domain name @@ -1631,16 +1591,22 @@ A -appid -string -App ID or path -com.google.Chrome.helper +... +... +... +... -interface +tag_key string -network interface. Mac only -en0 +--tag specifies the key value +tag_value + + +... +... +... +...

    out, if it is error type will be recorded in the log. Ignored if not of type map

    @@ -1666,25 +1632,358 @@ 1.2.3.4 +dnsserverkey +string +Use the dnsserver specified by key to resolve +custom name + + +dohserverkey +string +Use the dohserver specified by key to resolve +custom name + + +

    in_address

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    networkstringtcp or udptcp
    fromipaddressstringclient address which send this request1.2.3.4:5
    ipaddressstringip address to be proxied1.2.3.4:443
    domainaddressstringdomain address to be proxiedgoogle.com:443
    userstringuser ID, only available when used with --userAPI9
    ............
    tag_keystring--tag specifies the key valuetag_value
    ............
    +

    out, if it is error type will be recorded in the log. Ignored if not of type map

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    blockboolWhether Block, default falsefalse
    addressstringRewrite destination to an address1.2.3.4
    ipaddressfromdnsserverkeystringIf the destination is domain address, use the dnsserver specified by key to resolvecustom name
    ipaddressfromdnsserverkeystringIf the destination is domain address, use the dohserver specified by key to resolvecustom name
    aoraaaastringMust be used with ipaddressfromdnsserverkey or ipaddressfromdnsserverkey. Valid value is A/AAAAA
    speedlimitintSet a rate limit for this request, for example 1000000 means 1000 kb/s1000000
    brooklinkkeystringUse the brook link specified by key to proxycustom name
    dialwithstringIf your server has multiple IPs or network interfaces, you can specify the IP or network interface name to initiate this request192.168.1.2 or 2606:4700:3030::ac43:a86a or en1
    +

    Client

    +

    CLI

    +

    Before discussing the GUI client, let's first talk about the command line client brook. As we know, after you have deployed the server, you can use the command line client brook to create a local socks5 proxy or http proxy on your machine, and then configure it in your system proxy settings or in your browser to use this proxy. However:

    +
      +
    1. Not all apps will use this proxy, whether they use it is up to the app itself.
    2. +
    3. Generally, all UDP protocols will not go through this proxy, such as http3.
    4. +
    +

    For the specifics of socks5 and http proxy, you can read this article.

    +

    GUI

    +

    The GUI client does not use socks5 and http proxy mode, so there is no issue with some software not using the system proxy. Instead, it uses a virtual network card to take over the entire system's network, including UDP-based http3. Moreover, Brook allows us to control network requests programmatically, so it is necessary to have basic knowledge of network requests. 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

    +

    Without Brook

    +
    +

    Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: google.com:443, or an IP address: 8.8.8.8:53

    +
    +

    x

    +
      +
    1. When an app requests a domain address, such as google.com:443
    2. +
    3. It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as 8.8.8.8:53, to inquire about the IP of google.com
    4. +
    5. The system DNS will return the IP of google.com, such as 1.2.3.4, to the app
    6. +
    7. The app will combine the IP and port into an IP address, such as: 1.2.3.4:443
    8. +
    9. The app makes a network request to this IP address 1.2.3.4:443
    10. +
    11. The app receives the response data
    12. +
    +

    In the above process, the app actually makes two network requests: one to the IP address 8.8.8.8:53 and another to the IP address 1.2.3.4:443. In other words, the domain name is essentially an alias for the IP, and must obtain the domain's IP to establish a connection.

    +

    With Brook

    +

    Brook has a Fake DNS feature default, which can parse the domain name out of the query requests that an app sends to the system DNS UDP 53 and decide how to respond to the app.

    +

    x

    +
      +
    1. When an app requests a domain name address, such as google.com:443
    2. +
    3. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as 8.8.8.8:53, to inquire about the IP of google.com
    4. +
    5. The Brook client detects that an app is sending a network request to 8.8.8.8:53. This will trigger the in_dnsquery variable, carrying information such as domain
    6. +
    7. The Brook client returns a fake IP to the app, such as 240.0.0.1
    8. +
    9. The app combines the IP and port into an IP address, such as: 240.0.0.1:443
    10. +
    11. The app makes a network request to the IP address 240.0.0.1:443
    12. +
    13. The Brook client detects that an app is sending a network request to 240.0.0.1:443, discovers that this is a fake IP, and will convert the fake IP address back to the domain address google.com:443. This will trigger the in_address variable, carrying information such as domainaddress
    14. +
    15. The Brook client sends google.com:443 to the Brook Server
    16. +
    17. The Brook Server first requests its own DNS to resolve the domain name to find out the IP of google.com, such as receiving 1.2.3.4
    18. +
    19. The Brook Server combines the IP and port into an IP address, such as: 1.2.3.4:443
    20. +
    21. The Brook Server sends a network request to 1.2.3.4:443 and returns the data to the Brook client
    22. +
    23. The Brook client then returns the data to the app
    24. +
    25. The app receives the response data
    26. +
    +

    However, if the following situations occur, the domain name will not/cannot be parsed, meaning that the Brook client will not/cannot know what the domain name is and will treat it as a normal request sent to an IP address. To avoid the ineffectiveness of Fake DNS, please refer to this article:

    + +

    Script can do more:

    + +

    Variables

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    variabletypeconditiontimingdescriptionout type
    in_brooklinksmap/Before connectingPredefine multiple brook links, and then programmatically specify which one to connect tomap
    in_dnsquerymapFakeDNS: OnWhen a DNS query occursScript can decide how to handle this requestmap
    in_addressmap/When connecting to an addressScript can decide how to handle this requestmap
    in_httprequestmap/When an HTTP(S) request comes inScript can decide how to handle this requestmap
    in_httprequest,in_httpresponsemap/when an HTTP(S) response comes inScript can decide how to handle this responsemap
    + + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    _boolmeaninglesstrue
    +

    out, ignored if not of type map

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    ............
    custom namestringbrook linkbrook://...
    ............
    +

    in_dnsquery

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyTypeDescriptionExample
    domainstringdomain namegoogle.com
    typestringquery typeA
    appidstringmacOS App Mode: this is app id; Linux and Windows: this is app path; OpenWrt: this is IP address of client device. Note: In some operating systems, the app may initiate DNS queries through the system app.com.google.Chrome.helper
    +

    out, if it is error type will be recorded in the log. Ignored if not of type map

    + + + + + + + + + + + + + + + + + + + + + + - + - + - +
    KeyTypeDescriptionExample
    blockboolWhether Block, default falsefalse
    ipstringIgnore fake DNS, specify IP directly, only valid when type is A/AAAA1.2.3.4
    system boolResolve by System DNS, default falseIgnore fake DNS, resolve by System DNS over brook, default false false
    bypass boolResolve by Bypass DNS, default falseIgnore fake DNS, resolve by Bypass DNS, default false false
    brooklinkkey stringWhen need to connect the Server,instead, connect to the Server specified by the key in_brooklinksWhen need to connect the Server, instead, perfer connect to the Server specified by the key in_brooklinks custom name
    -

    in_address

    +

    in_address

    @@ -1703,7 +2002,7 @@ - + @@ -1715,15 +2014,9 @@ - + - - - - - -
    ipaddress stringIP type address. There is only of ipaddress and domainaddress. Note that there is no relationship between these twoIP type address. There is only one of ipaddress and domainaddress. Note that there is no relationship between these two 1.2.3.4:443
    appid stringApp ID or pathmacOS App Mode: this is app id; Linux and Windows: this is app path; OpenWrt: this is IP address of client device com.google.Chrome.helper
    interfacestringnetwork interface. Mac onlyen0

    out, if it is error type will be recorded in the log. Ignored if not of type map

    @@ -1744,7 +2037,7 @@ - + @@ -1756,7 +2049,7 @@ - + @@ -1774,7 +2067,7 @@ - + @@ -1786,7 +2079,7 @@ - + @@ -1849,7 +2142,7 @@
    ipaddress stringIP type address, rewrite destinationRewrite destination to an ip address 1.2.3.4:443
    bypass boolBypass, default false. If true and domainaddress, then ipaddress or ipaddressfrombypassdns must be specifiedBypass, default false. If true and domainaddress exists, then ipaddress or ipaddressfrombypassdns must be specified false
    mitmcertdomain stringThe 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 explicitlyThe MITM certificate domain name, which is taken from domainaddress by default. If ipaddress exists and mitm is true and mitmprotocol is https then must be must be specified explicitly example.com
    mitmautohandlecompress boolWhether to automatically decompress the http body when interacting with the script, default falseWhether to automatically decompress the http body when interacting with the script, default false. Usually need set this to true false
    /
    -

    out, must be set to a request or response

    +

    out, must be set to an unmodified or modified request or a response

    in_httpresponse

    @@ -1879,9 +2172,9 @@
    /
    -

    out, must be set to a response

    +

    out, must be set to an unmodified or modified response

    Modules

    -

    In Brook GUI, scripts are abstracted into Modules. There are already some modules, and thre is no magic, it just automatically combine _header.tengo and _footer.tengo, so you only need to write the module itself.

    +

    In Brook GUI, scripts are abstracted into Modules. There are already some modules, and there is no magic, it just 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) {
    @@ -1905,9 +2198,9 @@
         }
     })
     
    -

    tun2brook

    -

    https://github.com/txthinking/tun2brook

    -

    If you are using tun2brook, you can manually combine multiple modules into a complete script in the following way. For example:

    +

    ipio

    +

    https://github.com/txthinking/ipio

    +

    ipio uses the same script as the GUI. If you are using ipio, you can manually 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
    @@ -1915,61 +2208,18 @@ cat block_aaaa.tengo >> my.tengo
     
     cat _footer.tengo >> my.tengo
     
    -

    Syntax

    -

    Tengo Language Syntax

    -

    Library

    -

    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

    +

    If you are writing complex scripts, the GUI may not be convenient for debugging. It is recommended to use ipio on desktop to debug with fmt.println

    CA

    https://txthinking.github.io/ca/ca.pem

    @@ -1999,8 +2249,6 @@ Functions

    Some software may not read the system CA,you can use curl --cacert ~/.nami/bin/ca.pem to debug

    -

    OpenWrt

    -

    Brook OpenWRT: Perfectly supports IPv4/IPv6/TCP/UDP

    IPv6

    Brook's stance on IPv6 is positive, if your server or local environment doesn't have an IPv6 stack, read this article.

    Troubleshooting Steps

    @@ -2054,8 +2302,166 @@ Functions
  • Submit new issue
  • Seek help in the group
  • +

    Other

    +

    Script Syntax

    +

    I think just reading this one page is enough: Tengo Language Syntax

    +

    Library

    + +

    Example

    +

    Each subcommand has a --example, such as:

    +
    brook server --example
    +
    +

    Resources

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CLIDescription
    namiA clean and tidy decentralized package manager
    jokerJoker can turn process into daemon. Zero-Configuration
    nicoNico can work with brook wsserver together
    zz - process manager
    ipioProxy all traffic just one line command
    madGenerate root CA and derivative certificate for any domains and any IPs
    hancockManage multiple remote servers and execute commands remotely
    sshexecA command-line tool to execute remote command through ssh
    bashMany one-click scripts
    dockerdocker run txthinking/brook
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ResourcesDescription
    ProtocolBrook Protocol
    BlogSome articles you should read
    YouTubeSome videos you should watch
    TelegramAsk questions here
    AnnounceAll news you should care
    GitHubOther useful repos
    Socks5 ConfiguratorIf you prefer CLI brook client
    IPvBarSee domain, IP and country in browser
    TxThinking SSHA SSH Terminal
    brook-storeA Brook User System
    TxThinkingEverything

    CLI Documentation

    -

    Each subcommand has a --example parameter that can print the minimal example of usage

    NAME

    Brook - A cross-platform programmable network tool

    SYNOPSIS

    @@ -2067,83 +2473,37 @@ Functions

    GLOBAL OPTIONS

    COMMANDS

    -

    server

    +

    server

    Start a brook server that supports tcp and udp

    client

    Start a brook client that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook client <-> $ brook server <-> dst]

    @@ -2182,14 +2540,6 @@ Functions

    wsserver

    Start a brook wsserver that supports tcp and udp. It opens a standard http server and a websocket server

    @@ -2234,14 +2580,6 @@ Functions

    wssserver

    Start a brook wssserver that supports tcp and udp. It opens a standard https server and a websocket server

    wssclient

    Start a brook wssclient that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook wssclient <-> $ brook wssserver <-> dst]

    @@ -2288,14 +2622,6 @@ Functions

    quicserver

    Start a brook quicserver that supports tcp and udp.

    quicclient

    -

    Start a brook quicclient that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook quicclient <-> $ brook quicserver <-> dst]. (The global-dial-parameter is ignored)

    +

    Start a brook quicclient that supports tcp and udp. It can open a socks5 proxy, [src <-> socks5 <-> $ brook quicclient <-> $ brook quicserver <-> dst]

    dnsserveroverbrook

    -

    Run a dns server over brook, which supports TCP and UDP, [src <-> $ brook dnserversoverbrook <-> $ brook server/wsserver/wssserver/quicserver <-> dns] or [src <-> $ brook dnsserveroverbrook <-> dnsForBypass]

    +

    Run a dns server over brook, which supports TCP and UDP, [src <-> $ brook dnserversoverbrook <-> $ brook server/wsserver/wssserver/quicserver <-> dns]

    +

    connect

    +

    Run a client and connect with a brook link, which supports TCP and UDP. It can start a socks5 proxy, [src <-> socks5 <-> $ brook connect <-> $ brook server/wsserver/wssserver/quicserver <-> dst]

    +

    Generate a brook link

    -

    connect

    -

    Run a client and connect with a brook link, which supports TCP and UDP. It can start a socks5 proxy, [src <-> socks5 <-> $ brook connect <-> $ brook server/wsserver/wssserver/quicserver <-> dst]

    -

    relay

    Run a standalone relay, which supports TCP and UDP. Accessing [from address] is equal to accessing [to address], [src <-> from address <-> to address]

    @@ -2454,12 +2764,6 @@ Functions

    dnsserver

    Run a standalone dns server

    help, h

    Shows a list of commands or help for one command

    -

    Examples

    -

    List some examples of common scene commands, pay attention to replace the parameters such as IP, port, password, domain name, certificate path, etc. in the example by yourself

    -

    Run brook server

    -
    brook server --listen :9999 --password hello
    -
    -

    then

    - -

    or get brook link

    -
    brook link --server 1.2.3.4:9999 --password hello --name 'my brook server'
    -
    -

    or get brook link with --udpovertcp

    -
    brook link --server 1.2.3.4:9999 --password hello --udpovertcp --name 'my brook server'
    -
    -

    Run brook wsserver

    -
    brook wsserver --listen :9999 --password hello
    -
    -

    then

    - -

    or get brook link

    -
    brook link --server ws://1.2.3.4:9999 --password hello --name 'my brook wsserver'
    -
    -

    or get brook link with domain, even if that's not your domain

    -
    brook link --server ws://hello.com:9999 --password hello --address 1.2.3.4:9999 --name 'my brook wsserver'
    -
    -

    Run brook wssserver: automatically certificate

    -
    -

    Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80

    -
    -
    brook wssserver --domainaddress domain.com:443 --password hello
    -
    -

    then

    - -

    or get brook link

    -
    brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver'
    -
    -

    Run brook wssserver Use a certificate issued by an existing trust authority

    -
    -

    Make sure your domain has been resolved to your server IP successfully

    -
    -
    brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem
    -
    -

    then

    - -

    or get brook link

    -
    brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver'
    -
    -

    Run brook wssserver issue untrusted certificates yourself, any domain

    -

    Install mad

    -
    nami install mad
    -
    -

    Generate root ca

    -
    mad ca --ca /root/ca.pem --key /root/cakey.pem
    -
    -

    Generate domain cert by root ca

    -
    mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com
    -
    -

    Run brook

    -
    brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem
    -
    -

    get brook link with --insecure

    -
    brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --insecure
    -
    -

    or get brook link with --ca

    -
    brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --address 1.2.3.4:443 --ca /root/ca.pem
    -
    -

    withoutBrookProtocol

    -

    Better performance, but data is not strongly encrypted using Brook protocol. So please use certificate encryption, and it is not recommended to use --withoutBrookProtocol and --insecure together

    -

    withoutBrookProtocol automatically certificate

    -
    -

    Make sure your domain has been resolved to your server IP successfully. Automatic certificate issuance requires the use of port 80

    -
    -
    brook wssserver --domainaddress domain.com:443 --password hello --withoutBrookProtocol
    -
    -

    get brook link

    -
    brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol
    -
    -

    withoutBrookProtocol Use a certificate issued by an existing trust authority

    -
    -

    Make sure your domain has been resolved to your server IP successfully

    -
    -
    brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol
    -
    -

    get brook link

    -
    brook link --server wss://domain.com:443 --password hello --name 'my brook wssserver' --withoutBrookProtocol
    -
    -

    withoutBrookProtocol issue untrusted certificates yourself, any domain

    -

    Install mad

    -
    nami install mad
    -
    -

    Generate root ca

    -
    mad ca --ca /root/ca.pem --key /root/cakey.pem
    -
    -

    Generate domain cert by root ca

    -
    mad cert --ca /root/ca.pem --ca_key /root/cakey.pem --cert /root/cert.pem --key /root/certkey.pem --domain domain.com
    -
    -

    Run brook wssserver

    -
    brook wssserver --domainaddress domain.com:443 --password hello --cert /root/cert.pem --certkey /root/certkey.pem --withoutBrookProtocol
    -
    -

    Get brook link

    -
    brook link --server wss://domain.com:443 --password hello --withoutBrookProtocol --address 1.2.3.4:443 --ca /root/ca.pem
    -
    -

    Run brook socks5, A stand-alone standard socks5 server

    -
    brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4
    -
    -

    then

    - -

    or get brook link

    -
    brook link --server socks5://1.2.3.4:1080
    -
    -

    Run brook socks5 with username and password. A stand-alone standard socks5 server

    -
    brook socks5 --listen :1080 --socks5ServerIP 1.2.3.4 --username hello --password world
    -
    -

    then

    - -

    or get brook link

    -
    brook link --server socks5://1.2.3.4:1080 --username hello --password world
    -
    -

    brook relayoverbrook can relay a local address to a remote address over brook, both TCP and UDP, it works with brook server wsserver wssserver.

    -
    brook relayoverbrook ... --from 127.0.0.1:5353 --to 8.8.8.8:53
    -
    -

    brook dnsserveroverbrook can create a encrypted DNS server, both TCP and UDP, it works with brook server wsserver wssserver.

    -
    brook dnsserveroverbrook ... --listen 127.0.0.1:53
    -
    -

    Brook OpenWRT Router: Perfectly supports IPv4/IPv6/TCP/UDP. Native IPv6

    -

    https://www.txthinking.com/talks/articles/brook-openwrt-en.article

    -

    Turn macOS into a Gateway with Brook

    -

    https://www.txthinking.com/talks/articles/brook-macos-gateway-en.article

    -

    Turn Windows into a Gateway with Brook

    -

    https://www.txthinking.com/talks/articles/brook-windows-gateway-en.article

    -

    Turn Linux into a Gateway with Brook

    -

    https://www.txthinking.com/talks/articles/brook-linux-gateway-en.article

    -

    brook relay can relay a address to a remote address. It can relay any tcp and udp server

    -
    brook relay --from :9999 --to 1.2.3.4:9999
    -
    -

    brook socks5tohttp can convert a socks5 to a http proxy

    -
    brook socks5tohttp --socks5 127.0.0.1:1080 --listen 127.0.0.1:8010
    -
    -

    There are countless examples; for more feature suggestions, it's best to look at the commands and parameters in the CLI documentation one by one, and blog, YouTube...

    -

    Resources

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    CLIDescription
    namiA clean and tidy decentralized package manager
    jokerJoker can turn process into daemon. Zero-Configuration
    nicoNico can work with brook wsserver together
    zz - process manager
    tun2brookProxy all traffic just one line command
    madGenerate root CA and derivative certificate for any domains and any IPs
    hancockManage multiple remote servers and execute commands remotely
    sshexecA command-line tool to execute remote command through ssh
    jbwrite script in an easier way than bash
    bashMany one-click scripts
    dockerdocker run txthinking/brook
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ResourcesDescription
    ProtocolBrook Protocol
    BlogSome articles you should read
    YouTubeSome videos you should watch
    TelegramAsk questions here
    AnnounceAll news you should care
    GitHubOther useful repos
    Socks5 ConfiguratorIf you prefer CLI brook client
    IPvBarSee domain, IP and country in browser
    TxThinking SSHA SSH Terminal
    brook-user-systemA Brook User System
    TxThinkingEverything
    diff --git a/brook/docs/other.md b/brook/docs/other.md new file mode 100644 index 0000000000..cea2fa47c4 --- /dev/null +++ b/brook/docs/other.md @@ -0,0 +1,86 @@ +# Other + +## Script Syntax + +I think just reading this one page is enough: [Tengo Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md) + +Library + +- [text](https://github.com/d5/tengo/blob/master/docs/stdlib-text.md): regular expressions, string conversion, and manipulation +- [math](https://github.com/d5/tengo/blob/master/docs/stdlib-math.md): mathematical constants and functions +- [times](https://github.com/d5/tengo/blob/master/docs/stdlib-times.md): time-related functions +- [rand](https://github.com/d5/tengo/blob/master/docs/stdlib-rand.md): random functions +- [fmt](https://github.com/d5/tengo/blob/master/docs/stdlib-fmt.md): formatting functions +- [json](https://github.com/d5/tengo/blob/master/docs/stdlib-json.md): JSON functions +- [enum](https://github.com/d5/tengo/blob/master/docs/stdlib-enum.md): Enumeration functions +- [hex](https://github.com/d5/tengo/blob/master/docs/stdlib-hex.md): hex encoding and decoding functions +- [base64](https://github.com/d5/tengo/blob/master/docs/stdlib-base64.md): base64 encoding and decoding functions +- `brook`: brook module + + ``` + Constants + + * 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 + ``` + +## Example + +Each `subcommand` has a `--example`, such as: + +``` +brook server --example +``` + +## Resources + +| CLI | Description | +| --- | --- | +| [nami](https://github.com/txthinking/nami) | A clean and tidy decentralized package manager | +| [joker](https://github.com/txthinking/joker) | Joker can turn process into daemon. Zero-Configuration | +| [nico](https://github.com/txthinking/nico) | Nico can work with brook wsserver together | +| [z](https://github.com/txthinking/z) | z - process manager | +| [ipio](https://github.com/txthinking/ipio) | Proxy all traffic just one line command | +| [mad](https://github.com/txthinking/mad) | Generate root CA and derivative certificate for any domains and any IPs | +| [hancock](https://github.com/txthinking/hancock) | Manage multiple remote servers and execute commands remotely | +| [sshexec](https://github.com/txthinking/sshexec) | A command-line tool to execute remote command through ssh | +| [bash](https://github.com/txthinking/bash) | Many one-click scripts | +| [docker](https://hub.docker.com/r/txthinking/brook) | `docker run txthinking/brook` | + +| Resources | Description | +| --- | --- | +| [Protocol](https://github.com/txthinking/brook/tree/master/protocol) | Brook Protocol | +| [Blog](https://www.txthinking.com/talks/) | Some articles you should read | +| [YouTube](https://www.youtube.com/txthinking) | Some videos you should watch | +| [Telegram](https://t.me/txthinking) | Ask questions here | +| [Announce](https://t.me/s/txthinking_talks) | All news you should care | +| [GitHub](https://github.com/txthinking) | Other useful repos | +| [Socks5 Configurator](https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb) | If you prefer CLI brook client | +| [IPvBar](https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj) | See domain, IP and country in browser | +| [TxThinking SSH](https://www.txthinking.com/ssh.html) | A SSH Terminal | +| [brook-store](https://github.com/txthinkinginc/brook-store) | A Brook User System | +| [TxThinking](https://www.txthinking.com) | Everything | + diff --git a/brook/docs/resources.md b/brook/docs/resources.md deleted file mode 100644 index f4d61f62c3..0000000000 --- a/brook/docs/resources.md +++ /dev/null @@ -1,30 +0,0 @@ -# Resources - -| CLI | Description | -| --- | --- | -| [nami](https://github.com/txthinking/nami) | A clean and tidy decentralized package manager | -| [joker](https://github.com/txthinking/joker) | Joker can turn process into daemon. Zero-Configuration | -| [nico](https://github.com/txthinking/nico) | Nico can work with brook wsserver together | -| [z](https://github.com/txthinking/z) | z - process manager | -| [tun2brook](https://github.com/txthinking/tun2brook) | Proxy all traffic just one line command | -| [mad](https://github.com/txthinking/mad) | Generate root CA and derivative certificate for any domains and any IPs | -| [hancock](https://github.com/txthinking/hancock) | Manage multiple remote servers and execute commands remotely | -| [sshexec](https://github.com/txthinking/sshexec) | A command-line tool to execute remote command through ssh | -| [jb](https://github.com/txthinking/jb) | write script in an easier way than bash | -| [bash](https://github.com/txthinking/bash) | Many one-click scripts | -| [docker](https://hub.docker.com/r/txthinking/brook) | `docker run txthinking/brook` | - -| Resources | Description | -| --- | --- | -| [Protocol](https://github.com/txthinking/brook/tree/master/protocol) | Brook Protocol | -| [Blog](https://www.txthinking.com/talks/) | Some articles you should read | -| [YouTube](https://www.youtube.com/txthinking) | Some videos you should watch | -| [Telegram](https://t.me/txthinking) | Ask questions here | -| [Announce](https://t.me/s/txthinking_news) | All news you should care | -| [GitHub](https://github.com/txthinking) | Other useful repos | -| [Socks5 Configurator](https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb) | If you prefer CLI brook client | -| [IPvBar](https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj) | See domain, IP and country in browser | -| [TxThinking SSH](https://www.txthinking.com/ssh.html) | A SSH Terminal | -| [brook-user-system](https://github.com/txthinkinginc/brook-user-system) | A Brook User System | -| [TxThinking](https://www.txthinking.com) | Everything | - diff --git a/brook/docs/server.md b/brook/docs/server.md new file mode 100644 index 0000000000..3b2cf03c24 --- /dev/null +++ b/brook/docs/server.md @@ -0,0 +1,121 @@ +# Server + +brook dnsserver, dohserver, dnsserveroverbrook, server, wsserver, wssserver, quicserver can use script to do more complex thing. brook 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` + +## Brook DNS Server + +![x](./images/brook-dns-server.svg) + +Script can do more: + +- There are [examples](https://github.com/txthinking/brook/blob/master/programmable/dnsserver/) for dns server +- In the `script: in_dnsquery` step, script can do more, read more below + +## Brook Server + +![x](./images/brook-server.svg) + +Script can do more: + +- There are [examples](https://github.com/txthinking/brook/blob/master/programmable/server/) for server +- In the `script: in_address` step, script can do more, read more below + +## Variables + +| variable | type | command | timing | description | out type | +| ------------------------------ | ---- | ----------- | --------------------------------- | ------------------------------------------------- | -------- | +| in_dnsservers | map | dnsserver/dnsserveroverbrook/dohserver/server/wsserver/wssserver/quicserver | When just running | Predefine multiple dns servers, and then programmatically specify which one to use | map | +| in_dohservers | map | dnsserver/dnsserveroverbrook/dohserver/server/wsserver/wssserver/quicserver | When just running | Predefine multiple doh servers, and then programmatically specify which one to use | map | +| in_brooklinks | map | server/wsserver/wssserver/quicserver | When just running | Predefine multiple brook links, and then programmatically specify which one to use | map | +| in_dnsquery | map | dnsserver/dnsserveroverbrook/dohserver | When a DNS query occurs | Script can decide how to handle this request | map | +| in_address | map | server/wsserver/wssserver/quicserver | When the Server connects the proxied address | Script can decide how to handle this request | map | + +## in_dnsservers + +| Key | Type | Description | Example | +| ------ | ------ | -------- | ---------- | +| _ | bool | meaningless | true | + +`out`, ignored if not of type `map` + +| Key | Type | Description | Example | +| ------------ | ------ | -------------------------------------------------------------------------------------------------- | ------- | +| ... | ... | ... | ... | +| custom name | string | dns server | 8.8.8.8:53 | +| ... | ... | ... | ... | + + +## in_dohservers + +| Key | Type | Description | Example | +| ------ | ------ | -------- | ---------- | +| _ | bool | meaningless | true | + +`out`, ignored if not of type `map` + +| Key | Type | Description | Example | +| ------------ | ------ | -------------------------------------------------------------------------------------------------- | ------- | +| ... | ... | ... | ... | +| custom name | string | dohserver | https://dns.quad9.net/dns-query?address=9.9.9.9%3A443 | +| ... | ... | ... | ... | + + +## 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 | +| ------ | ------ | ----------- | ---------- | +| fromipaddress | string | client address which send this request | 1.2.3.4:5 | +| domain | string | domain name | google.com | +| type | string | query type | A | +| ... | ... | ... | ... | +| tag_key | string | --tag specifies the key value | tag_value | +| ... | ... | ... | ... | + +`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 | +| dnsserverkey | string | Use the dnsserver specified by key to resolve | custom name | +| dohserverkey | string | Use the dohserver specified by key to resolve | custom name | + +## in_address + +| Key | Type | Description | Example | +| ------ | ------ | ----------- | ---------- | +| network | string | `tcp` or `udp` | tcp | +| fromipaddress | string | client address which send this request | 1.2.3.4:5 | +| ipaddress | string | ip address to be proxied | 1.2.3.4:443 | +| domainaddress | string | domain address to be proxied | google.com:443 | +| user | string | user ID, only available when used with --userAPI | 9 | +| ... | ... | ... | ... | +| tag_key | string | --tag specifies the key value | tag_value | +| ... | ... | ... | ... | + +`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 | +| address | string | Rewrite destination to an address | 1.2.3.4 | +| ipaddressfromdnsserverkey | string | If the destination is domain address, use the dnsserver specified by key to resolve | custom name | +| ipaddressfromdnsserverkey | string | If the destination is domain address, use the dohserver specified by key to resolve | custom name | +| aoraaaa | string | Must be used with ipaddressfromdnsserverkey or ipaddressfromdnsserverkey. Valid value is `A`/`AAAA` | A | +| speedlimit | int | Set a rate limit for this request, for example `1000000` means 1000 kb/s | 1000000 | +| brooklinkkey | string | Use the brook link specified by key to proxy | custom name | +| dialwith | string | If your server has multiple IPs or network interfaces, you can specify the IP or network interface name to initiate this request | 192.168.1.2 or 2606:4700:3030::ac43:a86a or en1 | diff --git a/brook/programmable/dnsserver/check_syntax.js b/brook/programmable/dnsserver/check_syntax.js new file mode 100755 index 0000000000..402d22569b --- /dev/null +++ b/brook/programmable/dnsserver/check_syntax.js @@ -0,0 +1,18 @@ +#!/usr/bin/env bun + +import { $ } from 'bun' +import * as fs from 'node:fs/promises' + +var s = await $`ls`.text() +var l = s.split('\n').filter(v => v.endsWith('.tengo')) +for (var i = 0; i < l.length; i++) { + s = (await $`cat ${l[i]}`.text()).replaceAll('import("brook")', 'undefined') + await fs.writeFile('/tmp/_.tengo', ` +in_dnsservers := undefined +in_dohservers := undefined +in_dnsquery := undefined +${s} +`) + await $`tengo /tmp/_.tengo` +} + diff --git a/brook/programmable/dnsserver/example.tengo b/brook/programmable/dnsserver/example.tengo new file mode 100644 index 0000000000..84efe918ba --- /dev/null +++ b/brook/programmable/dnsserver/example.tengo @@ -0,0 +1,31 @@ +f := func() { + if in_dnsservers { + return { + "google4": "8.8.8.8:53", + "google6": "[2001:4860:4860::8888]:53", + "quad4": "9.9.9.9:53" + } + } + if in_dohservers { + return { + "google4": "https://dns.google/dns-query?address=8.8.8.8%3A443", + "google6": "https://dns.google/dns-query?address=%5B2001%3A4860%3A4860%3A%3A8888%5D%3A443", + "quad4": "https://dns.quad9.net/dns-query?address=9.9.9.9%3A443" + } + } + if in_dnsquery { + m := in_dnsquery + if m.domain == "360.cn" { + return { block: true } + } + if m.domain == "360.com" && m.type == "A" { + return { ip: "1.2.3.4" } + } + if m.domain == "http3.ooo" { + return { dohserverkey: "quad4" } + } + return + } +} +out := f() + diff --git a/brook/programmable/dnsserver/readme.md b/brook/programmable/dnsserver/readme.md new file mode 100644 index 0000000000..34f41068cd --- /dev/null +++ b/brook/programmable/dnsserver/readme.md @@ -0,0 +1,2 @@ +brook dnsserver, dohserver, dnsserveroverbrook + diff --git a/brook/programmable/list/example_cidr4.txt b/brook/programmable/list/example_cidr4.txt deleted file mode 100644 index 3b932ac363..0000000000 --- a/brook/programmable/list/example_cidr4.txt +++ /dev/null @@ -1,3 +0,0 @@ -127.0.0.0/32 -192.168.1.0/24 -1.2.4.8/32 diff --git a/brook/programmable/list/example_cidr6.txt b/brook/programmable/list/example_cidr6.txt deleted file mode 100644 index 4109838c1b..0000000000 --- a/brook/programmable/list/example_cidr6.txt +++ /dev/null @@ -1,3 +0,0 @@ -::1/128 -fd00::/8 -2001:dc7:1000::1/128 diff --git a/brook/programmable/list/example_domain.txt b/brook/programmable/list/example_domain.txt deleted file mode 100644 index 9fc0e571ba..0000000000 --- a/brook/programmable/list/example_domain.txt +++ /dev/null @@ -1,3 +0,0 @@ -lt -a.com -c.b.com diff --git a/brook/programmable/modules/bypass_china_domain.tengo b/brook/programmable/modules/bypass_china_domain.tengo index 526bff179e..3c0a543f3a 100644 --- a/brook/programmable/modules/bypass_china_domain.tengo +++ b/brook/programmable/modules/bypass_china_domain.tengo @@ -1,5 +1,5 @@ // 大陆域名用 Bypass DNS 来解析, 注意与 bypass_china_domain_a.tengo 区分. 这是一个包含主流的精小样本. -// generated by: jb https://bash.ooo/china.js +// generated by: https://bash.ooo/china.js // The script limits the stack size 2048. If your array or map exceeds max stack size, try splitting it into multiple. The memory occupied by a dictionary is approximately twice that of an array with same elements. modules = append(modules, { dnsquery: func(m) { diff --git a/brook/programmable/modules/bypass_china_domain_a.tengo b/brook/programmable/modules/bypass_china_domain_a.tengo index 48306b39d7..8bae91af3e 100644 --- a/brook/programmable/modules/bypass_china_domain_a.tengo +++ b/brook/programmable/modules/bypass_china_domain_a.tengo @@ -1,5 +1,5 @@ // 大陆域名用 Bypass DNS 来解析 A 并直连, 注意与 bypass_china_domain.tengo 区分. 这是一个包含主流的精小样本. -// generated by: jb https://bash.ooo/china.js +// generated by: https://bash.ooo/china.js // The script limits the stack size 2048. If your array or map exceeds max stack size, try splitting it into multiple. The memory occupied by a dictionary is approximately twice that of an array with same elements. modules = append(modules, { address: func(m) { diff --git a/brook/programmable/modules/chatgpt_advanced_voice.tengo b/brook/programmable/modules/chatgpt_advanced_voice.tengo new file mode 100644 index 0000000000..6bcdc3764f --- /dev/null +++ b/brook/programmable/modules/chatgpt_advanced_voice.tengo @@ -0,0 +1,14 @@ +// Ignore fake DNS for ChatGPT Advanced Voice +modules = append(modules, { + dnsquery: func(m) { + text := import("text") + l := [ + "livekit.cloud" + ] + for v in l { + if m.domain == v || text.has_suffix(m.domain, "."+v) { + return { system: true } + } + } + } +}) diff --git a/brook/programmable/modules/check_syntax.js b/brook/programmable/modules/check_syntax.js index 51e330fa4a..d757ebe2ef 100755 --- a/brook/programmable/modules/check_syntax.js +++ b/brook/programmable/modules/check_syntax.js @@ -1,10 +1,18 @@ -#!/usr/bin/env jb +#!/usr/bin/env bun -var s = $1`ls`.split('\n').filter(v => !v.startsWith('_') && v.endsWith('.tengo')).map(v => $1(`cat ${v}`).replaceAll('import("brook")', 'undefined')).join('\n') +import { $ } from 'bun' +import * as fs from 'node:fs/promises' -var h = $1`cat _header.tengo` -var f = $1`cat _footer.tengo` -write_file('/tmp/_.tengo', ` +var s = await $`ls`.text() +var l = s.split('\n').filter(v => !v.startsWith('_') && v.endsWith('.tengo')) +for (var i = 0; i < l.length; i++) { + l[i] = (await $`cat ${l[i]}`.text()).replaceAll('import("brook")', 'undefined') +} +s = l.join('\n') + +var h = await $`cat _header.tengo`.text() +var f = await $`cat _footer.tengo`.text() +await fs.writeFile('/tmp/_.tengo', ` in_brooklinks := undefined in_dnsquery := undefined in_address := undefined @@ -14,4 +22,4 @@ ${h} ${s} ${f} `) -$1`tengo /tmp/_.tengo` +await $`tengo /tmp/_.tengo` diff --git a/brook/programmable/modules/instagram_system_dns.tengo b/brook/programmable/modules/instagram_system_dns.tengo index 0a72fe6a47..c74a044650 100644 --- a/brook/programmable/modules/instagram_system_dns.tengo +++ b/brook/programmable/modules/instagram_system_dns.tengo @@ -1,41 +1,513 @@ -// Instagram has a non-standard DNS cache, so we force it don't use Fake DNS, but the list may not be enough. Or disable Fake DNS, but you will not see domain in activity. -// Instagram 使用了非标准的 DNS 机制,所以我们强制其不使用 Fake DNS, 列表不一定全. 或者关闭 Fake DNS,但日志就看不到域名了。 -// If Instagram is still experiencing network issues, you can turn off Fake DNS. -// 如果Instagram仍然遇到网络问题,可以关闭 Fake DNS。 +// Ignore fake DNS for instagram modules = append(modules, { dnsquery: func(m) { text := import("text") - l := [ - "analytics.google.com", - "apple.com", - "comodoca.com", - "autonavi.com", - "giphy.com", - "facebook.com", - "fbcdn.net", - "facebook.net", - "akamaihd.net", - "thefacebook.com", - "tfbnw.net", - "messenger.com", - "fb.me", - "fbsbx.com", - "fb.com", - "whatsapp.net", - "whatsapp.com", - "instagram.com", - "akamai.net", - "aaplimg.com", - "alibabadns.com", - "akamaiedge.net", - "apple-dns.net", - "akadns.net", - "cdninstagram.com" - ] - for v in l { - if m.domain == v || text.has_suffix(m.domain, "."+v) { - return { system: true } + f := func(domain, l){ + ss := text.split(text.to_lower(domain), ".") + s := "" + for i := len(ss) - 1; i >= 0; i-- { + if s == "" { + s = ss[i] + } else { + s = ss[i] + "." + s + } + if l[s] { + return { system: true } + } } } + l := { + "aboutfacebook.com": true, + "accessfacebookfromschool.com": true, + "acebooik.com": true, + "acebook.com": true, + "acheter-followers-instagram.com": true, + "acheterdesfollowersinstagram.com": true, + "acheterfollowersinstagram.com": true, + "advancediddetection.com": true, + "askfacebook.net": true, + "askfacebook.org": true, + "atdmt2.com": true, + "atlasdmt.com": true, + "atlasonepoint.com": true, + "bookstagram.com": true, + "buyingfacebooklikes.com": true, + "careersatfb.com": true, + "carstagram.com": true, + "cdninstagram.com": true, + "celebgramme.com": true, + "chickstagram.com": true, + "china-facebook.com": true, + "click-url.com": true, + "como-hackearfacebook.com": true, + "crowdtangle.com": true, + "dacebook.com": true, + "dlfacebook.com": true, + "dotfacebook.com": true, + "dotfacebook.net": true, + "expresswifi.com": true, + "faacebok.com": true, + "faacebook.com": true, + "faasbook.com": true, + "facbebook.com": true, + "facbeok.com": true, + "facboo.com": true, + "facbook.com": true, + "facbool.com": true, + "facboox.com": true, + "faccebook.com": true, + "faccebookk.com": true, + "facdbook.com": true, + "facdebook.com": true, + "face-book.com": true, + "faceabook.com": true, + "facebboc.com": true, + "facebbook.com": true, + "facebboook.com": true, + "facebcook.com": true, + "facebdok.com": true, + "facebgook.com": true, + "facebhook.com": true, + "facebkkk.com": true, + "facebo-ok.com": true, + "faceboak.com": true, + "facebock.com": true, + "facebocke.com": true, + "facebof.com": true, + "faceboik.com": true, + "facebok.com": true, + "facebokbook.com": true, + "facebokc.com": true, + "facebokk.com": true, + "facebokok.com": true, + "faceboks.com": true, + "facebol.com": true, + "facebolk.com": true, + "facebomok.com": true, + "faceboo.com": true, + "facebooa.com": true, + "faceboob.com": true, + "faceboobok.com": true, + "facebooc.com": true, + "faceboock.com": true, + "facebood.com": true, + "facebooe.com": true, + "faceboof.com": true, + "facebooi.com": true, + "facebooik.com": true, + "facebooik.org": true, + "facebooj.com": true, + "facebook-corp.com": true, + "facebook-covid-19.com": true, + "facebook-ebook.com": true, + "facebook-forum.com": true, + "facebook-hardware.com": true, + "facebook-inc.com": true, + "facebook-login.com": true, + "facebook-newsroom.com": true, + "facebook-newsroom.org": true, + "facebook-pmdcenter.com": true, + "facebook-pmdcenter.net": true, + "facebook-pmdcenter.org": true, + "facebook-privacy.com": true, + "facebook-program.com": true, + "facebook-studio.com": true, + "facebook-support.org": true, + "facebook-texas-holdem.com": true, + "facebook-texas-holdem.net": true, + "facebook.br": true, + "facebook.ca": true, + "facebook.cc": true, + "facebook.com": true, + "facebook.design": true, + "facebook.hu": true, + "facebook.in": true, + "facebook.net": true, + "facebook.nl": true, + "facebook.org": true, + "facebook.se": true, + "facebook.shop": true, + "facebook.tv": true, + "facebook.us": true, + "facebook.wang": true, + "facebook123.org": true, + "facebook30.com": true, + "facebook30.net": true, + "facebook30.org": true, + "facebook4business.com": true, + "facebookads.com": true, + "facebookadvertisingsecrets.com": true, + "facebookatschool.com": true, + "facebookawards.com": true, + "facebookblueprint.net": true, + "facebookbrand.com": true, + "facebookbrand.net": true, + "facebookcanadianelectionintegrityinitiative.com": true, + "facebookcareer.com": true, + "facebookcheats.com": true, + "facebookck.com": true, + "facebookclub.com": true, + "facebookcom.com": true, + "facebookconsultant.org": true, + "facebookcoronavirus.com": true, + "facebookcovers.org": true, + "facebookcredits.info": true, + "facebookdating.net": true, + "facebookdusexe.org": true, + "facebookemail.com": true, + "facebookenespanol.com": true, + "facebookexchange.com": true, + "facebookexchange.net": true, + "facebookfacebook.com": true, + "facebookflow.com": true, + "facebookgames.com": true, + "facebookgraphsearch.com": true, + "facebookgraphsearch.info": true, + "facebookgroups.com": true, + "facebookhome.cc": true, + "facebookhome.com": true, + "facebookhome.info": true, + "facebookhub.com": true, + "facebooki.com": true, + "facebookinc.com": true, + "facebookland.com": true, + "facebooklikeexchange.com": true, + "facebooklive.com": true, + "facebooklivestaging.net": true, + "facebooklivestaging.org": true, + "facebooklogin.com": true, + "facebooklogin.info": true, + "facebookloginhelp.net": true, + "facebooklogs.com": true, + "facebookmail.com": true, + "facebookmail.tv": true, + "facebookmanager.info": true, + "facebookmarketing.info": true, + "facebookmarketingpartner.com": true, + "facebookmarketingpartners.com": true, + "facebookmobile.com": true, + "facebookmsn.com": true, + "facebooknews.com": true, + "facebooknfl.com": true, + "facebooknude.com": true, + "facebookofsex.com": true, + "facebookook.com": true, + "facebookpaper.com": true, + "facebookpay.com": true, + "facebookphonenumber.net": true, + "facebookphoto.com": true, + "facebookphotos.com": true, + "facebookpmdcenter.com": true + + } + r := f(m.domain, l) + if r != undefined { + return r + } + + l = { + "facebookpoke.net": true, + "facebookpoke.org": true, + "facebookpoker.info": true, + "facebookpokerchips.info": true, + "facebookporn.net": true, + "facebookporn.org": true, + "facebookporno.net": true, + "facebookportal.com": true, + "facebooks.com": true, + "facebooksafety.com": true, + "facebooksecurity.net": true, + "facebookshop.com": true, + "facebooksignup.net": true, + "facebooksite.net": true, + "facebookstories.com": true, + "facebookstudios.net": true, + "facebookstudios.org": true, + "facebooksupplier.com": true, + "facebooksuppliers.com": true, + "facebookswagemea.com": true, + "facebookswagstore.com": true, + "facebooksz.com": true, + "facebookthreads.net": true, + "facebooktv.net": true, + "facebooktv.org": true, + "facebookvacation.com": true, + "facebookw.com": true, + "facebookwork.com": true, + "facebookworld.com": true, + "facebool.com": true, + "facebool.info": true, + "facebooll.com": true, + "faceboom.com": true, + "faceboon.com": true, + "faceboonk.com": true, + "faceboooik.com": true, + "faceboook.com": true, + "faceboop.com": true, + "faceboot.com": true, + "faceboox.com": true, + "facebopk.com": true, + "facebpook.com": true, + "facebuk.com": true, + "facebuok.com": true, + "facebvook.com": true, + "facebyook.com": true, + "facebzook.com": true, + "facecbgook.com": true, + "facecbook.com": true, + "facecbook.org": true, + "facecook.com": true, + "facecook.org": true, + "facedbook.com": true, + "faceebok.com": true, + "faceebook.com": true, + "faceebot.com": true, + "facegbok.com": true, + "facegbook.com": true, + "faceobk.com": true, + "faceobok.com": true, + "faceobook.com": true, + "faceook.com": true, + "facerbooik.com": true, + "facerbook.com": true, + "facesbooc.com": true, + "facesounds.com": true, + "facetook.com": true, + "facevbook.com": true, + "facewbook.co": true, + "facewook.com": true, + "facfacebook.com": true, + "facfebook.com": true, + "fackebook.com": true, + "facnbook.com": true, + "facrbook.com": true, + "facvebook.com": true, + "facwebook.com": true, + "facxebook.com": true, + "fadebook.com": true, + "faebok.com": true, + "faebook.com": true, + "faebookc.com": true, + "faeboook.com": true, + "faecebok.com": true, + "faesebook.com": true, + "fafacebook.com": true, + "faicbooc.com": true, + "fasebokk.com": true, + "fasebook.com": true, + "faseboox.com": true, + "favebook.com": true, + "faycbok.com": true, + "fb.careers": true, + "fb.com": true, + "fb.gg": true, + "fb.me": true, + "fb.watch": true, + "fbacebook.com": true, + "fbbmarket.com": true, + "fbboostyourbusiness.com": true, + "fbcdn-a.akamaihd.net": true, + "fbcdn.com": true, + "fbcdn.net": true, + "fbfeedback.com": true, + "fbhome.com": true, + "fbidb.io": true, + "fbinc.com": true, + "fbinnovation.com": true, + "fbmarketing.com": true, + "fbreg.com": true, + "fbrpms.com": true, + "fbsbx.com": true, + "fbsbx.net": true, + "fbsupport-covid.net": true, + "fbthirdpartypixel.com": true, + "fbthirdpartypixel.net": true, + "fbthirdpartypixel.org": true, + "fburl.com": true, + "fbwat.ch": true, + "fbworkmail.com": true, + "fcacebook.com": true, + "fcaebook.com": true, + "fcebook.com": true, + "fcebookk.com": true, + "fcfacebook.com": true, + "fdacebook.info": true, + "feacboo.com": true, + "feacbook.com": true, + "feacbooke.com": true, + "feacebook.com": true, + "fecbbok.com": true, + "fecbooc.com": true, + "fecbook.com": true, + "feceboock.com": true, + "fecebook.net": true, + "feceboox.com": true, + "fececbook.com": true, + "feook.com": true, + "ferabook.com": true, + "fescebook.com": true, + "fesebook.com": true, + "ffacebook.com": true, + "fgacebook.com": true, + "ficeboock.com": true, + "fmcebook.com": true, + "fnacebook.com": true, + "fosebook.com": true, + "fpacebook.com": true, + "fqcebook.com": true, + "fracebook.com": true, + "freeb.com": true, + "freebasics.com": true, + "freebasics.net": true, + "freebs.com": true, + "freefacebook.com": true, + "freefacebook.net": true, + "freefacebookads.net": true, + "freefblikes.com": true, + "freindfeed.com": true, + "friendbook.info": true, + "friendfed.com": true, + "friendfeed-api.com": true, + "friendfeed-media.com": true, + "friendfeed.com": true, + "friendfeedmedia.com": true, + "fsacebok.com": true, + "fscebook.com": true, + "fundraisingwithfacebook.com": true, + "funnyfacebook.org": true, + "futureofbusinesssurvey.org": true, + "gacebook.com": true, + "gameroom.com": true, + "gfacecbook.com": true, + "groups.com": true, + "hackerfacebook.com": true, + "hackfacebook.com": true, + "hackfacebookid.com": true, + "hifacebook.info": true, + "howtohackfacebook-account.com": true, + "hsfacebook.com": true, + "httpfacebook.com": true, + "httpsfacebook.com": true, + "httpwwwfacebook.com": true, + "i.org": true, + "iachat-followers-instagram.com": true, + "ig.me": true, + "igcdn.com": true, + "igsonar.com": true, + "igtv.com": true, + "imstagram.com": true, + "imtagram.com": true, + "instaadder.com": true, + "instachecker.com": true, + "instafallow.com": true, + "instafollower.com": true, + "instagainer.com": true, + "instagda.com": true, + "instagify.com": true, + "instagmania.com": true, + "instagor.com": true + } + r = f(m.domain, l) + if r != undefined { + return r + } + + l = { + "instagram-brand.com": true, + "instagram-engineering.com": true, + "instagram-help.com": true, + "instagram-press.com": true, + "instagram-press.net": true, + "instagram.com": true, + "instagramci.com": true, + "instagramcn.com": true, + "instagramdi.com": true, + "instagramhashtags.net": true, + "instagramhilecim.com": true, + "instagramhilesi.org": true, + "instagramium.com": true, + "instagramizlenme.com": true, + "instagramkusu.com": true, + "instagramlogin.com": true, + "instagramm.com": true, + "instagramn.com": true, + "instagrampartners.com": true, + "instagramphoto.com": true, + "instagramq.com": true, + "instagramsepeti.com": true, + "instagramtakipcisatinal.net": true, + "instagramtakiphilesi.com": true, + "instagramtips.com": true, + "instagramtr.com": true, + "instagran.com": true, + "instagranm.com": true, + "instagrem.com": true, + "instagrm.com": true, + "instagtram.com": true, + "instagy.com": true, + "instamgram.com": true, + "instangram.com": true, + "instanttelegram.com": true, + "instaplayer.net": true, + "instastyle.tv": true, + "instgram.com": true, + "intagram.com": true, + "intagrm.com": true, + "internet.org": true, + "intgram.com": true, + "kingstagram.com": true, + "klik.me": true, + "liverail.com": true, + "liverail.tv": true, + "lnstagram-help.com": true, + "login-account.net": true, + "markzuckerberg.com": true, + "messenger.com": true, + "midentsolutions.com": true, + "mobilefacebook.com": true, + "moneywithfacebook.com": true, + "myfbfans.com": true, + "newsfeed.com": true, + "nextstop.com": true, + "oninstagram.com": true, + "online-deals.net": true, + "online-instagram.com": true, + "onlineinstagram.com": true, + "opencreate.org": true, + "reachtheworldonfacebook.com": true, + "redkix.com": true, + "rocksdb.org": true, + "shopfacebook.com": true, + "sportsfacebook.com": true, + "sportstream.com": true, + "supportfacebook.com": true, + "terragraph.com": true, + "tfbnw.net": true, + "thefacebook.com": true, + "thefacebook.net": true, + "thefind.com": true, + "theinstagramhack.com": true, + "toplayerserver.com": true, + "viewpointsfromfacebook.com": true, + "web-instagram.net": true, + "whatsapp.com": true, + "whatsapp.net": true, + "whyfacebook.com": true, + "workplace.com": true, + "workplaceusecases.com": true, + "worldhack.com": true, + "www-facebook.com": true, + "wwwfacebok.com": true, + "wwwfacebook.com": true, + "wwwinstagram.com": true, + "wwwmfacebook.com": true, + "zuckerberg.com": true, + "zuckerberg.net": true + } + r = f(m.domain, l) + if r != undefined { + return r + } } }) + diff --git a/brook/programmable/modules/readme.md b/brook/programmable/modules/readme.md index a8e7f95dd8..5cff356176 100644 --- a/brook/programmable/modules/readme.md +++ b/brook/programmable/modules/readme.md @@ -27,9 +27,9 @@ modules = append(modules, { }) ``` -## tun2brook +## ipio or openwrt -If you are using tun2brook, you can combine multiple modules into a complete script in the following way. For example: +If you are using opio or openwrt, you can combine multiple modules into a complete script in the following way. For example: ``` cat _header.tengo > my.tengo diff --git a/brook/programmable/server/check_syntax.js b/brook/programmable/server/check_syntax.js new file mode 100755 index 0000000000..30cba7604b --- /dev/null +++ b/brook/programmable/server/check_syntax.js @@ -0,0 +1,19 @@ +#!/usr/bin/env bun + +import { $ } from 'bun' +import * as fs from 'node:fs/promises' + +var s = await $`ls`.text() +var l = s.split('\n').filter(v => v.endsWith('.tengo')) +for (var i = 0; i < l.length; i++) { + s = (await $`cat ${l[i]}`.text()).replaceAll('import("brook")', 'undefined') + await fs.writeFile('/tmp/_.tengo', ` +in_dnsservers := undefined +in_dohservers := undefined +in_brooklinks := undefined +in_address := undefined +${s} +`) + await $`tengo /tmp/_.tengo` +} + diff --git a/brook/programmable/server/example.tengo b/brook/programmable/server/example.tengo new file mode 100644 index 0000000000..8e965ce087 --- /dev/null +++ b/brook/programmable/server/example.tengo @@ -0,0 +1,69 @@ +f := func() { + if in_dnsservers { + return { + "google4": "8.8.8.8:53", + "google6": "[2001:4860:4860::8888]:53", + "quad4": "9.9.9.9:53" + } + } + if in_dohservers { + return { + "google4": "https://dns.google/dns-query?address=8.8.8.8%3A443", + "google6": "https://dns.google/dns-query?address=%5B2001%3A4860%3A4860%3A%3A8888%5D%3A443", + "quad4": "https://dns.quad9.net/dns-query?address=9.9.9.9%3A443" + } + } + if in_brooklinks { + return { + "huluwa": "brook://server?password=hello&server=1.3.6.9%3A9999", + "jiuyeye": "brook://socks5?password=&socks5=socks5%3A%2F%2F127.0.0.1%3A1080" + } + } + if in_address { + m := in_address + brook := import("brook") + if m.ipaddress { + r := brook.splithostport(m.ipaddress) + s := brook.country(r.host) + if s == "ZZ" { + return { block: true } + } + if m.network == "tcp" && m.ipaddress == "8.8.8.8:53" { + return { address: "9.9.9.9:53" } + } + return + } + if m.domainaddress { + r := brook.splithostport(m.domainaddress) + text := import("text") + if r.host == "localhost" || text.contains(r.host, "speedtest") { + return { block: true } + } + if m.domainaddress == "heygirl:443" { + return { address: "1.2.3.4:443" } + } + if m.domainaddress == "hello.com:443" { + return { ipaddressfromdohserverkey: "quad4", aoraaaa: "A" } + } + if m.network == "tcp" && m.domainaddress == "world.com:443" { + return { brooklinkkey: "jiuyeye" } + } + if m.domainaddress == "helloworld:443" { + return { ipaddressfromdohserverkey: "quad4", aoraaaa: "AAAA", brooklinkkey: "huluwa" } + } + if m.domainaddress == "nihao.com:443" { + return { speedlimit: 500000 } + } + if m.domainaddress == "shijie.com:443" { + return { speedlimit: 500000, brooklinkkey: "huluwa" } + } + if m.domainaddress == "nihaoshijie.com:443" { + return { speedlimit: 500000, dialwith: "192.168.3.99" } + } + return + } + return + } +} +out := f() + diff --git a/brook/programmable/server/readme.md b/brook/programmable/server/readme.md new file mode 100644 index 0000000000..21d44db7f3 --- /dev/null +++ b/brook/programmable/server/readme.md @@ -0,0 +1,2 @@ +brook server, wsserver, wssserver, quicserver + diff --git a/brook/protocol/brook-quicserver-wbp-protocol.md b/brook/protocol/brook-quicserver-wbp-protocol.md deleted file mode 100644 index c0031c7dab..0000000000 --- a/brook/protocol/brook-quicserver-wbp-protocol.md +++ /dev/null @@ -1,63 +0,0 @@ -# brook quicserver --withoutBrookProtocol protocol - - - - -## Terminology - -- **`DST Address`**: The address that the application actually wants to request, address contains IP/domain and port - - ``` - ATYP + IP/Domain + PORT - ``` - - - `ATYP`: 1 byte - - 0x01: IPv4 - - 0x03: Domain - - 0x04: IPv6 - - `IP/Domain`: 4/n/16 bytes - - If ATYP is 0x01, then this is IPv4, 4 bytes - - If ATYP is 0x03, then this is domain, n bytes, and the first byte is the domain length - - If ATYP is 0x04, then this is IPv6, 16 bytes - - `Port`: 2 bytes - - Big Endian 16-bit unsigned integer - -- **`Password`**: User-defined password -- **`SHA256`**: Defined in FIPS 180-4 - -## Client --TCP over QUIC Stream--> Server - -``` -[SHA256(Password) + (DST Address Length+4) + Unix Timestamp + DST Address] + [DATA]... -``` - -> The maximum length of `[SHA256(Password) + (DST Address Length+4) + Unix Timestamp + DST Address]` is 2048 bytes - -- `DST Address Length+4`: Big Endian 16-bit unsigned integer -- [`Unix Timestamp`](https://en.wikipedia.org/wiki/Unix_time): If it is not even, it should be increased by 1. Big Endian 32-bit unsigned integer -- `DATA`: Actual data being proxied - -## Server --TCP over QUIC Stream--> Client - -``` -[DATA]... -``` - -## Client --UDP over QUIC Datagram--> Server - -``` -SHA256(Password) + Unix Timestamp + DST Address + Data -``` - -> The maximum length of datagram is [1197](https://github.com/quic-go/quic-go/blob/a81365ece88ce9d4601ef140073abadc7657fec8/internal/protocol/params.go#L137) now, and may change in the [future](https://datatracker.ietf.org/doc/html/rfc9221#section-3) - -- [`Unix Timestamp`](https://en.wikipedia.org/wiki/Unix_time): Big Endian 32-bit unsigned integer -- `Data`: Actual data being proxied - -## Server --UDP over QUIC Datagram--> Client - -``` -DST Address + Data -``` - -> The maximum length of datagram is [1197](https://github.com/quic-go/quic-go/blob/a81365ece88ce9d4601ef140073abadc7657fec8/internal/protocol/params.go#L137) now, and may change in the [future](https://datatracker.ietf.org/doc/html/rfc9221#section-3) diff --git a/brook/protocol/brook-wsserver-wbp-protocol.md b/brook/protocol/brook-wsserver-wbp-protocol.md deleted file mode 100644 index 61862c6168..0000000000 --- a/brook/protocol/brook-wsserver-wbp-protocol.md +++ /dev/null @@ -1,69 +0,0 @@ -# brook wsserver --withoutBrookProtocol protocol - - - - -## Terminology - -- **`DST Address`**: The address that the application actually wants to request, address contains IP/domain and port - - ``` - ATYP + IP/Domain + PORT - ``` - - - `ATYP`: 1 byte - - 0x01: IPv4 - - 0x03: Domain - - 0x04: IPv6 - - `IP/Domain`: 4/n/16 bytes - - If ATYP is 0x01, then this is IPv4, 4 bytes - - If ATYP is 0x03, then this is domain, n bytes, and the first byte is the domain length - - If ATYP is 0x04, then this is IPv6, 16 bytes - - `Port`: 2 bytes - - Big Endian 16-bit unsigned integer - -- **`Password`**: User-defined password -- **`SHA256`**: Defined in FIPS 180-4 - -## Client --TCP--> Server - -``` -[Standard WebSocket Protocol Header] + [SHA256(Password) + (DST Address Length+4) + Unix Timestamp + DST Address] + [DATA]... -``` - -> The maximum length of `[SHA256(Password) + (DST Address Length+4) + Unix Timestamp + DST Address]` is 2048 bytes - -- `DST Address Length+4`: Big Endian 16-bit unsigned integer -- [`Unix Timestamp`](https://en.wikipedia.org/wiki/Unix_time): If it is not even, it should be increased by 1. Big Endian 32-bit unsigned integer -- `DATA`: Actual data being proxied - -## Server --TCP--> Client - -``` -[Standard WebSocket Protocol Header] + [DATA]... -``` - -## Client --UDP(UDP over TCP)--> Server - -``` -[Standard WebSocket Protocol Header] + [SHA256(Password) + (DST Address Length+4) + Unix Timestamp + DST Address] + [Fragment Length + Fragment]... -``` - -> The maximum length of `[SHA256(Password) + (DST Address Length+4) + Unix Timestamp + DST Address]` is 2048 bytes
    -> The maximum length of `[Fragment Length + Fragment]` is 65507 bytes
    - -- `DST Address Length+4`: Big Endian 16-bit unsigned integer -- `Fragment Length`: Big Endian 16-bit unsigned integer -- `Fragment`: Actual data being proxied -- [`Unix Timestamp`](https://en.wikipedia.org/wiki/Unix_time): If it is not odd, it should be increased by 1. Big Endian 32-bit unsigned integer - -## Server --UDP(UDP over TCP)--> Client - -``` -[Standard WebSocket Protocol Header] + [Fragment Length + Fragment]... -``` - -> The maximum length of `[Fragment Length + Fragment]` is 65507 bytes
    - -- `Fragment Length`: Big Endian 16-bit unsigned integer -- `Fragment`: Actual data being proxied diff --git a/brook/protocol/user.md b/brook/protocol/user.md index ddc4af15c8..1ebb7e5097 100644 --- a/brook/protocol/user.md +++ b/brook/protocol/user.md @@ -61,10 +61,10 @@ The user 9 has expired ## Run Brook Server with your User API ``` -brook --serverLog /path/to/log.txt --userAPI https://your-api-server.com/a_unpredictable_path server --listen :9999 --password hello +brook --userLog /path/to/log.txt --userAPI https://your-api-server.com/a_unpredictable_path server --listen :9999 --password hello ``` -You can count the traffic of each user from serverLog +You can count the traffic of each user from userLog ``` {"bytes":"2190","dst":"8.8.8.8:53","from":"34.105.110.232:49514","network":"tcp","time":"2024-02-26T09:56:12Z","user":"9"} diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 8b89d618dd..79032395c4 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -577,9 +577,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" dependencies = [ "proc-macro2", "quote", @@ -849,7 +849,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -1285,16 +1285,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" dependencies = [ "camino", "cargo-platform", "semver 1.0.24", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.9", ] [[package]] @@ -1586,7 +1586,7 @@ dependencies = [ "tracing-subscriber", "url", "uuid", - "webview2-com", + "webview2-com 0.33.0", "which 7.0.1", "whoami", "window-vibrancy", @@ -1666,7 +1666,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4702,7 +4702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -7122,12 +7122,14 @@ dependencies = [ [[package]] name = "rfd" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f6f80a9b882647d9014673ca9925d30ffc9750f2eed2b4490e189eaebd01e8" +checksum = "6a24763657bff09769a8ccf12c8b8a50416fb035fe199263b4c5071e4e3f006f" dependencies = [ "ashpd", "block2", + "core-foundation 0.10.0", + "core-foundation-sys", "glib-sys", "gobject-sys", "gtk-sys", @@ -7140,7 +7142,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -8318,9 +8320,9 @@ dependencies = [ [[package]] name = "tao" -version = "0.30.8" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" +checksum = "cc6b53216f32e60efc27dfa111268481e4dfba53e553e4cdebcaed9db36c11bb" dependencies = [ "bitflags 2.6.0", "cocoa", @@ -8333,7 +8335,6 @@ dependencies = [ "gdkwayland-sys", "gdkx11-sys", "gtk", - "instant", "jni", "lazy_static", "libc", @@ -8391,9 +8392,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e545de0a2dfe296fa67db208266cd397c5a55ae782da77973ef4c4fac90e9f2c" +checksum = "2e2e3349fbb2be7af9fad1b43d61ac83ba55ab48d47fbe1b2732f0c8211610a9" dependencies = [ "anyhow", "bytes", @@ -8435,16 +8436,16 @@ dependencies = [ "url", "urlpattern", "webkit2gtk", - "webview2-com", + "webview2-com 0.34.0", "window-vibrancy", "windows 0.58.0", ] [[package]] name = "tauri-build" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd2a4bcfaf5fb9f4be72520eefcb61ae565038f8ccba2a497d8c28f463b8c01" +checksum = "b274ec7239ada504deb615f1c8abd7ba99631e879709e6f10e5d17217058d976" dependencies = [ "anyhow", "cargo_toml", @@ -8464,9 +8465,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf79faeecf301d3e969b1fae977039edb77a4c1f25cc0a961be298b54bff97cf" +checksum = "f77894f9ddb5cb6c04fcfe8c8869ebe0aded4dabf19917118d48be4a95599ab5" dependencies = [ "base64 0.22.1", "brotli", @@ -8491,9 +8492,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52027c8c5afb83166dacddc092ee8fff50772f9646d461d8c33ee887e447a03" +checksum = "3240a5caed760a532e8f687be6f05b2c7d11a1d791fb53ccc08cfeb3e5308736" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -8706,9 +8707,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce18d43f80d4aba3aa8a0c953bbe835f3d0f2370aca75e8dbb14bd4bab27958" +checksum = "2274ef891ccc0a8d318deffa9d70053f947664d12d58b9c0d1ae5e89237e01f7" dependencies = [ "dpi", "gtk", @@ -8725,9 +8726,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f442a38863e10129ffe2cec7bd09c2dcf8a098a3a27801a476a304d5bb991d2" +checksum = "3707b40711d3b9f6519150869e358ffbde7c57567fb9b5a8b51150606939b2a0" dependencies = [ "gtk", "http 1.2.0", @@ -8744,16 +8745,16 @@ dependencies = [ "tauri-utils", "url", "webkit2gtk", - "webview2-com", + "webview2-com 0.34.0", "windows 0.58.0", "wry", ] [[package]] name = "tauri-utils" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9271a88f99b4adea0dc71d0baca4505475a0bbd139fb135f62958721aaa8fe54" +checksum = "96fb10e7cc97456b2d5b9c03e335b5de5da982039a303a20d10006885e4523a0" dependencies = [ "brotli", "cargo_metadata", @@ -8809,12 +8810,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand 2.3.0", + "getrandom 0.2.15", "once_cell", "rustix", "windows-sys 0.59.0", @@ -10230,7 +10232,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" dependencies = [ "webview2-com-macros", - "webview2-com-sys", + "webview2-com-sys 0.33.0", + "windows 0.58.0", + "windows-core 0.58.0", + "windows-implement 0.58.0", + "windows-interface 0.58.0", +] + +[[package]] +name = "webview2-com" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "823e7ebcfaea51e78f72c87fc3b65a1e602c321f407a0b36dbb327d7bb7cd921" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys 0.34.0", "windows 0.58.0", "windows-core 0.58.0", "windows-implement 0.58.0", @@ -10259,6 +10275,17 @@ dependencies = [ "windows-core 0.58.0", ] +[[package]] +name = "webview2-com-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a82bce72db6e5ee83c68b5de1e2cd6ea195b9fbff91cb37df5884cbe3222df4" +dependencies = [ + "thiserror 1.0.69", + "windows 0.58.0", + "windows-core 0.58.0", +] + [[package]] name = "weezl" version = "0.1.8" @@ -10447,7 +10474,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -10960,9 +10987,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "wry" -version = "0.47.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ce51277d65170f6379d8cda935c80e3c2d1f0ff712a123c8bddb11b31a4b73" +checksum = "1e644bf458e27b11b0ecafc9e5633d1304fdae82baca1d42185669752fe6ca4f" dependencies = [ "base64 0.22.1", "block2", @@ -10990,11 +11017,11 @@ dependencies = [ "sha2 0.10.8", "soup3", "tao-macros", - "thiserror 1.0.69", + "thiserror 2.0.9", "url", "webkit2gtk", "webkit2gtk-sys", - "webview2-com", + "webview2-com 0.34.0", "windows 0.58.0", "windows-core 0.58.0", "windows-version", diff --git a/clash-nyanpasu/frontend/interface/package.json b/clash-nyanpasu/frontend/interface/package.json index 416f63c780..a18bcb50d3 100644 --- a/clash-nyanpasu/frontend/interface/package.json +++ b/clash-nyanpasu/frontend/interface/package.json @@ -11,7 +11,7 @@ "build": "tsc" }, "dependencies": { - "@tauri-apps/api": "2.1.1", + "@tauri-apps/api": "2.2.0", "ahooks": "3.8.4", "ofetch": "1.4.1", "react": "19.0.0", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 6103496ba9..8479052ac5 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -22,7 +22,7 @@ "@nyanpasu/interface": "workspace:^", "@nyanpasu/ui": "workspace:^", "@tanstack/router-zod-adapter": "1.81.5", - "@tauri-apps/api": "2.1.1", + "@tauri-apps/api": "2.2.0", "@types/json-schema": "7.0.15", "ahooks": "3.8.4", "allotment": "1.20.2", @@ -80,12 +80,12 @@ "monaco-yaml": "5.2.3", "nanoid": "5.0.9", "sass-embedded": "1.83.0", - "shiki": "1.24.4", + "shiki": "1.26.1", "tailwindcss-textshadow": "2.1.3", "unplugin-auto-import": "0.19.0", "unplugin-icons": "0.22.0", "validator": "13.12.0", - "vite": "6.0.6", + "vite": "6.0.7", "vite-plugin-html": "3.2.2", "vite-plugin-sass-dts": "1.3.30", "vite-plugin-svgr": "4.3.0", diff --git a/clash-nyanpasu/frontend/ui/package.json b/clash-nyanpasu/frontend/ui/package.json index 5971512800..5b61d0a3af 100644 --- a/clash-nyanpasu/frontend/ui/package.json +++ b/clash-nyanpasu/frontend/ui/package.json @@ -22,7 +22,7 @@ "@mui/material": "6.3.0", "@radix-ui/react-portal": "1.1.3", "@radix-ui/react-scroll-area": "1.2.2", - "@tauri-apps/api": "2.1.1", + "@tauri-apps/api": "2.2.0", "@types/d3": "7.4.3", "@types/react": "19.0.2", "@vitejs/plugin-react": "4.3.4", @@ -34,7 +34,7 @@ "react-error-boundary": "5.0.0", "react-i18next": "15.4.0", "react-use": "17.6.0", - "vite": "6.0.6", + "vite": "6.0.7", "vite-tsconfig-paths": "5.1.4" }, "devDependencies": { diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 5bcae74e0e..26eb7a0334 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -61,10 +61,10 @@ "@commitlint/config-conventional": "19.6.0", "@eslint/compat": "1.2.4", "@ianvs/prettier-plugin-sort-imports": "4.4.0", - "@tauri-apps/cli": "2.1.0", + "@tauri-apps/cli": "2.2.0", "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", - "@types/node": "22.10.3", + "@types/node": "22.10.5", "@typescript-eslint/eslint-plugin": "8.19.0", "@typescript-eslint/parser": "8.19.0", "autoprefixer": "10.4.20", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 7c0a54c557..2b65671bc9 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -20,7 +20,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.6.1 - version: 19.6.1(@types/node@22.10.3)(typescript@5.7.2) + version: 19.6.1(@types/node@22.10.5)(typescript@5.7.2) '@commitlint/config-conventional': specifier: 19.6.0 version: 19.6.0 @@ -31,8 +31,8 @@ importers: specifier: 4.4.0 version: 4.4.0(prettier@3.4.2) '@tauri-apps/cli': - specifier: 2.1.0 - version: 2.1.0 + specifier: 2.2.0 + version: 2.2.0 '@types/fs-extra': specifier: 11.0.4 version: 11.0.4 @@ -40,8 +40,8 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: 22.10.3 - version: 22.10.3 + specifier: 22.10.5 + version: 22.10.5 '@typescript-eslint/eslint-plugin': specifier: 8.19.0 version: 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0(jiti@2.4.1))(typescript@5.7.2))(eslint@9.17.0(jiti@2.4.1))(typescript@5.7.2) @@ -101,7 +101,7 @@ importers: version: 15.14.0 knip: specifier: 5.41.1 - version: 5.41.1(@types/node@22.10.3)(typescript@5.7.2) + version: 5.41.1(@types/node@22.10.5)(typescript@5.7.2) lint-staged: specifier: 15.3.0 version: 15.3.0 @@ -172,8 +172,8 @@ importers: frontend/interface: dependencies: '@tauri-apps/api': - specifier: 2.1.1 - version: 2.1.1 + specifier: 2.2.0 + version: 2.2.0 ahooks: specifier: 3.8.4 version: 3.8.4(react@19.0.0) @@ -230,8 +230,8 @@ importers: specifier: 1.81.5 version: 1.81.5(@tanstack/react-router@1.89.2(@tanstack/router-generator@1.87.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(zod@3.24.1) '@tauri-apps/api': - specifier: 2.1.1 - version: 2.1.1 + specifier: 2.2.0 + version: 2.2.0 '@types/json-schema': specifier: 7.0.15 version: 7.0.15 @@ -331,7 +331,7 @@ importers: version: 1.89.2(@tanstack/react-router@1.89.2(@tanstack/router-generator@1.87.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@tanstack/router-plugin': specifier: 1.87.13 - version: 1.87.13(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 1.87.13(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.2.0 version: 2.2.0 @@ -367,13 +367,13 @@ importers: version: 13.12.2 '@vitejs/plugin-legacy': specifier: 6.0.0 - version: 6.0.0(terser@5.36.0)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 6.0.0(terser@5.36.0)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) '@vitejs/plugin-react': specifier: 4.3.4 - version: 4.3.4(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 4.3.4(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) '@vitejs/plugin-react-swc': specifier: 3.7.2 - version: 3.7.2(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 3.7.2(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) change-case: specifier: 5.4.4 version: 5.4.4 @@ -399,8 +399,8 @@ importers: specifier: 1.83.0 version: 1.83.0 shiki: - specifier: 1.24.4 - version: 1.24.4 + specifier: 1.26.1 + version: 1.26.1 tailwindcss-textshadow: specifier: 2.1.3 version: 2.1.3 @@ -414,20 +414,20 @@ importers: specifier: 13.12.0 version: 13.12.0 vite: - specifier: 6.0.6 - version: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + specifier: 6.0.7 + version: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) vite-plugin-html: specifier: 3.2.2 - version: 3.2.2(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 3.2.2(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) vite-plugin-sass-dts: specifier: 1.3.30 - version: 1.3.30(postcss@8.4.49)(prettier@3.4.2)(sass-embedded@1.83.0)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 1.3.30(postcss@8.4.49)(prettier@3.4.2)(sass-embedded@1.83.0)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) vite-plugin-svgr: specifier: 4.3.0 - version: 4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) zod: specifier: 3.24.1 version: 3.24.1 @@ -453,8 +453,8 @@ importers: specifier: 1.2.2 version: 1.2.2(@types/react-dom@19.0.2(@types/react@19.0.2))(@types/react@19.0.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@tauri-apps/api': - specifier: 2.1.1 - version: 2.1.1 + specifier: 2.2.0 + version: 2.2.0 '@types/d3': specifier: 7.4.3 version: 7.4.3 @@ -463,7 +463,7 @@ importers: version: 19.0.2 '@vitejs/plugin-react': specifier: 4.3.4 - version: 4.3.4(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 4.3.4(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) ahooks: specifier: 3.8.4 version: 3.8.4(react@19.0.0) @@ -489,11 +489,11 @@ importers: specifier: 17.6.0 version: 17.6.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) vite: - specifier: 6.0.6 - version: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + specifier: 6.0.7 + version: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 5.1.4(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) devDependencies: '@emotion/react': specifier: 11.14.0 @@ -518,7 +518,7 @@ importers: version: 5.1.0(typescript@5.7.2) vite-plugin-dts: specifier: 4.4.0 - version: 4.4.0(@types/node@22.10.3)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) + version: 4.4.0(@types/node@22.10.5)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)) scripts: dependencies: @@ -2529,20 +2529,26 @@ packages: '@rushstack/ts-command-line@4.23.2': resolution: {integrity: sha512-JJ7XZX5K3ThBBva38aomgsPv1L7FV6XmSOcR6HtM7HDFZJkepqT65imw26h9ggGqMjsY0R9jcl30tzKcVj9aOQ==} - '@shikijs/core@1.24.4': - resolution: {integrity: sha512-jjLsld+xEEGYlxAXDyGwWsKJ1sw5Pc1pnp4ai2ORpjx2UX08YYTC0NNqQYO1PaghYaR+PvgMOGuvzw2he9sk0Q==} + '@shikijs/core@1.26.1': + resolution: {integrity: sha512-yeo7sG+WZQblKPclUOKRPwkv1PyoHYkJ4gP9DzhFJbTdueKR7wYTI1vfF/bFi1NTgc545yG/DzvVhZgueVOXMA==} - '@shikijs/engine-javascript@1.24.4': - resolution: {integrity: sha512-TClaQOLvo9WEMJv6GoUsykQ6QdynuKszuORFWCke8qvi6PeLm7FcD9+7y45UenysxEWYpDL5KJaVXTngTE+2BA==} + '@shikijs/engine-javascript@1.26.1': + resolution: {integrity: sha512-CRhA0b8CaSLxS0E9A4Bzcb3LKBNpykfo9F85ozlNyArxjo2NkijtiwrJZ6eHa+NT5I9Kox2IXVdjUsP4dilsmw==} - '@shikijs/engine-oniguruma@1.24.4': - resolution: {integrity: sha512-Do2ry6flp2HWdvpj2XOwwa0ljZBRy15HKZITzPcNIBOGSeprnA8gOooA/bLsSPuy8aJBa+Q/r34dMmC3KNL/zw==} + '@shikijs/engine-oniguruma@1.26.1': + resolution: {integrity: sha512-F5XuxN1HljLuvfXv7d+mlTkV7XukC1cawdtOo+7pKgPD83CAB1Sf8uHqP3PK0u7njFH0ZhoXE1r+0JzEgAQ+kg==} - '@shikijs/types@1.24.4': - resolution: {integrity: sha512-0r0XU7Eaow0PuDxuWC1bVqmWCgm3XqizIaT7SM42K03vc69LGooT0U8ccSR44xP/hGlNx4FKhtYpV+BU6aaKAA==} + '@shikijs/langs@1.26.1': + resolution: {integrity: sha512-oz/TQiIqZejEIZbGtn68hbJijAOTtYH4TMMSWkWYozwqdpKR3EXgILneQy26WItmJjp3xVspHdiUxUCws4gtuw==} - '@shikijs/vscode-textmate@9.3.1': - resolution: {integrity: sha512-79QfK1393x9Ho60QFyLti+QfdJzRQCVLFb97kOIV7Eo9vQU/roINgk7m24uv0a7AUvN//RDH36FLjjK48v0s9g==} + '@shikijs/themes@1.26.1': + resolution: {integrity: sha512-JDxVn+z+wgLCiUhBGx2OQrLCkKZQGzNH3nAxFir4PjUcYiyD8Jdms9izyxIogYmSwmoPTatFTdzyrRKbKlSfPA==} + + '@shikijs/types@1.26.1': + resolution: {integrity: sha512-d4B00TKKAMaHuFYgRf3L0gwtvqpW4hVdVwKcZYbBfAAQXspgkbWqnFfuFl3MDH6gLbsubOcr+prcnsqah3ny7Q==} + + '@shikijs/vscode-textmate@10.0.1': + resolution: {integrity: sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==} '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} @@ -2806,71 +2812,71 @@ packages: '@taplo/lib@0.4.0-alpha.2': resolution: {integrity: sha512-DV/Re3DPVY+BhBtLZ3dmP4mP6YMLSsgq9qGLXwOV38lvNF/fBlgvQswzlXmzCEefL/3q2eMoefZpOI/+GLuCNA==} - '@tauri-apps/api@2.1.1': - resolution: {integrity: sha512-fzUfFFKo4lknXGJq8qrCidkUcKcH2UHhfaaCNt4GzgzGaW2iS26uFOg4tS3H4P8D6ZEeUxtiD5z0nwFF0UN30A==} + '@tauri-apps/api@2.2.0': + resolution: {integrity: sha512-R8epOeZl1eJEl603aUMIGb4RXlhPjpgxbGVEaqY+0G5JG9vzV/clNlzTeqc+NLYXVqXcn8mb4c5b9pJIUDEyAg==} - '@tauri-apps/cli-darwin-arm64@2.1.0': - resolution: {integrity: sha512-ESc6J6CE8hl1yKH2vJ+ALF+thq4Be+DM1mvmTyUCQObvezNCNhzfS6abIUd3ou4x5RGH51ouiANeT3wekU6dCw==} + '@tauri-apps/cli-darwin-arm64@2.2.0': + resolution: {integrity: sha512-Paxq9JUj1uxV/CDr8hNnr88GcjXLmmX1yBcclQldeUoAoSgsXN1eLLS4e0CHXIzYATmcsSbcl6Zgquo4wW4e9w==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tauri-apps/cli-darwin-x64@2.1.0': - resolution: {integrity: sha512-TasHS442DFs8cSH2eUQzuDBXUST4ECjCd0yyP+zZzvAruiB0Bg+c8A+I/EnqCvBQ2G2yvWLYG8q/LI7c87A5UA==} + '@tauri-apps/cli-darwin-x64@2.2.0': + resolution: {integrity: sha512-BpIQxYQmg+vyS4Z4hxnAcrR95Kn2cnQbkA37NZDW0x7nnx+IFTNremU0cxATJQ3vk1PPVi3PQgrnAX5HE5aXKA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tauri-apps/cli-linux-arm-gnueabihf@2.1.0': - resolution: {integrity: sha512-aP7ZBGNL4ny07Cbb6kKpUOSrmhcIK2KhjviTzYlh+pPhAptxnC78xQGD3zKQkTi2WliJLPmBYbOHWWQa57lQ9w==} + '@tauri-apps/cli-linux-arm-gnueabihf@2.2.0': + resolution: {integrity: sha512-JDYwiELRKKOStSA2QKpGiOZL4si+9ZZcwYCh7DRxnk0csM42vIv0bgcG+ucK5A/gltyDyavZgHNToxFGXaLKXA==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tauri-apps/cli-linux-arm64-gnu@2.1.0': - resolution: {integrity: sha512-ZTdgD5gLeMCzndMT2f358EkoYkZ5T+Qy6zPzU+l5vv5M7dHVN9ZmblNAYYXmoOuw7y+BY4X/rZvHV9pcGrcanQ==} + '@tauri-apps/cli-linux-arm64-gnu@2.2.0': + resolution: {integrity: sha512-ITpT44YDMrg3l0ZQMTeFjj+mRzjCZAGyD3GuJ414aL5X1GWO2CHMdAHYQT9gYtH2OHlixaWq9nRJXDL7W9998w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-arm64-musl@2.1.0': - resolution: {integrity: sha512-NzwqjUCilhnhJzusz3d/0i0F1GFrwCQbkwR6yAHUxItESbsGYkZRJk0yMEWkg3PzFnyK4cWTlQJMEU52TjhEzA==} + '@tauri-apps/cli-linux-arm64-musl@2.2.0': + resolution: {integrity: sha512-sj/NR2O99XeatAh4UgM4MltNipoi4A8ZbMhTb1/FaGEvs/ZVrushIX69hFIyxcHu8Nbe/OkZb5b+N80A/V30jA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-x64-gnu@2.1.0': - resolution: {integrity: sha512-TyiIpMEtZxNOQmuFyfJwaaYbg3movSthpBJLIdPlKxSAB2BW0VWLY3/ZfIxm/G2YGHyREkjJvimzYE0i37PnMA==} + '@tauri-apps/cli-linux-x64-gnu@2.2.0': + resolution: {integrity: sha512-mwX7EzQLKbHZ/VzSksiOLS0uqJUVDqY58cqCj2puiGaPVgCE7bxbKcO6P3PmqYX9P8XWR2K8t922k7K44dScqA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tauri-apps/cli-linux-x64-musl@2.1.0': - resolution: {integrity: sha512-/dQd0TlaxBdJACrR72DhynWftzHDaX32eBtS5WBrNJ+nnNb+znM3gON6nJ9tSE9jgDa6n1v2BkI/oIDtypfUXw==} + '@tauri-apps/cli-linux-x64-musl@2.2.0': + resolution: {integrity: sha512-9C8lVjVJPEjMZaOQdKA5SZV1NpjLP690Y9GodRMum5cIDE3T1AVrp9w6vjrsciQN42agTsO8UaREppF6OjxYnA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tauri-apps/cli-win32-arm64-msvc@2.1.0': - resolution: {integrity: sha512-NdQJO7SmdYqOcE+JPU7bwg7+odfZMWO6g8xF9SXYCMdUzvM2Gv/AQfikNXz5yS7ralRhNFuW32i5dcHlxh4pDg==} + '@tauri-apps/cli-win32-arm64-msvc@2.2.0': + resolution: {integrity: sha512-lbXYsLlvyanx1S/VSiylc6fMsDh1wnBpBid4VxscSfSPyyIOPC/p9uJvcEFWR5Caaet6vUwyJ3iKUaT5yqfsUA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tauri-apps/cli-win32-ia32-msvc@2.1.0': - resolution: {integrity: sha512-f5h8gKT/cB8s1ticFRUpNmHqkmaLutT62oFDB7N//2YTXnxst7EpMIn1w+QimxTvTk2gcx6EcW6bEk/y2hZGzg==} + '@tauri-apps/cli-win32-ia32-msvc@2.2.0': + resolution: {integrity: sha512-nlQ2iRFJTuZw5YelO2HNIsrkcZdqlt7HxdMkHJtCQkFReclpSupjbn6CrupIXHYO8NO6LcoDXiteOYhdWh0fJg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@tauri-apps/cli-win32-x64-msvc@2.1.0': - resolution: {integrity: sha512-P/+LrdSSb5Xbho1LRP4haBjFHdyPdjWvGgeopL96OVtrFpYnfC+RctB45z2V2XxqFk3HweDDxk266btjttfjGw==} + '@tauri-apps/cli-win32-x64-msvc@2.2.0': + resolution: {integrity: sha512-MupuZwaJqJv3YsNCGD0H/98S+7106E6HChGoobuPmN87eCniSL/mSsOaa0cVmxdIAwVcSi0fuDzDBRMt8wOhHw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tauri-apps/cli@2.1.0': - resolution: {integrity: sha512-K2VhcKqBhAeS5pNOVdnR/xQRU6jwpgmkSL2ejHXcl0m+kaTggT0WRDQnFtPq6NljA7aE03cvwsbCAoFG7vtkJw==} + '@tauri-apps/cli@2.2.0': + resolution: {integrity: sha512-8sA4LBU4kA73SZcL/mLjXvrpJjDqLFLQymg39FDlf3SVWyzbQxCyHBrokCLhUXLenG4qWVCl91oAImC/s47vzA==} engines: {node: '>= 10'} hasBin: true @@ -3087,8 +3093,8 @@ packages: '@types/node@22.10.1': resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} - '@types/node@22.10.3': - resolution: {integrity: sha512-DifAyw4BkrufCILvD3ucnuN8eydUfc/C1GlyrnI+LK6543w5/L3VeVgf05o3B4fqSXP1dKYLOZsKfutpxPzZrw==} + '@types/node@22.10.5': + resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -6198,8 +6204,8 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - oniguruma-to-es@0.8.1: - resolution: {integrity: sha512-dekySTEvCxCj0IgKcA2uUCO/e4ArsqpucDPcX26w9ajx+DvMWLc5eZeJaRQkd7oC/+rwif5gnT900tA34uN9Zw==} + oniguruma-to-es@0.10.0: + resolution: {integrity: sha512-zapyOUOCJxt+xhiNRPPMtfJkHGsZ98HHB9qJEkdT8BGytO/+kpe4m1Ngf0MzbzTmhacn11w9yGeDP6tzDhnCdg==} open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} @@ -6802,14 +6808,14 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - regex-recursion@5.0.0: - resolution: {integrity: sha512-UwyOqeobrCCqTXPcsSqH4gDhOjD5cI/b8kjngWgSZbxYh5yVjAwTjO5+hAuPRNiuR70+5RlWSs+U9PVcVcW9Lw==} + regex-recursion@5.1.1: + resolution: {integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==} regex-utilities@2.3.0: resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} - regex@5.0.2: - resolution: {integrity: sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==} + regex@5.1.1: + resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==} regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} @@ -7168,8 +7174,8 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - shiki@1.24.4: - resolution: {integrity: sha512-aVGSFAOAr1v26Hh/+GBIsRVDWJ583XYV7CuNURKRWh9gpGv4OdbisZGq96B9arMYTZhTQkmRF5BrShOSTvNqhw==} + shiki@1.26.1: + resolution: {integrity: sha512-Gqg6DSTk3wYqaZ5OaYtzjcdxcBvX5kCy24yvRJEgjT5U+WHlmqCThLuBUx0juyxQBi+6ug53IGeuQS07DWwpcw==} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -7973,8 +7979,8 @@ packages: vite: optional: true - vite@6.0.6: - resolution: {integrity: sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==} + vite@6.0.7: + resolution: {integrity: sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -9006,11 +9012,11 @@ snapshots: '@bufbuild/protobuf@2.2.3': {} - '@commitlint/cli@19.6.1(@types/node@22.10.3)(typescript@5.7.2)': + '@commitlint/cli@19.6.1(@types/node@22.10.5)(typescript@5.7.2)': dependencies: '@commitlint/format': 19.5.0 '@commitlint/lint': 19.6.0 - '@commitlint/load': 19.6.1(@types/node@22.10.3)(typescript@5.7.2) + '@commitlint/load': 19.6.1(@types/node@22.10.5)(typescript@5.7.2) '@commitlint/read': 19.5.0 '@commitlint/types': 19.5.0 tinyexec: 0.3.1 @@ -9057,7 +9063,7 @@ snapshots: '@commitlint/rules': 19.6.0 '@commitlint/types': 19.5.0 - '@commitlint/load@19.6.1(@types/node@22.10.3)(typescript@5.7.2)': + '@commitlint/load@19.6.1(@types/node@22.10.5)(typescript@5.7.2)': dependencies: '@commitlint/config-validator': 19.5.0 '@commitlint/execute-rule': 19.5.0 @@ -9065,7 +9071,7 @@ snapshots: '@commitlint/types': 19.5.0 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.7.2) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.10.3)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.10.5)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -9562,23 +9568,23 @@ snapshots: '@material/material-color-utilities@0.3.0': {} - '@microsoft/api-extractor-model@7.30.1(@types/node@22.10.3)': + '@microsoft/api-extractor-model@7.30.1(@types/node@22.10.5)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.10.1(@types/node@22.10.3) + '@rushstack/node-core-library': 5.10.1(@types/node@22.10.5) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.48.1(@types/node@22.10.3)': + '@microsoft/api-extractor@7.48.1(@types/node@22.10.5)': dependencies: - '@microsoft/api-extractor-model': 7.30.1(@types/node@22.10.3) + '@microsoft/api-extractor-model': 7.30.1(@types/node@22.10.5) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.10.1(@types/node@22.10.3) + '@rushstack/node-core-library': 5.10.1(@types/node@22.10.5) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.14.4(@types/node@22.10.3) - '@rushstack/ts-command-line': 4.23.2(@types/node@22.10.3) + '@rushstack/terminal': 0.14.4(@types/node@22.10.5) + '@rushstack/ts-command-line': 4.23.2(@types/node@22.10.5) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 @@ -10234,7 +10240,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/node-core-library@5.10.1(@types/node@22.10.3)': + '@rushstack/node-core-library@5.10.1(@types/node@22.10.5)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -10245,55 +10251,63 @@ snapshots: resolve: 1.22.8 semver: 7.5.4 optionalDependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.14.4(@types/node@22.10.3)': + '@rushstack/terminal@0.14.4(@types/node@22.10.5)': dependencies: - '@rushstack/node-core-library': 5.10.1(@types/node@22.10.3) + '@rushstack/node-core-library': 5.10.1(@types/node@22.10.5) supports-color: 8.1.1 optionalDependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 - '@rushstack/ts-command-line@4.23.2(@types/node@22.10.3)': + '@rushstack/ts-command-line@4.23.2(@types/node@22.10.5)': dependencies: - '@rushstack/terminal': 0.14.4(@types/node@22.10.3) + '@rushstack/terminal': 0.14.4(@types/node@22.10.5) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 transitivePeerDependencies: - '@types/node' - '@shikijs/core@1.24.4': + '@shikijs/core@1.26.1': dependencies: - '@shikijs/engine-javascript': 1.24.4 - '@shikijs/engine-oniguruma': 1.24.4 - '@shikijs/types': 1.24.4 - '@shikijs/vscode-textmate': 9.3.1 + '@shikijs/engine-javascript': 1.26.1 + '@shikijs/engine-oniguruma': 1.26.1 + '@shikijs/types': 1.26.1 + '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 hast-util-to-html: 9.0.4 - '@shikijs/engine-javascript@1.24.4': + '@shikijs/engine-javascript@1.26.1': dependencies: - '@shikijs/types': 1.24.4 - '@shikijs/vscode-textmate': 9.3.1 - oniguruma-to-es: 0.8.1 + '@shikijs/types': 1.26.1 + '@shikijs/vscode-textmate': 10.0.1 + oniguruma-to-es: 0.10.0 - '@shikijs/engine-oniguruma@1.24.4': + '@shikijs/engine-oniguruma@1.26.1': dependencies: - '@shikijs/types': 1.24.4 - '@shikijs/vscode-textmate': 9.3.1 + '@shikijs/types': 1.26.1 + '@shikijs/vscode-textmate': 10.0.1 - '@shikijs/types@1.24.4': + '@shikijs/langs@1.26.1': dependencies: - '@shikijs/vscode-textmate': 9.3.1 + '@shikijs/types': 1.26.1 + + '@shikijs/themes@1.26.1': + dependencies: + '@shikijs/types': 1.26.1 + + '@shikijs/types@1.26.1': + dependencies: + '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 - '@shikijs/vscode-textmate@9.3.1': {} + '@shikijs/vscode-textmate@10.0.1': {} '@sindresorhus/is@4.6.0': {} @@ -10502,7 +10516,7 @@ snapshots: tsx: 4.19.2 zod: 3.24.1 - '@tanstack/router-plugin@1.87.13(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': + '@tanstack/router-plugin@1.87.13(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': dependencies: '@babel/core': 7.26.0 '@babel/generator': 7.26.3 @@ -10523,7 +10537,7 @@ snapshots: unplugin: 1.16.0 zod: 3.24.1 optionalDependencies: - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -10546,82 +10560,82 @@ snapshots: dependencies: '@taplo/core': 0.1.1 - '@tauri-apps/api@2.1.1': {} + '@tauri-apps/api@2.2.0': {} - '@tauri-apps/cli-darwin-arm64@2.1.0': + '@tauri-apps/cli-darwin-arm64@2.2.0': optional: true - '@tauri-apps/cli-darwin-x64@2.1.0': + '@tauri-apps/cli-darwin-x64@2.2.0': optional: true - '@tauri-apps/cli-linux-arm-gnueabihf@2.1.0': + '@tauri-apps/cli-linux-arm-gnueabihf@2.2.0': optional: true - '@tauri-apps/cli-linux-arm64-gnu@2.1.0': + '@tauri-apps/cli-linux-arm64-gnu@2.2.0': optional: true - '@tauri-apps/cli-linux-arm64-musl@2.1.0': + '@tauri-apps/cli-linux-arm64-musl@2.2.0': optional: true - '@tauri-apps/cli-linux-x64-gnu@2.1.0': + '@tauri-apps/cli-linux-x64-gnu@2.2.0': optional: true - '@tauri-apps/cli-linux-x64-musl@2.1.0': + '@tauri-apps/cli-linux-x64-musl@2.2.0': optional: true - '@tauri-apps/cli-win32-arm64-msvc@2.1.0': + '@tauri-apps/cli-win32-arm64-msvc@2.2.0': optional: true - '@tauri-apps/cli-win32-ia32-msvc@2.1.0': + '@tauri-apps/cli-win32-ia32-msvc@2.2.0': optional: true - '@tauri-apps/cli-win32-x64-msvc@2.1.0': + '@tauri-apps/cli-win32-x64-msvc@2.2.0': optional: true - '@tauri-apps/cli@2.1.0': + '@tauri-apps/cli@2.2.0': optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.1.0 - '@tauri-apps/cli-darwin-x64': 2.1.0 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.1.0 - '@tauri-apps/cli-linux-arm64-gnu': 2.1.0 - '@tauri-apps/cli-linux-arm64-musl': 2.1.0 - '@tauri-apps/cli-linux-x64-gnu': 2.1.0 - '@tauri-apps/cli-linux-x64-musl': 2.1.0 - '@tauri-apps/cli-win32-arm64-msvc': 2.1.0 - '@tauri-apps/cli-win32-ia32-msvc': 2.1.0 - '@tauri-apps/cli-win32-x64-msvc': 2.1.0 + '@tauri-apps/cli-darwin-arm64': 2.2.0 + '@tauri-apps/cli-darwin-x64': 2.2.0 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.2.0 + '@tauri-apps/cli-linux-arm64-gnu': 2.2.0 + '@tauri-apps/cli-linux-arm64-musl': 2.2.0 + '@tauri-apps/cli-linux-x64-gnu': 2.2.0 + '@tauri-apps/cli-linux-x64-musl': 2.2.0 + '@tauri-apps/cli-win32-arm64-msvc': 2.2.0 + '@tauri-apps/cli-win32-ia32-msvc': 2.2.0 + '@tauri-apps/cli-win32-x64-msvc': 2.2.0 '@tauri-apps/plugin-clipboard-manager@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-dialog@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-fs@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-notification@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-os@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-process@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-shell@2.2.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@tauri-apps/plugin-updater@2.3.0': dependencies: - '@tauri-apps/api': 2.1.1 + '@tauri-apps/api': 2.2.0 '@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.4.2)': dependencies: @@ -10669,12 +10683,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@types/d3-array@3.2.1': {} @@ -10810,7 +10824,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@types/geojson@7946.0.14': {} @@ -10828,11 +10842,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@types/keyv@3.1.4': dependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@types/lodash-es@4.17.12': dependencies: @@ -10852,7 +10866,7 @@ snapshots: dependencies: undici-types: 6.20.0 - '@types/node@22.10.3': + '@types/node@22.10.5': dependencies: undici-types: 6.20.0 @@ -10882,7 +10896,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 '@types/retry@0.12.2': {} @@ -10894,7 +10908,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 optional: true '@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0(jiti@2.4.1))(typescript@5.7.2))(eslint@9.17.0(jiti@2.4.1))(typescript@5.7.2)': @@ -11013,7 +11027,7 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-legacy@6.0.0(terser@5.36.0)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': + '@vitejs/plugin-legacy@6.0.0(terser@5.36.0)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': dependencies: '@babel/core': 7.26.0 '@babel/preset-env': 7.26.0(@babel/core@7.26.0) @@ -11024,25 +11038,25 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.36.0 - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react-swc@3.7.2(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': + '@vitejs/plugin-react-swc@3.7.2(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': dependencies: '@swc/core': 1.7.26 - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.3.4(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': + '@vitejs/plugin-react@4.3.4(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -11734,9 +11748,9 @@ snapshots: core-js@3.39.0: {} - cosmiconfig-typescript-loader@6.1.0(@types/node@22.10.3)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.10.5)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2): dependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 cosmiconfig: 9.0.0(typescript@5.7.2) jiti: 2.4.1 typescript: 5.7.2 @@ -13748,11 +13762,11 @@ snapshots: kind-of@6.0.3: {} - knip@5.41.1(@types/node@22.10.3)(typescript@5.7.2): + knip@5.41.1(@types/node@22.10.5)(typescript@5.7.2): dependencies: '@nodelib/fs.walk': 1.2.8 '@snyk/github-codeowners': 1.1.0 - '@types/node': 22.10.3 + '@types/node': 22.10.5 easy-table: 1.2.0 enhanced-resolve: 5.17.1 fast-glob: 3.3.2 @@ -14518,11 +14532,11 @@ snapshots: dependencies: mimic-function: 5.0.1 - oniguruma-to-es@0.8.1: + oniguruma-to-es@0.10.0: dependencies: emoji-regex-xs: 1.0.0 - regex: 5.0.2 - regex-recursion: 5.0.0 + regex: 5.1.1 + regex-recursion: 5.1.1 open@8.4.2: dependencies: @@ -15078,13 +15092,14 @@ snapshots: dependencies: '@babel/runtime': 7.26.0 - regex-recursion@5.0.0: + regex-recursion@5.1.1: dependencies: + regex: 5.1.1 regex-utilities: 2.3.0 regex-utilities@2.3.0: {} - regex@5.0.2: + regex@5.1.1: dependencies: regex-utilities: 2.3.0 @@ -15446,13 +15461,15 @@ snapshots: shell-quote@1.8.1: {} - shiki@1.24.4: + shiki@1.26.1: dependencies: - '@shikijs/core': 1.24.4 - '@shikijs/engine-javascript': 1.24.4 - '@shikijs/engine-oniguruma': 1.24.4 - '@shikijs/types': 1.24.4 - '@shikijs/vscode-textmate': 9.3.1 + '@shikijs/core': 1.26.1 + '@shikijs/engine-javascript': 1.26.1 + '@shikijs/engine-oniguruma': 1.26.1 + '@shikijs/langs': 1.26.1 + '@shikijs/themes': 1.26.1 + '@shikijs/types': 1.26.1 + '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 side-channel-list@1.0.0: @@ -16399,9 +16416,9 @@ snapshots: - rollup - supports-color - vite-plugin-dts@4.4.0(@types/node@22.10.3)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): + vite-plugin-dts@4.4.0(@types/node@22.10.5)(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): dependencies: - '@microsoft/api-extractor': 7.48.1(@types/node@22.10.3) + '@microsoft/api-extractor': 7.48.1(@types/node@22.10.5) '@rollup/pluginutils': 5.1.4(rollup@4.27.4) '@volar/typescript': 2.4.11 '@vue/language-core': 2.1.10(typescript@5.7.2) @@ -16412,13 +16429,13 @@ snapshots: magic-string: 0.30.17 typescript: 5.7.2 optionalDependencies: - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-html@3.2.2(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): + vite-plugin-html@3.2.2(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): dependencies: '@rollup/pluginutils': 4.2.1 colorette: 2.0.20 @@ -16432,45 +16449,45 @@ snapshots: html-minifier-terser: 6.1.0 node-html-parser: 5.4.2 pathe: 0.2.0 - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) - vite-plugin-sass-dts@1.3.30(postcss@8.4.49)(prettier@3.4.2)(sass-embedded@1.83.0)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): + vite-plugin-sass-dts@1.3.30(postcss@8.4.49)(prettier@3.4.2)(sass-embedded@1.83.0)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): dependencies: postcss: 8.4.49 postcss-js: 4.0.1(postcss@8.4.49) prettier: 3.4.2 sass-embedded: 1.83.0 - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) - vite-plugin-svgr@4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): + vite-plugin-svgr@4.3.0(rollup@4.27.4)(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.27.4) '@svgr/core': 8.1.0(typescript@5.7.2) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.2)) - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): + vite-tsconfig-paths@5.1.4(typescript@5.7.2)(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.7.2) optionalDependencies: - vite: 6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1) transitivePeerDependencies: - supports-color - typescript - vite@6.0.6(@types/node@22.10.3)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1): + vite@6.0.7(@types/node@22.10.5)(jiti@2.4.1)(less@4.2.0)(sass-embedded@1.83.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1): dependencies: esbuild: 0.24.2 postcss: 8.4.49 rollup: 4.27.4 optionalDependencies: - '@types/node': 22.10.3 + '@types/node': 22.10.5 fsevents: 2.3.3 jiti: 2.4.1 less: 4.2.0 diff --git a/lede/target/linux/ramips/patches-5.10/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/lede/target/linux/ramips/patches-5.10/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch index a0b81bc6c5..6fb582bfb0 100644 --- a/lede/target/linux/ramips/patches-5.10/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch +++ b/lede/target/linux/ramips/patches-5.10/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch @@ -73,11 +73,28 @@ Signed-off-by: John Crispin unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq, min_delta; -@@ -326,11 +353,16 @@ int r4k_clockevent_init(void) +@@ -303,6 +330,15 @@ int r4k_clockevent_init(void) + if (!c0_compare_int_usable()) + return -ENXIO; + ++#ifdef CONFIG_CEVT_SYSTICK_QUIRK ++ /* ++ * With vectored interrupts things are getting platform specific. ++ * get_c0_compare_int is a hook to allow a platform to return the ++ * interrupt number of its liking. ++ */ ++ irq = get_c0_compare_int(); ++#endif ++ + cd = &per_cpu(mips_clockevent_device, cpu); + + cd->name = "MIPS"; +@@ -314,11 +350,17 @@ int r4k_clockevent_init(void) + cd->rating = 300; - cd->irq = irq; cd->cpumask = cpumask_of(cpu); +#ifdef CONFIG_CEVT_SYSTICK_QUIRK ++ cd->irq = irq; + cd->set_state_shutdown = mips_state_shutdown; + cd->set_state_oneshot = mips_state_oneshot; +#endif @@ -90,7 +107,7 @@ Signed-off-by: John Crispin if (cp0_timer_irq_installed) return 0; -@@ -339,6 +371,7 @@ int r4k_clockevent_init(void) +@@ -334,6 +376,7 @@ int r4k_clockevent_init(void) if (request_irq(irq, c0_compare_interrupt, flags, "timer", c0_compare_interrupt)) pr_err("Failed to request irq %d (timer)\n", irq); diff --git a/lede/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/lede/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch index 172cf98ad1..da6b5bc05c 100644 --- a/lede/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch +++ b/lede/target/linux/ramips/patches-5.15/311-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch @@ -73,11 +73,28 @@ Signed-off-by: John Crispin unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq, min_delta; -@@ -322,11 +349,16 @@ int r4k_clockevent_init(void) +@@ -303,6 +330,15 @@ int r4k_clockevent_init(void) + if (!c0_compare_int_usable()) + return -ENXIO; + ++#ifdef CONFIG_CEVT_SYSTICK_QUIRK ++ /* ++ * With vectored interrupts things are getting platform specific. ++ * get_c0_compare_int is a hook to allow a platform to return the ++ * interrupt number of its liking. ++ */ ++ irq = get_c0_compare_int(); ++#endif ++ + cd = &per_cpu(mips_clockevent_device, cpu); + + cd->name = "MIPS"; +@@ -314,11 +350,17 @@ int r4k_clockevent_init(void) + cd->rating = 300; - cd->irq = irq; cd->cpumask = cpumask_of(cpu); +#ifdef CONFIG_CEVT_SYSTICK_QUIRK ++ cd->irq = irq; + cd->set_state_shutdown = mips_state_shutdown; + cd->set_state_oneshot = mips_state_oneshot; +#endif @@ -90,7 +107,7 @@ Signed-off-by: John Crispin if (cp0_timer_irq_installed) return 0; -@@ -335,6 +367,7 @@ int r4k_clockevent_init(void) +@@ -334,6 +376,7 @@ int r4k_clockevent_init(void) if (request_irq(irq, c0_compare_interrupt, flags, "timer", c0_compare_interrupt)) pr_err("Failed to request irq %d (timer)\n", irq); diff --git a/openwrt-packages/luci-theme-alpha/README.md b/openwrt-packages/luci-theme-alpha/README.md index a3bff64d79..e251e3c4a3 100644 --- a/openwrt-packages/luci-theme-alpha/README.md +++ b/openwrt-packages/luci-theme-alpha/README.md @@ -28,7 +28,11 @@ [![paypal][paypal-badge]][paypal] -Luci theme for Official Openwrt and Alpha OS build ,based on bootstrap and material luCi theme refferences, +Luci theme for Official Openwrt and Alpha OS build ,based on bootstrap framework +and material luCi theme refferences, +Thanks To Komunitas Device Berbasis ARM Indonesia (DBAI) for support this theme. +This official 1'st theme in Indo-Wrt Community in indonesia. Not the result of modification from anyone, this is purely made by us +©Derisamedia Preview Screenshoot

    @@ -59,6 +63,14 @@ alpha os is my idea which wants to develop the OpenWrt community in Indonesia, e (old text) Mr. Sibondt once they said 'jalan ditempat komunitas indo', that's what moved my heart to make an innovation that I named alpha os (alpha = initial version, because it hasn't been perfect until now 😁) +### Credits +Indowrt (indonesian Openwrt Community) +DBAI (Device Berbasis Arm Indonesia) + +### frameworks +this theme using bootstrap framework + vanilla css +icons made by me + flaticons + donate buy me a padang rice or coffee https://saweria.co/derisamedia diff --git a/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua b/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua index 1dbeb84ad7..3d9ac38822 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua @@ -4,7 +4,6 @@ bin = require "nixio".bin fs = require "nixio.fs" sys = require "luci.sys" uci = require "luci.model.uci".cursor() -libuci = require "uci".cursor() util = require "luci.util" datatypes = require "luci.cbi.datatypes" jsonc = require "luci.jsonc" @@ -35,33 +34,20 @@ function is_js_luci() return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0 end -function uci_set_list(cursor, config, section, option, value) - if config and section and option then - if not value or #value == 0 then - return cursor:delete(config, section, option) - end - return cursor:set( - config, section, option, - ( type(value) == "table" and value or { value } ) - ) - end - return false -end - -function uci_section(cursor, config, type, name, values) - local stat = true - if name then - stat = cursor:set(config, name, type) - else - name = cursor:add(config, type) - stat = name and true - end - - return stat and name +function is_old_uci() + return sys.call("grep 'require \"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0 end function uci_save(cursor, config, commit, apply) - if is_js_luci() then + if is_old_uci() then + cursor:save(config) + if commit then + cursor:commit(config) + if apply then + sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") + end + end + else commit = true if commit then if apply then @@ -70,14 +56,6 @@ function uci_save(cursor, config, commit, apply) sh_uci_commit(config) end end - else - cursor:save(config) - if commit then - cursor:commit(config) - if apply then - sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") - end - end end end diff --git a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm index 287c1d2f48..37186c4b2c 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm @@ -20,6 +20,9 @@ local api = require "luci.passwall.api" //]]>

    " data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>"> - - -
    \ No newline at end of file + +
    + + +
    + diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh index 57b989bd2a..45e23031b8 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh @@ -233,11 +233,7 @@ check_ver() { get_new_port() { port=$1 - [ "$port" == "auto" ] && { - port=2082 - local GET_NEW_PORT=$(get_cache_var "get_new_port") - [ -n "${GET_NEW_PORT}" ] && port=${GET_NEW_PORT} - } + [ "$port" == "auto" ] && port=2082 protocol=$(echo $2 | tr 'A-Z' 'a-z') result=$(check_port_exists $port $protocol) if [ "$result" != 0 ]; then @@ -249,7 +245,6 @@ get_new_port() { fi get_new_port $temp $protocol else - set_cache_var "get_new_port" "$port" echo $port fi } diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 696c18e78a..546a41e868 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -17,7 +17,7 @@ local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string. local split = api.split local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify local base64Decode = api.base64Decode -local uci = api.libuci +local uci = api.uci local fs = api.fs uci:revert(appname) @@ -228,7 +228,7 @@ do set = function(o) for kk, vv in pairs(CONFIG) do if (vv.remarks == id .. "备用节点的列表") then - api.uci_set_list(uci, appname, id, "autoswitch_backup_node", vv.new_nodes) + uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) end end end @@ -299,8 +299,8 @@ do if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then uci:foreach(appname, "nodes", function(node2) if node2[".name"] == node[".name"] then - local section = api.uci_section(uci, appname, "nodes", node_id) - api.uci_set_list(uci, appname, section, "balancing_node", vv.new_nodes) + local section = uci:section(appname, "nodes", node_id) + uci:set_list(appname, section, "balancing_node", vv.new_nodes) end end) end @@ -1454,7 +1454,7 @@ local function update_node(manual) local remark = v["remark"] local list = v["list"] for _, vv in ipairs(list) do - local cfgid = api.uci_section(uci, appname, "nodes", api.gen_short_uuid()) + local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) for kkk, vvv in pairs(vv) do uci:set(appname, cfgid, kkk, vvv) -- sing-box 域名解析策略 diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/test.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/test.sh index 30d4ac34b3..0ac24e5696 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/test.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/test.sh @@ -72,7 +72,7 @@ url_test_node() { /usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json local curlx="socks5h://127.0.0.1:${_tmp_port}" fi - # sleep 1s + sleep 1s # 兼容 curl 8.6 time_starttransfer 错误 local curl_ver=$(curl -V 2>/dev/null | head -n 1 | awk '{print $2}' | cut -d. -f1,2) local curl_arg="-w %{http_code}:%{time_starttransfer} http://" diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua index 25a96da5e4..5dd8468d76 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua @@ -3,7 +3,6 @@ local com = require "luci.passwall2.com" bin = require "nixio".bin fs = require "nixio.fs" sys = require "luci.sys" -libuci = require "uci".cursor() uci = require"luci.model.uci".cursor() util = require "luci.util" datatypes = require "luci.cbi.datatypes" @@ -30,33 +29,20 @@ function log(...) end end -function uci_set_list(cursor, config, section, option, value) - if config and section and option then - if not value or #value == 0 then - return cursor:delete(config, section, option) - end - return cursor:set( - config, section, option, - ( type(value) == "table" and value or { value } ) - ) - end - return false -end - -function uci_section(cursor, config, type, name, values) - local stat = true - if name then - stat = cursor:set(config, name, type) - else - name = cursor:add(config, type) - stat = name and true - end - - return stat and name +function is_old_uci() + return sys.call("grep 'require \"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0 end function uci_save(cursor, config, commit, apply) - if is_js_luci() then + if is_old_uci() then + cursor:save(config) + if commit then + cursor:commit(config) + if apply then + sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") + end + end + else commit = true if commit then if apply then @@ -65,14 +51,6 @@ function uci_save(cursor, config, commit, apply) sh_uci_commit(config) end end - else - cursor:save(config) - if commit then - cursor:commit(config) - if apply then - sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") - end - end end end diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh index e31fc1db00..ed19cdf023 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -209,11 +209,7 @@ check_depends() { get_new_port() { port=$1 - [ "$port" == "auto" ] && { - port=2082 - local GET_NEW_PORT=$(get_cache_var "get_new_port") - [ -n "${GET_NEW_PORT}" ] && port=${GET_NEW_PORT} - } + [ "$port" == "auto" ] && port=2082 protocol=$(echo $2 | tr 'A-Z' 'a-z') result=$(check_port_exists $port $protocol) if [ "$result" != 0 ]; then @@ -225,7 +221,6 @@ get_new_port() { fi get_new_port $temp $protocol else - set_cache_var "get_new_port" "$port" echo $port fi } diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 3aabb321eb..1e93f415b4 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -17,7 +17,7 @@ local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string. local split = api.split local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify local base64Decode = api.base64Decode -local uci = api.libuci +local uci = api.uci local fs = api.fs uci:revert(appname) @@ -212,7 +212,7 @@ do set = function(o) for kk, vv in pairs(CONFIG) do if (vv.remarks == id .. "备用节点的列表") then - api.uci_set_list(uci, appname, id, "autoswitch_backup_node", vv.new_nodes) + uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) end end end @@ -284,8 +284,8 @@ do if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then uci:foreach(appname, "nodes", function(node2) if node2[".name"] == node[".name"] then - local section = api.uci_section(uci, appname, "nodes", node_id) - api.uci_set_list(uci, appname, section, "balancing_node", vv.new_nodes) + local section = uci:section(appname, "nodes", node_id) + uci:set_list(appname, section, "balancing_node", vv.new_nodes) end end) end @@ -1423,7 +1423,7 @@ local function update_node(manual) local remark = v["remark"] local list = v["list"] for _, vv in ipairs(list) do - local cfgid = api.uci_section(uci, appname, "nodes", api.gen_short_uuid()) + local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) for kkk, vvv in pairs(vv) do uci:set(appname, cfgid, kkk, vvv) -- sing-box 域名解析策略 diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs index 61ad111beb..85983a86b0 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs @@ -237,7 +237,7 @@ pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> } /// Create a `UdpSocket` binded to `bind_addr` -pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, _config: &ConnectOpts) -> io::Result { +pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOpts) -> io::Result { let af = AddrFamily::from(bind_addr); let socket = if af != AddrFamily::Ipv6 { diff --git a/small/luci-app-mihomo/Makefile b/small/luci-app-mihomo/Makefile index c930c382b4..b96df02703 100644 --- a/small/luci-app-mihomo/Makefile +++ b/small/luci-app-mihomo/Makefile @@ -1,6 +1,6 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=1.17.0 +PKG_VERSION:=1.17.1 LUCI_TITLE:=LuCI Support for mihomo LUCI_DEPENDS:=+luci-base +mihomo diff --git a/small/luci-app-passwall/luasrc/controller/passwall.lua b/small/luci-app-passwall/luasrc/controller/passwall.lua index c01e5ef27d..4a46e1eb99 100644 --- a/small/luci-app-passwall/luasrc/controller/passwall.lua +++ b/small/luci-app-passwall/luasrc/controller/passwall.lua @@ -289,6 +289,12 @@ function connect_status() local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1" local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode") or "proxy" local socks_server = api.get_cache_var("GLOBAL_TCP_SOCKS_server") + + -- 兼容 curl 8.6 time_starttransfer 错误 + local curl_ver = luci.sys.exec("curl -V 2>/dev/null | head -n 1 | awk '{print $2}' | cut -d. -f1,2") or "0" + url = (curl_ver == "8.6") and "-w %{http_code}:%{time_appconnect} https://" .. url + or "-w %{http_code}:%{time_starttransfer} http://" .. url + if socks_server and socks_server ~= "" then if (chn_list == "proxy" and gfw_list == "0" and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == "0" and gfw_list == "0" and proxy_mode == "proxy") then -- 中国列表+百度 or 全局 @@ -298,7 +304,7 @@ function connect_status() url = "-x socks5h://" .. socks_server .. " " .. url end end - local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -sk -w "%{http_code}:%{time_appconnect}" ' .. url) + local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -sk ' .. url) local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0") if code ~= 0 then local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'") diff --git a/small/luci-app-passwall/luasrc/passwall/api.lua b/small/luci-app-passwall/luasrc/passwall/api.lua index 1dbeb84ad7..3d9ac38822 100644 --- a/small/luci-app-passwall/luasrc/passwall/api.lua +++ b/small/luci-app-passwall/luasrc/passwall/api.lua @@ -4,7 +4,6 @@ bin = require "nixio".bin fs = require "nixio.fs" sys = require "luci.sys" uci = require "luci.model.uci".cursor() -libuci = require "uci".cursor() util = require "luci.util" datatypes = require "luci.cbi.datatypes" jsonc = require "luci.jsonc" @@ -35,33 +34,20 @@ function is_js_luci() return sys.call('[ -f "/www/luci-static/resources/uci.js" ]') == 0 end -function uci_set_list(cursor, config, section, option, value) - if config and section and option then - if not value or #value == 0 then - return cursor:delete(config, section, option) - end - return cursor:set( - config, section, option, - ( type(value) == "table" and value or { value } ) - ) - end - return false -end - -function uci_section(cursor, config, type, name, values) - local stat = true - if name then - stat = cursor:set(config, name, type) - else - name = cursor:add(config, type) - stat = name and true - end - - return stat and name +function is_old_uci() + return sys.call("grep 'require \"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0 end function uci_save(cursor, config, commit, apply) - if is_js_luci() then + if is_old_uci() then + cursor:save(config) + if commit then + cursor:commit(config) + if apply then + sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") + end + end + else commit = true if commit then if apply then @@ -70,14 +56,6 @@ function uci_save(cursor, config, commit, apply) sh_uci_commit(config) end end - else - cursor:save(config) - if commit then - cursor:commit(config) - if apply then - sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") - end - end end end diff --git a/small/luci-app-passwall/luasrc/view/passwall/global/status.htm b/small/luci-app-passwall/luasrc/view/passwall/global/status.htm index e8d76ec4ce..eb5527e57b 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/global/status.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/global/status.htm @@ -138,7 +138,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md -
    +
    @@ -150,7 +150,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
    -
    +
    @@ -162,7 +162,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
    -
    +
    @@ -174,7 +174,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
    -
    +
    diff --git a/small/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm b/small/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm index 287c1d2f48..37186c4b2c 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/socks_auto_switch/btn.htm @@ -20,6 +20,9 @@ local api = require "luci.passwall.api" //]]>
    " data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>"> - - -
    \ No newline at end of file + +
    + + +
    +
    diff --git a/small/luci-app-passwall/root/usr/share/passwall/app.sh b/small/luci-app-passwall/root/usr/share/passwall/app.sh index 57b989bd2a..45e23031b8 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/app.sh @@ -233,11 +233,7 @@ check_ver() { get_new_port() { port=$1 - [ "$port" == "auto" ] && { - port=2082 - local GET_NEW_PORT=$(get_cache_var "get_new_port") - [ -n "${GET_NEW_PORT}" ] && port=${GET_NEW_PORT} - } + [ "$port" == "auto" ] && port=2082 protocol=$(echo $2 | tr 'A-Z' 'a-z') result=$(check_port_exists $port $protocol) if [ "$result" != 0 ]; then @@ -249,7 +245,6 @@ get_new_port() { fi get_new_port $temp $protocol else - set_cache_var "get_new_port" "$port" echo $port fi } diff --git a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 696c18e78a..546a41e868 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -17,7 +17,7 @@ local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string. local split = api.split local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify local base64Decode = api.base64Decode -local uci = api.libuci +local uci = api.uci local fs = api.fs uci:revert(appname) @@ -228,7 +228,7 @@ do set = function(o) for kk, vv in pairs(CONFIG) do if (vv.remarks == id .. "备用节点的列表") then - api.uci_set_list(uci, appname, id, "autoswitch_backup_node", vv.new_nodes) + uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) end end end @@ -299,8 +299,8 @@ do if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then uci:foreach(appname, "nodes", function(node2) if node2[".name"] == node[".name"] then - local section = api.uci_section(uci, appname, "nodes", node_id) - api.uci_set_list(uci, appname, section, "balancing_node", vv.new_nodes) + local section = uci:section(appname, "nodes", node_id) + uci:set_list(appname, section, "balancing_node", vv.new_nodes) end end) end @@ -1454,7 +1454,7 @@ local function update_node(manual) local remark = v["remark"] local list = v["list"] for _, vv in ipairs(list) do - local cfgid = api.uci_section(uci, appname, "nodes", api.gen_short_uuid()) + local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) for kkk, vvv in pairs(vv) do uci:set(appname, cfgid, kkk, vvv) -- sing-box 域名解析策略 diff --git a/small/luci-app-passwall/root/usr/share/passwall/test.sh b/small/luci-app-passwall/root/usr/share/passwall/test.sh index 1f596e9292..0ac24e5696 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/test.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/test.sh @@ -73,10 +73,15 @@ url_test_node() { local curlx="socks5h://127.0.0.1:${_tmp_port}" fi sleep 1s + # 兼容 curl 8.6 time_starttransfer 错误 + local curl_ver=$(curl -V 2>/dev/null | head -n 1 | awk '{print $2}' | cut -d. -f1,2) + local curl_arg="-w %{http_code}:%{time_starttransfer} http://" + [ "${curl_ver}" = "8.6" ] && curl_arg="-w %{http_code}:%{time_appconnect} https://" + local chn_list=$(config_n_get @global[0] chn_list direct) - local probeUrl="https://www.google.com/generate_204" - [ "${chn_list}" = "proxy" ] && probeUrl="https://www.baidu.com" - result=$(curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_appconnect}" -x $curlx "${probeUrl}") + local probeUrl="www.google.com/generate_204" + [ "${chn_list}" = "proxy" ] && probeUrl="www.baidu.com" + result=$(curl --connect-timeout 3 -o /dev/null -I -skL -x $curlx ${curl_arg}${probeUrl}) pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}.json" } diff --git a/small/luci-app-passwall2/luasrc/passwall2/api.lua b/small/luci-app-passwall2/luasrc/passwall2/api.lua index 25a96da5e4..5dd8468d76 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/api.lua @@ -3,7 +3,6 @@ local com = require "luci.passwall2.com" bin = require "nixio".bin fs = require "nixio.fs" sys = require "luci.sys" -libuci = require "uci".cursor() uci = require"luci.model.uci".cursor() util = require "luci.util" datatypes = require "luci.cbi.datatypes" @@ -30,33 +29,20 @@ function log(...) end end -function uci_set_list(cursor, config, section, option, value) - if config and section and option then - if not value or #value == 0 then - return cursor:delete(config, section, option) - end - return cursor:set( - config, section, option, - ( type(value) == "table" and value or { value } ) - ) - end - return false -end - -function uci_section(cursor, config, type, name, values) - local stat = true - if name then - stat = cursor:set(config, name, type) - else - name = cursor:add(config, type) - stat = name and true - end - - return stat and name +function is_old_uci() + return sys.call("grep 'require \"uci\"' /usr/lib/lua/luci/model/uci.lua >/dev/null 2>&1") == 0 end function uci_save(cursor, config, commit, apply) - if is_js_luci() then + if is_old_uci() then + cursor:save(config) + if commit then + cursor:commit(config) + if apply then + sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") + end + end + else commit = true if commit then if apply then @@ -65,14 +51,6 @@ function uci_save(cursor, config, commit, apply) sh_uci_commit(config) end end - else - cursor:save(config) - if commit then - cursor:commit(config) - if apply then - sys.call("/etc/init.d/" .. config .. " reload > /dev/null 2>&1 &") - end - end end end diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh index e31fc1db00..ed19cdf023 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -209,11 +209,7 @@ check_depends() { get_new_port() { port=$1 - [ "$port" == "auto" ] && { - port=2082 - local GET_NEW_PORT=$(get_cache_var "get_new_port") - [ -n "${GET_NEW_PORT}" ] && port=${GET_NEW_PORT} - } + [ "$port" == "auto" ] && port=2082 protocol=$(echo $2 | tr 'A-Z' 'a-z') result=$(check_port_exists $port $protocol) if [ "$result" != 0 ]; then @@ -225,7 +221,6 @@ get_new_port() { fi get_new_port $temp $protocol else - set_cache_var "get_new_port" "$port" echo $port fi } diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 3aabb321eb..1e93f415b4 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -17,7 +17,7 @@ local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string. local split = api.split local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify local base64Decode = api.base64Decode -local uci = api.libuci +local uci = api.uci local fs = api.fs uci:revert(appname) @@ -212,7 +212,7 @@ do set = function(o) for kk, vv in pairs(CONFIG) do if (vv.remarks == id .. "备用节点的列表") then - api.uci_set_list(uci, appname, id, "autoswitch_backup_node", vv.new_nodes) + uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) end end end @@ -284,8 +284,8 @@ do if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then uci:foreach(appname, "nodes", function(node2) if node2[".name"] == node[".name"] then - local section = api.uci_section(uci, appname, "nodes", node_id) - api.uci_set_list(uci, appname, section, "balancing_node", vv.new_nodes) + local section = uci:section(appname, "nodes", node_id) + uci:set_list(appname, section, "balancing_node", vv.new_nodes) end end) end @@ -1423,7 +1423,7 @@ local function update_node(manual) local remark = v["remark"] local list = v["list"] for _, vv in ipairs(list) do - local cfgid = api.uci_section(uci, appname, "nodes", api.gen_short_uuid()) + local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) for kkk, vvv in pairs(vv) do uci:set(appname, cfgid, kkk, vvv) -- sing-box 域名解析策略 diff --git a/small/mihomo/Makefile b/small/mihomo/Makefile index 9723643f2b..57e835b750 100644 --- a/small/mihomo/Makefile +++ b/small/mihomo/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mihomo -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/MetaCubeX/mihomo.git diff --git a/small/mihomo/files/nftables/hijack.nft b/small/mihomo/files/nftables/hijack.nft index ab4388583c..6105d6e9b1 100644 --- a/small/mihomo/files/nftables/hijack.nft +++ b/small/mihomo/files/nftables/hijack.nft @@ -183,7 +183,7 @@ table inet mihomo { ip6 daddr @china_ip6 counter return meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return - meta l4proto { tcp, udp } ip dscp == @bypass_dscp counter return + meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return } @@ -199,7 +199,7 @@ table inet mihomo { ip6 daddr @china_ip6 counter return meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return - meta l4proto { tcp, udp } ip dscp == @bypass_dscp counter return + meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return } @@ -215,7 +215,7 @@ table inet mihomo { ip6 daddr @china_ip6 counter return meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return - meta l4proto { tcp, udp } ip dscp == @bypass_dscp counter return + meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return meta l4proto udp th dport 53 counter return } @@ -232,7 +232,7 @@ table inet mihomo { ip6 daddr @china_ip6 counter return meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return - meta l4proto { tcp, udp } ip dscp == @bypass_dscp counter return + meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return meta l4proto udp th dport 53 counter return } diff --git a/v2rayn/v2rayN/AmazTool/UpgradeApp.cs b/v2rayn/v2rayN/AmazTool/UpgradeApp.cs index 9554f923de..b633c877a5 100644 --- a/v2rayn/v2rayN/AmazTool/UpgradeApp.cs +++ b/v2rayn/v2rayN/AmazTool/UpgradeApp.cs @@ -10,7 +10,7 @@ namespace AmazTool { Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}"); - Waiting(8); + Waiting(3); if (!File.Exists(fileName)) { @@ -91,7 +91,7 @@ namespace AmazTool } Console.WriteLine(Resx.Resource.Restartv2rayN); - Waiting(3); + Waiting(2); Process process = new() { StartInfo = new() diff --git a/v2rayn/v2rayN/ServiceLib/Common/FileManager.cs b/v2rayn/v2rayN/ServiceLib/Common/FileManager.cs index b98b165526..b7bc3a8fd5 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/FileManager.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/FileManager.cs @@ -6,6 +6,8 @@ namespace ServiceLib.Common { public static class FileManager { + private static readonly string _tag = "FileManager"; + public static bool ByteArrayToFile(string fileName, byte[] content) { try @@ -15,7 +17,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return false; } @@ -30,7 +32,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -46,7 +48,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -60,7 +62,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -79,7 +81,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); throw; } } @@ -105,13 +107,13 @@ namespace ServiceLib.Common } catch (IOException ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return false; } return true; @@ -130,7 +132,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return null; } } @@ -148,7 +150,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return false; } return true; diff --git a/v2rayn/v2rayN/ServiceLib/Common/JsonUtils.cs b/v2rayn/v2rayN/ServiceLib/Common/JsonUtils.cs index cf5ec25c38..09b62ddae4 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/JsonUtils.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/JsonUtils.cs @@ -6,6 +6,8 @@ namespace ServiceLib.Common { public class JsonUtils { + private static readonly string _tag = "JsonUtils"; + /// /// DeepCopy /// @@ -90,7 +92,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return result; } diff --git a/v2rayn/v2rayN/ServiceLib/Common/Utils.cs b/v2rayn/v2rayN/ServiceLib/Common/Utils.cs index 5dd5a4ec7f..5985fa9f0c 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/Utils.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/Utils.cs @@ -15,6 +15,8 @@ namespace ServiceLib.Common { public class Utils { + private static readonly string _tag = "Utils"; + #region 资源操作 /// @@ -36,7 +38,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return result; @@ -57,7 +59,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return null; @@ -92,7 +94,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return string.Empty; @@ -117,7 +119,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return null; @@ -139,7 +141,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return null; @@ -159,7 +161,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog("Base64Encode", ex); + Logging.SaveLog(_tag, ex); } return string.Empty; @@ -193,7 +195,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog("Base64Decode", ex); + Logging.SaveLog(_tag, ex); } return string.Empty; @@ -483,7 +485,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return false; @@ -535,7 +537,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return Global.AppName; @@ -549,7 +551,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return "0.0"; } } @@ -578,7 +580,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return string.Empty; @@ -605,7 +607,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -631,7 +633,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return systemHosts; diff --git a/v2rayn/v2rayN/ServiceLib/Common/WindowsUtils.cs b/v2rayn/v2rayN/ServiceLib/Common/WindowsUtils.cs index a7b8fc5ffd..94b3b811db 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/WindowsUtils.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/WindowsUtils.cs @@ -4,6 +4,7 @@ namespace ServiceLib.Common { internal static class WindowsUtils { + private static readonly string _tag = "WindowsUtils"; public static string? RegReadValue(string path, string name, string def) { RegistryKey? regKey = null; @@ -15,7 +16,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } finally { @@ -41,7 +42,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } finally { diff --git a/v2rayn/v2rayN/ServiceLib/Common/YamlUtils.cs b/v2rayn/v2rayN/ServiceLib/Common/YamlUtils.cs index 94d572b56a..13ad2d78ca 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/YamlUtils.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/YamlUtils.cs @@ -6,6 +6,8 @@ namespace ServiceLib.Common { public class YamlUtils { + private static readonly string _tag = "YamlUtils"; + #region YAML /// @@ -26,7 +28,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog("FromYaml", ex); + Logging.SaveLog(_tag, ex); return deserializer.Deserialize(""); } } @@ -53,7 +55,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return result; } @@ -71,7 +73,7 @@ namespace ServiceLib.Common } catch (Exception ex) { - Logging.SaveLog("PreprocessYaml", ex); + Logging.SaveLog(_tag, ex); return null; } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs index 12dc292131..881532fcec 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs @@ -5,6 +5,8 @@ namespace ServiceLib.Handler { public static class AutoStartupHandler { + private static readonly string _tag = "AutoStartupHandler"; + public static async Task UpdateTask(Config config) { if (Utils.IsWindows()) @@ -62,7 +64,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -123,7 +125,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -143,7 +145,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/ClashApiHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/ClashApiHandler.cs index cae3c035f3..81d92b048b 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/ClashApiHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/ClashApiHandler.cs @@ -9,6 +9,7 @@ namespace ServiceLib.Handler private Dictionary? _proxies; public Dictionary ProfileContent { get; set; } + private static readonly string _tag = "ClashApiHandler"; public async Task?> GetClashProxiesAsync(Config config) { @@ -109,7 +110,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog("GetClashProxyGroups", ex); + Logging.SaveLog(_tag, ex); return null; } } @@ -125,7 +126,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -153,7 +154,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -169,7 +170,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return null; @@ -184,7 +185,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs index c1ff96ca94..fea4b3f4f0 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -9,6 +9,7 @@ namespace ServiceLib.Handler public class ConfigHandler { private static readonly string _configRes = Global.ConfigFileName; + private static readonly string _tag = "ConfigHandler"; #region ConfigHandler @@ -194,7 +195,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog("ToJsonFile", ex); + Logging.SaveLog(_tag, ex); return -1; } @@ -500,7 +501,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return -1; } @@ -987,7 +988,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog("Remove Item", ex); + Logging.SaveLog(_tag, ex); } return 0; diff --git a/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs index 84c694c6b1..a034712d4e 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/CoreConfigHandler.cs @@ -1,10 +1,14 @@ -namespace ServiceLib.Handler +using YamlDotNet.Core.Tokens; + +namespace ServiceLib.Handler { /// /// Core configuration file processing class /// public class CoreConfigHandler { + private static readonly string _tag = "CoreConfigHandler"; + public static async Task GenerateClientConfig(ProfileItem node, string? fileName) { var config = AppHandler.Instance.Config; @@ -82,7 +86,7 @@ } catch (Exception ex) { - Logging.SaveLog("GenerateClientCustomConfig", ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs index 0a212e0a1f..8c5b46ca6f 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/CoreHandler.cs @@ -15,6 +15,7 @@ namespace ServiceLib.Handler private Process? _processPre; private int _linuxSudoPid = -1; private Action? _updateFunc; + private const string _tag = "CoreHandler"; public async Task Init(Config config, Action updateFunc) { @@ -97,12 +98,14 @@ namespace ServiceLib.Handler { if (_process != null) { - _process = await KillProcess(_process); + await KillProcess(_process, true); + _process = null; } if (_processPre != null) { - _processPre = await KillProcess(_processPre); + await KillProcess(_processPre, true); + _processPre = null; } if (_linuxSudoPid > 0) @@ -113,7 +116,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -121,11 +124,11 @@ namespace ServiceLib.Handler { try { - await KillProcess(Process.GetProcessById(pid)); + await KillProcess(Process.GetProcessById(pid), false); } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -206,7 +209,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ShowMsg(false, ex.Message); return -1; } @@ -315,25 +318,39 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ShowMsg(true, ex.Message); return null; } } - private async Task KillProcess(Process? proc) + private async Task KillProcess(Process? proc, bool review) { if (proc is null) { - return null; + return; } - try { proc?.Kill(true); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); } - try { proc?.Kill(); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); } - try { proc?.Close(); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); } - try { proc?.Dispose(); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); } - await Task.Delay(100); - return null; + var fileName = proc?.MainModule?.FileName; + var processName = proc?.ProcessName; + + try { proc?.Kill(true); } catch (Exception ex) { Logging.SaveLog(_tag, ex); } + try { proc?.Kill(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); } + try { proc?.Close(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); } + try { proc?.Dispose(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); } + + await Task.Delay(500); + if (review) + { + var proc2 = Process.GetProcessesByName(processName) + .FirstOrDefault(t => t.MainModule?.FileName == fileName); + if (proc2 != null) + { + Logging.SaveLog($"{_tag}, KillProcess not completing the job"); + await KillProcess(proc2, false); + proc2 = null; + } + } } #endregion Process diff --git a/v2rayn/v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs index 4e95b12980..1830c8afa1 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs @@ -2,6 +2,8 @@ { public class FmtHandler { + private static readonly string _tag = "FmtHandler"; + public static string? GetShareUri(ProfileItem item) { try @@ -23,7 +25,7 @@ } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return ""; } } @@ -81,7 +83,7 @@ } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); msg = ResUI.Incorrectconfiguration; return null; } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs index 1eee755883..b630171fb0 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/ProfileExHandler.cs @@ -10,6 +10,7 @@ namespace ServiceLib.Handler private ConcurrentBag _lstProfileEx = []; private Queue _queIndexIds = new(); public static ProfileExHandler Instance => _instance.Value; + private static readonly string _tag = "ProfileExHandler"; public ProfileExHandler() { @@ -87,7 +88,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog("ProfileExHandler", ex); + Logging.SaveLog(_tag, ex); } } } @@ -119,7 +120,7 @@ namespace ServiceLib.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs index 1858780e91..b5aabe7a27 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs @@ -12,7 +12,7 @@ private StatisticsXrayService? _statisticsXray; private StatisticsSingboxService? _statisticsSingbox; - + private static readonly string _tag = "StatisticsHandler"; public List ServerStat => _lstServerStat; public async Task Init(Config config, Action updateFunc) @@ -39,7 +39,7 @@ } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } @@ -61,7 +61,7 @@ } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingWindows.cs b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingWindows.cs index 2662f95936..8d6dbc130f 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingWindows.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingWindows.cs @@ -72,7 +72,6 @@ namespace ServiceLib.Handler.SysProxy catch (Exception ex) { SetProxyFallback(strProxy, exceptions, type); - //Logging.SaveLog(ex.Message, ex); return false; } } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs index 3275b6d059..7aceb5fd45 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs @@ -2,6 +2,7 @@ { public static class SysProxyHandler { + private static readonly string _tag = "SysProxyHandler"; public static async Task UpdateSysProxy(Config config, bool forceDisable) { var type = config.SystemProxyItem.SysProxyType; @@ -59,7 +60,7 @@ } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return true; } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/WebDavHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/WebDavHandler.cs index c034d06f70..4deed95690 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/WebDavHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/WebDavHandler.cs @@ -13,7 +13,8 @@ namespace ServiceLib.Handler private string? _lastDescription; private string _webDir = Global.AppName + "_backup"; private readonly string _webFileName = "backup.zip"; - private string _logTitle = "WebDav--"; + private readonly string _tag = "WebDav--"; + public WebDavHandler() { @@ -81,13 +82,13 @@ namespace ServiceLib.Handler private void SaveLog(string desc) { _lastDescription = desc; - Logging.SaveLog(_logTitle + desc); + Logging.SaveLog(_tag + desc); } private void SaveLog(Exception ex) { _lastDescription = ex.Message; - Logging.SaveLog(_logTitle, ex); + Logging.SaveLog(_tag, ex); } public async Task CheckConnection() diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs index e48f3a5f44..2a732e2b05 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs @@ -6,6 +6,7 @@ namespace ServiceLib.Services.CoreConfig public class CoreConfigClashService { private Config _config; + private static readonly string _tag = "CoreConfigClashService"; public CoreConfigClashService(Config config) { @@ -131,7 +132,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog("GenerateClientConfigClash-Mixin", ex); + Logging.SaveLog($"{_tag}-Mixin", ex); } var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3); @@ -151,7 +152,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog("GenerateClientConfigClash", ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs index b1a907d26e..91d17d4461 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs @@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig public class CoreConfigSingboxService { private Config _config; + private static readonly string _tag = "CoreConfigSingboxService"; public CoreConfigSingboxService(Config config) { @@ -71,7 +72,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog("GenerateClientConfig4Singbox", ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -114,7 +115,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } await GenLog(singboxConfig); @@ -235,7 +236,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -351,7 +352,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -432,7 +433,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -473,7 +474,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -562,7 +563,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -695,7 +696,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -718,7 +719,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -768,7 +769,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -845,7 +846,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -897,7 +898,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; @@ -969,7 +970,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -1085,7 +1086,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -1184,7 +1185,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs index e54eebc1e4..8f71460a29 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs @@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig public class CoreConfigV2rayService { private Config _config; + private static readonly string _tag = "CoreConfigV2rayService"; public CoreConfigV2rayService(Config config) { @@ -70,7 +71,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog("GenerateClientConfig4V2ray", ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -197,7 +198,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -240,7 +241,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } await GenLog(v2rayConfig); @@ -349,7 +350,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); ret.Msg = ResUI.FailedGenDefaultConfiguration; return ret; } @@ -379,7 +380,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -423,7 +424,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -482,7 +483,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -560,7 +561,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -754,7 +755,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -778,7 +779,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -1020,7 +1021,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -1083,7 +1084,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; } @@ -1241,7 +1242,7 @@ namespace ServiceLib.Services.CoreConfig } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return 0; diff --git a/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs index 5801e53208..e420ce7874 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/DownloadService.cs @@ -13,6 +13,7 @@ namespace ServiceLib.Services public event EventHandler? UpdateCompleted; public event ErrorEventHandler? Error; + private static readonly string _tag = "DownloadService"; public async Task DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action updateFunc) { @@ -68,7 +69,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); Error?.Invoke(this, new ErrorEventArgs(ex)); if (ex.InnerException != null) @@ -113,7 +114,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); Error?.Invoke(this, new ErrorEventArgs(ex)); if (ex.InnerException != null) { @@ -131,7 +132,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); Error?.Invoke(this, new ErrorEventArgs(ex)); if (ex.InnerException != null) { @@ -177,7 +178,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); Error?.Invoke(this, new ErrorEventArgs(ex)); if (ex.InnerException != null) { @@ -208,7 +209,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); Error?.Invoke(this, new ErrorEventArgs(ex)); if (ex.InnerException != null) { @@ -232,13 +233,13 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return -1; } } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return -1; } } diff --git a/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs index 928fb0eef5..05a5ffd76c 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/SpeedtestService.cs @@ -11,6 +11,7 @@ namespace ServiceLib.Services private Action? _updateFunc; private bool _exitLoop = false; + private static readonly string _tag = "SpeedtestService"; public SpeedtestService(Config config, List selecteds, ESpeedActionType actionType, Action updateFunc) { @@ -146,7 +147,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } })); } @@ -154,7 +155,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } finally { @@ -201,7 +202,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } })); } @@ -209,7 +210,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } finally { @@ -389,7 +390,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return responseTime; } diff --git a/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs b/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs index ef70e3f7b9..2b5a737a3c 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs @@ -10,6 +10,7 @@ namespace ServiceLib.Services.Statistics private ClientWebSocket? webSocket; private Action? _updateFunc; private string Url => $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic"; + private static readonly string _tag = "StatisticsSingboxService"; public StatisticsSingboxService(Config config, Action updateFunc) { @@ -48,7 +49,7 @@ namespace ServiceLib.Services.Statistics } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } } diff --git a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs index bd0f6a2b2c..d737459cc2 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs @@ -7,6 +7,7 @@ namespace ServiceLib.Services { private Action? _updateFunc; private int _timeout = 30; + private static readonly string _tag = "UpdateService"; public async Task CheckUpdateGuiN(Config config, Action updateFunc, bool preRelease) { @@ -272,7 +273,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); _updateFunc?.Invoke(false, ex.Message); return new RetResult(false, ex.Message); } @@ -356,7 +357,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); _updateFunc?.Invoke(false, ex.Message); return new SemanticVersion(""); } @@ -415,7 +416,7 @@ namespace ServiceLib.Services } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); _updateFunc?.Invoke(false, ex.Message); return new RetResult(false, ex.Message); } diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index cd1c2d13bd..e8def23f17 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -279,9 +279,8 @@ namespace ServiceLib.ViewModels Locator.Current.GetService()?.UpdateStatistics(update); } } - catch (Exception ex) + catch { - Logging.SaveLog(ex.Message, ex); } } diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs index 26251bf10f..f4a583d6db 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs @@ -235,7 +235,7 @@ namespace v2rayN.Desktop.Views } catch (Exception ex) { - Logging.SaveLog("fill fonts error", ex); + Logging.SaveLog("GetFonts", ex); } return lstFonts; } diff --git a/v2rayn/v2rayN/v2rayN/Common/WindowsUtils.cs b/v2rayn/v2rayN/v2rayN/Common/WindowsUtils.cs index fdb9be0ca1..d07920f3da 100644 --- a/v2rayn/v2rayN/v2rayN/Common/WindowsUtils.cs +++ b/v2rayn/v2rayN/v2rayN/Common/WindowsUtils.cs @@ -13,6 +13,7 @@ namespace v2rayN { internal static class WindowsUtils { + private static readonly string _tag = "WindowsUtils"; /// /// 获取剪贴板数 /// @@ -31,7 +32,7 @@ namespace v2rayN } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); } return strData; } diff --git a/v2rayn/v2rayN/v2rayN/Handler/WindowsHandler.cs b/v2rayn/v2rayN/v2rayN/Handler/WindowsHandler.cs index ddc7d2f3e4..95404085fa 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/WindowsHandler.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/WindowsHandler.cs @@ -8,6 +8,7 @@ namespace v2rayN.Handler { private static readonly Lazy instance = new(() => new()); public static WindowsHandler Instance => instance.Value; + private static readonly string _tag = "WindowsHandler"; public async Task GetNotifyIcon(Config config) { @@ -39,7 +40,7 @@ namespace v2rayN.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return Properties.Resources.NotifyIcon1; } } @@ -89,7 +90,7 @@ namespace v2rayN.Handler } catch (Exception ex) { - Logging.SaveLog(ex.Message, ex); + Logging.SaveLog(_tag, ex); return null; } } diff --git a/v2rayn/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs index 9302c0d02f..d1c859d558 100644 --- a/v2rayn/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs @@ -246,7 +246,7 @@ namespace v2rayN.Views } catch (Exception ex) { - Logging.SaveLog("fill fonts error", ex); + Logging.SaveLog("GetFonts", ex); } return lstFonts.OrderBy(t => t).ToList(); } diff --git a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml index e3fab958d1..c373556f55 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -40,33 +40,33 @@ کانفیگ سفارشی را از طریق نشانی اینترنتی وارد کنید نشانی اینترنتی اسکن کانفیگ سفارشی را وارد کنید حذف شود؟ - لطفا قبل از حذف کانفیگ نامعتبر تایید کنید! حذف کانفیگ را تایید می کنید؟ + لطفا قبل از حذف کانفیگ نامعتبر بررسی کنید! حذف کانفیگ را تایید می کنید؟ ملاحظات نشانی پورت شناسه - alterId + شناسه جایگزین امنیت شبکه انتقال - نوع HEAD - حالت GRPC - HOST - HTTP HOST - WS HOST - HTTPUPGRADE HOST - XHTTP HOST - H2 HOST + نوع سربرگ + حالت gRPC + هاست + هاست HTTP + هاست WS + هاست HTTPUpgrade + هاست XHTTP + هاست H2 QUIC security - GRPC Authority - PATH - WS PATH - HTTPUPGRADE PATH - XHTTP PATH - H2 PATH - QUIC key - KCP SEED - GRPC SERVICENAME + gRPC Authority + مسیر + مسیر WS + مسیر HTTPUpgrade + مسیر XHTTP + مسیر H2 + مسیر QUIC + KCP seed + gRPC ServiceName TLS اثرانگشت AlPN @@ -82,12 +82,12 @@ جریان کلید عمومی کلید رمزگذاری اضافی (اختیاری) - SHORTID - SPIDERX + ShortID + SpiderX کلید خصوصی - Reserved (اختیاری) - آدرس محلی IPV4(اختیاری) - MTU (اختیاری، پیش فرض: 1420) + Reserved (اختیاری، جدا شده با کاما) + آدرس محلی IPV4 (اختیاری) + MTU (اختیاری، پیش‌فرض 1420) با موفقیت انجام شد شکست هیچ داده ای وجود ندارد @@ -103,17 +103,17 @@ لطفاً از آدرس اشتراک پروتکل HTTP ناامن استفاده نکنید اطمینان حاصل کنید که پورت ورودی با تنظیمات مطابقت دارد کانفیگ درست نیست - میزبان (SNI) (اختیاری) + هاست (SNI) (اختیاری) کپی فایل انجام نشد، لطفا از برنامه مدیریت فایل استفاده کنید افزودن فایل ‌ها اسکن QRcode URL دانلود فایل‌ ها این عمل ممنوع است - رمز عبور OBFS + رمز عبور obfs پورت پرش (درگاه سرور را بازنویسی می کند) فاصله پورت پرش (ثانیه) - PINSHA256 + pinSHA256 حالت XHTTP خام JSON XHTTP Extra، قالب: { XHTTPObject } @@ -153,12 +153,12 @@ فعال کردن نمایش سرعت - نمایش سرعت فعلی در قسمت آگاه‌سازی. \nآیکون آگاه‌سازی بر اساس استفاده تغییر می‌کند. + نمایش سرعت فعلی در قسمت اعلان. \nآیکون اعلان بر اساس استفاده تغییر می‌کند. - فعال کردن SNIFFING - دامنه SNIFF را از بسته امتحان کنید (پیش‌فرض روشن) - فعال کردن ROUTEONLY - از نام دامنه SNIFFED فقط برای مسیریابی استفاده کنید و آدرس مورد نظر را به عنوان آدرس IP نگه دارید. + فعال کردن تجزیه و تحلیل بسته ها (SNIFFING) + استفاده از تشخیص نام دامنه (Sniff) در بسته ها (به طور پیش فرض فعال است) + فعال کردن دامنه فقط مسیر یابی (RouteOnly) + از نام دامنه (Snnifed) فقط برای مسیریابی استفاده کنید و آدرس مقصد را به عنوان IP ذخیره کنید. فعال کردن DNS محلی @@ -174,7 +174,7 @@ DNS VPN DNS (فقط IPv4/v6) - آیا VPN از LAN ؟عبور کند + آیا VPN از شبکه محلی عبور می کند؟ DNS داخلی (اختیاری) DNS @@ -185,9 +185,9 @@ آدرس اینترنتی آزمایش تاخیر واقعی کانفیگ ها (HTTP/HTTPS) URL - اجازه اتصالات از طریق LAN - سایر دستگاه‌ها می‌توانند با آدرس آی‌پی شما از طریق پراکسی محلی به پروکسی متصل شوند، فقط در شبکه قابل اعتماد فعال شود تا از اتصال غیرمجاز جلوگیری شود. - اتصالات از طریق LAN را مجاز کنید، مطمئن شوید که در یک شبکه قابل اعتماد هستید + اجازه اتصالات از طریق شبکه محلی + سایر دستگاه ها می توانند با استفاده از آدرس آیپی شما برای استفاده از یک پروکسی محلی متصل شوند. فقط در یک شبکه قابل اعتماد برای جلوگیری از اتصالات غیرمجاز استفاده کنید. + اتصالات از طریق شبکه محلی را مجاز کنید، مطمئن شوید که در یک شبکه قابل اعتماد هستید. اعطای مجوز ناامن هنگام استفاده از TLS، به طور پیش‌ فرض مجوز ناامن فعال است. @@ -229,7 +229,7 @@ فاصله به‌ روزرسانی خودکار ( حداقل مقدار ، 15 دقیقه ) سطح گزارشات حالت - برای راهنمایی بیشتر روی این متن، کلیک کنید + برای اطلاعات و راهنمایی بیشتر، روی این متن کلیک کنید زبان تنظیمات رابط کاربری تنظیمات حالت رابط کاربری @@ -245,12 +245,12 @@ تنظیمات گروه‌ اشتراک ملاحظات نشانی اینترنتی اختیاری - REMARKS REGULAR FILTER + نام مستعار فیلتر فعال کردن به‌روزرسانی فعال سازی به‌روزرسانی خودکار - Previous proxy remarks - Next proxy remarks - The remarks exists and is unique + نام مستعار پروکسی قبلی + نام مستعار پروکسی بعدی + لطفاً مطمئن شوید که نام مستعار وجود دارد و منحصر به فرد است به‌روزرسانی گروه فعلی اشتراک TCPING کانفیگ های گروه فعلی تاخیر واقعی کانفیگ های گروه فعلی diff --git a/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml index bb1e3667f3..778db64693 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml @@ -175,7 +175,7 @@ DNS VPN DNS (только IPv4/v6) - Does VPN bypass LAN + VPN пропускает LAN Внутренняя DNS (необязательно) DNS @@ -339,9 +339,9 @@ - Follow config - Bypass - Not Bypass + Как в профиле + Пропускает + Не пропускает diff --git a/xray-core/go.mod b/xray-core/go.mod index ac0a26f381..aea10b8bd4 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -29,7 +29,7 @@ require ( golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 google.golang.org/grpc v1.69.2 google.golang.org/protobuf v1.36.1 - gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 + gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h12.io/socks v1.0.3 lukechampine.com/blake3 v1.3.0 ) @@ -50,10 +50,10 @@ require ( github.com/vishvananda/netns v0.0.4 // indirect go.uber.org/mock v0.4.0 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect - golang.org/x/mod v0.18.0 // indirect + golang.org/x/mod v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.26.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/xray-core/go.sum b/xray-core/go.sum index 933f1483ab..e29de52bce 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -100,8 +100,8 @@ golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ss golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -127,13 +127,13 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -156,8 +156,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE= -gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk= +gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h1:P+U/06iIKPQ3DLcg+zBfSCia1luZ2msPZrJ8jYDFPs0= +gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0= h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo= h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= diff --git a/xray-core/proxy/wireguard/gvisortun/tun.go b/xray-core/proxy/wireguard/gvisortun/tun.go index 9e9a0b2bed..65677c483e 100644 --- a/xray-core/proxy/wireguard/gvisortun/tun.go +++ b/xray-core/proxy/wireguard/gvisortun/tun.go @@ -157,7 +157,7 @@ func (tun *netTun) Write(buf [][]byte, offset int) (int, error) { // WriteNotify implements channel.Notification func (tun *netTun) WriteNotify() { pkt := tun.ep.Read() - if pkt.IsNil() { + if pkt == nil { return } diff --git a/xray-core/proxy/wireguard/tun.go b/xray-core/proxy/wireguard/tun.go index 7fd8a817d6..74a3b71d87 100644 --- a/xray-core/proxy/wireguard/tun.go +++ b/xray-core/proxy/wireguard/tun.go @@ -194,7 +194,7 @@ func createGVisorTun(localAddresses []netip.Addr, mtu int, handler promiscuousMo Timeout: 15 * time.Second, }) - handler(xnet.UDPDestination(xnet.IPAddress(id.LocalAddress.AsSlice()), xnet.Port(id.LocalPort)), gonet.NewUDPConn(stack, &wq, ep)) + handler(xnet.UDPDestination(xnet.IPAddress(id.LocalAddress.AsSlice()), xnet.Port(id.LocalPort)), gonet.NewUDPConn(&wq, ep)) }(r) }) stack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)