├── .cargo
└── config.toml
├── .gitattributes
├── .github
├── Dockerfile
├── PULL_REQUEST_TEMPLATE.md
├── cliff.toml
├── dependabot.yaml
├── email-blacklist.txt
└── workflows
│ ├── ci.yml
│ ├── coverage.yml
│ ├── email-check.yml
│ └── spell-check.yml
├── .gitignore
├── .gitmodules
├── CONTRIBUTING.md
├── Cargo.lock
├── Cargo.toml
├── Cross.toml
├── LICENSE
├── Makefile
├── NOTICE.md
├── README.md
├── _typos.toml
├── bench
├── README.md
└── flamegraph.svg
├── clash
├── Cargo.toml
├── build.rs
├── src
│ └── main.rs
└── tests
│ └── data
│ ├── config
│ ├── Country-asn.mmdb
│ ├── Country.mmdb
│ ├── GeoLite2-ASN.mmdb
│ ├── config.test.yaml
│ ├── dns.cert
│ ├── dns.key
│ ├── dns.yaml
│ ├── empty.yaml
│ ├── example.org-key.pem
│ ├── example.org.pem
│ ├── hysteria.json
│ ├── hysteria2.yaml
│ ├── listeners
│ │ └── tunnel.yaml
│ ├── public
│ │ ├── CNAME
│ │ ├── _headers
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── assets
│ │ │ ├── Config.39d8d2ef.css
│ │ │ ├── Config.c09e8dbe.js
│ │ │ ├── Connections.e48eac36.js
│ │ │ ├── Connections.fb8ea59b.css
│ │ │ ├── Fab.a0a7e573.css
│ │ │ ├── Fab.ef67ff10.js
│ │ │ ├── Logs.4b8e75d1.css
│ │ │ ├── Logs.ac990610.js
│ │ │ ├── Proxies.16b46af4.js
│ │ │ ├── Proxies.3fa3509d.css
│ │ │ ├── Rules.70e6962f.js
│ │ │ ├── Rules.e03c54a8.css
│ │ │ ├── Select.1e55eba1.css
│ │ │ ├── Select.6c389032.js
│ │ │ ├── TextFitler.61537a57.js
│ │ │ ├── TextFitler.b21c0577.css
│ │ │ ├── chart-lib.a8ad03fd.js
│ │ │ ├── chevron-down.dd238e96.js
│ │ │ ├── debounce.c2d20996.js
│ │ │ ├── en.fb34eaf7.js
│ │ │ ├── index.171f553a.js
│ │ │ ├── index.8bb012c6.js
│ │ │ ├── index.92e2d967.js
│ │ │ ├── index.b38debfc.css
│ │ │ ├── index.esm.e4dd1508.js
│ │ │ ├── inter-latin-400-normal.0364d368.woff2
│ │ │ ├── inter-latin-400-normal.3ea830d4.woff
│ │ │ ├── inter-latin-800-normal.a51ac27d.woff2
│ │ │ ├── inter-latin-800-normal.d08d7178.woff
│ │ │ ├── logs.43986220.js
│ │ │ ├── play.7b1a5f99.js
│ │ │ ├── roboto-mono-latin-400-normal.7295944e.woff2
│ │ │ ├── roboto-mono-latin-400-normal.dffdffa7.woff
│ │ │ ├── useRemainingViewPortHeight.7395542b.js
│ │ │ └── zh.9b79b7bf.js
│ │ ├── index.html
│ │ ├── manifest.webmanifest
│ │ ├── registerSW.js
│ │ ├── sw.js
│ │ ├── yacd-128.png
│ │ ├── yacd-64.png
│ │ └── yacd.ico
│ ├── rule-set-classical.yaml
│ ├── rule-set.yaml
│ ├── rules.yaml
│ ├── shadowquic.yaml
│ ├── simple.yaml
│ ├── socks5.yaml
│ ├── ss-loop.yaml
│ ├── ss.json
│ ├── ss.yaml
│ ├── ssh
│ │ ├── .ssh
│ │ │ ├── authorized_keys
│ │ │ ├── test_ed25519
│ │ │ └── test_rsa
│ │ └── ssh_host_keys
│ │ │ └── sshd_config
│ ├── tor.yaml
│ ├── tproxy.yaml
│ ├── trojan-grpc.json
│ ├── trojan-ws.json
│ ├── tuic.json
│ ├── tun.yaml
│ ├── uot.yaml
│ ├── vmess-grpc.json
│ ├── vmess-http2.json
│ ├── vmess-ws.json
│ ├── wg.yaml
│ └── wg_config
│ │ ├── .donoteditthisfile
│ │ ├── coredns
│ │ └── Corefile
│ │ ├── peer1
│ │ ├── peer1.conf
│ │ ├── peer1.png
│ │ ├── presharedkey-peer1
│ │ ├── privatekey-peer1
│ │ └── publickey-peer1
│ │ ├── server
│ │ ├── privatekey-server
│ │ └── publickey-server
│ │ ├── templates
│ │ ├── peer.conf
│ │ └── server.conf
│ │ └── wg_confs
│ │ └── wg0.conf
│ └── docker
│ ├── docker-compose.yml
│ ├── nginx
│ └── nginx.conf
│ ├── ss
│ ├── Dockerfile
│ └── config.json
│ ├── v2ray
│ ├── cert.pem
│ ├── config.json
│ └── key.pem
│ └── wg
│ └── wg0.conf
├── clash_doc
├── BUILD.bazel
├── Cargo.toml
└── src
│ └── lib.rs
├── clash_ffi
├── Cargo.toml
├── cbindgen.toml
└── src
│ └── lib.rs
├── clash_lib
├── .gitignore
├── Cargo.toml
├── build.rs
├── src
│ ├── app
│ │ ├── api
│ │ │ ├── handlers
│ │ │ │ ├── config.rs
│ │ │ │ ├── connection.rs
│ │ │ │ ├── dns.rs
│ │ │ │ ├── hello.rs
│ │ │ │ ├── log.rs
│ │ │ │ ├── memory.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── provider.rs
│ │ │ │ ├── proxy.rs
│ │ │ │ ├── restart.rs
│ │ │ │ ├── rule.rs
│ │ │ │ ├── traffic.rs
│ │ │ │ ├── utils.rs
│ │ │ │ └── version.rs
│ │ │ ├── middlewares
│ │ │ │ ├── auth.rs
│ │ │ │ └── mod.rs
│ │ │ └── mod.rs
│ │ ├── dispatcher
│ │ │ ├── dispatcher_impl.rs
│ │ │ ├── mod.rs
│ │ │ ├── statistics_manager.rs
│ │ │ └── tracked.rs
│ │ ├── dns
│ │ │ ├── config.rs
│ │ │ ├── dhcp.rs
│ │ │ ├── dns_client.rs
│ │ │ ├── fakeip
│ │ │ │ ├── file_store.rs
│ │ │ │ ├── mem_store.rs
│ │ │ │ └── mod.rs
│ │ │ ├── filters.rs
│ │ │ ├── helper.rs
│ │ │ ├── mod.rs
│ │ │ ├── resolver
│ │ │ │ ├── enhanced.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── system.rs
│ │ │ │ └── system_static_crt.rs
│ │ │ ├── runtime.rs
│ │ │ └── server
│ │ │ │ ├── handler.rs
│ │ │ │ └── mod.rs
│ │ ├── inbound
│ │ │ ├── manager.rs
│ │ │ ├── mod.rs
│ │ │ └── network_listener.rs
│ │ ├── logging.rs
│ │ ├── mod.rs
│ │ ├── net
│ │ │ └── mod.rs
│ │ ├── outbound
│ │ │ ├── manager.rs
│ │ │ ├── mod.rs
│ │ │ └── utils.rs
│ │ ├── profile
│ │ │ └── mod.rs
│ │ ├── remote_content_manager
│ │ │ ├── healthcheck.rs
│ │ │ ├── http_client.rs
│ │ │ ├── mod.rs
│ │ │ └── providers
│ │ │ │ ├── fetcher.rs
│ │ │ │ ├── file_vehicle.rs
│ │ │ │ ├── http_vehicle.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── proxy_provider
│ │ │ │ ├── mod.rs
│ │ │ │ ├── plain_provider.rs
│ │ │ │ └── proxy_set_provider.rs
│ │ │ │ └── rule_provider
│ │ │ │ ├── cidr_trie.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── mrs.rs
│ │ │ │ └── provider.rs
│ │ └── router
│ │ │ ├── mod.rs
│ │ │ └── rules
│ │ │ ├── domain.rs
│ │ │ ├── domain_keyword.rs
│ │ │ ├── domain_regex.rs
│ │ │ ├── domain_suffix.rs
│ │ │ ├── final_.rs
│ │ │ ├── geodata
│ │ │ ├── attribute.rs
│ │ │ ├── matcher_group.rs
│ │ │ ├── mod.rs
│ │ │ └── str_matcher.rs
│ │ │ ├── geoip.rs
│ │ │ ├── ipcidr.rs
│ │ │ ├── mod.rs
│ │ │ ├── port.rs
│ │ │ ├── process.rs
│ │ │ └── ruleset.rs
│ ├── common
│ │ ├── auth.rs
│ │ ├── crypto.rs
│ │ ├── defer.rs
│ │ ├── errors.rs
│ │ ├── geodata
│ │ │ ├── geodata.proto
│ │ │ └── mod.rs
│ │ ├── http
│ │ │ ├── client.rs
│ │ │ ├── hyper
│ │ │ │ └── mod.rs
│ │ │ └── mod.rs
│ │ ├── io
│ │ │ ├── mod.rs
│ │ │ └── splice.rs
│ │ ├── mmdb.rs
│ │ ├── mod.rs
│ │ ├── succinct_set.rs
│ │ ├── timed_future.rs
│ │ ├── tls.rs
│ │ ├── trie.rs
│ │ └── utils.rs
│ ├── config
│ │ ├── def.rs
│ │ ├── internal
│ │ │ ├── config.rs
│ │ │ ├── convert
│ │ │ │ ├── general.rs
│ │ │ │ ├── listener.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── proxy_group.rs
│ │ │ │ ├── rule_provider.rs
│ │ │ │ └── tun.rs
│ │ │ ├── listener.rs
│ │ │ ├── mod.rs
│ │ │ ├── proxy.rs
│ │ │ └── rule.rs
│ │ ├── mod.rs
│ │ └── utils.rs
│ ├── lib.rs
│ ├── proxy
│ │ ├── common.rs
│ │ ├── converters
│ │ │ ├── hysteria2.rs
│ │ │ ├── mod.rs
│ │ │ ├── shadowquic.rs
│ │ │ ├── shadowsocks.rs
│ │ │ ├── socks5.rs
│ │ │ ├── ssh.rs
│ │ │ ├── tor.rs
│ │ │ ├── trojan.rs
│ │ │ ├── tuic.rs
│ │ │ ├── utils.rs
│ │ │ ├── vmess.rs
│ │ │ └── wireguard.rs
│ │ ├── datagram.rs
│ │ ├── direct
│ │ │ └── mod.rs
│ │ ├── group
│ │ │ ├── fallback
│ │ │ │ └── mod.rs
│ │ │ ├── loadbalance
│ │ │ │ ├── helpers.rs
│ │ │ │ └── mod.rs
│ │ │ ├── mod.rs
│ │ │ ├── relay
│ │ │ │ └── mod.rs
│ │ │ ├── selector
│ │ │ │ └── mod.rs
│ │ │ ├── smart
│ │ │ │ ├── mod.rs
│ │ │ │ ├── penalty.rs
│ │ │ │ ├── state.rs
│ │ │ │ └── stats.rs
│ │ │ └── urltest
│ │ │ │ └── mod.rs
│ │ ├── http
│ │ │ ├── inbound
│ │ │ │ ├── auth.rs
│ │ │ │ ├── connector.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── proxy.rs
│ │ │ └── mod.rs
│ │ ├── hysteria2
│ │ │ ├── codec.rs
│ │ │ ├── congestion.rs
│ │ │ ├── datagram.rs
│ │ │ ├── mod.rs
│ │ │ ├── salamander.rs
│ │ │ └── udp_hop.rs
│ │ ├── inbound.rs
│ │ ├── mixed
│ │ │ └── mod.rs
│ │ ├── mocks.rs
│ │ ├── mod.rs
│ │ ├── options.rs
│ │ ├── reject
│ │ │ └── mod.rs
│ │ ├── shadowquic
│ │ │ ├── compat.rs
│ │ │ └── mod.rs
│ │ ├── shadowsocks
│ │ │ ├── datagram.rs
│ │ │ ├── mod.rs
│ │ │ └── stream.rs
│ │ ├── socks
│ │ │ ├── inbound
│ │ │ │ ├── datagram.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── stream.rs
│ │ │ ├── mod.rs
│ │ │ ├── outbound
│ │ │ │ ├── datagram.rs
│ │ │ │ └── mod.rs
│ │ │ └── socks5.rs
│ │ ├── ssh
│ │ │ ├── auth.rs
│ │ │ ├── connector.rs
│ │ │ └── mod.rs
│ │ ├── tor
│ │ │ ├── mod.rs
│ │ │ └── stream.rs
│ │ ├── tproxy
│ │ │ ├── iptables.sh
│ │ │ └── mod.rs
│ │ ├── transport
│ │ │ ├── grpc.rs
│ │ │ ├── h2.rs
│ │ │ ├── mod.rs
│ │ │ ├── shadow_tls
│ │ │ │ ├── mod.rs
│ │ │ │ ├── prelude.rs
│ │ │ │ ├── stream.rs
│ │ │ │ └── utils.rs
│ │ │ ├── simple_obfs
│ │ │ │ ├── http.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── tls.rs
│ │ │ ├── sip003
│ │ │ │ └── mod.rs
│ │ │ ├── tls.rs
│ │ │ ├── v2ray
│ │ │ │ ├── mod.rs
│ │ │ │ └── websocket.rs
│ │ │ └── ws
│ │ │ │ ├── mod.rs
│ │ │ │ ├── websocket.rs
│ │ │ │ └── websocket_early_data.rs
│ │ ├── trojan
│ │ │ ├── datagram.rs
│ │ │ └── mod.rs
│ │ ├── tuic
│ │ │ ├── compat.rs
│ │ │ ├── handle_stream.rs
│ │ │ ├── handle_task.rs
│ │ │ ├── mod.rs
│ │ │ └── types.rs
│ │ ├── tun
│ │ │ ├── datagram.rs
│ │ │ ├── inbound.rs
│ │ │ ├── mod.rs
│ │ │ ├── routes
│ │ │ │ ├── linux.rs
│ │ │ │ ├── macos.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── other.rs
│ │ │ │ └── windows.rs
│ │ │ └── stream.rs
│ │ ├── tunnel
│ │ │ └── mod.rs
│ │ ├── utils
│ │ │ ├── mod.rs
│ │ │ ├── platform
│ │ │ │ ├── apple.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── unix.rs
│ │ │ │ └── win.rs
│ │ │ ├── provider_helper.rs
│ │ │ ├── proxy_connector.rs
│ │ │ ├── socket_helpers.rs
│ │ │ └── test_utils
│ │ │ │ ├── docker_utils
│ │ │ │ ├── config_helper.rs
│ │ │ │ ├── consts.rs
│ │ │ │ ├── docker_runner.rs
│ │ │ │ └── mod.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── noop.rs
│ │ ├── vmess
│ │ │ ├── mod.rs
│ │ │ └── vmess_impl
│ │ │ │ ├── cipher.rs
│ │ │ │ ├── client.rs
│ │ │ │ ├── datagram.rs
│ │ │ │ ├── header.rs
│ │ │ │ ├── http.rs
│ │ │ │ ├── kdf.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── stream.rs
│ │ │ │ └── user.rs
│ │ └── wg
│ │ │ ├── device.rs
│ │ │ ├── events.rs
│ │ │ ├── keys.rs
│ │ │ ├── mod.rs
│ │ │ ├── ports.rs
│ │ │ ├── stack
│ │ │ ├── mod.rs
│ │ │ ├── tcp.rs
│ │ │ └── udp.rs
│ │ │ └── wireguard.rs
│ └── session.rs
└── tests
│ └── data
│ └── Country.mmdb
├── docs
├── .lock
├── clash_doc
│ ├── all.html
│ ├── index.html
│ ├── sidebar-items.js
│ ├── struct.ClashConfigDef.html
│ └── struct.ClashDNSConfigDef.html
├── crates.js
├── help.html
├── index.html
├── search-index.js
├── settings.html
├── source-files.js
├── src
│ └── clash_doc
│ │ └── lib.rs.html
└── static.files
│ ├── COPYRIGHT-23e9bde6c69aea69.txt
│ ├── FiraSans-LICENSE-db4b642586e02d97.txt
│ ├── FiraSans-Medium-8f9a781e4970d388.woff2
│ ├── FiraSans-Regular-018c141bf0843ffd.woff2
│ ├── LICENSE-APACHE-b91fa81cba47b86a.txt
│ ├── LICENSE-MIT-65090b722b3f6c56.txt
│ ├── NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2
│ ├── NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt
│ ├── SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2
│ ├── SourceCodePro-LICENSE-d180d465a756484a.txt
│ ├── SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2
│ ├── SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2
│ ├── SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2
│ ├── SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2
│ ├── SourceSerif4-LICENSE-3bb119e13b1258b7.md
│ ├── SourceSerif4-Regular-46f98efaafac5295.ttf.woff2
│ ├── ayu-614652228113ac93.css
│ ├── clipboard-7571035ce49a181d.svg
│ ├── dark-1097f8e92a01e3cf.css
│ ├── favicon-16x16-8b506e7a72182f1c.png
│ ├── favicon-2c020d218678b618.svg
│ ├── favicon-32x32-422f7d1d52889060.png
│ ├── light-0f8c037637f9eb3e.css
│ ├── main-f61008743c98d196.js
│ ├── normalize-76eba96aa4d2e634.css
│ ├── noscript-13285aec31fa243e.css
│ ├── rust-logo-151179464ae7ed46.svg
│ ├── rustdoc-ba5701c5741a7b69.css
│ ├── scrape-examples-ef1e698c1d417c0c.js
│ ├── search-e077946657036a58.js
│ ├── settings-298e1ea74db45b39.js
│ ├── settings-7bfb4c59cc6bc502.css
│ ├── source-script-905937fbbdc8e9ea.js
│ ├── storage-62ce34ea385b278a.js
│ └── wheel-7b819b6101059cd0.svg
├── rust-toolchain.toml
├── rustfmt.toml
└── scripts
├── build_apple.sh
├── check_socks5.py
├── logs.py
└── requirements.txt
/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | target-dir = "target"
3 | rustflags = ["--cfg", "tokio_unstable"]
4 |
5 | [env]
6 | RUST_LOG = { value = "clash=trace" }
7 | SENTRY_DSN = { value = "PLEASE DEFINE AT COMPILE TIME" }
8 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/.gitattributes
--------------------------------------------------------------------------------
/.github/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:latest
2 | # Define an ARG for the target architecture
3 | ARG TARGETARCH
4 | COPY ./clash-rs/clash-${TARGETARCH} /usr/bin/clash
5 | # The yq library installed here is used to rewrite the config.yaml configuration file for clash, merge it, and other related operations.
6 | RUN apk update && apk add --no-cache -f yq && mkdir -p /root/.config/clash/ && chmod +x /usr/bin/clash
7 | WORKDIR /root
8 | ENTRYPOINT [ "/usr/bin/clash" ]
9 | CMD [ "-d", "/root/.config/clash/" ]
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
8 |
9 | ### 🤔 This is a ...
10 |
11 | - [ ] New feature
12 | - [ ] Bug fix
13 | - [ ] Performance optimization
14 | - [ ] Enhancement feature
15 | - [ ] Refactoring
16 | - [ ] Code style optimization
17 | - [ ] Test Case
18 | - [ ] Branch merge
19 | - [ ] Workflow
20 | - [ ] Other (about what?)
21 |
22 | ### 🔗 Related issue link
23 |
24 |
28 |
29 | ### 💡 Background and solution
30 |
31 |
36 |
37 | ### 📝 Changelog
38 |
39 |
42 |
43 |
44 | ### ☑️ Self-Check before Merge
45 |
46 | ⚠️ Please check all items below before requesting a reviewing. ⚠️
47 |
48 | - [ ] Doc is updated/provided or not needed
49 | - [ ] Changelog is provided or not needed
50 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "cargo"
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | groups:
8 | rust-dependencies:
9 | patterns:
10 | - "*"
11 | - package-ecosystem: "github-actions"
12 | directory: "/"
13 | schedule:
14 | interval: weekly
15 | groups:
16 | actions-dependencies:
17 | patterns:
18 | - "*"
19 |
20 |
--------------------------------------------------------------------------------
/.github/email-blacklist.txt:
--------------------------------------------------------------------------------
1 | *@qq.com
2 | *@foxmail.com
3 | *@126.com
4 | *@163.com
5 | *@sina.com
6 | MX-RECORD,mxbiz1.qq.com
7 | MX-RECORD,mx1.qiye.aliyun.com
8 | MX-RECORD,mx.ym.163.com
9 | MX-RECORD,mx.huaweicloud.com
10 |
--------------------------------------------------------------------------------
/.github/workflows/coverage.yml:
--------------------------------------------------------------------------------
1 | name: Coverage
2 |
3 | on:
4 | push:
5 | tags: ["v*"]
6 | branches: ["master"]
7 | pull_request:
8 | branches: ["master"]
9 |
10 | concurrency:
11 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | compile:
16 | name: Coverage
17 | runs-on: 'ubuntu-latest'
18 | steps:
19 | - uses: actions/checkout@v4
20 | with:
21 | submodules: true
22 |
23 | - uses: actions/cache@v4
24 | with:
25 | path: |
26 | ~/.cargo/registry
27 | ~/.cargo/git
28 | ~/.cargo/bin/
29 | ~/.cargo/registry/index/
30 | ~/.cargo/registry/cache/
31 | ~/.cargo/git/db/
32 | key: coverage-${{ hashFiles('**/Cargo.toml') }}
33 |
34 | - name: Install cargo-llvm-cov
35 | uses: taiki-e/install-action@cargo-llvm-cov
36 | - name: Install Protoc
37 | uses: arduino/setup-protoc@v3
38 | with:
39 | version: "23.x"
40 | repo-token: ${{ secrets.GITHUB_TOKEN }}
41 |
42 | - name: Cargo test and coverage
43 | uses: clechasseur/rs-cargo@v3
44 | with:
45 | tool: cross
46 | command: 'llvm-cov'
47 | args: --workspace --exclude clash_ffi -F "plus" --codecov --output-path codecov.json
48 | env:
49 | CROSS_CONTAINER_OPTS: "--network host"
50 | CLASH_DOCKER_TEST: 'true'
51 |
52 | - name: Upload coverage to Codecov
53 | uses: codecov/codecov-action@v5
54 | if: ${{ !cancelled() }}
55 | with:
56 | token: ${{ secrets.CODECOV_TOKEN }}
57 | files: codecov.json
58 | fail_ci_if_error: true
59 |
--------------------------------------------------------------------------------
/.github/workflows/spell-check.yml:
--------------------------------------------------------------------------------
1 | name: Spelling
2 |
3 | permissions:
4 | contents: read
5 |
6 | on: [ pull_request ]
7 |
8 | env:
9 | CLICOLOR: 1
10 |
11 | jobs:
12 | spelling:
13 | name: Spell Check with Typos
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Checkout Actions Repository
17 | uses: actions/checkout@v4
18 | - name: Spell Check Repo
19 | uses: crate-ci/typos@v1.33.1
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | debug/
2 | target/
3 | **/*.rs.bk
4 | *.pdb
5 | .idea/
6 | .vscode/
7 | .config/
8 | .venv/
9 | /bazel-*
10 | /output/
11 | rust-project.json
12 | /build/
13 |
14 | # don't check in this real config
15 | ignore*.yaml
16 | config.yaml
17 | cache.db
18 | Country.mmdb
19 | ruleset/
20 | geosite.dat
21 |
22 | # for NixOS direnv
23 | .envrc
24 | shell.nix
25 |
26 | # macOS
27 | .DS_Store
28 |
29 | codecov.json
30 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/.gitmodules
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | - Try to use this project and report issues
2 | - Request any features that you'd like to see
3 | - Contributing to coding is more than welcome
4 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 |
4 | members = [
5 | "clash",
6 | "clash_lib",
7 | "clash_doc",
8 | "clash_ffi",
9 | ]
10 |
11 |
12 | [workspace.package]
13 | version = "0.7.8"
14 | repository = "https://github.com/Watfaq/clash-rs.git"
15 | edition = "2024"
16 | authors = ["https://github.com/Watfaq/clash-rs/graphs/contributors"]
17 | homepage = "https://github.com/watfaq/clash-rs"
18 |
19 | [profile.release]
20 | opt-level = "s"
21 | codegen-units = 1
22 | lto = "thin"
23 | strip = true
24 | debug = 2
25 | panic = "abort"
26 |
--------------------------------------------------------------------------------
/Cross.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | pre-build = [
3 | "apt update",
4 | "apt install -y protobuf-compiler"
5 | ]
6 |
7 | [build.env]
8 | volumes = ["/var/run/docker.sock=/var/run/docker.sock", "/tmp=/tmp"] # Docker in docker
9 | passthrough = ["CLASH_GIT_REF", "CLASH_GIT_SHA", "RUSTFLAGS", "RUST_LOG", "CLASH_DOCKER_TEST", "SENTRY_DSN"]
10 |
11 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: docs
2 | docs:
3 | @rm -rf ./docs
4 | @cargo doc -p clash_doc --no-deps
5 | @echo "" > target/doc/index.html
6 | @cp -r target/doc ./docs
7 |
8 | test-no-docker:
9 | CLASH_RS_CI=true cargo test --all --all-features
10 |
--------------------------------------------------------------------------------
/NOTICE.md:
--------------------------------------------------------------------------------
1 | When compiled with the following features, distributed with `GPL3` license
2 | - `tuic`
3 |
4 | Otherwise distributed with `Apache 2.0` license
5 |
--------------------------------------------------------------------------------
/_typos.toml:
--------------------------------------------------------------------------------
1 | [default]
2 | locale = "en"
3 |
4 | [default.extend-words]
5 | # Session:typ
6 | typ = "typ"
7 |
8 | [files]
9 | extend-exclude = [
10 | "docs",
11 | "bench",
12 | "clash/tests/data/config/public",
13 | "clash/tests/data/config/*.cert",
14 | ]
15 |
16 |
--------------------------------------------------------------------------------
/clash/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "clash-rs"
3 | repository = { workspace = true }
4 | version = { workspace = true }
5 | edition = { workspace = true }
6 | homepage = { workspace = true }
7 | authors = { workspace = true }
8 |
9 | [features]
10 | default = ["standard"]
11 | standard = ["shadowsocks", "tuic", "ssh", "clash_lib/zero_copy", "shadowquic"]
12 | plus = ["standard", "onion"]
13 | perf = ["plus", "jemallocator"]
14 |
15 | android = ["shadowsocks", "tuic"] # Android build failed with libc
16 | bsd = ["shadowsocks", "tuic"]
17 |
18 | shadowsocks = ["clash_lib/shadowsocks"]
19 | ssh = ["clash_lib/ssh"]
20 | tuic = ["clash_lib/tuic"]
21 | onion = ["clash_lib/onion"]
22 | shadowquic = ["clash_lib/shadowquic"]
23 |
24 | bench = ["clash_lib/bench"]
25 | dhat-heap = ["dep:dhat"]
26 | tokio-console = ["clash_lib/tokio-console"]
27 | jemallocator = ["dep:tikv-jemallocator"]
28 |
29 | [dependencies]
30 | clap = { version = "4", features = ["derive"] }
31 |
32 | clash_lib = { path = "../clash_lib", default-features = false }
33 |
34 | dhat = { version = "0.3", optional = true }
35 | tikv-jemallocator = { version = "0.6", optional = true }
36 |
37 | sentry = { version = "0.38", default-features = false, features = ["backtrace", "contexts", "panic", "reqwest", "rustls"] }
38 | human-panic = "2.0"
39 |
--------------------------------------------------------------------------------
/clash/build.rs:
--------------------------------------------------------------------------------
1 | #![feature(let_chains)]
2 | fn main() {
3 | let vars = ["CLASH_GIT_REF", "CLASH_GIT_SHA"];
4 | for var in vars {
5 | println!("cargo:rerun-if-env-changed={var}");
6 | }
7 |
8 | let version = if let Some("refs/heads/master") = option_env!("CLASH_GIT_REF")
9 | && let Some(sha) = option_env!("CLASH_GIT_SHA")
10 | {
11 | let short_sha = &sha[..7];
12 | // Nightly release below
13 | format!("{}-alpha+sha.{short_sha}", env!("CARGO_PKG_VERSION"))
14 | } else {
15 | env!("CARGO_PKG_VERSION").into()
16 | };
17 | println!("cargo:rustc-env=CLASH_VERSION_OVERRIDE={version}");
18 | }
19 |
--------------------------------------------------------------------------------
/clash/tests/data/config/Country-asn.mmdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/Country-asn.mmdb
--------------------------------------------------------------------------------
/clash/tests/data/config/Country.mmdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/Country.mmdb
--------------------------------------------------------------------------------
/clash/tests/data/config/GeoLite2-ASN.mmdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/GeoLite2-ASN.mmdb
--------------------------------------------------------------------------------
/clash/tests/data/config/dns.cert:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDITCCAgmgAwIBAgIQOp++4lLpVGLWkaGuRrrP2zANBgkqhkiG9w0BAQsFADAS
3 | MRAwDgYDVQQKEwdBY21lIENvMB4XDTIzMDkwMjA4MzIyM1oXDTI0MDkwMTA4MzIy
4 | M1owEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
5 | AQoCggEBAPS+pfYexKHq50myjnY6kAZ1uLDmgR/Vy9y7rPcrkqci25ClCnuUiUgY
6 | ABhrdq16oW2wOymc9A56YH9X99UNX6E+VmckCP8v9xcPV4/Zoc+KIeuJHRUBHFMK
7 | ieiWe560XcRCTP7OudUZ+iSHbjhaxZJCEfFaE8aSZXmiLKUETZ7z2lAm75fRCBaR
8 | Vy+jewy04F1BKg4VlnrZnVHzQCcBHZEpsAz4YpbNHMYf9sYRrh+T2j9Zya5tUklI
9 | LzEobWXUzjhrkcBXSVC5dLa9sxz7eSeg0dY0SkP7O5pelr8LaXnBudAk5B0ByqFD
10 | s83Z1AZMkv7vL2L8AGA/X1PP2UV3BrECAwEAAaNzMHEwDgYDVR0PAQH/BAQDAgKk
11 | MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
12 | FIiHKw+Z9rUjV6pbqcDl+teSTLxoMBoGA1UdEQQTMBGCD2Rucy5leGFtcGxlLmNv
13 | bTANBgkqhkiG9w0BAQsFAAOCAQEACTYIij1QqPhke3aI6HVLuXy75YHjxic0cIcX
14 | 7u41WSnZWOrnsBYAFPfjwH7sW6dX+5twUludSCSQ9Xyhl/tdQ0AKWJJNZ7irArS9
15 | kz2rU4u7YjtR4tuuRB2t+8UEcGA/m0EPhQfFbZedAy/Y2oc+RodwlqibVB/WCMOQ
16 | BL4HS1wFaYZw9WhXk3nzb+wjBhvyEQkI9oeMqVYZLN/9kIY9QuGtDg5onFrVSgjZ
17 | qiR7EfdICe8ogM6IiemQJfZ5SeWkoLpuRlaeVhqFFaFFeJ6cMTJ+Jluh6a3DGP91
18 | aRaPVO7r8gPq4mACua0HQcBfmH4VKS3hsQHdWDivRUT7xkZ/6g==
19 | -----END CERTIFICATE-----
20 |
--------------------------------------------------------------------------------
/clash/tests/data/config/dns.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD0vqX2HsSh6udJ
3 | so52OpAGdbiw5oEf1cvcu6z3K5KnItuQpQp7lIlIGAAYa3ateqFtsDspnPQOemB/
4 | V/fVDV+hPlZnJAj/L/cXD1eP2aHPiiHriR0VARxTConolnuetF3EQkz+zrnVGfok
5 | h244WsWSQhHxWhPGkmV5oiylBE2e89pQJu+X0QgWkVcvo3sMtOBdQSoOFZZ62Z1R
6 | 80AnAR2RKbAM+GKWzRzGH/bGEa4fk9o/WcmubVJJSC8xKG1l1M44a5HAV0lQuXS2
7 | vbMc+3knoNHWNEpD+zuaXpa/C2l5wbnQJOQdAcqhQ7PN2dQGTJL+7y9i/ABgP19T
8 | z9lFdwaxAgMBAAECggEAaMFNYcoLmc5kjsvJZFtumAU9NyKCNDEbX/BIeUcCL12h
9 | IwkxMnICTIRRTiJ5Gom5nKxotkgCwkupD/iEEIH345k9/EmVPDy4gvtDHEQnmSBj
10 | ol/+vaXLDNQe8Rmv8d77n2xNbmbnbYn/4jDBgYeAtzhmW6qVelHg8y3x8/OikZyy
11 | EB+ORiH/p4XN+3xBuEnFwBjQSHlayYVL8E68rp2wcKIeB2wo27Noh+VNqc2jks/l
12 | h9V+cydCOHY2OQ0iepZwPmsVVjEObtckksBTFWgpc5ZH6Ctq1YjtTpcOey9FRzhZ
13 | fuK9cj7bO5uW1duocgMPGsgiYMdvGyOCmM4tgp4lwQKBgQD+SXkzutxu0577g3Td
14 | 8BWYvksM6O3Lq8ZHKQtcxcNpp9S/fQ134IMErlykS1FJ5290KkHwQ4tojiOhtYQo
15 | GOlmbS7USR2puhNzEWxmhi0CIyyWyRDECrVZVnLfcVxZrxpoh4LjZFA6nVRhZipN
16 | oMig1zDhVmhvUTrTxVygFp9/aQKBgQD2ZLgGTK0kZ4npsUEL/ZantlZwEpY8S3TK
17 | muLlcGx3EFwPrX558xhYSwkh/afNTcRekJkoBA9SXaioZNKlOD/XyIFq0OeurygB
18 | gC8RdBs3xAjNHyj9qxajhuBqxxxTa/HmUnWqH2zDv20DcyvLTXjpRuFBxBj77ka9
19 | eVyGBxmsCQKBgQCC2tJpIWagDXyJl2tDbnHeqUY7vX3pSlr9cYysUASwUTJ02+hb
20 | YQhrF0MLNMr/Cf7bu4c1Gb0ar9J8O8lnTPKGx/bKPVnrZprtovCyjaeJqwoeChf7
21 | mjsaXxc8DrzkVex0EA/17kAu+ZlbidSJIA0+X56CxxF0/0sTgUOaCipHyQKBgQDl
22 | Bie7y0fhH9CkhRtWPufrimP8FnrJHsY3kRK4e/CGF5HLDNQUHK8TWuPpUXLJNbEC
23 | yVtjQ6rOP7qGk/jslEVbmMca94Vy7OK9yl111rt58WDQ8VbTu1T2uWceOWeN7zdR
24 | hHJUqJMbvHJjE4mwlpl+FGFLFTC38/qTIhyrhCwLqQKBgQDz67mt3XyD5HUT/GYn
25 | A91ZGjWfh3YPXYkjOOjw1MWqeO7LQi6A8uWkfRFPWn/h3gECqItrWFogJixRyL+G
26 | TWQ7SWmJctHD8YjU3E6tlPSWQhD2U75pZWtjpGAIYSdvS5V9Q+95jaKKhsYneThB
27 | SNEnosgWOR5eg9c0FznaDn6nRw==
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/clash/tests/data/config/dns.yaml:
--------------------------------------------------------------------------------
1 | mixed-port: 7890
2 | mode: rule
3 | log-level: trace
4 |
5 | tun:
6 | enable: true
7 | route-all: true
8 | device-id: dev://utun1989
9 | dns-hijack: true
10 |
11 | dns:
12 | enable: true
13 | enhanced-mode: fake-ip
14 | listen:
15 | udp: 127.0.0.1:53
16 | fake-ip-range: 198.18.0.1/16
17 | nameserver:
18 | - 223.5.5.5
19 | - 180.184.1.1
20 |
21 | rules:
22 | - MATCH,DIRECT
23 |
--------------------------------------------------------------------------------
/clash/tests/data/config/empty.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8888
3 | socks-port: 8889
4 | mixed-port: 8899
5 |
6 | dns:
7 | enable: true
8 | listen: 127.0.0.1:53533
9 | # ipv6: false # when the false, response to AAAA questions will be empty
10 |
11 | # These nameservers are used to resolve the DNS nameserver hostnames below.
12 | # Specify IP addresses only
13 | default-nameserver:
14 | - 114.114.114.114
15 | - 8.8.8.8
16 | enhanced-mode: fake-ip # or fake-ip
17 | fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR
18 | # use-hosts: true # lookup hosts and return IP record
19 |
20 | # Hostnames in this list will not be resolved with fake IPs
21 | # i.e. questions to these domain names will always be answered with their
22 | # real IP addresses
23 | # fake-ip-filter:
24 | # - '*.lan'
25 | # - localhost.ptlogin2.qq.com
26 |
27 | # Supports UDP, TCP, DoT, DoH. You can specify the port to connect to.
28 | # All DNS questions are sent directly to the nameserver, without proxies
29 | # involved. Clash answers the DNS question with the first result gathered.
30 | nameserver:
31 | - 114.114.114.114 # default value
32 | - 8.8.8.8 # default value
33 | - tls://dns.google:853 # DNS over TLS
34 | - https://1.1.1.1/dns-query # DNS over HTTPS
35 |
36 | allow-lan: true
37 | mode: rule
38 | log-level: debug
39 | external-controller: 127.0.0.1:6170
40 | experimental:
41 | ignore-resolve-fail: true
42 |
43 | rules:
44 | - MATCH, DIRECT
45 |
--------------------------------------------------------------------------------
/clash/tests/data/config/example.org-key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDQ+c++LkDTdaw5
3 | 5spCu9MWMcvVdrYBZZ5qZy7DskphSUSQp25cIu34GJXVPNxtbWx1CQCmdLlwqXvo
4 | PfUt5/pz9qsfhdAbzFduZQgGd7GTQOTJBDrAhm2+iVsQyGHHhF68muN+SgT+AtRE
5 | sJyZoHNYtjjWEIHQ++FHEDqwUVnj6Ut99LHlyfCjOZ5+WyBiKCjyMNots/gDep7R
6 | i4X2kMTqNMIIqPUcAaP5EQk41bJbFhKe915qN9b1dRISKFKmiWeOsxgTB/O/EaL5
7 | LsBYwZ/BiIMDk30aZvzRJeloasIR3z4hrKQqBfB0lfeIdiPpJIs5rXJQEiWH89ge
8 | gplsLbfrAgMBAAECggEBAKpMGaZzDPMF/v8Ee6lcZM2+cMyZPALxa+JsCakCvyh+
9 | y7hSKVY+RM0cQ+YM/djTBkJtvrDniEMuasI803PAitI7nwJGSuyMXmehP6P9oKFO
10 | jeLeZn6ETiSqzKJlmYE89vMeCevdqCnT5mW/wy5Smg0eGj0gIJpM2S3PJPSQpv9Z
11 | ots0JXkwooJcpGWzlwPkjSouY2gDbE4Coi+jmYLNjA1k5RbggcutnUCZZkJ6yMNv
12 | H52VjnkffpAFHRouK/YgF+5nbMyyw5YTLOyTWBq7qfBMsXynkWLU73GC/xDZa3yG
13 | o/Ph2knXCjgLmCRessTOObdOXedjnGWIjiqF8fVboDECgYEA6x5CteYiwthDBULZ
14 | CG5nE9VKkRHJYdArm+VjmGbzK51tKli112avmU4r3ol907+mEa4tWLkPqdZrrL49
15 | aHltuHizZJixJcw0rcI302ot/Ov0gkF9V55gnAQS/Kemvx9FHWm5NHdYvbObzj33
16 | bYRLJBtJWzYg9M8Bw9ZrUnegc/MCgYEA44kq5OSYCbyu3eaX8XHTtFhuQHNFjwl7
17 | Xk/Oel6PVZzmt+oOlDHnOfGSB/KpR3YXxFRngiiPZzbrOwFyPGe7HIfg03HAXiJh
18 | ivEfrPHbQqQUI/4b44GpDy6bhNtz777ivFGYEt21vpwd89rFiye+RkqF8eL/evxO
19 | pUayDZYvwikCgYEA07wFoZ/lkAiHmpZPsxsRcrfzFd+pto9splEWtumHdbCo3ajT
20 | 4W5VFr9iHF8/VFDT8jokFjFaXL1/bCpKTOqFl8oC68XiSkKy8gPkmFyXm5y2LhNi
21 | GGTFZdr5alRkgttbN5i9M/WCkhvMZRhC2Xp43MRB9IUzeqNtWHqhXbvjYGcCgYEA
22 | vTMOztviLJ6PjYa0K5lp31l0+/SeD21j/y0/VPOSHi9kjeN7EfFZAw6DTkaSShDB
23 | fIhutYVCkSHSgfMW6XGb3gKCiW/Z9KyEDYOowicuGgDTmoYu7IOhbzVjLhtJET7Z
24 | zJvQZ0eiW4f3RBFTF/4JMuu+6z7FD6ADSV06qx+KQNkCgYBw26iQxmT5e/4kVv8X
25 | DzBJ1HuliKBnnzZA1YRjB4H8F6Yrq+9qur1Lurez4YlbkGV8yPFt+Iu82ViUWL28
26 | 9T7Jgp3TOpf8qOqsWFv8HldpEZbE0Tcib4x6s+zOg/aw0ac/xOPY1sCVFB81VODP
27 | XCar+uxMBXI1zbXqd9QdEwy4Ig==
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/clash/tests/data/config/example.org.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIESzCCArOgAwIBAgIQIi5xRZvFZaSweWU9Y5mExjANBgkqhkiG9w0BAQsFADCB
3 | hzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMS4wLAYDVQQLDCVkcmVh
4 | bWFjcm9ARHJlYW1hY3JvLmxvY2FsIChEcmVhbWFjcm8pMTUwMwYDVQQDDCxta2Nl
5 | cnQgZHJlYW1hY3JvQERyZWFtYWNyby5sb2NhbCAoRHJlYW1hY3JvKTAeFw0yMTAz
6 | MTcxNDQwMzZaFw0yMzA2MTcxNDQwMzZaMFkxJzAlBgNVBAoTHm1rY2VydCBkZXZl
7 | bG9wbWVudCBjZXJ0aWZpY2F0ZTEuMCwGA1UECwwlZHJlYW1hY3JvQERyZWFtYWNy
8 | by5sb2NhbCAoRHJlYW1hY3JvKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
9 | ggEBAND5z74uQNN1rDnmykK70xYxy9V2tgFlnmpnLsOySmFJRJCnblwi7fgYldU8
10 | 3G1tbHUJAKZ0uXCpe+g99S3n+nP2qx+F0BvMV25lCAZ3sZNA5MkEOsCGbb6JWxDI
11 | YceEXrya435KBP4C1ESwnJmgc1i2ONYQgdD74UcQOrBRWePpS330seXJ8KM5nn5b
12 | IGIoKPIw2i2z+AN6ntGLhfaQxOo0wgio9RwBo/kRCTjVslsWEp73Xmo31vV1EhIo
13 | UqaJZ46zGBMH878RovkuwFjBn8GIgwOTfRpm/NEl6WhqwhHfPiGspCoF8HSV94h2
14 | I+kkizmtclASJYfz2B6CmWwtt+sCAwEAAaNgMF4wDgYDVR0PAQH/BAQDAgWgMBMG
15 | A1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFO800LQ6Pa85RH4EbMmFH6ln
16 | F150MBYGA1UdEQQPMA2CC2V4YW1wbGUub3JnMA0GCSqGSIb3DQEBCwUAA4IBgQAP
17 | TsF53h7bvJcUXT3Y9yZ2vnW6xr9r92tNnM1Gfo3D2Yyn9oLf2YrfJng6WZ04Fhqa
18 | Wh0HOvE0n6yPNpm/Q7mh64DrgolZ8Ce5H4RTJDAabHU9XhEzfGSVtzRSFsz+szu1
19 | Y30IV+08DxxqMmNPspYdpAET2Lwyk2WhnARGiGw11CRkQCEkVEe6d702vS9UGBUz
20 | Du6lmCYCm0SbFrZ0CGgmHSHoTcCtf3EjVam7dPg3yWiPbWjvhXxgip6hz9sCqkhG
21 | WA5f+fPgSZ1I9U4i+uYnqjfrzwgC08RwUYordm15F6gPvXw+KVwDO8yUYQoEH0b6
22 | AFJtbzoAXDysvBC6kWYFFOr62EaisaEkELTS/NrPD9ux1eKbxcxHCwEtVjgC0CL6
23 | gAxEAQ+9maJMbrAFhsOBbGGFC+mMCGg4eEyx6+iMB0oQe0W7QFeRUAFi7Ptc/ocS
24 | tZ9lbrfX1/wrcTTWIYWE+xH6oeb4fhs29kxjHcf2l+tQzmpl0aP3Z/bMW4BSB+w=
25 | -----END CERTIFICATE-----
26 |
--------------------------------------------------------------------------------
/clash/tests/data/config/hysteria.json:
--------------------------------------------------------------------------------
1 | {
2 | "listen": ":10002",
3 | "tls":{
4 | "cert": "/home/ubuntu/my.crt",
5 | "key": "/home/ubuntu/my.key"
6 | },
7 | "obfs": {
8 | "type": "salamander",
9 | "salamander": {
10 | "password": "beauty will save the world"
11 | }
12 | },
13 | "up_mbps": 100,
14 | "down_mbps": 100,
15 | "auth": {
16 | "type": "password",
17 | "password": "passwd"
18 | }
19 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/hysteria2.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8891
3 | socks-port: 8889
4 | mixed-port: 8888
5 |
6 |
7 | dns:
8 | enable: true
9 | listen: 127.0.0.1:53533
10 | # ipv6: false # when the false, response to AAAA questions will be empty
11 |
12 | # These nameservers are used to resolve the DNS nameserver hostnames below.
13 | # Specify IP addresses only
14 | default-nameserver:
15 | - 114.114.114.114
16 | - 8.8.8.8
17 | enhanced-mode: fake-ip # or fake-ip
18 | fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR
19 | # use-hosts: true # lookup hosts and return IP record
20 |
21 | # Hostnames in this list will not be resolved with fake IPs
22 | # i.e. questions to these domain names will always be answered with their
23 | # real IP addresses
24 | # fake-ip-filter:
25 | # - '*.lan'
26 | # - localhost.ptlogin2.qq.com
27 |
28 | # Supports UDP, TCP, DoT, DoH. You can specify the port to connect to.
29 | # All DNS questions are sent directly to the nameserver, without proxies
30 | # involved. Clash answers the DNS question with the first result gathered.
31 | nameserver:
32 | - 114.114.114.114 # default value
33 | - 8.8.8.8 # default value
34 | # - tls://dns.google:853 # DNS over TLS
35 | # - https://1.1.1.1/dns-query # DNS over HTTPS
36 | # - dhcp://en0 # dns from dhcp
37 |
38 | allow-lan: true
39 | mode: rule
40 | log-level: debug
41 | external-controller: 127.0.0.1:6170
42 | experimental:
43 | ignore-resolve-fail: true
44 |
45 | proxies:
46 | - name: "local"
47 | type: hysteria2
48 | server: 127.0.0.1
49 | port: 10086
50 | password: passwd
51 | sni: example.com
52 | skip-cert-verify: true
53 | obfs: salamander
54 | obfs-password: "passwd"
55 |
56 | rules:
57 | - MATCH, local
58 |
--------------------------------------------------------------------------------
/clash/tests/data/config/listeners/tunnel.yaml:
--------------------------------------------------------------------------------
1 | port: 8080
2 | socks-port: 8081
3 | log-level: trace
4 | listeners:
5 | - name: tunnel-in
6 | type: tunnel
7 | port: 15201
8 | listen: 127.0.0.1
9 | network: [tcp, udp]
10 | target: 127.0.0.1:5201
--------------------------------------------------------------------------------
/clash/tests/data/config/public/CNAME:
--------------------------------------------------------------------------------
1 | yacd.haishan.me
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/_headers:
--------------------------------------------------------------------------------
1 | # for netlify hosting
2 | # https://docs.netlify.com/routing/headers/#syntax-for-the-headers-file
3 |
4 | /*
5 | X-Frame-Options: DENY
6 | X-XSS-Protection: 1; mode=block
7 | X-Content-Type-Options: nosniff
8 | Referrer-Policy: same-origin
9 | /*.css
10 | Cache-Control: public, max-age=31536000, immutable
11 | /*.js
12 | Cache-Control: public, max-age=31536000, immutable
13 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/Config.39d8d2ef.css:
--------------------------------------------------------------------------------
1 | ._root_v2s4h_1,._section_v2s4h_2{display:grid;grid-template-columns:repeat(auto-fill,minmax(345px,1fr));max-width:900px;gap:5px}@media screen and (min-width: 30em){._root_v2s4h_1,._section_v2s4h_2{gap:15px}}._root_v2s4h_1,._section_v2s4h_2{padding:6px 15px 10px}@media screen and (min-width: 30em){._root_v2s4h_1,._section_v2s4h_2{padding:10px 40px 15px}}._wrapSwitch_v2s4h_26{height:40px;display:flex;align-items:center}._sep_v2s4h_32{max-width:900px;padding:0 15px}@media screen and (min-width: 30em){._sep_v2s4h_32{padding:0 40px}}._sep_v2s4h_32>div{border-top:1px dashed #373737}._label_v2s4h_45{padding:11px 0}._fieldset_1ghjp_1{margin:0;padding:0;border:0;display:flex;flex-wrap:wrap}._input_1ghjp_9+._cnt_1ghjp_9{border:1px solid transparent;border-radius:8px;cursor:pointer;margin-right:5px;margin-bottom:5px}._input_1ghjp_9:focus+._cnt_1ghjp_9{border-color:#387cec}._input_1ghjp_9:checked+._cnt_1ghjp_9{border-color:#387cec}
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/Fab.ef67ff10.js:
--------------------------------------------------------------------------------
1 | import{j as e,b,i as y,r as l}from"./index.171f553a.js";const F="_spining_4i8sg_1",M="_spining_keyframes_4i8sg_1",j={spining:F,spining_keyframes:M},{useState:v}=y;function B({children:s}){return e("span",{className:j.spining,children:s})}const H={right:10,bottom:10},L=({children:s,...n})=>e("button",{type:"button",...n,className:"rtf--ab",children:s}),E=({children:s,...n})=>e("button",{type:"button",className:"rtf--mb",...n,children:s}),O={bottom:24,right:24},R=({event:s="hover",style:n=O,alwaysShowTitle:o=!1,children:f,icon:g,mainButtonStyles:h,onClick:p,text:d,..._})=>{const[a,r]=v(!1),c=o||!a,u=()=>r(!0),m=()=>r(!1),x=()=>s==="hover"&&u(),k=()=>s==="hover"&&m(),N=t=>p?p(t):(t.persist(),s==="click"?a?m():u():null),$=(t,i)=>{t.persist(),r(!1),setTimeout(()=>{i(t)},1)},C=()=>l.exports.Children.map(f,(t,i)=>l.exports.isValidElement(t)?b("li",{className:`rtf--ab__c ${"top"in n?"top":""}`,children:[l.exports.cloneElement(t,{"data-testid":`action-button-${i}`,"aria-label":t.props.text||`Menu button ${i+1}`,"aria-hidden":c,tabIndex:a?0:-1,...t.props,onClick:I=>{t.props.onClick&&$(I,t.props.onClick)}}),t.props.text&&e("span",{className:`${"right"in n?"right":""} ${o?"always-show":""}`,"aria-hidden":c,children:t.props.text})]}):null);return e("ul",{onMouseEnter:x,onMouseLeave:k,className:`rtf ${a?"open":"closed"}`,"data-testid":"fab",style:n,..._,children:b("li",{className:"rtf--mb__c",children:[e(E,{onClick:N,style:h,"data-testid":"main-button",role:"button","aria-label":"Floating menu",tabIndex:0,children:g}),d&&e("span",{className:`${"right"in n?"right":""} ${o?"always-show":""}`,"aria-hidden":c,children:d}),e("ul",{children:C()})]})})};export{L as A,R as F,B as I,H as p};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/Logs.4b8e75d1.css:
--------------------------------------------------------------------------------
1 | ._RuleSearch_1oz2t_1{padding:0 40px 5px}._RuleSearchContainer_1oz2t_5{position:relative;height:40px}._inputWrapper_1oz2t_10{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:0;width:100%}._input_1oz2t_10{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 15px 0 35px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._iconWrapper_1oz2t_35{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:10px;display:flex;justify-content:center;align-items:center}._logMeta_7a1x3_1{display:flex;align-items:center;flex-wrap:wrap;font-size:.9em}._logType_7a1x3_8{color:#eee;flex-shrink:0;text-align:center;width:66px;border-radius:100px;padding:3px 5px;margin:0 8px}._logTime_7a1x3_18{flex-shrink:0;color:#999;font-size:14px}._logText_7a1x3_24{flex-shrink:0;display:flex;font-family:Roboto Mono,Menlo,monospace;align-items:center;padding:8px 0;width:100%;white-space:pre;overflow:auto}._logsWrapper_7a1x3_37{margin:0;padding:0;color:var(--color-text)}._logsWrapper_7a1x3_37 .log{padding:10px 40px;background:var(--color-background)}._logsWrapper_7a1x3_37 .log.even{background:var(--color-background)}._logPlaceholder_7a1x3_51{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#2d2d30}._logPlaceholder_7a1x3_51 div:nth-child(2){color:var(--color-text-secondary);font-size:1.4em;opacity:.6}._logPlaceholderIcon_7a1x3_64{opacity:.3}._search_7a1x3_68{max-width:1000px}
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/Rules.e03c54a8.css:
--------------------------------------------------------------------------------
1 | ._RuleProviderItem_12aid_1{display:grid;grid-template-columns:40px 1fr 46px;height:100%}._left_12aid_7{display:inline-flex;align-items:center;color:var(--color-text-secondary);opacity:.4}._middle_12aid_14{display:grid;gap:6px;grid-template-rows:1fr auto auto;align-items:center}._gray_12aid_21{color:#777}._action_12aid_25{display:grid;gap:4px;grid-template-columns:auto 1fr;align-items:center}._refreshBtn_12aid_32{padding:5px}._rule_1ymqx_1{display:flex;align-items:center;padding:6px 15px}@media screen and (min-width: 30em){._rule_1ymqx_1{padding:10px 40px}}._left_1ymqx_12{width:40px;padding-right:15px;color:var(--color-text-secondary);opacity:.4}._a_1ymqx_19{display:flex;align-items:center;font-size:12px;opacity:.8}._b_1ymqx_26{padding:10px 0;font-family:Roboto Mono,Menlo,monospace;font-size:16px}@media screen and (min-width: 30em){._b_1ymqx_26{font-size:19px}}._type_1ymqx_37{width:110px}._header_1j1w3_1{display:grid;grid-template-columns:1fr minmax(auto,330px);align-items:center;padding-right:15px}@media screen and (min-width: 30em){._header_1j1w3_1{padding-right:40px}}._RuleProviderItemWrapper_1j1w3_17{padding:6px 15px}@media screen and (min-width: 30em){._RuleProviderItemWrapper_1j1w3_17{padding:10px 40px}}
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/Select.1e55eba1.css:
--------------------------------------------------------------------------------
1 | ._select_13zm8_1{height:40px;line-height:1.5;width:100%;padding-left:8px;-webkit-appearance:none;appearance:none;background-color:var(--color-input-bg);color:var(--color-text);padding-right:20px;border-radius:4px;border:1px solid var(--color-input-border);background-image:url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);background-position:right 8px center;background-repeat:no-repeat}._select_13zm8_1:hover,._select_13zm8_1:focus{border-color:#343434;outline:none!important;color:var(--color-text-highlight);background-image:var(--select-bg-hover)}._select_13zm8_1:focus{box-shadow:#4299e199 0 0 0 3px}._select_13zm8_1 option{background-color:var(--color-background)}
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/Select.6c389032.js:
--------------------------------------------------------------------------------
1 | import{j as s}from"./index.171f553a.js";const o="_select_13zm8_1",r={select:o};function i({options:t,selected:c,onChange:l}){return s("select",{className:r.select,value:c,onChange:l,children:t.map(([e,n])=>s("option",{value:e,children:n},e))})}export{i as S};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/TextFitler.61537a57.js:
--------------------------------------------------------------------------------
1 | import{r as u,b as g,j as i,k as c,c as f,V as x,i as d}from"./index.171f553a.js";import{d as h}from"./debounce.c2d20996.js";function v(t,n){if(t==null)return{};var o=_(t,n),r,e;if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(t);for(e=0;e=0)&&(!Object.prototype.propertyIsEnumerable.call(t,r)||(o[r]=t[r]))}return o}function _(t,n){if(t==null)return{};var o={},r=Object.keys(t),e,s;for(s=0;s=0)&&(o[e]=t[e]);return o}var l=u.exports.forwardRef(function(t,n){var o=t.color,r=o===void 0?"currentColor":o,e=t.size,s=e===void 0?24:e,a=v(t,["color","size"]);return g("svg",{ref:n,xmlns:"http://www.w3.org/2000/svg",width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:r,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...a,children:[i("polyline",{points:"23 4 23 10 17 10"}),i("path",{d:"M20.49 15a9 9 0 1 1-2.12-9.36L23 10"})]})});l.propTypes={color:c.exports.string,size:c.exports.oneOfType([c.exports.string,c.exports.number])};l.displayName="RotateCw";const b=l,y="_rotate_1dspl_1",m="_isRotating_1dspl_5",R="_rotating_1dspl_1",p={rotate:y,isRotating:m,rotating:R};function P(t){const n=t.size||16,o=f(p.rotate,{[p.isRotating]:t.isRotating});return i("span",{className:o,children:i(b,{size:n})})}const{useCallback:w,useState:j,useMemo:k}=d;function O(t){const[,n]=x(t),[o,r]=j(""),e=k(()=>h(n,300),[n]);return[w(a=>{r(a.target.value),e(a.target.value)},[e]),o]}const T="_input_16a1f_1",C={input:T};function $(t){const[n,o]=O(t.textAtom);return i("input",{className:C.input,type:"text",value:o,onChange:n,placeholder:t.placeholder})}export{P as R,$ as T,b as a};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/TextFitler.b21c0577.css:
--------------------------------------------------------------------------------
1 | ._rotate_1dspl_1{display:inline-flex}._isRotating_1dspl_5{-webkit-animation:_rotating_1dspl_1 3s infinite linear;animation:_rotating_1dspl_1 3s infinite linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes _rotating_1dspl_1{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes _rotating_1dspl_1{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}._input_16a1f_1{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;outline:none;padding:8px 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._input_16a1f_1:focus{border:1px solid var(--color-focus-blue)}
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/chevron-down.dd238e96.js:
--------------------------------------------------------------------------------
1 | import{r as f,j as l,k as s}from"./index.171f553a.js";function c(r,i){if(r==null)return{};var n=v(r,i),o,e;if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(r);for(e=0;e=0)&&(!Object.prototype.propertyIsEnumerable.call(r,o)||(n[o]=r[o]))}return n}function v(r,i){if(r==null)return{};var n={},o=Object.keys(r),e,t;for(t=0;t=0)&&(n[e]=r[e]);return n}var p=f.exports.forwardRef(function(r,i){var n=r.color,o=n===void 0?"currentColor":n,e=r.size,t=e===void 0?24:e,a=c(r,["color","size"]);return l("svg",{ref:i,xmlns:"http://www.w3.org/2000/svg",width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:o,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...a,children:l("polyline",{points:"6 9 12 15 18 9"})})});p.propTypes={color:s.exports.string,size:s.exports.oneOfType([s.exports.string,s.exports.number])};p.displayName="ChevronDown";const u=p;export{u as C};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/debounce.c2d20996.js:
--------------------------------------------------------------------------------
1 | function O(e){var n=typeof e;return e!=null&&(n=="object"||n=="function")}var M=typeof global=="object"&&global&&global.Object===Object&&global;const R=M;var w=typeof self=="object"&&self&&self.Object===Object&&self,B=R||w||Function("return this")();const W=B;var F=function(){return W.Date.now()};const S=F;var G=/\s/;function U(e){for(var n=e.length;n--&&G.test(e.charAt(n)););return n}var _=/^\s+/;function D(e){return e&&e.slice(0,U(e)+1).replace(_,"")}var H=W.Symbol;const y=H;var L=Object.prototype,X=L.hasOwnProperty,q=L.toString,g=y?y.toStringTag:void 0;function z(e){var n=X.call(e,g),i=e[g];try{e[g]=void 0;var o=!0}catch{}var f=q.call(e);return o&&(n?e[g]=i:delete e[g]),f}var J=Object.prototype,K=J.toString;function Q(e){return K.call(e)}var V="[object Null]",Y="[object Undefined]",$=y?y.toStringTag:void 0;function Z(e){return e==null?e===void 0?Y:V:$&&$ in Object(e)?z(e):Q(e)}function ee(e){return e!=null&&typeof e=="object"}var ne="[object Symbol]";function te(e){return typeof e=="symbol"||ee(e)&&Z(e)==ne}var E=0/0,re=/^[-+]0x[0-9a-f]+$/i,ie=/^0b[01]+$/i,oe=/^0o[0-7]+$/i,ae=parseInt;function k(e){if(typeof e=="number")return e;if(te(e))return E;if(O(e)){var n=typeof e.valueOf=="function"?e.valueOf():e;e=O(n)?n+"":n}if(typeof e!="string")return e===0?e:+e;e=D(e);var i=ie.test(e);return i||oe.test(e)?ae(e.slice(2),i?2:8):re.test(e)?E:+e}var fe="Expected a function",ce=Math.max,ue=Math.min;function se(e,n,i){var o,f,s,u,r,c,d=0,v=!1,l=!1,T=!0;if(typeof e!="function")throw new TypeError(fe);n=k(n)||0,O(i)&&(v=!!i.leading,l="maxWait"in i,s=l?ce(k(i.maxWait)||0,n):s,T="trailing"in i?!!i.trailing:T);function j(t){var a=o,b=f;return o=f=void 0,d=t,u=e.apply(b,a),u}function N(t){return d=t,r=setTimeout(m,n),v?j(t):u}function P(t){var a=t-c,b=t-d,I=n-a;return l?ue(I,s-b):I}function h(t){var a=t-c,b=t-d;return c===void 0||a>=n||a<0||l&&b>=s}function m(){var t=S();if(h(t))return x(t);r=setTimeout(m,P(t))}function x(t){return r=void 0,T&&o?j(t):(o=f=void 0,u)}function A(){r!==void 0&&clearTimeout(r),d=0,o=c=f=r=void 0}function C(){return r===void 0?u:x(S())}function p(){var t=S(),a=h(t);if(o=arguments,f=this,c=t,a){if(r===void 0)return N(c);if(l)return clearTimeout(r),r=setTimeout(m,n),j(c)}return r===void 0&&(r=setTimeout(m,n)),u}return p.cancel=A,p.flush=C,p}export{se as d};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/en.fb34eaf7.js:
--------------------------------------------------------------------------------
1 | const e={Overview:"Overview",Proxies:"Proxies",Rules:"Rules",Conns:"Conns",Config:"Config",Logs:"Logs",Upload:"Upload",Download:"Download","Upload Total":"Upload Total","Download Total":"Download Total","Active Connections":"Active Connections","Pause Refresh":"Pause Refresh","Resume Refresh":"Resume Refresh",Up:"Up",Down:"Down","Test Latency":"Test Latency",settings:"settings",sort_in_grp:"Sorting in group",hide_unavail_proxies:"Hide unavailable proxies",auto_close_conns:"Automatically close old connections",order_natural:"Original order in config file",order_latency_asc:"By latency from small to big",order_latency_desc:"By latency from big to small",order_name_asc:"By name alphabetically (A-Z)",order_name_desc:"By name alphabetically (Z-A)",Connections:"Connections",Active:"Active",Closed:"Closed",switch_theme:"Switch theme",theme:"theme",about:"about",no_logs:"No logs yet, hang tight...",chart_style:"Chart Style",latency_test_url:"Latency Test URL",lang:"Language",update_all_rule_provider:"Update all rule providers",update_all_proxy_provider:"Update all proxy providers"};export{e as data};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/inter-latin-400-normal.0364d368.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/assets/inter-latin-400-normal.0364d368.woff2
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/inter-latin-400-normal.3ea830d4.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/assets/inter-latin-400-normal.3ea830d4.woff
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/inter-latin-800-normal.a51ac27d.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/assets/inter-latin-800-normal.a51ac27d.woff2
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/inter-latin-800-normal.d08d7178.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/assets/inter-latin-800-normal.d08d7178.woff
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/logs.43986220.js:
--------------------------------------------------------------------------------
1 | import{E as w,G as D,H as u}from"./index.171f553a.js";const v="/logs",L=new TextDecoder("utf-8"),M=()=>Math.floor((1+Math.random())*65536).toString(16);let h=!1,i=!1,f="",s,g;function m(e,n){let t;try{t=JSON.parse(e)}catch{console.log("JSON.parse error",JSON.parse(e))}const r=new Date,l=$(r);t.time=l,t.id=+r-0+M(),t.even=h=!h,n(t)}function $(e){const n=e.getFullYear()%100,t=u(e.getMonth()+1,2),r=u(e.getDate(),2),l=u(e.getHours(),2),o=u(e.getMinutes(),2),c=u(e.getSeconds(),2);return`${n}-${t}-${r} ${l}:${o}:${c}`}function p(e,n){return e.read().then(({done:t,value:r})=>{const l=L.decode(r,{stream:!t});f+=l;const o=f.split(`
2 | `),c=o[o.length-1];for(let d=0;de[t]).join("|")}let b,a;function k(e,n){if(e.logLevel==="uninit"||i||s&&s.readyState===1)return;g=n;const t=w(e,v);s=new WebSocket(t),s.addEventListener("error",()=>{y(e,n)}),s.addEventListener("message",function(r){m(r.data,n)})}function H(){s.close(),a&&a.abort()}function O(e){!g||!s||(s.close(),i=!1,k(e,g))}function y(e,n){if(a&&S(e)!==b)a.abort();else if(i)return;i=!0,b=S(e),a=new AbortController;const t=a.signal,{url:r,init:l}=D(e);fetch(r+v+"?level="+e.logLevel,{...l,signal:t}).then(o=>{const c=o.body.getReader();p(c,n)},o=>{i=!1,!t.aborted&&console.log("GET /logs error:",o.message)})}export{k as f,O as r,H as s};
3 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/play.7b1a5f99.js:
--------------------------------------------------------------------------------
1 | import{r as c,b as u,j as p,k as s}from"./index.171f553a.js";function y(e,n){if(e==null)return{};var i=g(e,n),t,r;if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0)&&(!Object.prototype.propertyIsEnumerable.call(e,t)||(i[t]=e[t]))}return i}function g(e,n){if(e==null)return{};var i={},t=Object.keys(e),r,o;for(o=0;o=0)&&(i[r]=e[r]);return i}var l=c.exports.forwardRef(function(e,n){var i=e.color,t=i===void 0?"currentColor":i,r=e.size,o=r===void 0?24:r,a=y(e,["color","size"]);return u("svg",{ref:n,xmlns:"http://www.w3.org/2000/svg",width:o,height:o,viewBox:"0 0 24 24",fill:"none",stroke:t,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...a,children:[p("rect",{x:"6",y:"4",width:"4",height:"16"}),p("rect",{x:"14",y:"4",width:"4",height:"16"})]})});l.propTypes={color:s.exports.string,size:s.exports.oneOfType([s.exports.string,s.exports.number])};l.displayName="Pause";const d=l;function h(e,n){if(e==null)return{};var i=v(e,n),t,r;if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0)&&(!Object.prototype.propertyIsEnumerable.call(e,t)||(i[t]=e[t]))}return i}function v(e,n){if(e==null)return{};var i={},t=Object.keys(e),r,o;for(o=0;o=0)&&(i[r]=e[r]);return i}var f=c.exports.forwardRef(function(e,n){var i=e.color,t=i===void 0?"currentColor":i,r=e.size,o=r===void 0?24:r,a=h(e,["color","size"]);return p("svg",{ref:n,xmlns:"http://www.w3.org/2000/svg",width:o,height:o,viewBox:"0 0 24 24",fill:"none",stroke:t,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...a,children:p("polygon",{points:"5 3 19 12 5 21 5 3"})})});f.propTypes={color:s.exports.string,size:s.exports.oneOfType([s.exports.string,s.exports.number])};f.displayName="Play";const w=f;export{w as P,d as a};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/roboto-mono-latin-400-normal.7295944e.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/assets/roboto-mono-latin-400-normal.7295944e.woff2
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/roboto-mono-latin-400-normal.dffdffa7.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/assets/roboto-mono-latin-400-normal.dffdffa7.woff
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/useRemainingViewPortHeight.7395542b.js:
--------------------------------------------------------------------------------
1 | import{i as r}from"./index.171f553a.js";const{useState:s,useRef:u,useCallback:a,useLayoutEffect:c}=r;function d(){const t=u(null),[n,i]=s(200),e=a(()=>{const{top:o}=t.current.getBoundingClientRect();i(window.innerHeight-o)},[]);return c(()=>(e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}),[e]),[t,n]}export{d as u};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/assets/zh.9b79b7bf.js:
--------------------------------------------------------------------------------
1 | const u={Overview:"\u6982\u89C8",Proxies:"\u4EE3\u7406",Rules:"\u89C4\u5219",Conns:"\u8FDE\u63A5",Config:"\u914D\u7F6E",Logs:"\u65E5\u5FD7",Upload:"\u4E0A\u4F20",Download:"\u4E0B\u8F7D","Upload Total":"\u4E0A\u4F20\u603B\u91CF","Download Total":"\u4E0B\u8F7D\u603B\u91CF","Active Connections":"\u6D3B\u52A8\u8FDE\u63A5","Pause Refresh":"\u6682\u505C\u5237\u65B0","Resume Refresh":"\u7EE7\u7EED\u5237\u65B0",Up:"\u4E0A\u4F20",Down:"\u4E0B\u8F7D","Test Latency":"\u5EF6\u8FDF\u6D4B\u901F",settings:"\u8BBE\u7F6E",sort_in_grp:"\u4EE3\u7406\u7EC4\u6761\u76EE\u6392\u5E8F",hide_unavail_proxies:"\u9690\u85CF\u4E0D\u53EF\u7528\u4EE3\u7406",auto_close_conns:"\u5207\u6362\u4EE3\u7406\u65F6\u81EA\u52A8\u65AD\u5F00\u65E7\u8FDE\u63A5",order_natural:"\u539F config \u6587\u4EF6\u4E2D\u7684\u6392\u5E8F",order_latency_asc:"\u6309\u5EF6\u8FDF\u4ECE\u5C0F\u5230\u5927",order_latency_desc:"\u6309\u5EF6\u8FDF\u4ECE\u5927\u5230\u5C0F",order_name_asc:"\u6309\u540D\u79F0\u5B57\u6BCD\u6392\u5E8F (A-Z)",order_name_desc:"\u6309\u540D\u79F0\u5B57\u6BCD\u6392\u5E8F (Z-A)",Connections:"\u8FDE\u63A5",Active:"\u6D3B\u52A8",Closed:"\u5DF2\u65AD\u5F00",switch_theme:"\u5207\u6362\u4E3B\u9898",theme:"\u4E3B\u9898",about:"\u5173\u4E8E",no_logs:"\u6682\u65E0\u65E5\u5FD7...",chart_style:"\u6D41\u91CF\u56FE\u6837\u5F0F",latency_test_url:"\u5EF6\u8FDF\u6D4B\u901F URL",lang:"\u8BED\u8A00",update_all_rule_provider:"\u66F4\u65B0\u6240\u6709 rule provider",update_all_proxy_provider:"\u66F4\u65B0\u6240\u6709 proxy providers"};export{u as data};
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | yacd
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"yacd","short_name":"yacd","start_url":"./","display":"standalone","background_color":"#ffffff","lang":"en","scope":"./"}
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/public/registerSW.js:
--------------------------------------------------------------------------------
1 | if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('./sw.js', { scope: './' })})}
--------------------------------------------------------------------------------
/clash/tests/data/config/public/yacd-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/yacd-128.png
--------------------------------------------------------------------------------
/clash/tests/data/config/public/yacd-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/yacd-64.png
--------------------------------------------------------------------------------
/clash/tests/data/config/public/yacd.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/public/yacd.ico
--------------------------------------------------------------------------------
/clash/tests/data/config/rule-set-classical.yaml:
--------------------------------------------------------------------------------
1 | payload:
2 | - DOMAIN-REGEX,^www.twitter.com$
3 |
--------------------------------------------------------------------------------
/clash/tests/data/config/rule-set.yaml:
--------------------------------------------------------------------------------
1 | payload:
2 | - 'httpbin.yba.dev'
--------------------------------------------------------------------------------
/clash/tests/data/config/shadowquic.yaml:
--------------------------------------------------------------------------------
1 | inbound:
2 | type: shadowquic
3 | bind-addr: 0.0.0.0:10002
4 | jls-pwd: "12345678"
5 | jls-iv: "87654321"
6 | jls-upstream: "echo.free.beeceptor.com:443" # domain + port, domain must be the same as client
7 | alpn: ["h3"]
8 | congestion-control: bbr
9 | zero-rtt: true
10 | outbound:
11 | type: direct
12 | log-level: "trace"
--------------------------------------------------------------------------------
/clash/tests/data/config/simple.yaml:
--------------------------------------------------------------------------------
1 | mixed-port: 8899
2 | external-controller: 127.0.0.1:9090
3 | mode: global
4 | bind-address: "0.0.0.0"
5 |
--------------------------------------------------------------------------------
/clash/tests/data/config/socks5.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8888
3 | socks-port: 8889
4 | mixed-port: 8899
5 |
6 | mode: rule
7 | log-level: debug
8 | external-controller: 127.0.0.1:6170
9 |
10 |
11 | proxies:
12 | - name: "socks5-noauth"
13 | type: socks5
14 | server: 10.0.0.13
15 | port: 10800
16 | udp: true
17 |
18 | - name: "socks5-auth"
19 | type: socks5
20 | server: 10.0.0.13
21 | port: 10801
22 | username: user
23 | password: password
24 | udp: true
25 |
26 | - name: "socks5-tls"
27 | type: socks5
28 | server: 10.0.0.13
29 | port: 10802
30 | username: user
31 | password: password
32 | tls: true
33 | udp: true
34 | skip-cert-verify: true
35 | rules:
36 | # - MATCH, socks5-noauth
37 | # - MATCH, socks5-auth
38 | - MATCH, socks5-tls
39 | ...
40 |
--------------------------------------------------------------------------------
/clash/tests/data/config/ss.json:
--------------------------------------------------------------------------------
1 | {
2 | "server":"0.0.0.0",
3 | "server_port": 10004,
4 | "password":"FzcLbKs2dY9mhL",
5 | "timeout":300,
6 | "method":"aes-256-gcm",
7 | "nameserver":"1.1.1.1",
8 | "mode":"tcp_and_udp",
9 | "plugin":"v2ray-plugin",
10 | "plugin_opts":"server;tls;host=example.org"
11 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/ss.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8888
3 | socks-port: 8889
4 | mixed-port: 8899
5 |
6 | dns:
7 | enable: true
8 | listen: 127.0.0.1:53533
9 | # ipv6: false # when the false, response to AAAA questions will be empty
10 |
11 | # These nameservers are used to resolve the DNS nameserver hostnames below.
12 | # Specify IP addresses only
13 | default-nameserver:
14 | - 114.114.114.114
15 | - 8.8.8.8
16 | enhanced-mode: fake-ip # or fake-ip
17 | fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR
18 | # use-hosts: true # lookup hosts and return IP record
19 |
20 | # Hostnames in this list will not be resolved with fake IPs
21 | # i.e. questions to these domain names will always be answered with their
22 | # real IP addresses
23 | # fake-ip-filter:
24 | # - '*.lan'
25 | # - localhost.ptlogin2.qq.com
26 |
27 | # Supports UDP, TCP, DoT, DoH. You can specify the port to connect to.
28 | # All DNS questions are sent directly to the nameserver, without proxies
29 | # involved. Clash answers the DNS question with the first result gathered.
30 | nameserver:
31 | - 114.114.114.114 # default value
32 | - 8.8.8.8 # default value
33 | - tls://dns.google:853 # DNS over TLS
34 | - https://1.1.1.1/dns-query # DNS over HTTPS
35 |
36 | allow-lan: true
37 | mode: rule
38 | log-level: debug
39 | external-controller: 127.0.0.1:6170
40 | experimental:
41 | ignore-resolve-fail: true
42 |
43 | proxies:
44 | - name: "ss-01"
45 | type: ss
46 | server: 10.0.0.13
47 | port: 8388
48 | cipher: aes-256-gcm
49 | password: "password"
50 | udp: true
51 | connect-via: ss-02
52 | # dialer-proxy: ss-02
53 |
54 | - name: "ss-02"
55 | type: ss
56 | server: 10.0.0.13
57 | port: 8388
58 | cipher: aes-256-gcm
59 | password: "password"
60 | udp: true
61 |
62 | - name: ss-2022
63 | type: ss
64 | server: 127.0.0.1
65 | port: 8390
66 | cipher: 2022-blake3-aes-256-gcm
67 | password: 3SYJ/f8nmVuzKvKglykRQDSgg10e/ADilkdRWrrY9HU=:4w0GKJ9U3Ox7CIXGU4A3LDQAqP6qrp/tUi/ilpOR9p4=
68 |
69 | proxy-groups:
70 | - name: "udp-relay"
71 | type: relay
72 | proxies:
73 | - ss-01
74 | - ss-02
75 | - ss-2022
76 | rules:
77 | - MATCH, ss-2022
78 |
--------------------------------------------------------------------------------
/clash/tests/data/config/ssh/.ssh/authorized_keys:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCgWVElNdRL4sx7013uQ8FmuWxIrDdYzjuKKc45ef1uEHkORlj3QZ8RAemAF8hiHa9uTL/i79pAdOHPST8nLgPvP37kTIrmxy2wD1D3Gi43UNSBTFlFrcyFORieB0EvgCaRqPueQ4Rj5gOjx9yJ+ald/U41D/I/3bRXNw0BPeUWildnh6zJbcRuYXXq4srFKAlTA9xT0Z/J5c0BVuSd2v5LaZgbnj4+VJtx7VBv4NntL0NCCyMjLt61lltgV0LBm9aY4SPe2xpEn5HBKkNYFr/1aRRnbs9k0Cfe7eC7BJKKEq4ZpYk0d2kGuwXqBrd1Xem12wkvwkOL5SOiQ3mmjWDUAUDyv4YiW65kx83twUMJHmov//ouBrhtMR/aAVBl/6yPzopLThUK1JEMxOBdNE2R4NbnARWL5PUAQTtPKfKq//sSaPiG62+6Vj+Mph+qD2cu1yLoFBw4pk/t5lwXV7IQ20mP0UymOYJ6XxMfquEmkTVN+K8ovfiQtIHiZBvu1P0= vendettareborn@proton.me
2 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMkoG/VIYONdo3B0TRWLuniNViuETe7GnPa4PWac8hTv vendettareborn@proton.me
3 |
--------------------------------------------------------------------------------
/clash/tests/data/config/ssh/.ssh/test_ed25519:
--------------------------------------------------------------------------------
1 | -----BEGIN OPENSSH PRIVATE KEY-----
2 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
3 | QyNTUxOQAAACDJKBv1SGDjXaNwdE0Vi7p4jVYrhE3uxpz2uD1mnPIU7wAAAKBknE6IZJxO
4 | iAAAAAtzc2gtZWQyNTUxOQAAACDJKBv1SGDjXaNwdE0Vi7p4jVYrhE3uxpz2uD1mnPIU7w
5 | AAAED2upkxism+P9SqtaYMqLTyvH0V7KnGL+YpdHCAwsydcskoG/VIYONdo3B0TRWLuniN
6 | ViuETe7GnPa4PWac8hTvAAAAGHZlbmRldHRhcmVib3JuQHByb3Rvbi5tZQECAwQF
7 | -----END OPENSSH PRIVATE KEY-----
8 |
--------------------------------------------------------------------------------
/clash/tests/data/config/tor.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8888
3 | socks-port: 8889
4 | mixed-port: 8899
5 |
6 | mode: rule
7 | log-level: debug
8 | external-controller: 127.0.0.1:6170
9 |
10 |
11 | proxies:
12 | - name: "tor"
13 | type: tor
14 | - name: "ss-02"
15 | type: ss
16 | server: 10.0.0.13
17 | port: 8388
18 | cipher: aes-256-gcm
19 | password: "password"
20 | udp: true
21 |
22 | rules:
23 | - MATCH, tor
24 | ...
25 |
--------------------------------------------------------------------------------
/clash/tests/data/config/tproxy.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | tproxy-port: 8900
3 |
4 | mode: rule
5 | log-level: debug
6 |
7 | rules:
8 | - MATCH, DIRECT
9 | ...
10 |
--------------------------------------------------------------------------------
/clash/tests/data/config/trojan-grpc.json:
--------------------------------------------------------------------------------
1 | {
2 | "inbounds": [
3 | {
4 | "port": 10002,
5 | "listen": "0.0.0.0",
6 | "protocol": "trojan",
7 | "settings": {
8 | "clients": [
9 | {
10 | "password": "example",
11 | "email": "grpc@example.com"
12 | }
13 | ]
14 | },
15 | "streamSettings": {
16 | "network": "grpc",
17 | "security": "tls",
18 | "tlsSettings": {
19 | "certificates": [
20 | {
21 | "certificateFile": "/etc/ssl/v2ray/fullchain.pem",
22 | "keyFile": "/etc/ssl/v2ray/privkey.pem"
23 | }
24 | ]
25 | },
26 | "grpcSettings": {
27 | "serviceName": "example"
28 | }
29 | }
30 | }
31 | ],
32 | "outbounds": [
33 | {
34 | "protocol": "freedom"
35 | }
36 | ],
37 | "log": {
38 | "loglevel": "debug"
39 | }
40 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/trojan-ws.json:
--------------------------------------------------------------------------------
1 | {
2 | "run_type": "server",
3 | "local_addr": "0.0.0.0",
4 | "local_port": 10002,
5 | "disable_http_check": true,
6 | "password": [
7 | "example"
8 | ],
9 | "websocket": {
10 | "enabled": true,
11 | "path": "/",
12 | "host": "example.org"
13 | },
14 | "ssl": {
15 | "verify": true,
16 | "cert": "/fullchain.pem",
17 | "key": "/privkey.pem",
18 | "sni": "example.org"
19 | }
20 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/tuic.json:
--------------------------------------------------------------------------------
1 | {
2 | "server": "0.0.0.0:10002",
3 | "users": {
4 | "00000000-0000-0000-0000-000000000001": "passwd"
5 | },
6 | "certificate": "/opt/tuic/fullchain.pem",
7 | "private_key": "/opt/tuic/privkey.pem",
8 | "ip": "0.0.0.0",
9 | "dual_stack": false,
10 | "congestion_controller": "bbr",
11 | "alpn": [
12 | "h3"
13 | ]
14 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/tun.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8888
3 |
4 | tun:
5 | enable: true
6 | device-id: "dev://utun1989"
7 | route-all: false
8 | gateway: "198.19.0.1/24"
9 | so-mark: 3389
10 | dns-hijack: false
11 | # dns-hijack:
12 | # - 1.1.1.1:53
13 | # routes:
14 | # - 1.1.1.1/32
15 |
16 | rules:
17 | - MATCH, DIRECT
18 |
--------------------------------------------------------------------------------
/clash/tests/data/config/uot.yaml:
--------------------------------------------------------------------------------
1 | proxies:
2 | - name: plain-vmess
3 | type: vmess
4 | server: 10.0.0.13
5 | port: 16823
6 | uuid: b831381d-6324-4d53-ad4f-8cda48b30811
7 | alterId: 0
8 | cipher: auto
9 | udp: true
10 | skip-cert-verify: true
11 |
12 | - name: ws-vmess
13 | type: vmess
14 | server: 10.0.0.13
15 | port: 16824
16 | uuid: b831381d-6324-4d53-ad4f-8cda48b30811
17 | alterId: 0
18 | cipher: auto
19 | udp: true
20 | skip-cert-verify: true
21 | network: ws
22 | ws-opts:
23 | path: /api/v3/download.getFile
24 | headers:
25 | Host: www.amazon.com
26 |
27 | - name: "trojan"
28 | type: trojan
29 | server: 10.0.0.13
30 | port: 9443
31 | password: password1
32 | udp: true
33 | # sni: example.com # aka server name
34 | alpn:
35 | - h2
36 | - http/1.1
37 | skip-cert-verify: true
38 |
--------------------------------------------------------------------------------
/clash/tests/data/config/vmess-grpc.json:
--------------------------------------------------------------------------------
1 | {
2 | "inbounds": [
3 | {
4 | "port": 10002,
5 | "listen": "0.0.0.0",
6 | "protocol": "vmess",
7 | "settings": {
8 | "clients": [
9 | {
10 | "id": "b831381d-6324-4d53-ad4f-8cda48b30811"
11 | }
12 | ]
13 | },
14 | "streamSettings": {
15 | "network": "grpc",
16 | "security": "tls",
17 | "tlsSettings": {
18 | "certificates": [
19 | {
20 | "certificateFile": "/etc/ssl/v2ray/fullchain.pem",
21 | "keyFile": "/etc/ssl/v2ray/privkey.pem"
22 | }
23 | ]
24 | },
25 | "grpcSettings": {
26 | "serviceName": "example!"
27 | }
28 | }
29 | }
30 | ],
31 | "outbounds": [
32 | {
33 | "protocol": "freedom"
34 | }
35 | ],
36 | "log": {
37 | "loglevel": "debug"
38 | }
39 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/vmess-http2.json:
--------------------------------------------------------------------------------
1 | {
2 | "inbounds": [
3 | {
4 | "port": 10002,
5 | "listen": "0.0.0.0",
6 | "protocol": "vmess",
7 | "settings": {
8 | "clients": [
9 | {
10 | "id": "b831381d-6324-4d53-ad4f-8cda48b30811"
11 | }
12 | ]
13 | },
14 | "streamSettings": {
15 | "network": "http",
16 | "security": "tls",
17 | "tlsSettings": {
18 | "certificates": [
19 | {
20 | "certificateFile": "/etc/ssl/v2ray/fullchain.pem",
21 | "keyFile": "/etc/ssl/v2ray/privkey.pem"
22 | }
23 | ]
24 | },
25 | "httpSettings": {
26 | "host": [
27 | "example.org"
28 | ],
29 | "path": "/test"
30 | }
31 | }
32 | }
33 | ],
34 | "outbounds": [
35 | {
36 | "protocol": "freedom"
37 | }
38 | ],
39 | "log": {
40 | "loglevel": "debug"
41 | }
42 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/vmess-ws.json:
--------------------------------------------------------------------------------
1 | {
2 | "inbounds": [
3 | {
4 | "port": 10002,
5 | "listen": "0.0.0.0",
6 | "protocol": "vmess",
7 | "settings": {
8 | "clients": [
9 | {
10 | "id": "b831381d-6324-4d53-ad4f-8cda48b30811"
11 | }
12 | ]
13 | },
14 | "streamSettings": {
15 | "network": "ws",
16 | "security": "tls",
17 | "tlsSettings": {
18 | "certificates": [
19 | {
20 | "certificateFile": "/etc/ssl/v2ray/fullchain.pem",
21 | "keyFile": "/etc/ssl/v2ray/privkey.pem"
22 | }
23 | ]
24 | }
25 | }
26 | }
27 | ],
28 | "outbounds": [
29 | {
30 | "protocol": "freedom"
31 | }
32 | ]
33 | }
--------------------------------------------------------------------------------
/clash/tests/data/config/wg.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | port: 8888
3 | socks-port: 8889
4 | mixed-port: 8899
5 |
6 |
7 | dns:
8 | enable: true
9 | listen: 127.0.0.1:53533
10 | # ipv6: false # when the false, response to AAAA questions will be empty
11 |
12 | # These nameservers are used to resolve the DNS nameserver hostnames below.
13 | # Specify IP addresses only
14 | default-nameserver:
15 | - 114.114.114.114
16 | - 8.8.8.8
17 | enhanced-mode: fake-ip # or fake-ip
18 | fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR
19 | # use-hosts: true # lookup hosts and return IP record
20 |
21 | # Hostnames in this list will not be resolved with fake IPs
22 | # i.e. questions to these domain names will always be answered with their
23 | # real IP addresses
24 | # fake-ip-filter:
25 | # - '*.lan'
26 | # - localhost.ptlogin2.qq.com
27 |
28 | # Supports UDP, TCP, DoT, DoH. You can specify the port to connect to.
29 | # All DNS questions are sent directly to the nameserver, without proxies
30 | # involved. Clash answers the DNS question with the first result gathered.
31 | nameserver:
32 | - 114.114.114.114 # default value
33 | - 8.8.8.8 # default value
34 | - tls://dns.google:853 # DNS over TLS
35 | - https://1.1.1.1/dns-query # DNS over HTTPS
36 |
37 | allow-lan: true
38 | mode: rule
39 | log-level: debug
40 | external-controller: 127.0.0.1:6170
41 | experimental:
42 | ignore-resolve-fail: true
43 |
44 | proxies:
45 | - name: "wg"
46 | type: wireguard
47 | server: engage.cloudflareclient.com
48 | port: 2408
49 | private-key: 0LQye/+HjLvgnXLs5ETQcHe5AcR7G4Bv78xu6Qja230=
50 | ip: 172.16.0.2/32
51 | ipv6: 2606:4700:110:82f3:873f:ed26:e24d:c2cb/128
52 | public-key: bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
53 | allowed-ips: ['0.0.0.0/0', '::/0']
54 | remote-dns-resolve: true
55 | dns:
56 | - 1.1.1.1
57 | udp: true
58 | connect-via: plain-vmess
59 | - name: plain-vmess
60 | type: vmess
61 | server: 10.0.0.13
62 | port: 16823
63 | uuid: b831381d-6324-4d53-ad4f-8cda48b30811
64 | alterId: 0
65 | cipher: auto
66 | udp: true
67 | skip-cert-verify: true
68 |
69 | rules:
70 | - MATCH, wg
71 | ...
72 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/.donoteditthisfile:
--------------------------------------------------------------------------------
1 | ORIG_SERVERURL="127.0.0.1"
2 | ORIG_SERVERPORT="10002"
3 | ORIG_PEERDNS="10.13.13.1"
4 | ORIG_PEERS="1"
5 | ORIG_INTERFACE="10.13.13"
6 | ORIG_ALLOWEDIPS="0.0.0.0/0"
7 | ORIG_PERSISTENTKEEPALIVE_PEERS=""
8 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/coredns/Corefile:
--------------------------------------------------------------------------------
1 | . {
2 | loop
3 | health
4 | forward . /etc/resolv.conf
5 | }
6 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/peer1/peer1.conf:
--------------------------------------------------------------------------------
1 | [Interface]
2 | Address = 10.13.13.2
3 | PrivateKey = KIlDUePHyYwzjgn18przw/ZwPioJhh2aEyhxb/dtCXI=
4 | ListenPort = 51820
5 | DNS = 10.13.13.1
6 |
7 | [Peer]
8 | PublicKey = INBZyvB715sA5zatkiX8Jn3Dh5tZZboZ09x4pkr66ig=
9 | PresharedKey = +JmZErvtDT4ZfQequxWhZSydBV+ItqUcPMHUWY1j2yc=
10 | Endpoint = 127.0.0.1:10002
11 | AllowedIPs = 0.0.0.0/0
12 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/peer1/peer1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash/tests/data/config/wg_config/peer1/peer1.png
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/peer1/presharedkey-peer1:
--------------------------------------------------------------------------------
1 | +JmZErvtDT4ZfQequxWhZSydBV+ItqUcPMHUWY1j2yc=
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/peer1/privatekey-peer1:
--------------------------------------------------------------------------------
1 | KIlDUePHyYwzjgn18przw/ZwPioJhh2aEyhxb/dtCXI=
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/peer1/publickey-peer1:
--------------------------------------------------------------------------------
1 | H7NHC22d44AhrJf7BSzbNJrW1wiTDCRYNfP0rQicM3g=
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/server/privatekey-server:
--------------------------------------------------------------------------------
1 | CA7cMGAh7BF/kD000ZRN+ZXDe1SGd1Z3kqNjQxnCAmQ=
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/server/publickey-server:
--------------------------------------------------------------------------------
1 | INBZyvB715sA5zatkiX8Jn3Dh5tZZboZ09x4pkr66ig=
2 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/templates/peer.conf:
--------------------------------------------------------------------------------
1 | [Interface]
2 | Address = ${CLIENT_IP}
3 | PrivateKey = $(cat /config/${PEER_ID}/privatekey-${PEER_ID})
4 | ListenPort = 51820
5 | DNS = ${PEERDNS}
6 |
7 | [Peer]
8 | PublicKey = $(cat /config/server/publickey-server)
9 | PresharedKey = $(cat /config/${PEER_ID}/presharedkey-${PEER_ID})
10 | Endpoint = ${SERVERURL}:${SERVERPORT}
11 | AllowedIPs = ${ALLOWEDIPS}
12 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/templates/server.conf:
--------------------------------------------------------------------------------
1 | [Interface]
2 | Address = ${INTERFACE}.1
3 | ListenPort = 10002
4 | PrivateKey = $(cat /config/server/privatekey-server)
5 | PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE
6 | PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE
7 |
--------------------------------------------------------------------------------
/clash/tests/data/config/wg_config/wg_confs/wg0.conf:
--------------------------------------------------------------------------------
1 | [Interface]
2 | Address = 10.13.13.1
3 | ListenPort = 10002
4 | PrivateKey = CA7cMGAh7BF/kD000ZRN+ZXDe1SGd1Z3kqNjQxnCAmQ=
5 | PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE
6 | PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE
7 |
8 | [Peer]
9 | # peer1
10 | PublicKey = H7NHC22d44AhrJf7BSzbNJrW1wiTDCRYNfP0rQicM3g=
11 | PresharedKey = +JmZErvtDT4ZfQequxWhZSydBV+ItqUcPMHUWY1j2yc=
12 | AllowedIPs = 10.13.13.2/32
13 |
14 |
--------------------------------------------------------------------------------
/clash/tests/data/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 |
3 | services:
4 | socks5-auth:
5 | image: ghcr.io/wzshiming/socks5/socks5:v0.4.3
6 | network_mode: "host"
7 | command:
8 | - "-u"
9 | - "user"
10 | - "-p"
11 | - "password"
12 | - "-a"
13 | - "0.0.0.0:10801"
14 | restart: unless-stopped
15 |
16 | socks5-noauth:
17 | image: ghcr.io/wzshiming/socks5/socks5:v0.4.3
18 | network_mode: "host"
19 | command:
20 | - "-a"
21 | - "0.0.0.0:10800"
22 | restart: unless-stopped
23 | shadowsocks:
24 | build: ./ss
25 | network_mode: "host"
26 | command: ["-s", "ss://AEAD_AES_256_GCM:password@:8388", "-udp", "-verbose"]
27 | restart: unless-stopped
28 |
29 | v2ray-vmess:
30 | image: v2fly/v2fly-core
31 | environment:
32 | - V2RAY_VMESS_AEAD_FORCED=false
33 | network_mode: "host"
34 | command: ["run", "-c", "/etc/v2ray/config.json"]
35 | volumes:
36 | - type: bind
37 | source: ./v2ray/config.json
38 | target: /etc/v2ray/config.json
39 | - type: bind
40 | source: ./v2ray/cert.pem
41 | target: /etc/v2ray/v2ray.crt
42 | - type: bind
43 | source: ./v2ray/key.pem
44 | target: /etc/v2ray/v2ray.key
45 | restart: unless-stopped
46 |
47 | nginx:
48 | image: nginx
49 | network_mode: "host"
50 | volumes:
51 | - type: bind
52 | source: ./nginx/nginx.conf
53 | target: /etc/nginx/nginx.conf
54 | - type: bind
55 | source: ./v2ray/cert.pem
56 | target: /etc/v2ray/v2ray.crt
57 | - type: bind
58 | source: ./v2ray/key.pem
59 | target: /etc/v2ray/v2ray.key
60 | restart: unless-stopped
61 |
62 | hysteria2:
63 | image: tobyxdd/hysteria
64 | network_mode: "host"
65 | command:
66 | - server
67 | - "-c"
68 | - "/etc/hysteria/config.yaml"
69 | volumes:
70 | - type: bind
71 | source: ./hysteria2/config.yaml
72 | target: /etc/hysteria/config.yaml
73 | - type: bind
74 | source: ./v2ray/cert.pem
75 | target: /etc/hysteria/cert.pem
76 | - type: bind
77 | source: ./v2ray/key.pem
78 | target: /etc/hysteria/key.pem
79 | restart: unless-stopped
--------------------------------------------------------------------------------
/clash/tests/data/docker/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | events {
2 | worker_connections 4096; ## Default: 1024
3 | }
4 |
5 | http {
6 | error_log /tmp/error.log debug;
7 |
8 | server {
9 | listen 19443 ssl;
10 | server_name localhost;
11 | http2 on;
12 |
13 | ssl_certificate /etc/v2ray/v2ray.crt;
14 | ssl_certificate_key /etc/v2ray/v2ray.key;
15 | ssl_protocols TLSv1.2 TLSv1.3;
16 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
17 |
18 |
19 | location /abc/Tun {
20 | grpc_pass grpc://127.0.0.1:16825;
21 | }
22 |
23 | location /def/Tun {
24 | grpc_pass grpc://127.0.0.1:9444;
25 | }
26 | }
27 | }
28 |
29 | stream {
30 |
31 | server {
32 | listen 10802 ssl;
33 |
34 | ssl_certificate /etc/v2ray/v2ray.crt;
35 | ssl_certificate_key /etc/v2ray/v2ray.key;
36 | ssl_protocols TLSv1.2 TLSv1.3;
37 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
38 |
39 | proxy_pass 127.0.0.1:10801;
40 | }
41 | }
--------------------------------------------------------------------------------
/clash/tests/data/docker/ss/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.19
2 |
3 | RUN go install github.com/shadowsocks/go-shadowsocks2@latest
4 |
5 | ENTRYPOINT ["go-shadowsocks2"]
--------------------------------------------------------------------------------
/clash/tests/data/docker/ss/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "servers": [
3 | {
4 | // AEAD-2022
5 | "server": "::",
6 | "mode": "tcp_and_udp",
7 | "server_port": 8390,
8 | "method": "2022-blake3-aes-256-gcm",
9 | "password": "3SYJ/f8nmVuzKvKglykRQDSgg10e/ADilkdRWrrY9HU=",
10 | // For Server (OPTIONAL)
11 | // Support multiple users with Extensible Identity Header
12 | // https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md
13 | "users": [
14 | {
15 | "name": "username",
16 | // User's password must have the same length as server's password
17 | "password": "4w0GKJ9U3Ox7CIXGU4A3LDQAqP6qrp/tUi/ilpOR9p4="
18 | }
19 | ],
20 | }
21 | ],
22 | }
--------------------------------------------------------------------------------
/clash/tests/data/docker/v2ray/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDLzCCAhegAwIBAgIQAc1RNqU2laok+DH4GTtUGDANBgkqhkiG9w0BAQsFADAS
3 | MRAwDgYDVQQKEwdBY21lIENvMB4XDTIzMDgxODEwMjU1MloXDTI0MDgxNzEwMjU1
4 | MlowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
5 | AQoCggEBAKwY24NJm0blObfiZP99h63u7Oy+jvOBqZ15DU4nF0G8xJ6bcmIsBREN
6 | XQ1kVL861MH7wTPwRG62GWZTuFGrBeag/D1LW8Zx+aHMK5ndHI/Mks6sZ0YwMdK1
7 | KrmJlqiLtb947dQoKEBGk12qA6p8U+Ywbmv6nTVs/r7zG4srqGJSnf5qgmdUAP4K
8 | +tRTsJZ5IP5rJ6+tK7Qp9HwKM9L/I+JAz4Ehwujt9nKtKTHLHv/ObcK4eUEtBfKV
9 | VbxsFeX0G/Su0fDX1M/TVGVMCzFD/rSt1tjzOaZW30HqRD6ZpGFvpOtfZeCiUyRM
10 | Yp8m5mrs2B+LjqMabLfuD2hLJrlATzUCAwEAAaOBgDB+MA4GA1UdDwEB/wQEAwIC
11 | pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
12 | BBTCLqiC1GarCl9QBJBN7Ghwl1dzRzAnBgNVHREEIDAeghxsb2NhbC12MnJheS10
13 | ZXN0LmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBiOkEsKAqghSmgGqKq
14 | E648J2JFm3RU8RQ6h4O+oYiuD2y++v5XfEwvaUVy9v9OkZZNMT2nk2Z5E3ecRL4d
15 | Ajd8sFutLJa4L4xz19OPbhwpQqNTqwgUGsRW4y0OJI0baY1hx8YmGW2vBJTB78bA
16 | e9P12HNJXz0D8iumCwSir2oxTamA89q8vRiHxlchhT11BJPf8o+OEuXhzJezku0H
17 | eMLUwPLGIz1XA89ZHExshcgyshQo3Kx25iRRmvhW4sc7ho/XriF7C3CHvSPo1/23
18 | nS0bv6pFFeOZrOPmsP+x96H9i5njNax5NX/YbYhh6bqJ8cAMh7tVBVcKhSximIFB
19 | 2fG/
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/clash/tests/data/docker/v2ray/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsGNuDSZtG5Tm3
3 | 4mT/fYet7uzsvo7zgamdeQ1OJxdBvMSem3JiLAURDV0NZFS/OtTB+8Ez8ERuthlm
4 | U7hRqwXmoPw9S1vGcfmhzCuZ3RyPzJLOrGdGMDHStSq5iZaoi7W/eO3UKChARpNd
5 | qgOqfFPmMG5r+p01bP6+8xuLK6hiUp3+aoJnVAD+CvrUU7CWeSD+ayevrSu0KfR8
6 | CjPS/yPiQM+BIcLo7fZyrSkxyx7/zm3CuHlBLQXylVW8bBXl9Bv0rtHw19TP01Rl
7 | TAsxQ/60rdbY8zmmVt9B6kQ+maRhb6TrX2XgolMkTGKfJuZq7Ngfi46jGmy37g9o
8 | Sya5QE81AgMBAAECggEAakvEMdgh520n9FMKbN/9EMp1Xljo9LCOsiwVssLkU38j
9 | to9u3AIycvDdG6tvyNmulc5I7CqoKfWhxJlLTG4k6+ldQwKrweud83inKZbv0EXc
10 | G3lTJIAaFfo+VHEONDZu4L/xrcvL6L9uwDiFoSS/sXsSiPE3bstOoWSJC7HAhFFd
11 | eJbZkZQ9cNX35XuRixyPHDELwoczGjuyljEWZoQZTXJm0doH+lEd3uRlLWzV7Euw
12 | Eb8elTZnV7OhUWfeqlrnHDad5fNKaTyu9ei/zcgTYq6YlJ+4fSnJUUZKPddoaw9P
13 | l9tDs8Y44uaA4QUY+Ij0xu4HTWsSrWi7gThV35aGlQKBgQDecKwS0dgpcCd81/S9
14 | u+uaOs3u9js0giPxma8m68AxcaspnQvXct8CBgfU3u1QI1IzkzEYWEfqUZeMRkVs
15 | IHhvM28UertupDHLfTs0Te0ysW/Oy3QNfhV1EoG4fYarhaqGhxIPu+7Rt8v4WEJW
16 | e+N12E4jQ8mx3cIh8p9xeS/oqwKBgQDGD8gMOhsK62JO2sLDrtuauz1lhzfV1Qhg
17 | r7nD5GP20A68sDcFpdMzsTsWbEO9icxFbwxuxtn8gak+eQ8a1dJIYBjqKf2pL3ND
18 | 5HGderRu1rnVabWA6NPk+G8bdA81IDNFSpNswJuFDzw1lg3HDVLzvlO8fanDJyeA
19 | SltZ7aZnnwKBgQCd2n+Ca4BnB7w+EFMSQkWUEZ8KsZqaTLCNR27QxASEEhJRWa2J
20 | m28+1GDCY+EtOaOgDhiNGjkOxBAz77pcXT6aS3nMorxYbBUaPyjAmXx2uQyLSD53
21 | RL6dciC0eAAVwKmfBkN+/vMfyLrq5ldNYGWuv23UAMsleiXGSZN0x3eEOQKBgB5z
22 | drJKjLXVErxE7gTf8WuMthfR/kemBS+4VLtFdgkQW/OutAbuQ9aCvS7pXlDZysoy
23 | FJtDf2hPFxI/0o6xqS7vd2UpJ5LHdNVPXhh0MSGJafDh28ICCfH+MDbsVRo55SgW
24 | GyxxQHfoq70hYOTlq4dGD+G/AEa80lnrFLhyzU7JAoGAXKPEEjWBqBh7NZyIOzoc
25 | 1IZYruqwGVmpxQnwl+ThQ5iYI+EsXqRoUxajosHug3Db2LdYzKzoPLz3oTBXHtjl
26 | e4WRpbTt0Cubu2tupswtaMIRAUYB2w3IxOHkXY7FHTE+3OKd7kF4faJDJ5Tmjd5A
27 | wy+P6ptS0zfps19eklKsJcg=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/clash/tests/data/docker/wg/wg0.conf:
--------------------------------------------------------------------------------
1 | [Interface]
2 | Address = 192.168.2.2/24
3 | PrivateKey = 2AS8PSccSenWrws5ExglmpwjVBub9Oy9X3zOlk6heHU=
4 | DNS = 1.1.1.1
5 |
6 | [Peer]
7 | PublicKey = MAZPwQBniuXmQf5w8BwM3owlO7Kw07rzyZUXxOvsF3w=
8 | Endpoint = 10.0.0.17:51820
9 | AllowedIPs = 0.0.0.0/0, ::/0
--------------------------------------------------------------------------------
/clash_doc/BUILD.bazel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Watfaq/clash-rs/21f880729f0bbcd4c3f4fda5a8b64b2f0253ad58/clash_doc/BUILD.bazel
--------------------------------------------------------------------------------
/clash_doc/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "clash_doc"
3 | repository = { workspace = true }
4 | version = { workspace = true }
5 | edition = { workspace = true }
6 |
7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8 |
9 | [dependencies]
10 | clash_lib = { path = "../clash_lib", version = "*" }
--------------------------------------------------------------------------------
/clash_doc/src/lib.rs:
--------------------------------------------------------------------------------
1 | #[doc = "docs for clash"]
2 | #[doc(inline)]
3 | pub use clash_lib::ClashConfigDef;
4 | #[doc(inline)]
5 | pub use clash_lib::ClashDNSConfigDef;
6 |
--------------------------------------------------------------------------------
/clash_ffi/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "clash_ffi"
3 | repository = { workspace = true }
4 | version = { workspace = true }
5 | edition = { workspace = true }
6 |
7 | [dependencies]
8 | clash_lib = { path = "../clash_lib", default-features = false, features = ["shadowsocks", "tuic", "ssh", "zero_copy"] }
9 |
10 | [lib]
11 | name = "clashrs"
12 | crate-type = ["staticlib", "cdylib"]
13 |
14 |
--------------------------------------------------------------------------------
/clash_ffi/cbindgen.toml:
--------------------------------------------------------------------------------
1 | language = "C"
2 |
3 | [export]
4 | include = ["clash_start", "clash_shutdown", "clash_free_string"]
5 |
6 | [parse]
7 | parse_deps = false
8 | include = ["clash_ffi"]
--------------------------------------------------------------------------------
/clash_ffi/src/lib.rs:
--------------------------------------------------------------------------------
1 | use clash_lib::{Config, Options, TokioRuntime, shutdown, start_scaffold};
2 | use std::{
3 | ffi::{CStr, CString},
4 | os::raw::{c_char, c_int},
5 | };
6 |
7 | /// # Safety
8 | /// This function is unsafe because it dereferences raw pointers.
9 | #[unsafe(no_mangle)]
10 | pub unsafe extern "C" fn clash_start(
11 | config: *const c_char,
12 | log: *const c_char,
13 | cwd: *const c_char,
14 | multithread: c_int,
15 | ) -> *mut c_char {
16 | unsafe {
17 | let config_str = CStr::from_ptr(config)
18 | .to_str()
19 | .unwrap_or_default()
20 | .to_string();
21 | let log_str = CStr::from_ptr(log).to_str().unwrap_or_default().to_string();
22 | let cwd_str = CStr::from_ptr(cwd).to_str().unwrap_or_default().to_string();
23 |
24 | let rt = if multithread != 0 {
25 | Some(TokioRuntime::MultiThread)
26 | } else {
27 | Some(TokioRuntime::SingleThread)
28 | };
29 |
30 | let options = Options {
31 | config: Config::Str(config_str),
32 | cwd: Some(cwd_str),
33 | rt,
34 | log_file: Some(log_str),
35 | };
36 |
37 | match start_scaffold(options) {
38 | Ok(_) => CString::new("").unwrap().into_raw(),
39 | Err(e) => CString::new(format!("Error: {}", e)).unwrap().into_raw(),
40 | }
41 | }
42 | }
43 |
44 | #[unsafe(no_mangle)]
45 | pub extern "C" fn clash_shutdown() -> c_int {
46 | if shutdown() {
47 | 1 // Success
48 | } else {
49 | 0 // Failure
50 | }
51 | }
52 |
53 | /// # Safety
54 | /// This function is unsafe because it dereferences raw pointers.
55 | #[unsafe(no_mangle)]
56 | #[allow(unused_must_use)]
57 | pub unsafe extern "C" fn clash_free_string(s: *mut c_char) {
58 | if s.is_null() {
59 | return;
60 | }
61 | unsafe {
62 | CString::from_raw(s);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/clash_lib/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | Cargo.lock
3 |
--------------------------------------------------------------------------------
/clash_lib/build.rs:
--------------------------------------------------------------------------------
1 | fn main() -> std::io::Result<()> {
2 | println!("cargo::rustc-check-cfg=cfg(docker_test)");
3 | println!("cargo:rerun-if-env-changed=CLASH_DOCKER_TEST");
4 | if let Some("1" | "true") = option_env!("CLASH_DOCKER_TEST") {
5 | println!("cargo::rustc-cfg=docker_test");
6 | }
7 |
8 | println!("cargo:rerun-if-changed=src/common/geodata/geodata.proto");
9 | prost_build::compile_protos(
10 | &["src/common/geodata/geodata.proto"],
11 | &["src/common/geodata"],
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/hello.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use axum::response::IntoResponse;
4 |
5 | pub async fn handle() -> axum::response::Response {
6 | let mut val = HashMap::new();
7 | val.insert("hello".to_owned(), "clash-rs".to_owned());
8 | axum::response::Json(val).into_response()
9 | }
10 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/log.rs:
--------------------------------------------------------------------------------
1 | use std::{net::SocketAddr, sync::Arc};
2 |
3 | use axum::{
4 | extract::{ConnectInfo, State, WebSocketUpgrade, ws::Message},
5 | response::IntoResponse,
6 | };
7 |
8 | use tracing::warn;
9 |
10 | use crate::app::api::AppState;
11 |
12 | pub async fn handle(
13 | ws: WebSocketUpgrade,
14 | ConnectInfo(addr): ConnectInfo,
15 | State(state): State>,
16 | ) -> impl IntoResponse {
17 | ws.on_failed_upgrade(move |e| {
18 | warn!("ws upgrade error: {} with {}", e, addr);
19 | })
20 | .on_upgrade(move |mut socket| async move {
21 | let mut rx = state.log_source_tx.subscribe();
22 | while let Ok(evt) = rx.recv().await {
23 | let res = serde_json::to_vec(&evt).unwrap();
24 |
25 | if let Err(e) = socket
26 | .send(Message::Text(String::from_utf8(res).unwrap().into()))
27 | .await
28 | {
29 | warn!("ws send error: {}", e);
30 | break;
31 | }
32 | }
33 | })
34 | }
35 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/memory.rs:
--------------------------------------------------------------------------------
1 | use std::sync::Arc;
2 |
3 | use axum::{
4 | Json,
5 | body::Body,
6 | extract::{FromRequest, Query, Request, State, WebSocketUpgrade, ws::Message},
7 | response::IntoResponse,
8 | };
9 | use http::HeaderMap;
10 | use serde::{Deserialize, Serialize};
11 | use tracing::{debug, warn};
12 |
13 | use crate::app::api::AppState;
14 |
15 | use super::utils::is_request_websocket;
16 |
17 | #[derive(Deserialize)]
18 | pub struct GetMemoryQuery {
19 | interval: Option,
20 | }
21 |
22 | #[derive(Serialize)]
23 | struct GetMemoryResponse {
24 | inuse: usize,
25 | oslimit: usize,
26 | }
27 | pub async fn handle(
28 | headers: HeaderMap,
29 | State(state): State>,
30 | q: Query,
31 | req: Request,
32 | ) -> impl IntoResponse {
33 | if !is_request_websocket(headers) {
34 | let mgr = state.statistics_manager.clone();
35 | let snapshot = GetMemoryResponse {
36 | inuse: mgr.memory_usage(),
37 | oslimit: 0,
38 | };
39 | return Json(snapshot).into_response();
40 | }
41 |
42 | let ws = match WebSocketUpgrade::from_request(req, &state).await {
43 | Ok(ws) => ws,
44 | Err(e) => {
45 | warn!("ws upgrade error: {}", e);
46 | return e.into_response();
47 | }
48 | };
49 |
50 | ws.on_failed_upgrade(|e| {
51 | warn!("ws upgrade error: {}", e);
52 | })
53 | .on_upgrade(move |mut socket| async move {
54 | let interval = q.interval;
55 |
56 | let mgr = state.statistics_manager.clone();
57 |
58 | loop {
59 | let snapshot = GetMemoryResponse {
60 | inuse: mgr.memory_usage(),
61 | oslimit: 0,
62 | };
63 | let j = serde_json::to_vec(&snapshot).unwrap();
64 | let body = String::from_utf8(j).unwrap();
65 |
66 | if let Err(e) = socket.send(Message::Text(body.into())).await {
67 | debug!("send memory snapshot failed: {}", e);
68 | break;
69 | }
70 |
71 | tokio::time::sleep(tokio::time::Duration::from_secs(
72 | interval.unwrap_or(1),
73 | ))
74 | .await;
75 | }
76 | })
77 | }
78 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod config;
2 | pub mod connection;
3 | pub mod dns;
4 | pub mod hello;
5 | pub mod log;
6 | pub mod memory;
7 | pub mod provider;
8 | pub mod proxy;
9 | pub mod restart;
10 | pub mod rule;
11 | pub mod traffic;
12 | pub mod version;
13 |
14 | mod utils;
15 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/restart.rs:
--------------------------------------------------------------------------------
1 | #[cfg(unix)]
2 | use std::os::unix::process::CommandExt;
3 |
4 | use axum::{Json, response::IntoResponse};
5 | use serde_json::Map;
6 |
7 | pub async fn handle() -> impl IntoResponse {
8 | match std::env::current_exe() {
9 | Ok(exec) => {
10 | let mut map = Map::new();
11 | map.insert("status".to_owned(), "ok".into());
12 | tokio::spawn(async move {
13 | tokio::time::sleep(std::time::Duration::from_secs(1)).await;
14 |
15 | #[cfg(unix)]
16 | {
17 | use tracing::info;
18 |
19 | let err = std::process::Command::new(exec)
20 | .args(std::env::args().skip(1))
21 | .envs(std::env::vars())
22 | .exec();
23 | info!("process restarted: {}", err);
24 | }
25 | #[cfg(windows)]
26 | {
27 | use tracing::error;
28 |
29 | match std::process::Command::new(exec)
30 | .args(std::env::args().skip(1))
31 | .envs(std::env::vars())
32 | .stdin(std::process::Stdio::inherit())
33 | .stdout(std::process::Stdio::inherit())
34 | .stderr(std::process::Stdio::inherit())
35 | .spawn()
36 | {
37 | Ok(_) => {
38 | // exit the current process
39 | std::process::exit(0);
40 | }
41 | Err(e) => {
42 | error!("Failed to restart: {}", e);
43 | }
44 | }
45 | }
46 | });
47 | Json(map).into_response()
48 | }
49 | Err(e) => {
50 | (http::StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response()
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/rule.rs:
--------------------------------------------------------------------------------
1 | use std::{collections::HashMap, sync::Arc};
2 |
3 | use axum::{Router, extract::State, response::IntoResponse, routing::get};
4 |
5 | use crate::app::{api::AppState, router::ThreadSafeRouter};
6 |
7 | #[derive(Clone)]
8 | struct RuleState {
9 | router: ThreadSafeRouter,
10 | }
11 |
12 | pub fn routes(router: ThreadSafeRouter) -> Router> {
13 | Router::new()
14 | .route("/", get(get_rules))
15 | .with_state(RuleState { router })
16 | }
17 |
18 | async fn get_rules(State(state): State) -> impl IntoResponse {
19 | let rules = state.router.get_all_rules();
20 | let mut r = HashMap::new();
21 | r.insert(
22 | "rules",
23 | rules.iter().map(|r| r.as_map()).collect::>(),
24 | );
25 | axum::response::Json(r)
26 | }
27 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/traffic.rs:
--------------------------------------------------------------------------------
1 | use std::{net::SocketAddr, sync::Arc};
2 |
3 | use axum::{
4 | extract::{ConnectInfo, State, WebSocketUpgrade, ws::Message},
5 | response::IntoResponse,
6 | };
7 |
8 | use serde::Serialize;
9 | use tracing::warn;
10 |
11 | use crate::app::api::AppState;
12 |
13 | #[derive(Serialize)]
14 | struct TrafficResponse {
15 | up: u64,
16 | down: u64,
17 | }
18 | pub async fn handle(
19 | ws: WebSocketUpgrade,
20 | ConnectInfo(addr): ConnectInfo,
21 | State(state): State>,
22 | ) -> impl IntoResponse {
23 | ws.on_failed_upgrade(move |e| {
24 | warn!("ws upgrade error: {} with {}", e, addr);
25 | })
26 | .on_upgrade(move |mut socket| async move {
27 | let mgr = state.statistics_manager.clone();
28 | loop {
29 | let (up, down) = mgr.now();
30 | let res = TrafficResponse { up, down };
31 | let j = serde_json::to_vec(&res).unwrap();
32 |
33 | if let Err(e) = socket
34 | .send(Message::Text(String::from_utf8(j).unwrap().into()))
35 | .await
36 | {
37 | warn!("ws send error: {}", e);
38 | break;
39 | }
40 |
41 | tokio::time::sleep(std::time::Duration::from_secs(1)).await;
42 | }
43 | })
44 | }
45 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/utils.rs:
--------------------------------------------------------------------------------
1 | use http::{HeaderMap, header};
2 |
3 | pub fn is_request_websocket(header: HeaderMap) -> bool {
4 | header
5 | .get(header::CONNECTION)
6 | .and_then(|x| x.to_str().ok().map(|x| x.to_ascii_lowercase()))
7 | // Firefox sends "Connection: keep-alive, Upgrade"
8 | .is_some_and(|x| x.contains(&"upgrade".to_ascii_lowercase()))
9 | && header
10 | .get(header::UPGRADE)
11 | .and_then(|x| x.to_str().ok().map(|x| x.to_ascii_lowercase()))
12 | == Some("websocket".to_ascii_lowercase())
13 | }
14 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/handlers/version.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use axum::response::IntoResponse;
4 |
5 | const VERSION: &str = env!("CARGO_PKG_VERSION");
6 |
7 | pub async fn handle() -> impl IntoResponse {
8 | let mut val = HashMap::new();
9 | val.insert("version".to_owned(), VERSION.to_owned());
10 | axum::response::Json(val)
11 | }
12 |
--------------------------------------------------------------------------------
/clash_lib/src/app/api/middlewares/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod auth;
2 |
--------------------------------------------------------------------------------
/clash_lib/src/app/dispatcher/mod.rs:
--------------------------------------------------------------------------------
1 | mod dispatcher_impl;
2 | mod statistics_manager;
3 | mod tracked;
4 |
5 | pub use dispatcher_impl::Dispatcher;
6 | pub use statistics_manager::Manager as StatisticsManager;
7 | #[allow(unused)]
8 | pub use tracked::{
9 | BoxedChainedDatagram, BoxedChainedStream, ChainedDatagram,
10 | ChainedDatagramWrapper, ChainedStream, ChainedStreamWrapper, TrackCopy,
11 | TrackedStream,
12 | };
13 |
--------------------------------------------------------------------------------
/clash_lib/src/app/dns/fakeip/file_store.rs:
--------------------------------------------------------------------------------
1 | use async_trait::async_trait;
2 |
3 | use crate::app::profile::ThreadSafeCacheFile;
4 |
5 | use super::Store;
6 |
7 | pub struct FileStore(ThreadSafeCacheFile);
8 |
9 | impl FileStore {
10 | pub fn new(store: ThreadSafeCacheFile) -> Self {
11 | Self(store)
12 | }
13 | }
14 |
15 | #[async_trait]
16 | impl Store for FileStore {
17 | async fn get_by_host(&mut self, host: &str) -> Option {
18 | self.0
19 | .get_fake_ip(host)
20 | .await
21 | .and_then(|ip| ip.parse().ok())
22 | }
23 |
24 | async fn pub_by_host(&mut self, host: &str, ip: std::net::IpAddr) {
25 | self.0.set_host_to_ip(host, &ip.to_string()).await;
26 | }
27 |
28 | async fn get_by_ip(&mut self, ip: std::net::IpAddr) -> Option {
29 | self.0.get_fake_ip(&ip.to_string()).await
30 | }
31 |
32 | async fn put_by_ip(&mut self, ip: std::net::IpAddr, host: &str) {
33 | self.0.set_ip_to_host(&ip.to_string(), host).await;
34 | }
35 |
36 | async fn del_by_ip(&mut self, ip: std::net::IpAddr) {
37 | let host = self.get_by_ip(ip).await.unwrap_or_default();
38 | self.0.delete_fake_ip_pair(&ip.to_string(), &host).await;
39 | }
40 |
41 | async fn exist(&mut self, ip: std::net::IpAddr) -> bool {
42 | self.0.get_fake_ip(&ip.to_string()).await.is_some()
43 | }
44 |
45 | async fn copy_to(&self, #[allow(unused)] store: &mut Box) {
46 | // NO-OP
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/clash_lib/src/app/dns/fakeip/mem_store.rs:
--------------------------------------------------------------------------------
1 | use std::net::IpAddr;
2 |
3 | use async_trait::async_trait;
4 |
5 | use super::Store;
6 |
7 | pub struct InMemStore {
8 | itoh: lru_time_cache::LruCache,
9 | htoi: lru_time_cache::LruCache,
10 | }
11 |
12 | impl InMemStore {
13 | pub fn new(size: usize) -> Self {
14 | Self {
15 | itoh: lru_time_cache::LruCache::with_capacity(size),
16 | htoi: lru_time_cache::LruCache::with_capacity(size),
17 | }
18 | }
19 | }
20 |
21 | #[async_trait]
22 | impl Store for InMemStore {
23 | async fn get_by_host(&mut self, host: &str) -> Option {
24 | self.htoi.get_mut(host).map(|ip| {
25 | self.itoh.get_mut(ip);
26 | *ip
27 | })
28 | }
29 |
30 | async fn pub_by_host(&mut self, host: &str, ip: std::net::IpAddr) {
31 | self.htoi.insert(host.into(), ip);
32 | }
33 |
34 | async fn get_by_ip(&mut self, ip: std::net::IpAddr) -> Option {
35 | self.itoh.get_mut(&ip).map(|h| {
36 | self.htoi.get_mut(h);
37 | h.to_string()
38 | })
39 | }
40 |
41 | async fn put_by_ip(&mut self, ip: std::net::IpAddr, host: &str) {
42 | self.itoh.insert(ip, host.into());
43 | }
44 |
45 | async fn del_by_ip(&mut self, ip: std::net::IpAddr) {
46 | if let Some(host) = self.itoh.remove(&ip) {
47 | self.htoi.remove(&host);
48 | }
49 | }
50 |
51 | async fn exist(&mut self, ip: std::net::IpAddr) -> bool {
52 | self.itoh.contains_key(&ip)
53 | }
54 |
55 | async fn copy_to(&self, #[allow(unused)] store: &mut Box) {
56 | // TODO: copy
57 | // NOTE: use file based persistence store
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/clash_lib/src/app/dns/filters.rs:
--------------------------------------------------------------------------------
1 | use std::{net, sync::Arc};
2 |
3 | use crate::common::{mmdb::Mmdb, trie};
4 |
5 | pub trait FallbackIPFilter: Sync + Send {
6 | fn apply(&self, ip: &net::IpAddr) -> bool;
7 | }
8 |
9 | pub struct GeoIPFilter(String, Arc);
10 |
11 | impl GeoIPFilter {
12 | pub fn new(code: &str, mmdb: Arc) -> Self {
13 | Self(code.to_owned(), mmdb)
14 | }
15 | }
16 |
17 | impl FallbackIPFilter for GeoIPFilter {
18 | fn apply(&self, ip: &net::IpAddr) -> bool {
19 | self.1
20 | .lookup_country(*ip)
21 | .map(|x| x.country)
22 | .is_ok_and(|x| x.is_some_and(|x| x.iso_code == Some(self.0.as_str())))
23 | }
24 | }
25 |
26 | pub struct IPNetFilter(ipnet::IpNet);
27 |
28 | impl IPNetFilter {
29 | pub fn new(ipnet: ipnet::IpNet) -> Self {
30 | Self(ipnet)
31 | }
32 | }
33 |
34 | impl FallbackIPFilter for IPNetFilter {
35 | fn apply(&self, ip: &net::IpAddr) -> bool {
36 | self.0.contains(ip)
37 | }
38 | }
39 |
40 | pub trait FallbackDomainFilter: Sync + Send {
41 | fn apply(&self, domain: &str) -> bool;
42 | }
43 |
44 | pub struct DomainFilter(trie::StringTrie