https://talks.txthinking.com
Created at: 22 Apr 2022
Updated at: 01 May 2022
cloud@txthinking.com
https://github.com/txthinking/brook
You can see the proxy mode in Proxy & Tun in the left menu of the graphical client. In this mode, it will ignore: Bypass CIDR4 list, Bypass CIDR6 list, DNS Server, Fake DNS, Block list, Block configuration items.
In this mode, will create:
socks5://[::1]:1080
may be created under IPv6 network, socks5://127.0.0.1:1080
may be created under IPv4 network
curl -x socks5://[::1]:1080 ipip.ooo
or curl -x socks5://127.0.0.1 :1080 ipip.ooo
http://[::1]:8010
may be created under IPv6 network, http://127.0.0.1:8010
may be created under IPv4 network
curl -x http://[::1]:1080 ipip.ooo
or curl -x http://127.0.0.1 :1080 ipip.ooo
If read system proxy, such as Chrome:
The domain name does not match the Bypass Domain list (domain name resolve will be completed on the server)
Initiate a request--HTTP/HTTPS(TCP)--> pac server --> Brook client--(Brook protocol)--> brook server/wsserver/wssserver/socks5 --HTTP/HTTPS(TCP)--> DST
The domain name matches the Bypass Domain list (domain name resolve will be done locally)
Initiate a request --HTTP/HTTPS(TCP)--> pac server --> local --HTTP/HTTPS(TCP)--> DST
If don't read system proxy, for example, on the Telegram client (Telegram should only use TCP?), configure the socks5 proxy created above separately (domain name resolve will be done on the server):
Initiate request --TCP/UDP--> socks5 proxy --TCP/UDP--> Brook client --(Brook protocol) --> brook server/wsserver/wssserver/socks5 --TCP/UDP--> DST
can be specified
8.8.8.8:53
https://dns.google/dns-query?address=8.8.8.8%3A443
[2001:4860:4860::8888]:53
https://dns.google/dns-query?address=%5B2001%3A4860%3A4860%3A%3A8888%5D%3A443
223.5.5.5:53
https://dns.alidns.com/dns-query?address=223.5.5.5%3A443
[2400:3200::1]:53
https://dns.alidns.com/dns-query?address=%5B2400%3A3200%3A%3A1%5D%3A443
Brook client will automatically choose to configure the system v4 DNS or v6 DNS according to the current network IPv4/IPv6 situation and server IPv4/IPv6.
Under normal circumstances, the block domain name list is used to block advertisements, and the second situation is for you to discover.
We know that a network request generally first queries the domain name to get the IP, and then initiates a request to the IP.
The first is DNS query IP of domain name
The domain name does not match the bypass domain name list
Make a query to the default DNS
If the default DNS does not match the bypass CIDR list (the default DNS is also an IP)
Initiate DNS query --(DNS protocol)--> Brook client --(Brook protocol)--> brook server/wsserver/wssserver --(DNS protocol)--> Default DNS
If the default DNS matches the bypass CIDR list (the default DNS is also an IP)
Initiate DNS query --(DNS protocol)--> Brook client --(DNS protocol)--> Default DNS
The domain name matches the bypass domain name list
Make a query to bypass DNS
If bypass DNS does not match the bypass CIDR list (bypass DNS is also an IP)
Initiate DNS query --(DNS protocol)--> Brook client --(Brook protocol)--> brook server/wsserver/wssserver --(DNS protocol)--> bypass DNS
If bypass DNS matches bypass CIDR list (bypass DNS is also an IP)
Initiate DNS query --(DNS protocol)--> Brook client --(DNS protocol)--> bypass DNS
The IP of the domain name has been queried, and is ready to initiate a network request to this target IP
If IP does not match to bypass CIDR list
Initiate request --TCP/UDP--> Brook client --(Brook protocol)--> brook server/wsserver/wssserver --TCP/UDP--> target IP
If the IP matches the bypass CIDR list
Initiate request --TCP/UDP--> Brook client --TCP/UDP--> target IP
We know that a network request generally first queries the domain name to get the IP, and then initiates a request to the IP.
The first is query the IP of the domain name
The domain name matches the bypass domain name list
Make a query to bypass DNS
If bypass DNS does not match the bypass CIDR list (bypass DNS is also an IP)
Initiate DNS query --(DNS protocol)--> Brook client --(Brook protocol)--> brook server/wsserver/wssserver --(DNS protocol)--> bypass DNS
If bypass DNS matches bypass CIDR list (bypass DNS is also an IP)
Initiate DNS query --(DNS protocol)--> Brook client --(DNS protocol)--> bypass DNS
The IP of the domain name has been queried, and is ready to initiate a network request to this target IP
If it is Fake IP (the resovle of the domain name will be completed on the server)
Brook client --(convert Fake IP to original domain name)--(Brook protocol)--> brook server/wsserver/wssserver --TCP/UDP--> DST
If not Fake IP
If IP does not match to bypass CIDR list
Initiate a request --TCP/UDP--> Brook client --(Brook protocol)--> brook server/wsserver/wssserver --TCP/UDP--> target IP
If the IP matches the bypass CIDR list
Initiate request --TCP/UDP--> Brook client --TCP/UDP--> target IP
At present, the Android system has built-in Private DNS (DoT), and the desktop and mobile versions of Chrome provide built-in Secure DNS (DoH). This is ideal for the full-scale Anycast network world and the DNS query of ordinary users without proxy can be encrypted in the intermediate network. But Reality is not ideal.
Suppose a domain name provides different IPs for multiple regions, and the final resolved IP depends on:
When DoT or DoH is turned on, the query content cannot be intercepted to achieve the effect of using different DNS resolutions for different domain names, and FakeDNS cannot be used to resolve domain names on the server side to avoid one more network request.
So we're going to close it:
You can enable FakeDNS or configure DoH in Brook GUI.
Note: This feature requires programming skills and will run your script to intercept and modify HTTP and HTTPS. At the same time, if the writing is complex, it may take up more resources and performance.
https://txthinking.github.io/ca/ca.pem
To perform MITM
MITM requires tun mode
nami install mad ca.txthinking
sudo mad install --ca ~/.nami/bin/ca.pem
MITM requires tun mode
nami install mad ca.txthinking
Open GitBash as administrator
mad install --ca ~/.nami/bin/ca.pem
https://www.youtube.com/watch?v=uctNsfl3lio
Android has system CA and user CA, which must be installed into the system CA after ROOT
One protocol and address per line
http://
and https://
Example
http://ipip.ooo:80
https://ipip.ooo:443
Suffix matches mode: ipip.ooo:80
, xxx.ipip.ooo:80
, xxx.xxx.ipip.ooo:80
..., ipip.ooo:443
, xxx.ipip.ooo:443
, xxx.xxx.ipip.ooo:443
...
https://txthinking.github.io/bypass/mitm.txt
request
Represents an HTTP Request, which is a map
{
"Method": "GET", // string, request method
"URL": "https://ipip.ooo/", // string, request url
"Body": bytes, // bytes, request body
"...": "...",
"User-Agent": "...", // string, all other keys are request header
"...": "..."
}
response
Represents an HTTP Rsponse, which is a map
{
"StatusCode": 200, // int, response status code
"Body": bytes, // bytes, request body
"...": "...",
"Server": "txthinking", // string, all other keys are response header
"...": "..."
}
request
to the script, and response
is now undefined
. The script can choose:
request
and return request
response
. End.request
returned by the script to the serverresponse
from the serverresponse
to the script, request
is now the request
of the step 1 returned, the script must: modify or not modify response
and return response
If off
request["Body"]
passed to script in step 2 is empty
request["Body"]
returned by the script will be ignored. The body of the original request is still used to send to the serverresponse["Body"]
will also be ignored. Only respond to client with StatusCode
and headersresponse["Body"]
and request["Body"]
passed to the script in step 5 are empty. The response["Body"]
returned by the script will also be ignored. The body of the original response is still used to respond to the clientIf on
request["Body"]
passed to the script in step 2 is not empty
request["Body"]
returned by the script is sent to the server as the body of the requestresponse["Body"]
is sent to the client as the body of the responseresponse["Body"]
and request["Body"]
passed to the script in step 5 are not empty. The response["Body"]
returned by the script will be sent to the client as the body of the responsetext := import("text")
_ := (func(request, response) {
// Begin
if(!response){
if(text.has_prefix(request["URL"], "http://ipip.ooo")){
return {
"StatusCode": 301,
"Location": text.replace(request["URL"], "http://", "https://", 1)
}
}
if(text.has_prefix(request["URL"], "https://ipip.ooo")){
request["User-Agent"] = "curl/7.79.1"
return request
}
return request
}
return response
// End
})(request, response)
You can use mitmproxy helper and Wireshark Helper to capture packets to determine what to modify. The difference of mobile phone packet capture software
You can use tun2brook to debug the script, so you can print data inside the script
macOS and Windows need to enable tun mode
It is recommended to enable it only when necessary. Prevent the log file from being too large.
To use Apple Push Notification Service (APNs), your macOS, iOS, tvOS, and watchOS devices need a persistent connection to Apple's servers over Ethernet, cellular data (if capable), or Wi-Fi.
https://support.apple.com/en-us/HT210060
https://support.apple.com/en-us/HT210060
Domain
apple.com
icloud.com
cdn-apple.com
mzstatic.com
entrust.net
digicert.com
verisign.net
CIDR4
17.0.0.0/8
103.81.148.0/22
103.81.148.0/24
103.81.149.0/24
CIDR6
2620:149:a44::/48
2403:300:a42::/48
2403:300:a51::/48
2a01:b740:a42::/48
If your Windows supports IPv6. If something wrong, turn off IPv6 networking. reboot