2023-11-09 09:04:08 +00:00
|
|
|
|
---
|
|
|
|
|
icon: material/cellphone-link
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Client
|
|
|
|
|
|
|
|
|
|
### :material-ray-start: Introduction
|
|
|
|
|
|
|
|
|
|
For a long time, the modern usage and principles of proxy clients
|
|
|
|
|
for graphical operating systems have not been clearly described.
|
|
|
|
|
However, we can categorize them into three types:
|
|
|
|
|
system proxy, firewall redirection, and virtual interface.
|
|
|
|
|
|
|
|
|
|
### :material-web-refresh: System Proxy
|
|
|
|
|
|
|
|
|
|
Almost all graphical environments support system-level proxies,
|
|
|
|
|
which are essentially ordinary HTTP proxies that only support TCP.
|
|
|
|
|
|
|
|
|
|
| Operating System / Desktop Environment | System Proxy | Application Support |
|
|
|
|
|
|:---------------------------------------------|:-------------------------------------|:--------------------|
|
|
|
|
|
| Windows | :material-check: | :material-check: |
|
|
|
|
|
| macOS | :material-check: | :material-check: |
|
|
|
|
|
| GNOME/KDE | :material-check: | :material-check: |
|
|
|
|
|
| Android | ROOT or adb (permission) is required | :material-check: |
|
|
|
|
|
| Android/iOS (with sing-box graphical client) | via `tun.platform.http_proxy` | :material-check: |
|
|
|
|
|
|
|
|
|
|
As one of the most well-known proxy methods, it has many shortcomings:
|
|
|
|
|
many TCP clients that are not based on HTTP do not check and use the system proxy.
|
|
|
|
|
Moreover, UDP and ICMP traffics bypass the proxy.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart LR
|
|
|
|
|
dns[DNS query] -- Is HTTP request? --> proxy[HTTP proxy]
|
|
|
|
|
dns --> leak[Leak]
|
|
|
|
|
tcp[TCP connection] -- Is HTTP request? --> proxy
|
|
|
|
|
tcp -- Check and use HTTP CONNECT? --> proxy
|
|
|
|
|
tcp --> leak
|
|
|
|
|
udp[UDP packet] --> leak
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### :material-wall-fire: Firewall Redirection
|
|
|
|
|
|
|
|
|
|
This type of usage typically relies on the firewall or hook interface provided by the operating system,
|
|
|
|
|
such as Windows’ WFP, Linux’s redirect, TProxy and eBPF, and macOS’s pf.
|
|
|
|
|
Although it is intrusive and cumbersome to configure,
|
|
|
|
|
it remains popular within the community of amateur proxy open source projects like V2Ray,
|
|
|
|
|
due to the low technical requirements it imposes on the software.
|
|
|
|
|
|
|
|
|
|
### :material-expansion-card: Virtual Interface
|
|
|
|
|
|
|
|
|
|
All L2/L3 proxies (seriously defined VPNs, such as OpenVPN, WireGuard) are based on virtual network interfaces,
|
|
|
|
|
which is also the only way for all L4 proxies to work as VPNs on mobile platforms like Android, iOS.
|
|
|
|
|
|
|
|
|
|
The sing-box inherits and develops clash-premium’s TUN inbound (L3 to L4 conversion)
|
|
|
|
|
as the most reasonable method for performing transparent proxying.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TB
|
|
|
|
|
packet[IP Packet]
|
|
|
|
|
packet --> windows[Windows / macOS]
|
|
|
|
|
packet --> linux[Linux]
|
|
|
|
|
tun[TUN interface]
|
|
|
|
|
windows -. route .-> tun
|
|
|
|
|
linux -. iproute2 route/rule .-> tun
|
|
|
|
|
tun --> gvisor[gVisor TUN stack]
|
|
|
|
|
tun --> system[system TUN stack]
|
|
|
|
|
assemble([L3 to L4 assemble])
|
|
|
|
|
gvisor --> assemble
|
|
|
|
|
system --> assemble
|
|
|
|
|
assemble --> conn[TCP and UDP connections]
|
|
|
|
|
conn --> router[sing-box Router]
|
|
|
|
|
router --> direct[Direct outbound]
|
|
|
|
|
router --> proxy[Proxy outbounds]
|
|
|
|
|
router -- DNS hijack --> dns_out[DNS outbound]
|
|
|
|
|
dns_out --> dns_router[DNS router]
|
|
|
|
|
dns_router --> router
|
|
|
|
|
direct --> adi([auto detect interface])
|
|
|
|
|
proxy --> adi
|
|
|
|
|
adi --> default[Default network interface in the system]
|
|
|
|
|
default --> destination[Destination server]
|
|
|
|
|
default --> proxy_server[Proxy server]
|
|
|
|
|
proxy_server --> destination
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## :material-cellphone-link: Examples
|
|
|
|
|
|
|
|
|
|
### Basic TUN usage for Chinese users
|
|
|
|
|
|
|
|
|
|
=== ":material-numeric-4-box: IPv4 only"
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"dns": {
|
|
|
|
|
"servers": [
|
|
|
|
|
{
|
|
|
|
|
"tag": "google",
|
|
|
|
|
"address": "tls://8.8.8.8"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "local",
|
|
|
|
|
"address": "223.5.5.5",
|
|
|
|
|
"detour": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"outbound": "any",
|
|
|
|
|
"server": "local"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"strategy": "ipv4_only"
|
|
|
|
|
},
|
|
|
|
|
"inbounds": [
|
|
|
|
|
{
|
|
|
|
|
"type": "tun",
|
|
|
|
|
"inet4_address": "172.19.0.1/30",
|
|
|
|
|
"auto_route": true,
|
|
|
|
|
"strict_route": false
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"outbounds": [
|
|
|
|
|
// ...
|
|
|
|
|
{
|
|
|
|
|
"type": "direct",
|
|
|
|
|
"tag": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "dns",
|
|
|
|
|
"tag": "dns-out"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"route": {
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"protocol": "dns",
|
|
|
|
|
"outbound": "dns-out"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"geoip": [
|
|
|
|
|
"private"
|
|
|
|
|
],
|
|
|
|
|
"outbound": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"auto_detect_interface": true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== ":material-numeric-6-box: IPv4 & IPv6"
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"dns": {
|
|
|
|
|
"servers": [
|
|
|
|
|
{
|
|
|
|
|
"tag": "google",
|
|
|
|
|
"address": "tls://8.8.8.8"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "local",
|
|
|
|
|
"address": "223.5.5.5",
|
|
|
|
|
"detour": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"outbound": "any",
|
|
|
|
|
"server": "local"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"inbounds": [
|
|
|
|
|
{
|
|
|
|
|
"type": "tun",
|
|
|
|
|
"inet4_address": "172.19.0.1/30",
|
|
|
|
|
"inet6_address": "fdfe:dcba:9876::1/126",
|
|
|
|
|
"auto_route": true,
|
|
|
|
|
"strict_route": false
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"outbounds": [
|
|
|
|
|
// ...
|
|
|
|
|
{
|
|
|
|
|
"type": "direct",
|
|
|
|
|
"tag": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "dns",
|
|
|
|
|
"tag": "dns-out"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"route": {
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"protocol": "dns",
|
|
|
|
|
"outbound": "dns-out"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"geoip": [
|
|
|
|
|
"private"
|
|
|
|
|
],
|
|
|
|
|
"outbound": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"auto_detect_interface": true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== ":material-domain-switch: FakeIP"
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"dns": {
|
|
|
|
|
"servers": [
|
|
|
|
|
{
|
|
|
|
|
"tag": "google",
|
|
|
|
|
"address": "tls://8.8.8.8"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "local",
|
|
|
|
|
"address": "223.5.5.5",
|
|
|
|
|
"detour": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "remote",
|
|
|
|
|
"address": "fakeip"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"outbound": "any",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"query_type": [
|
|
|
|
|
"A",
|
|
|
|
|
"AAAA"
|
|
|
|
|
],
|
|
|
|
|
"server": "remote"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"fakeip": {
|
|
|
|
|
"enabled": true,
|
|
|
|
|
"inet4_range": "198.18.0.0/15",
|
|
|
|
|
"inet6_range": "fc00::/18"
|
|
|
|
|
},
|
|
|
|
|
"independent_cache": true
|
|
|
|
|
},
|
|
|
|
|
"inbounds": [
|
|
|
|
|
{
|
|
|
|
|
"type": "tun",
|
|
|
|
|
"inet4_address": "172.19.0.1/30",
|
|
|
|
|
"inet6_address": "fdfe:dcba:9876::1/126",
|
|
|
|
|
"auto_route": true,
|
|
|
|
|
"strict_route": true
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"outbounds": [
|
|
|
|
|
// ...
|
|
|
|
|
{
|
|
|
|
|
"type": "direct",
|
|
|
|
|
"tag": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "dns",
|
|
|
|
|
"tag": "dns-out"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"route": {
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"protocol": "dns",
|
|
|
|
|
"outbound": "dns-out"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"geoip": [
|
|
|
|
|
"private"
|
|
|
|
|
],
|
|
|
|
|
"outbound": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"auto_detect_interface": true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Traffic bypass usage for Chinese users
|
|
|
|
|
|
|
|
|
|
=== ":material-dns: DNS rules"
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"dns": {
|
|
|
|
|
"servers": [
|
|
|
|
|
{
|
|
|
|
|
"tag": "google",
|
|
|
|
|
"address": "tls://8.8.8.8"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "local",
|
|
|
|
|
"address": "223.5.5.5",
|
|
|
|
|
"detour": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"outbound": "any",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Direct",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Global",
|
|
|
|
|
"server": "google"
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-02-03 09:45:27 +00:00
|
|
|
|
"rule_set": "geosite-geolocation-cn",
|
2023-11-09 09:04:08 +00:00
|
|
|
|
"server": "local"
|
|
|
|
|
}
|
|
|
|
|
]
|
2024-02-03 09:45:27 +00:00
|
|
|
|
},
|
|
|
|
|
"route": {
|
|
|
|
|
"rule_set": [
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
|
|
|
|
"tag": "geosite-geolocation-cn",
|
|
|
|
|
"format": "binary",
|
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
|
|
|
|
|
}
|
|
|
|
|
]
|
2023-11-09 09:04:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-03 09:45:27 +00:00
|
|
|
|
=== ":material-dns: DNS rules (1.9.0+)"
|
|
|
|
|
|
2024-02-09 10:37:25 +00:00
|
|
|
|
=== ":material-shield-off: With DNS Leaks"
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"dns": {
|
|
|
|
|
"servers": [
|
|
|
|
|
{
|
|
|
|
|
"tag": "google",
|
|
|
|
|
"address": "tls://8.8.8.8"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "local",
|
|
|
|
|
"address": "https://223.5.5.5/dns-query",
|
|
|
|
|
"detour": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"outbound": "any",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Direct",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Global",
|
|
|
|
|
"server": "google"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"rule_set": "geosite-geolocation-cn",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Default",
|
|
|
|
|
"server": "google"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"rule_set": "geoip-cn",
|
|
|
|
|
"server": "local"
|
|
|
|
|
}
|
|
|
|
|
]
|
2024-02-03 09:45:27 +00:00
|
|
|
|
},
|
2024-02-09 10:37:25 +00:00
|
|
|
|
"route": {
|
|
|
|
|
"rule_set": [
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
|
|
|
|
"tag": "geosite-geolocation-cn",
|
|
|
|
|
"format": "binary",
|
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
|
|
|
|
"tag": "geoip-cn",
|
|
|
|
|
"format": "binary",
|
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
|
|
|
|
|
}
|
|
|
|
|
]
|
2024-02-03 09:45:27 +00:00
|
|
|
|
},
|
2024-02-09 10:37:25 +00:00
|
|
|
|
"experimental": {
|
|
|
|
|
"clash_api": {
|
|
|
|
|
"default_mode": "Leak"
|
|
|
|
|
}
|
2023-12-01 05:24:18 +00:00
|
|
|
|
}
|
2024-02-09 10:37:25 +00:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== ":material-security: Without DNS Leaks (1.9.0-alpha.2+)"
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"dns": {
|
|
|
|
|
"servers": [
|
|
|
|
|
{
|
|
|
|
|
"tag": "google",
|
|
|
|
|
"address": "tls://8.8.8.8"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"tag": "local",
|
|
|
|
|
"address": "https://223.5.5.5/dns-query",
|
|
|
|
|
"detour": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"outbound": "any",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Direct",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Global",
|
|
|
|
|
"server": "google"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"rule_set": "geosite-geolocation-cn",
|
|
|
|
|
"server": "local"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"rule_set": "geoip-cn",
|
|
|
|
|
"server": "google",
|
2024-05-12 07:06:21 +00:00
|
|
|
|
"client_subnet": "114.114.114.114/24" // Any China client IP address
|
2024-02-09 10:37:25 +00:00
|
|
|
|
}
|
|
|
|
|
]
|
2023-11-09 09:04:08 +00:00
|
|
|
|
},
|
2024-02-09 10:37:25 +00:00
|
|
|
|
"route": {
|
|
|
|
|
"rule_set": [
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
|
|
|
|
"tag": "geosite-geolocation-cn",
|
|
|
|
|
"format": "binary",
|
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
|
|
|
|
"tag": "geoip-cn",
|
|
|
|
|
"format": "binary",
|
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
|
|
|
|
|
}
|
|
|
|
|
]
|
2023-11-09 09:04:08 +00:00
|
|
|
|
}
|
2024-02-03 09:45:27 +00:00
|
|
|
|
}
|
2024-02-09 10:37:25 +00:00
|
|
|
|
```
|
2023-12-01 05:24:18 +00:00
|
|
|
|
|
2024-02-03 09:45:27 +00:00
|
|
|
|
=== ":material-router-network: Route rules"
|
2023-12-01 05:24:18 +00:00
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"outbounds": [
|
|
|
|
|
{
|
|
|
|
|
"type": "direct",
|
|
|
|
|
"tag": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "block",
|
|
|
|
|
"tag": "block"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"route": {
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"type": "logical",
|
|
|
|
|
"mode": "or",
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"protocol": "dns"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"port": 53
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"outbound": "dns"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"ip_is_private": true,
|
|
|
|
|
"outbound": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Direct",
|
|
|
|
|
"outbound": "direct"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"clash_mode": "Global",
|
|
|
|
|
"outbound": "default"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "logical",
|
|
|
|
|
"mode": "or",
|
|
|
|
|
"rules": [
|
|
|
|
|
{
|
|
|
|
|
"port": 853
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"network": "udp",
|
|
|
|
|
"port": 443
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"protocol": "stun"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"outbound": "block"
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-01-23 03:57:14 +00:00
|
|
|
|
"rule_set": [
|
|
|
|
|
"geoip-cn",
|
|
|
|
|
"geosite-geolocation-cn"
|
2023-12-01 05:24:18 +00:00
|
|
|
|
],
|
|
|
|
|
"outbound": "direct"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"rule_set": [
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
|
|
|
|
"tag": "geoip-cn",
|
|
|
|
|
"format": "binary",
|
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "remote",
|
2024-01-23 03:57:14 +00:00
|
|
|
|
"tag": "geosite-geolocation-cn",
|
2023-12-01 05:24:18 +00:00
|
|
|
|
"format": "binary",
|
2024-01-23 03:57:14 +00:00
|
|
|
|
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
|
2023-12-01 05:24:18 +00:00
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-09 09:04:08 +00:00
|
|
|
|
```
|