From ca42ca2ca8c6d7541c3cd1a7855cd97ed2412d57 Mon Sep 17 00:00:00 2001 From: Birkhoff Lee Date: Mon, 15 May 2023 21:47:01 +0800 Subject: [PATCH] Docs: new documentation site (#2723) This commit adds a VitePress build to the main repository, aiming to ditch GitHub Wiki. Moving further, we're going to host our own documentation site eithor on GitHub Pages or something alike. --- .github/workflows/deploy-docs.yml | 42 ++ .gitignore | 11 + docs/.vitepress/config.ts | 104 ++++ docs/advanced-usages/golang-api.md | 59 +++ docs/advanced-usages/openconnect.md | 93 ++++ docs/advanced-usages/wireguard.md | 40 ++ docs/assets/connection-flow.png | Bin 0 -> 80006 bytes docs/configuration/configuration-reference.md | 480 ++++++++++++++++++ docs/configuration/dns.md | 72 +++ docs/configuration/getting-started.md | 64 +++ docs/configuration/inbound.md | 69 +++ docs/configuration/introduction.md | 38 ++ docs/configuration/outbound.md | 432 ++++++++++++++++ docs/configuration/rules.md | 153 ++++++ docs/index.md | 38 ++ docs/introduction/_dummy-index.md | 6 + docs/introduction/faq.md | 73 +++ docs/introduction/getting-started.md | 50 ++ docs/introduction/service.md | 132 +++++ docs/package.json | 13 + docs/premium/ebpf.md | 22 + docs/premium/experimental-features.md | 19 + docs/premium/introduction.md | 26 + docs/premium/rule-providers.md | 100 ++++ docs/premium/script-shortcuts.md | 38 ++ docs/premium/script.md | 70 +++ docs/premium/the-profiling-engine.md | 13 + docs/premium/tun-device.md | 65 +++ docs/premium/userspace-wireguard.md | 25 + docs/runtime/external-controller.md | 130 +++++ 30 files changed, 2477 insertions(+) create mode 100644 .github/workflows/deploy-docs.yml create mode 100644 docs/.vitepress/config.ts create mode 100644 docs/advanced-usages/golang-api.md create mode 100644 docs/advanced-usages/openconnect.md create mode 100644 docs/advanced-usages/wireguard.md create mode 100644 docs/assets/connection-flow.png create mode 100644 docs/configuration/configuration-reference.md create mode 100644 docs/configuration/dns.md create mode 100644 docs/configuration/getting-started.md create mode 100644 docs/configuration/inbound.md create mode 100644 docs/configuration/introduction.md create mode 100644 docs/configuration/outbound.md create mode 100644 docs/configuration/rules.md create mode 100644 docs/index.md create mode 100644 docs/introduction/_dummy-index.md create mode 100644 docs/introduction/faq.md create mode 100644 docs/introduction/getting-started.md create mode 100644 docs/introduction/service.md create mode 100644 docs/package.json create mode 100644 docs/premium/ebpf.md create mode 100644 docs/premium/experimental-features.md create mode 100644 docs/premium/introduction.md create mode 100644 docs/premium/rule-providers.md create mode 100644 docs/premium/script-shortcuts.md create mode 100644 docs/premium/script.md create mode 100644 docs/premium/the-profiling-engine.md create mode 100644 docs/premium/tun-device.md create mode 100644 docs/premium/userspace-wireguard.md create mode 100644 docs/runtime/external-controller.md diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..baeabc5 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,42 @@ +name: Deploy +on: + workflow_dispatch: {} + push: + branches: + - master +jobs: + deploy: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20] + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: pnpm/action-setup@v2 + with: + version: latest + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Install dependencies + working-directory: docs + run: pnpm install --frozen-lockfile=false + - name: Build + working-directory: docs + run: pnpm run docs:build + - uses: actions/configure-pages@v2 + - uses: actions/upload-pages-artifact@v1 + with: + path: docs/.vitepress/dist + - name: Deploy + id: deployment + uses: actions/deploy-pages@v1 diff --git a/.gitignore b/.gitignore index 52efcc9..f4a739e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,14 @@ vendor # test suite test/config/cache* + +# docs site generator +node_modules +package-lock.json +pnpm-lock.yaml + +# docs site cache +docs/.vitepress/cache + +# docs site build files +docs/.vitepress/dist diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts new file mode 100644 index 0000000..ff4158e --- /dev/null +++ b/docs/.vitepress/config.ts @@ -0,0 +1,104 @@ +import { defineConfig } from 'vitepress' +import directoryTree from 'directory-tree' +import fs from 'fs' +import metadataParser from 'markdown-yaml-metadata-parser' + +function getMetadataFromDoc(path: string): { sidebarTitle?: string, sidebarOrder?: number } { + const fileContents = fs.readFileSync(path, 'utf8') + + return metadataParser(fileContents).metadata +} + +function generateSidebarChapter(chapterDirName: string): any { + const chapterPath = `./docs/${chapterDirName}` + const tree = directoryTree(chapterPath) + + if (!tree || !tree.children) { + console.error(tree) + throw new Error(`Could not genereate sidebar: invalid chapter at ${chapterPath}`) + } + + let items: { sidebarOrder: number, text: string, link: string }[] = [] + + // Look into files in the chapter + for (const doc of tree.children) { + // make sure it's a .md file + if (doc.children || !doc.name.endsWith('.md')) + continue + + const { sidebarOrder, sidebarTitle } = getMetadataFromDoc(doc.path) + + if (!sidebarOrder) + throw new Error('Cannot find sidebarOrder in doc metadata: ' + doc.path) + + if (!sidebarTitle) + throw new Error('Cannot find sidebarTitle in doc metadata: ' + doc.path) + + items.push({ + sidebarOrder, + text: sidebarTitle, + link: doc.path.replace(/^docs/, '') + }) + } + + items = items.sort((a, b) => a.sidebarOrder - b.sidebarOrder) + + // remove dash and capitalize first character of each word as chapter title + const text = chapterDirName.split('-').join(' ').replace(/\b\w/g, l => l.toUpperCase()) + + return { + text, + items, + } +} + +const chapters = [ + 'introduction', + 'configuration', + 'premium', + 'runtime', + 'advanced-usages', +].map(generateSidebarChapter) + +// Override index page link +chapters[0]['items'][0]['link'] = '/' + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + title: "Clash", + description: "Rule-based Tunnel", + + themeConfig: { + outline: 'deep', + + search: { + provider: 'local' + }, + + editLink: { + pattern: 'https://github.com/Dreamacro/clash/edit/master/docs/:path', + text: 'Edit this page on GitHub' + }, + + logo: '/logo.png', + + // https://vitepress.dev/reference/default-theme-config + nav: [ + { text: 'Home', link: '/' }, + { text: 'Configuration', link: '/configuration/configuration-reference.md' }, + { + text: 'Download', + items: [ + { text: 'Open-source Edition', link: 'https://github.com/Dreamacro/clash/releases/' }, + { text: 'Premium Edition', link: 'https://github.com/Dreamacro/clash/releases/tag/premium' }, + ] + } + ], + + socialLinks: [ + { icon: 'github', link: 'https://github.com/Dreamacro/clash' }, + ], + + sidebar: chapters + } +}) diff --git a/docs/advanced-usages/golang-api.md b/docs/advanced-usages/golang-api.md new file mode 100644 index 0000000..db7a927 --- /dev/null +++ b/docs/advanced-usages/golang-api.md @@ -0,0 +1,59 @@ +--- +sidebarTitle: Integrating Clash in Golang Programs +sidebarOrder: 3 +--- + +# Integrating Clash in Golang Programs + +If clash does not fit your own usage, you can use Clash in your own Golang code. + +There is already basic support: + +```go +package main + +import ( + "context" + "fmt" + "io" + "net" + + "github.com/Dreamacro/clash/adapter/outbound" + "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/listener/socks" +) + +func main() { + in := make(chan constant.ConnContext, 100) + defer close(in) + + l, err := socks.New("127.0.0.1:10000", in) + if err != nil { + panic(err) + } + defer l.Close() + + println("listen at:", l.Address()) + + direct := outbound.NewDirect() + + for c := range in { + conn := c + metadata := conn.Metadata() + fmt.Printf("request incoming from %s to %s\n", metadata.SourceAddress(), metadata.RemoteAddress()) + go func () { + remote, err := direct.DialContext(context.Background(), metadata) + if err != nil { + fmt.Printf("dial error: %s\n", err.Error()) + return + } + relay(remote, conn.Conn()) + }() + } +} + +func relay(l, r net.Conn) { + go io.Copy(l, r) + io.Copy(r, l) +} +``` diff --git a/docs/advanced-usages/openconnect.md b/docs/advanced-usages/openconnect.md new file mode 100644 index 0000000..11a6f49 --- /dev/null +++ b/docs/advanced-usages/openconnect.md @@ -0,0 +1,93 @@ +--- +sidebarTitle: Rule-based OpenConnect +sidebarOrder: 2 +--- + +# Rule-based OpenConnect + +OpenConnect supports Cisco AnyConnect SSL VPN, Juniper Network Connect, Palo Alto Networks (PAN) GlobalProtect SSL VPN, Pulse Connect Secure SSL VPN, F5 BIG-IP SSL VPN, FortiGate SSL VPN and Array Networks SSL VPN. + +For example, there would be a use case where your company uses Cisco AnyConnect for internal network access. Here I'll show you how you can use OpenConnect with policy routing powered by Clash. + +First, [install vpn-slice](https://github.com/dlenski/vpn-slice#requirements). This tool overrides default routing table behaviour of OpenConnect. Simply saying, it stops the VPN from overriding your default routes. + +Next you would have a script (let's say `tun0.sh`) similar to this: + +```sh +#!/bin/bash +ANYCONNECT_HOST="vpn.example.com" +ANYCONNECT_USER="john" +ANYCONNECT_PASSWORD="foobar" +ROUTING_TABLE_ID="6667" +TUN_INTERFACE="tun0" + +# Add --no-dtls if the server is in mainland China. UDP in China is choppy. +echo "$ANYCONNECT_PASSWORD" | \ + openconnect \ + --non-inter \ + --passwd-on-stdin \ + --protocol=anyconnect \ + --interface $TUN_INTERFACE \ + --script "vpn-slice +if [ \"\$reason\" = 'connect' ]; then + ip rule add from \$INTERNAL_IP4_ADDRESS table $ROUTING_TABLE_ID + ip route add default dev \$TUNDEV scope link table $ROUTING_TABLE_ID +elif [ \"\$reason\" = 'disconnect' ]; then + ip rule del from \$INTERNAL_IP4_ADDRESS table $ROUTING_TABLE_ID + ip route del default dev \$TUNDEV scope link table $ROUTING_TABLE_ID +fi" \ + --user $ANYCONNECT_USER \ + https://$ANYCONNECT_HOST +``` + +After that, we configure it as a systemd service. Create `/etc/systemd/system/tun0.service`: + +```ini +[Unit] +Description=Cisco AnyConnect VPN +After=network-online.target +Conflicts=shutdown.target sleep.target + +[Service] +Type=simple +ExecStart=/path/to/tun0.sh +KillSignal=SIGINT +Restart=always +RestartSec=3 +StartLimitIntervalSec=0 + +[Install] +WantedBy=multi-user.target +``` + +Then we enable & start the service. + +```shell +chmod +x /path/to/tun0.sh +systemctl daemon-reload +systemctl enable tun0 +systemctl start tun0 +``` + +From here you can look at the logs to see if it's running properly. Simple way is to look at if `tun0` interface has been created. + +Similar to the Wireguard one, having an outbound to a TUN device is simple as adding a proxy group: + +```yaml +proxy-groups: + - name: Cisco AnyConnect VPN + type: select + interface-name: tun0 + proxies: + - DIRECT +``` + +... and it's ready to use! Add the desired rules: + +```yaml +rules: + - DOMAIN-SUFFIX,internal.company.com,Cisco AnyConnect VPN +``` + +You should look at the debug level logs when something does not seem right. + diff --git a/docs/advanced-usages/wireguard.md b/docs/advanced-usages/wireguard.md new file mode 100644 index 0000000..e4ba144 --- /dev/null +++ b/docs/advanced-usages/wireguard.md @@ -0,0 +1,40 @@ +--- +sidebarTitle: Rule-based Wireguard +sidebarOrder: 1 +--- + +# Rule-based Wireguard + +Suppose your kernel supports Wireguard and you have it enabled. The `Table` option stops _wg-quick_ from overriding default routes. + +Example `wg0.conf`: + +```ini +[Interface] +PrivateKey = ... +Address = 172.16.0.1/32 +MTU = ... +Table = off +PostUp = ip rule add from 172.16.0.1/32 table 6666 + +[Peer] +AllowedIPs = 0.0.0.0/0 +AllowedIPs = ::/0 +PublicKey = ... +Endpoint = ... +``` + +Then in Clash you would only need to have a DIRECT proxy group that has a specific outbound interface: + +```yaml +proxy-groups: + - name: Wireguard + type: select + interface-name: wg0 + proxies: + - DIRECT +rules: + - DOMAIN,google.com,Wireguard +``` + +This should perform better than whereas if Clash implemented its own userspace Wireguard client. Wireguard is supported in the kernel. diff --git a/docs/assets/connection-flow.png b/docs/assets/connection-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb6203d0c242625cd3cd0dcdcb9c41a308522dd GIT binary patch literal 80006 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 *.example.com > .example.com +# P.S. +.foo.com equals to .foo.com and foo.com +# hosts: + # '*.clash.dev': 127.0.0.1 + # '.dev': 127.0.0.1 + # 'alpha.clash.dev': '::1' + +# profile: + # Store the `select` results in $HOME/.config/clash/.cache + # set false If you don't want this behavior + # when two different configurations have groups with the same name, the selected values are shared + # store-selected: true + + # persistence fakeip + # store-fake-ip: false + +# DNS server settings +# This section is optional. When not present, the DNS server will be disabled. +dns: + enable: false + listen: 0.0.0.0:53 + # ipv6: false # when the false, response to AAAA questions will be empty + + # These nameservers are used to resolve the DNS nameserver hostnames below. + # Specify IP addresses only + default-nameserver: + - 114.114.114.114 + - 8.8.8.8 + # enhanced-mode: fake-ip + fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR + # use-hosts: true # lookup hosts and return IP record + + # search-domains: [local] # search domains for A/AAAA record + + # Hostnames in this list will not be resolved with fake IPs + # i.e. questions to these domain names will always be answered with their + # real IP addresses + # fake-ip-filter: + # - '*.lan' + # - localhost.ptlogin2.qq.com + + # Supports UDP, TCP, DoT, DoH. You can specify the port to connect to. + # All DNS questions are sent directly to the nameserver, without proxies + # involved. Clash answers the DNS question with the first result gathered. + nameserver: + - 114.114.114.114 # default value + - 8.8.8.8 # default value + - tls://dns.rubyfish.cn:853 # DNS over TLS + - https://1.1.1.1/dns-query # DNS over HTTPS + - dhcp://en0 # dns from dhcp + # - '8.8.8.8#en0' + + # When `fallback` is present, the DNS server will send concurrent requests + # to the servers in this section along with servers in `nameservers`. + # The answers from fallback servers are used when the GEOIP country + # is not `CN`. + # fallback: + # - tcp://1.1.1.1 + # - 'tcp://1.1.1.1#en0' + + # If IP addresses resolved with servers in `nameservers` are in the specified + # subnets below, they are considered invalid and results from `fallback` + # servers are used instead. + # + # IP address resolved with servers in `nameserver` is used when + # `fallback-filter.geoip` is true and when GEOIP of the IP address is `CN`. + # + # If `fallback-filter.geoip` is false, results from `nameserver` nameservers + # are always used if not match `fallback-filter.ipcidr`. + # + # This is a countermeasure against DNS pollution attacks. + # fallback-filter: + # geoip: true + # geoip-code: CN + # ipcidr: + # - 240.0.0.0/4 + # domain: + # - '+.google.com' + # - '+.facebook.com' + # - '+.youtube.com' + + # Lookup domains via specific nameservers + # nameserver-policy: + # 'www.baidu.com': '114.114.114.114' + # '+.internal.crop.com': '10.0.0.1' + +proxies: + # Shadowsocks + # The supported ciphers (encryption methods): + # aes-128-gcm aes-192-gcm aes-256-gcm + # aes-128-cfb aes-192-cfb aes-256-cfb + # aes-128-ctr aes-192-ctr aes-256-ctr + # rc4-md5 chacha20-ietf xchacha20 + # chacha20-ietf-poly1305 xchacha20-ietf-poly1305 + - name: "ss1" + type: ss + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + # udp: true + + - name: "ss2" + type: ss + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + plugin: obfs + plugin-opts: + mode: tls # or http + # host: bing.com + + - name: "ss3" + type: ss + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + plugin: v2ray-plugin + plugin-opts: + mode: websocket # no QUIC now + # tls: true # wss + # skip-cert-verify: true + # host: bing.com + # path: "/" + # mux: true + # headers: + # custom: value + + # vmess + # cipher support auto/aes-128-gcm/chacha20-poly1305/none + - name: "vmess" + type: vmess + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + # udp: true + # tls: true + # skip-cert-verify: true + # servername: example.com # priority over wss host + # network: ws + # ws-opts: + # path: /path + # headers: + # Host: v2ray.com + # max-early-data: 2048 + # early-data-header-name: Sec-WebSocket-Protocol + + - name: "vmess-h2" + type: vmess + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + network: h2 + tls: true + h2-opts: + host: + - http.example.com + - http-alt.example.com + path: / + + - name: "vmess-http" + type: vmess + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + # udp: true + # network: http + # http-opts: + # # method: "GET" + # # path: + # # - '/' + # # - '/video' + # # headers: + # # Connection: + # # - keep-alive + + - name: vmess-grpc + server: server + port: 443 + type: vmess + uuid: uuid + alterId: 32 + cipher: auto + network: grpc + tls: true + servername: example.com + # skip-cert-verify: true + grpc-opts: + grpc-service-name: "example" + + # socks5 + - name: "socks" + type: socks5 + server: server + port: 443 + # username: username + # password: password + # tls: true + # skip-cert-verify: true + # udp: true + + # http + - name: "http" + type: http + server: server + port: 443 + # username: username + # password: password + # tls: true # https + # skip-cert-verify: true + # sni: custom.com + + # Snell + # Beware that there's currently no UDP support yet + - name: "snell" + type: snell + server: server + port: 44046 + psk: yourpsk + # version: 2 + # obfs-opts: + # mode: http # or tls + # host: bing.com + + # Trojan + - name: "trojan" + type: trojan + server: server + port: 443 + password: yourpsk + # udp: true + # sni: example.com # aka server name + # alpn: + # - h2 + # - http/1.1 + # skip-cert-verify: true + + - name: trojan-grpc + server: server + port: 443 + type: trojan + password: "example" + network: grpc + sni: example.com + # skip-cert-verify: true + udp: true + grpc-opts: + grpc-service-name: "example" + + - name: trojan-ws + server: server + port: 443 + type: trojan + password: "example" + network: ws + sni: example.com + # skip-cert-verify: true + udp: true + # ws-opts: + # path: /path + # headers: + # Host: example.com + + # ShadowsocksR + # The supported ciphers (encryption methods): all stream ciphers in ss + # The supported obfses: + # plain http_simple http_post + # random_head tls1.2_ticket_auth tls1.2_ticket_fastauth + # The supported supported protocols: + # origin auth_sha1_v4 auth_aes128_md5 + # auth_aes128_sha1 auth_chain_a auth_chain_b + - name: "ssr" + type: ssr + server: server + port: 443 + cipher: chacha20-ietf + password: "password" + obfs: tls1.2_ticket_auth + protocol: auth_sha1_v4 + # obfs-param: domain.tld + # protocol-param: "#" + # udp: true + +proxy-groups: + # relay chains the proxies. proxies shall not contain a relay. No UDP support. + # Traffic: clash <-> http <-> vmess <-> ss1 <-> ss2 <-> Internet + - name: "relay" + type: relay + proxies: + - http + - vmess + - ss1 + - ss2 + + # url-test select which proxy will be used by benchmarking speed to a URL. + - name: "auto" + type: url-test + proxies: + - ss1 + - ss2 + - vmess1 + # tolerance: 150 + # lazy: true + url: 'http://www.gstatic.com/generate_204' + interval: 300 + + # fallback selects an available policy by priority. The availability is tested by accessing an URL, just like an auto url-test group. + - name: "fallback-auto" + type: fallback + proxies: + - ss1 + - ss2 + - vmess1 + url: 'http://www.gstatic.com/generate_204' + interval: 300 + + # load-balance: The request of the same eTLD+1 will be dial to the same proxy. + - name: "load-balance" + type: load-balance + proxies: + - ss1 + - ss2 + - vmess1 + url: 'http://www.gstatic.com/generate_204' + interval: 300 + # strategy: consistent-hashing # or round-robin + + # select is used for selecting proxy or proxy group + # you can use RESTful API to switch proxy is recommended for use in GUI. + - name: Proxy + type: select + # disable-udp: true + # filter: 'someregex' + proxies: + - ss1 + - ss2 + - vmess1 + - auto + + # direct to another interfacename or fwmark, also supported on proxy + - name: en1 + type: select + interface-name: en1 + routing-mark: 6667 + proxies: + - DIRECT + + - name: UseProvider + type: select + use: + - provider1 + proxies: + - Proxy + - DIRECT + +proxy-providers: + provider1: + type: http + url: "url" + interval: 3600 + path: ./provider1.yaml + health-check: + enable: true + interval: 600 + # lazy: true + url: http://www.gstatic.com/generate_204 + test: + type: file + path: /test.yaml + health-check: + enable: true + interval: 36000 + url: http://www.gstatic.com/generate_204 + +tunnels: + # one line config + - tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy + - tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn + # full yaml config + - network: [tcp, udp] + address: 127.0.0.1:7777 + target: target.com + proxy: proxy + +rules: + - DOMAIN-SUFFIX,google.com,auto + - DOMAIN-KEYWORD,google,auto + - DOMAIN,google.com,auto + - DOMAIN-SUFFIX,ad.com,REJECT + - SRC-IP-CIDR,192.168.1.201/32,DIRECT + # optional param "no-resolve" for IP rules (GEOIP, IP-CIDR, IP-CIDR6) + - IP-CIDR,127.0.0.0/8,DIRECT + - GEOIP,CN,DIRECT + - DST-PORT,80,DIRECT + - SRC-PORT,7777,DIRECT + - RULE-SET,apple,REJECT # Premium only + - MATCH,auto +``` diff --git a/docs/configuration/dns.md b/docs/configuration/dns.md new file mode 100644 index 0000000..d3520bf --- /dev/null +++ b/docs/configuration/dns.md @@ -0,0 +1,72 @@ +--- +sidebarTitle: Clash DNS +sidebarOrder: 6 +--- + +# Clash DNS + +Since some parts of Clash run on the Layer 3 (Network Layer), they would've been impossible to obtain domain names of the packets for rule-based routing. + +*Enter fake-ip*. It enables rule-based routing, minimises the impact of DNS pollution attack and improves network performance, sometimes drastically. + +## fake-ip + +The concept of "fake IP" addresses is originated from [RFC 3089](https://tools.ietf.org/rfc/rfc3089): + +> A "fake IP" address is used as a key to look up the corresponding "FQDN" information. + +The default CIDR for the fake-ip pool is `198.18.0.1/16`, a reserved IPv4 address space, which can be changed in `dns.fake-ip-range`. + +When a DNS request is sent to the Clash DNS, the core allocates a *free* fake-ip address from the pool, by managing an internal mapping of domain names and their fake-ip addresses. + +Take an example of accessing `http://google.com` with your browser. + +1. The browser asks Clash DNS for the IP address of `google.com` +2. Clash checks the internal mapping and returned `198.18.1.5` +3. The browser sends an HTTP request to `198.18.1.5` on `80/tcp` +4. When receiving the inbound packet for `198.18.1.5`, Clash looks up the internal mapping and realises the client is actually sending a packet to `google.com` +5. Depending on the rules: + + 1. Clash may just send the domain name to an outbound proxy like SOCKS5 or shadowsocks and establish the connection with the proxy server + + 2. or Clash might look for the real IP address of `google.com`, in the case of encountering a `SCRIPT`, `GEOIP`, `IP-CIDR` rule, or the case of DIRECT outbound + +Being a confusing concept, I'll take another example of accessing `http://google.com` with the cURL utility: + +```txt{2,3,5,6,8,9} +$ curl -v http://google.com +<---- cURL asks your system DNS (Clash) about the IP address of google.com +----> Clash decided 198.18.1.70 should be used as google.com and remembers it +* Trying 198.18.1.70:80... +<---- cURL connects to 198.18.1.70 tcp/80 +----> Clash will accept the connection immediately, and.. +* Connected to google.com (198.18.1.70) port 80 (#0) +----> Clash looks up in its memory and found 198.18.1.70 being google.com +----> Clash looks up in the rules and sends the packet via the matching outbound +> GET / HTTP/1.1 +> Host: google.com +> User-Agent: curl/8.0.1 +> Accept: */* +> +< HTTP/1.1 301 Moved Permanently +< Location: http://www.google.com/ +< Content-Type: text/html; charset=UTF-8 +< Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-ahELFt78xOoxhySY2lQ34A' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp +< Date: Thu, 11 May 2023 06:52:19 GMT +< Expires: Sat, 10 Jun 2023 06:52:19 GMT +< Cache-Control: public, max-age=2592000 +< Server: gws +< Content-Length: 219 +< X-XSS-Protection: 0 +< X-Frame-Options: SAMEORIGIN +< + +301 Moved +

    301 Moved

    +The document has moved +here. + +* Connection #0 to host google.com left intact +``` + + diff --git a/docs/configuration/getting-started.md b/docs/configuration/getting-started.md new file mode 100644 index 0000000..89967d2 --- /dev/null +++ b/docs/configuration/getting-started.md @@ -0,0 +1,64 @@ +--- +sidebarTitle: Getting Started +sidebarOrder: 2 +--- + +# Getting Started + +It's recommended that you read the [Introduction](/configuration/introduction) before proceeding. After you have a brief understanding of how Clash works, you can start writing your own configuration. + +## Configuration Files + +The main configuration file is called `config.yaml`. By default, Clash reads the configuration files at `$HOME/.config/clash`. If it doesn't exist, Clash will generate a minimal configuration file at that location. + +If you want to place your configurations elsewhere (e.g. `/etc/clash`), you can use command-line option `-d` to specify a configuration directory: + +```shell +clash -d . # current directory +clash -d /etc/clash +``` + +Or, you can use option `-f` to specify a configuration file: + +```shell +clash -f ./config.yaml +clash -f /etc/clash/config.yaml +``` + +## Special Syntaxes + +There are some special syntaxes in Clash configuration files, of which you might want to be aware: + +### IPv6 Addresses + +You should wrap IPv6 addresses in square brackets, for example: + +```txt +[aaaa::a8aa:ff:fe09:57d8] +``` + +### DNS Wildcard Domain Matching + +In some cases, you will need to match against wildcard domains. For example, when you're setting up [Clash DNS](/configuration/dns), you might want to match against all subdomains of `localdomain`. + +Clash do offer support on matching different levels of wildcard domains in the DNS configuration, while the syntaxes defined below: + +::: tip +Any domain with these characters should be wrapped with single quotes (`'`). For example, `'*.google.com'`. +::: + +Use an astrisk (`*`) to match against a single-level wildcard subdomain. + +| Expression | Matches | Does Not Match | +| ---------- | ------- | -------------- | +| `*.google.com` | `www.google.com` | `google.com` | +| `*.bar.google.com` | `foo.bar.google.com` | `bar.google.com` | +| `*.*.google.com` | `thoughtful.sandbox.google.com` | `one.two.three.google.com` | + +Use a plus sign (`+`) to match against multi-level wildcard subdomains. + +| Expression | Matches | Does Not Match | +| ---------- | ------- | -------------- | +| `+.google.com` | `www.google.com` | `www.google.com` | +| `+.google.com` | `thoughtful.sandbox.google.com` | `www.google.com` | +| `+.google.com` | `one.two.three.google.com` | `www.google.com` | diff --git a/docs/configuration/inbound.md b/docs/configuration/inbound.md new file mode 100644 index 0000000..fc4d593 --- /dev/null +++ b/docs/configuration/inbound.md @@ -0,0 +1,69 @@ +--- +sidebarTitle: Inbound +sidebarOrder: 3 +--- + +# Inbound + +Clash supports multiple inbound protocols, including: + +- SOCKS5 +- HTTP(S) +- Redirect TCP +- TProxy TCP +- TProxy UDP +- Linux TUN device (Premium only) + +Connections to any inbound protocol listed above will be handled by the same internal rule-matching engine. That is to say, Clash does not (currently) support different rule sets for different inbounds. + +## Configuration + +```yaml +# Port of HTTP(S) proxy server on the local end +# port: 7890 + +# Port of SOCKS5 proxy server on the local end +# socks-port: 7891 + +# HTTP(S) and SOCKS4(A)/SOCKS5 server on the same port +mixed-port: 7890 + +# Transparent proxy server port for Linux and macOS (Redirect TCP and TProxy UDP) +# redir-port: 7892 + +# Transparent proxy server port for Linux (TProxy TCP and TProxy UDP) +# tproxy-port: 7893 + +# Allow clients other than 127.0.0.1 to connect to the inbounds +allow-lan: false +``` + +## The Mixed Port + +The mixed port is a special port that supports both HTTP(S) and SOCKS5 protocols. You can have any programs that support either HTTP or SOCKS proxy to connect to this port, for example: + +```shell +$ curl -x socks5h://127.0.0.1:7890 -v http://connect.rom.miui.com/generate_204 +* Trying 127.0.0.1:7890... +* SOCKS5 connect to connect.rom.miui.com:80 (remotely resolved) +* SOCKS5 request granted. +* Connected to (nil) (127.0.0.1) port 7890 (#0) +> GET /generate_204 HTTP/1.1 +> Host: connect.rom.miui.com +> User-Agent: curl/7.81.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 204 No Content +< Date: Thu, 11 May 2023 06:18:22 GMT +< Connection: keep-alive +< Content-Type: text/plain +< +* Connection #0 to host (nil) left intact +``` + +## Redirect and TProxy + +Redirect and TProxy are two different ways of implementing transparent proxying. They are both supported by Clash. + +However, you most likely don't need to mess with these two inbounds - we recommend using [Clash Premium](/premium/introduction) if you want to use transparent proxying, as it has built-in support of the automatic management of the route table, rules and nftables. diff --git a/docs/configuration/introduction.md b/docs/configuration/introduction.md new file mode 100644 index 0000000..aefbe3f --- /dev/null +++ b/docs/configuration/introduction.md @@ -0,0 +1,38 @@ +--- +sidebarTitle: Introduction +sidebarOrder: 1 +--- + +# Introduction + +In this chapter, we'll cover the common features of Clash and how they should be used and configured. + +Clash uses [YAML](https://yaml.org), _YAML Ain't Markup Language_, for configuration files. YAML is designed to be easy to be read, be written, and be interpreted by computers, and is commonly used for exact configuration files. + +## Understanding how Clash works + +Before proceeding, it's important to understand how Clash works, in which there are two critical components: + +![](/assets/connection-flow.png) + + + +### Inbound + +Inbound is the component that listens on the local end. It works by opening a local port and listening for incoming connections. When a connection comes in, Clash looks up the rules that are configured in the configuration file, and decides which outbound that the connection should go next. + +### Outbound + +Outbound is the component that connects to the remote end. Depending on the configuration, it can be a specific network interface, a proxy server, or a [proxy group](#proxy-groups). + +## Rule-based Routing + +Clash supports rule-based routing, which means you can route packets to different outbounds based on the a variety of contraints. The rules can be defined in the `rules` section of the configuration file. + +There's a number of available rule types, and each rule type has its own syntax. The general syntax of a rule is: + +```txt +TYPE,ARGUMENT,POLICY(,no-resolve) +``` + +In the upcoming guides, you will learn more about how rules can be configured. diff --git a/docs/configuration/outbound.md b/docs/configuration/outbound.md new file mode 100644 index 0000000..104d3de --- /dev/null +++ b/docs/configuration/outbound.md @@ -0,0 +1,432 @@ +--- +sidebarTitle: Outbound +sidebarOrder: 4 +--- + +# Outbound + +There are several types of outbound targets in Clash. Each type has its own features and usage scenarios. In this page, we'll cover the common features of each type and how they should be used and configured. + +[[toc]] + +## Proxies + +Proxies are the basic type of outbound targets. + +### Shadowsocks + +Clash supports the following ciphers (encryption methods) for Shadowsocks: + +| Family | Ciphers | +| ------ | ------- | +| AEAD | aes-128-gcm, aes-192-gcm, aes-256-gcm, chacha20-ietf-poly1305, xchacha20-ietf-poly1305 | +| Stream | aes-128-cfb, aes-192-cfb, aes-256-cfb, rc4-md5, chacha20-ietf, xchacha20 | +| Block | aes-128-ctr, aes-192-ctr, aes-256-ctr | + +In addition, Clash also supports popular Shadsocks plugins `obfs` and `v2ray-plugin`. + +::: code-group + +```yaml [basic] +- name: "ss1" + type: ss + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + # udp: true +``` + +```yaml [obfs] +- name: "ss2" + type: ss + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + plugin: obfs + plugin-opts: + mode: tls # or http + # host: bing.com +``` + +```yaml [ws (websocket)] +- name: "ss3" + type: ss + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + plugin: v2ray-plugin + plugin-opts: + mode: websocket # no QUIC now + # tls: true # wss + # skip-cert-verify: true + # host: bing.com + # path: "/" + # mux: true + # headers: + # custom: value +``` + +::: + +### ShadowsocksR + +Clash supports the infamous anti-censorship protocol ShadowsocksR as well. The supported ciphers: + +| Family | Ciphers | +| ------ | ------- | +| Stream | aes-128-cfb, aes-192-cfb, aes-256-cfb, rc4-md5, chacha20-ietf, xchacha20 | + +Supported obfuscation methods: + +- plain +- http_simple +- http_post +- random_head +- tls1.2_ticket_auth +- tls1.2_ticket_fastauth + +Supported protocols: + +- origin +- auth_sha1_v4 +- auth_aes128_md5 +- auth_aes128_sha1 +- auth_chain_a auth_chain_b + +```yaml +- name: "ssr" + type: ssr + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + cipher: chacha20-ietf + password: "password" + obfs: tls1.2_ticket_auth + protocol: auth_sha1_v4 + # obfs-param: domain.tld + # protocol-param: "#" + # udp: true +``` + +### Vmess + +Clash supports the following ciphers (encryption methods) for Vmess: + +- auto +- aes-128-gcm +- chacha20-poly1305 +- none + +::: code-group + +```yaml [basic] +- name: "vmess" + type: vmess + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + # udp: true + # tls: true + # skip-cert-verify: true + # servername: example.com # priority over wss host + # network: ws + # ws-opts: + # path: /path + # headers: + # Host: v2ray.com + # max-early-data: 2048 + # early-data-header-name: Sec-WebSocket-Protocol +``` + +```yaml [HTTP] +- name: "vmess-http" + type: vmess + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + # udp: true + # network: http + # http-opts: + # # method: "GET" + # # path: + # # - '/' + # # - '/video' + # # headers: + # # Connection: + # # - keep-alive +``` + +```yaml [HTTP/2] +- name: "vmess-h2" + type: vmess + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + network: h2 + tls: true + h2-opts: + host: + - http.example.com + - http-alt.example.com + path: / +``` + +```yaml [gRPC] +- name: vmess-grpc + type: vmess + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + uuid: uuid + alterId: 32 + cipher: auto + network: grpc + tls: true + servername: example.com + # skip-cert-verify: true + grpc-opts: + grpc-service-name: "example" +``` + +::: + +### SOCKS5 + +In addition, Clash supports SOCKS5 outbound as well: + +```yaml +- name: "socks" + type: socks5 + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + # username: username + # password: password + # tls: true + # skip-cert-verify: true + # udp: true +``` + +### HTTP + +Clash also supports HTTP outbound: + +::: code-group + +```yaml [HTTP] +- name: "http" + type: http + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + # username: username + # password: password +``` + +```yaml [HTTPS] +- name: "http" + type: http + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + tls: true + # skip-cert-verify: true + # sni: custom.com + # username: username + # password: password +``` + +::: + +### Snell + +Being an alternative protocol for anti-censorship, Clash has integrated support for Snell as well. + +```yaml +# No UDP support yet +- name: "snell" + type: snell + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 44046 + psk: yourpsk + # version: 2 + # obfs-opts: + # mode: http # or tls + # host: bing.com +``` + +### Trojan + +Clash has built support for the popular protocol Trojan: + +::: code-group + +```yaml [basic] +- name: "trojan" + type: trojan + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + password: yourpsk + # udp: true + # sni: example.com # aka server name + # alpn: + # - h2 + # - http/1.1 + # skip-cert-verify: true +``` + +```yaml [gRPC] +- name: trojan-grpc + type: trojan + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + password: "example" + network: grpc + sni: example.com + # skip-cert-verify: true + udp: true + grpc-opts: + grpc-service-name: "example" +``` + +```yaml [ws (websocket)] +- name: trojan-ws + type: trojan + # interface-name: eth0 + # routing-mark: 1234 + server: server + port: 443 + password: "example" + network: ws + sni: example.com + # skip-cert-verify: true + udp: true + # ws-opts: + # path: /path + # headers: + # Host: example.com +``` + +::: + +## Proxy Groups + +Proxy Groups are groups of proxies that you can use directly as a rule policy. + +### relay + +The request sent to this proxy group will be relayed through the specified proxy servers sequently. There's currently no UDP support on this. The specified proxy servers should not contain another relay. + +### url-test + +Clash benchmarks each proxy servers in the list, by sending HTTP HEAD requests to a specified URL through these servers periodically. It's possible to set a maximum tolerance value, benchmarking interval, and the target URL. + +### fallback + +Clash periodically tests the availability of servers in the list with the same mechanism of `url-test`. The first available server will be used. + +### load-balance + +The request to the same eTLD+1 will be dialed with the same proxy. + +### select + +The first server is by default used when Clash starts up. Users can choose the server to use with the RESTful API. In this mode, you can hardcode servers in the config or use [Proxy Providers](/configuration/outbound#proxy-providers). + +Either way, sometimes you might as well just route packets with a direct connection. In this case, you can use the `DIRECT` outbound. + +To use a different network interface, you will need to use a Proxy Group that contains a `DIRECT` outbound with the `interface-name` option set. + +```yaml +- name: "My Wireguard Outbound" + type: select + interface-name: wg0 + proxies: [ 'DIRECT' ] +``` + +## Proxy Providers + +Proxy Providers give users the power to load proxy server lists dynamically, instead of hardcoding them in the configuration file. There are currently two sources for a proxy provider to load server list from: + +- `http`: Clash loads the server list from a specified URL on startup. Clash periodically pulls the server list from remote if the `interval` option is set. +- `file`: Clash loads the server list from a specified location on the filesystem on startup. + +Health check is available for both modes, and works exactly like `fallback` in Proxy Groups. The configuration format for the server list files is also exactly the same in the main configuration file: + +::: code-group + +```yaml [config.yaml] +proxy-providers: + provider1: + type: http + url: "url" + interval: 3600 + path: ./provider1.yaml + # filter: 'a|b' # golang regex string + health-check: + enable: true + interval: 600 + # lazy: true + url: http://www.gstatic.com/generate_204 + test: + type: file + path: /test.yaml + health-check: + enable: true + interval: 36000 + url: http://www.gstatic.com/generate_204 +``` + +```yaml [test.yaml] +proxies: + - name: "ss1" + type: ss + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + + - name: "ss2" + type: ss + server: server + port: 443 + cipher: chacha20-ietf-poly1305 + password: "password" + plugin: obfs + plugin-opts: + mode: tls +``` + +::: diff --git a/docs/configuration/rules.md b/docs/configuration/rules.md new file mode 100644 index 0000000..75d06d5 --- /dev/null +++ b/docs/configuration/rules.md @@ -0,0 +1,153 @@ +--- +sidebarTitle: Rules +sidebarOrder: 5 +--- + +# Rules + +In the Getting Started guide, we covered the basics of rule-based matching in Clash. In this chapter, we'll cover all available rule types in the latest version of Clash. + +```txt +TYPE,ARGUMENT,POLICY(,no-resolve) +``` + +The `no-resolve` option is optional, and it's used to skip DNS resolution for the rule. It's useful when you want to use `GEOIP`, `IP-CIDR`, `IP-CIDR6`, `SCRIPT` rules, but don't want to resolve the domain name to an IP address just yet. + +[[toc]] + +## Policy + +There are four types of POLICY for now, in which: + +- DIRECT: directly connects to the target through `interface-name` (does not lookup system route table) +- REJECT: drops the packet +- Proxy: routes the packet to the specified proxy server +- Proxy Group: routes the packet to the specified proxy group + +## Types of rules + +There are a number of rules where one might find useful. The following section covers each rule type and how they should be used. + +### DOMAIN + +`DOMAIN,www.google.com,policy` routes only `www.google.com` to `policy`. + +### DOMAIN-SUFFIX + +`DOMAIN-SUFFIX,youtube.com,policy` routes any domain names that ends with `youtube.com`. + +In this case, `www.youtube.com` and `foo.bar.youtube.com` will be routed to `policy`. + +### DOMAIN-KEYWORD + +`DOMAIN-KEYWORD,google,policy` routes any domain names to policy that contains `google`. + +In this case, `www.google.com` or `googleapis.com` are routed to `policy`. + +### GEOIP + +GEOIP rules are used to route packets based on the **country code** of the target IP address. Clash uses [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geoip2/geolite2/) database for this feature. + +::: warning +When encountering this rule, Clash will resolve the domain name to an IP address and then look up the country code of the IP address. If you want to skip the DNS resolution, use `no-resolve` option. +::: + +`GEOIP,CN,policy` routes any packets destined to a China IP address to `policy`. + +### IP-CIDR + +IP-CIDR rules are used to route packets based on the **destination IPv4 address** of the packet. + +::: warning +When encountering this rule, Clash will resolve the domain name to an IP address and then look up the country code of the IP address. If you want to skip the DNS resolution, use `no-resolve` option. +::: + +`IP-CIDR,127.0.0.0/8,DIRECT` routes any packets destined to `127.0.0.0/8` to the `DIRECT` outbound. + +### IP-CIDR6 + +IP-CIDR6 rules are used to route packets based on the **destination IPv6 address** of the packet. + +::: warning +When encountering this rule, Clash will resolve the domain name to an IP address and then look up the country code of the IP address. If you want to skip the DNS resolution, use `no-resolve` option. +::: + +`IP-CIDR6,2620:0:2d0:200::7/32,policy` routes any packets destined to `2620:0:2d0:200::7/32` to `policy`. + +### SRC-IP-CIDR + +SRC-IP-CIDR rules are used to route packets based on the **source IPv4 address** of the packet. + +`SRC-IP-CIDR,192.168.1.201/32,DIRECT` routes any packets **from** `192.168.1.201/32` to the `DIRECT` policy. + +### SRC-PORT + +SRC-PORT rules are used to route packets based on the **source port** of the packet. + +`SRC-PORT,80,policy` routes any packets **from** the port 80 to `policy`. + +### DST-PORT + +DST-PORT rules are used to route packets based on the **destination port** of the packet. + +`DST-PORT,80,policy` routes any packets **to** the port 80 to `policy`. + +### PROCESS-NAME + +PROCESS-NAME rules are used to route packets based on the name of process that is sending the packet. + +::: warning +Currently, only macOS, Linux, FreeBSD and Windows are supported. +::: + +`PROCESS-NAME,nc,DIRECT` routes all packets from the process `nc` to the `DIRECT` outbound. + +### PROCESS-PATH + +PROCESS-PATH rules are used to route packets based on the PATH of process that is sending the packet. + +::: warning +Currently, only macOS, Linux, FreeBSD and Windows are supported. +::: + +`PROCESS-PATH,/bin/sh,DIRECT` routes all packets from the process `/bin/sh` to the `DIRECT` outbound. + +### IPSET + +IPSET rules are used to match against an IP set and route packets based on the result. According to the [official website of IPSET](https://ipset.netfilter.org/): + +> IP sets are a framework inside the Linux kernel, which can be administered by the ipset utility. Depending on the type, an IP set may store IP addresses, networks, (TCP/UDP) port numbers, MAC addresses, interface names or combinations of them in a way, which ensures lightning speed when matching an entry against a set. + +::: warning +This feature only works on Linux and requires `ipset` to be installed. +::: + +`PROCESS-PATH,/bin/sh,DIRECT` routes all packets from the process `/bin/sh` to the `DIRECT` outbound. + +### RULE-SET + +::: info +This feature is only available in the [Premium](/premium/introduction) edtion. +::: + +RULE-SET rules are used to route packets based on the result of a [rule provider](/premium/rule-providers). When Clash encounters this rule, it loads the rules from the specified rule provider and then matches the packet against the rules. If the packet matches any of the rules, the packet will be routed to the specified policy, otherwise the rule is skipped. + +`RULE-SET,my-rule-provider,DIRECT` loads all rules from `my-rule-provider` and sends the matched packets to the `DIRECT` outbound. + +### SCRIPT + +::: info +This feature is only available in the [Premium](/premium/introduction) edtion. +::: + +SCRIPT rules are special rules that are used to route packets based on the result of a [script shortcut](/premium/script-shortcuts). When Clash encounters this rule, it evaluates the expression. If it returns `true`, the packet will be routed to the specified policy, otherwise the rule is skipped. + +::: warning +When encountering this rule, Clash will resolve the domain name to an IP address and then look up the country code of the IP address. If you want to skip the DNS resolution, use `no-resolve` option. +::: + +`SCRIPT,SHORTCUT-NAME,policy` routes any packets to `policy` if they have the shortcut evaluated `true`. + +### MATCH + +`MATCH,policy` routes the rest of the packets to `policy`. This rule is **required**. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..c6f2c5a --- /dev/null +++ b/docs/index.md @@ -0,0 +1,38 @@ + +# What is Clash? + +Welcome to the official knowledge base of the Clash core project ("Clash"). + +Clash is a cross-platform rule-based proxy utility that runs on the network and application layer, supporting various proxy and anti-censorship protocols out-of-the-box. + +It has been adopted widely by the Internet users in some countries and regions where the Internet is heavily censored or blocked. Either way, Clash can be used by anyone who wants to improve their Internet experience. + +There are currently two editions of Clash: + +- [Clash](https://github.com/Dreamacro/clash): the open-source version released at [github.com/Dreamacro/clash](https://github.com/Dreamacro/clash) +- [Clash Premium](https://github.com/Dreamacro/clash/releases/tag/premium): proprietary core with [TUN support and more](/premium/introduction) (free of charge) + +While this wiki covers both, however, the use of Clash could be challenging for the average users. Those might want to consider using a GUI client instead, and we do have some recommendations: + +- [Clash for Windows](https://github.com/Fndroid/clash_for_windows_pkg/releases) (Windows and macOS) +- [Clash for Android](https://github.com/Kr328/ClashForAndroid) +- [ClashX](https://github.com/yichengchen/clashX) or [ClashX Pro](https://install.appcenter.ms/users/clashx/apps/clashx-pro/distribution_groups/public) (macOS) + +## Feature Overview + +- Inbound: HTTP, HTTPS, SOCKS5 server, TUN device* +- Outbound: Shadowsocks(R), VMess, Trojan, Snell, SOCKS5, HTTP(S), Wireguard* +- Rule-based Routing: dynamic scripting, domain, IP addresses, process name and more* +- Fake-IP DNS: minimises impact on DNS pollution and improves network performance +- Transparent Proxy: Redirect TCP and TProxy TCP/UDP with automatic route table/rule management* +- Proxy Groups: automatic fallback, load balancing or latency testing +- Remote Providers: load remote proxy lists dynamically +- RESTful API: update configuration in-place via a comprehensive API + + +\*: Only available in the free-of-charge Premium edition. + + +## License + +Clash is released under the [GPL-3.0](https://github.com/Dreamacro/clash/blob/master/LICENSE) open-source license. Prior to [v0.16.0](https://github.com/Dreamacro/clash/releases/tag/v0.16.0) or commit [e5284c](https://github.com/Dreamacro/clash/commit/e5284cf647717a8087a185d88d15a01096274bc2), it was licensed under the MIT license. diff --git a/docs/introduction/_dummy-index.md b/docs/introduction/_dummy-index.md new file mode 100644 index 0000000..d9d4f6d --- /dev/null +++ b/docs/introduction/_dummy-index.md @@ -0,0 +1,6 @@ +--- +sidebarTitle: What is Clash? +sidebarOrder: 1 +--- + + diff --git a/docs/introduction/faq.md b/docs/introduction/faq.md new file mode 100644 index 0000000..8a36303 --- /dev/null +++ b/docs/introduction/faq.md @@ -0,0 +1,73 @@ +--- +sidebarTitle: Frequently Asked Questions +sidebarOrder: 4 +--- + +# Frequently Asked Questions + +Here we have some common questions people ask. If you have any questions not listed here, feel free to [open an issue](https://github.com/Dreamacro/clash/issues/new/choose). + +[[toc]] + +## Which release should I use for my system? + +Here are some common systems that people use Clash on, and the recommended release for each of them: + +- NETGEAR WNDR3700v2: mips-hardfloat [#846](https://github.com/Dreamacro/clash/issues/846) +- NETGEAR WNDR3800: mips-softfloat [#579](https://github.com/Dreamacro/clash/issues/579) +- ASUS RT-AC5300: armv5 [#2356](https://github.com/Dreamacro/clash/issues/2356) +- MediaTek MT7620A, MT7621A: mipsle-softfloat ([#136](https://github.com/Dreamacro/clash/issues/136)) +- mips_24kc: [#192](https://github.com/Dreamacro/clash/issues/192) + +If your device is not listed here, you can check the CPU architecture of your device with `uname -m` and find the corresponding release in the release page. + +## List of wontfix + +The official Clash core project will not implement/fix these things: + +- [Snell](https://github.com/Dreamacro/clash/issues/2466) +- [Custom CA](https://github.com/Dreamacro/clash/issues/2333) +- [VMess Mux](https://github.com/Dreamacro/clash/issues/450) +- [VLess](https://github.com/Dreamacro/clash/issues/1185) +- [KCP](https://github.com/Dreamacro/clash/issues/16) +- [mKCP](https://github.com/Dreamacro/clash/issues/2308) +- [TLS Encrypted Client Hello](https://github.com/Dreamacro/clash/issues/2295) +- [TCP support for Clash DNS server](https://github.com/Dreamacro/clash/issues/368) +- [MITM](https://github.com/Dreamacro/clash/issues/227#issuecomment-508693628) + +The following will be considered implementing when the official Go QUIC library releases. + +- [TUIC](https://github.com/Dreamacro/clash/issues/2222) +- [Hysteria](https://github.com/Dreamacro/clash/issues/1863) + +## Proxies work on my local machine, but not on my router or in a container + +Your system might be out of sync in time. Refer to your platform documentations about time synchronisation - things will break if time is not in sync. + +## Time complexity of rule matching + +Refer to this discussion: [#422](https://github.com/Dreamacro/clash/issues/422) + +## Clash Premium unable to access Internet + +You can refer to these relevant discussions: + +- [#432](https://github.com/Dreamacro/clash/issues/432#issuecomment-571634905) +- [#2480](https://github.com/Dreamacro/clash/issues/2480) + +## error: unsupported rule type RULE-SET + +If you stumbled on this error message: + +```txt +FATA[0000] Parse config error: Rules[0] [RULE-SET,apple,REJECT] error: unsupported rule type RULE-SET +``` + +You're using Clash open-source edition. Rule Providers is currently only available in the [Premium core](https://github.com/Dreamacro/clash/releases/tag/premium). (it's free) + +## DNS Hijack does not work + +Since `tun.auto-route` does not intercept LAN traffic, if your system DNS is set to servers in private subnets, DNS hijack will not work. You can either: + +1. Use a non-private DNS server as your system DNS like `1.1.1.1` +2. Or manually set up your system DNS to the Clash DNS (by default, `198.18.0.1`) diff --git a/docs/introduction/getting-started.md b/docs/introduction/getting-started.md new file mode 100644 index 0000000..4f2ecef --- /dev/null +++ b/docs/introduction/getting-started.md @@ -0,0 +1,50 @@ +--- +sidebarTitle: Getting Started +sidebarOrder: 2 +--- + +# Getting Started + +To get started with Clash, you can either build it from source or download pre-built binaries. + +## Using pre-built binaries + +You can download Clash core binaries here: [https://github.com/Dreamacro/clash/releases](https://github.com/Dreamacro/clash/releases) + +## Install from source + +You can build Clash on your own device with Golang 1.19+: + +```shell +$ go install github.com/Dreamacro/clash@latest +go: downloading github.com/Dreamacro/clash v1.15.1 +``` + +The binary is built under `$GOPATH/bin`: + +```shell +$ $GOPATH/bin/clash -v +Clash unknown version darwin arm64 with go1.20.3 unknown time +``` + +## Build for a different arch/os + +Golang supports cross-compilation, so you can build for a device on a different architecture or operating system. You can use _make_ to build them easily - for example: + +```shell +$ git clone --depth 1 https://github.com/Dreamacro/clash +Cloning into 'clash'... +remote: Enumerating objects: 359, done. +remote: Counting objects: 100% (359/359), done. +remote: Compressing objects: 100% (325/325), done. +remote: Total 359 (delta 25), reused 232 (delta 17), pack-reused 0 +Receiving objects: 100% (359/359), 248.99 KiB | 1.63 MiB/s, done. +Resolving deltas: 100% (25/25), done. +$ cd clash && make darwin-arm64 +fatal: No names found, cannot describe anything. +GOARCH=arm64 GOOS=darwin CGO_ENABLED=0 go build -trimpath -ldflags '-X "github.com/Dreamacro/clash/constant.Version=unknown version" -X "github.com/Dreamacro/clash/constant.BuildTime=Mon May 8 16:47:10 UTC 2023" -w -s -buildid=' -o bin/clash-darwin-arm64 +$ file bin/clash-darwin-arm64 +bin/clash-darwin-arm64: Mach-O 64-bit executable arm64 +``` + +For other build targets, check out the [Makefile](https://github.com/Dreamacro/clash/blob/master/Makefile). diff --git a/docs/introduction/service.md b/docs/introduction/service.md new file mode 100644 index 0000000..7a0e9a8 --- /dev/null +++ b/docs/introduction/service.md @@ -0,0 +1,132 @@ +--- +sidebarTitle: Clash as a Service +sidebarOrder: 3 +--- + +# Clash as a Service + +While Clash is meant to be run in the background, there's currently no elegant way to implement daemons with Golang, hence we recommend you to daemonize Clash with third-party tools. + +## systemd + +Copy Clash binary to `/usr/local/bin` and configuration files to `/etc/clash`: + +```shell +cp clash /usr/local/bin +cp config.yaml /etc/clash/ +cp Country.mmdb /etc/clash/ +``` + +Create the systemd configuration file at `/etc/systemd/system/clash.service`: + +```ini +[Unit] +Description=Clash daemon, A rule-based proxy in Go. +After=network-online.target + +[Service] +Type=simple +Restart=always +ExecStart=/usr/local/bin/clash -d /etc/clash + +[Install] +WantedBy=multi-user.target +``` + +After that you're supposed to reload systemd: + +```shell +systemctl daemon-reload +``` + +Launch clashd on system startup with: + +```shell +systemctl enable clash +``` + +Launch clashd immediately with: + +```shell +systemctl start clash +``` + +Check the health and logs of Clash with: + +```shell +systemctl status clash +journalctl -xe +``` + +Credits to [ktechmidas](https://github.com/ktechmidas) for this guide. ([#754](https://github.com/Dreamacro/clash/issues/754)) + +## Docker + +We provide pre-built images of Clash and Clash Premium. Therefore you can deploy Clash with [Docker Compose](https://docs.docker.com/compose/) if you're on Linux. However, you should be advised that it's [not recommended](https://github.com/Dreamacro/clash/issues/2249#issuecomment-1203494599) to run **Clash Premium** in a container. + +::: warning +This setup will not work on macOS systems due to the lack of [host networking and TUN support](https://github.com/Dreamacro/clash/issues/770#issuecomment-650951876) in Docker for Mac. +::: + + +::: code-group + +```yaml [Clash] +services: + clash: + image: ghcr.io/dreamacro/clash + restart: always + volumes: + - ./config.yaml:/root/.config/clash/config.yaml:ro + # - ./ui:/ui:ro # dashboard volume + ports: + - "7890:7890" + - "7891:7891" + # - "8080:8080" # The External Controller (RESTful API) + network_mode: "bridge" +``` + +```yaml [Clash Premium] +services: + clash: + image: ghcr.io/dreamacro/clash-premium + restart: always + volumes: + - ./config.yaml:/root/.config/clash/config.yaml:ro + # - ./ui:/ui:ro # dashboard volume + ports: + - "7890:7890" + - "7891:7891" + # - "8080:8080" # The External Controller (RESTful API) + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun + network_mode: "host" +``` + +::: + +Save as `docker-compose.yaml` and place your `config.yaml` in the same directory. + +::: tip +Before proceeding, refer to your platform documentations about time synchronisation - things will break if time is not in sync. +::: + +When you're ready, run the following commands to bring up Clash: + +```shell +docker-compose up -d +``` + +You can view the logs with: + +```shell +docker-compose logs +``` + +Stop Clash with: + +```shell +docker-compose stop +``` diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..654efb8 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "docs:dev": "vitepress dev docs", + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" + }, + "devDependencies": { + "@types/node": "^20.1.4", + "directory-tree": "^3.5.1", + "markdown-yaml-metadata-parser": "^3.0.0", + "vitepress": "^1.0.0-alpha.75" + } +} diff --git a/docs/premium/ebpf.md b/docs/premium/ebpf.md new file mode 100644 index 0000000..74cc6a9 --- /dev/null +++ b/docs/premium/ebpf.md @@ -0,0 +1,22 @@ +--- +sidebarTitle: "Feature: eBPF Redirect to TUN" +sidebarOrder: 3 +--- + +# eBPF Redirect to TUN + +eBPF redirect to TUN is a feature that intercepts all network traffic on a specific network interface and redirects it to the TUN interface. + +::: warning +This feature conflicts with `tun.auto-route`. +::: + +It requires [kernel support](https://github.com/iovisor/bcc/blob/master/INSTALL.md#kernel-configuration) and is less tested, however it would bring better performance compared to `tun.auto-redir` and `tun.auto-route`. + +## Configuration + +```yaml +ebpf: + redirect-to-tun: + - eth0 +``` diff --git a/docs/premium/experimental-features.md b/docs/premium/experimental-features.md new file mode 100644 index 0000000..89c8d1e --- /dev/null +++ b/docs/premium/experimental-features.md @@ -0,0 +1,19 @@ +--- +sidebarTitle: Experimental Features +sidebarOrder: 9 +--- + +# Experimental Features + +Occasionally we make new features that would require a fair amount of testing before having it in the main release. These features are marked as experimental and are disabled by default. + +::: warning +Some features listed here can be unstable, and might get removed in any future version - we do not recommend using them unless you have a specific reason to do so. +::: + +## Sniff TLS SNI + +```yaml +experimental: + sniff-tls-sni: true +``` diff --git a/docs/premium/introduction.md b/docs/premium/introduction.md new file mode 100644 index 0000000..2d3aecb --- /dev/null +++ b/docs/premium/introduction.md @@ -0,0 +1,26 @@ +--- +sidebarTitle: Introduction +sidebarOrder: 1 +--- + +# Introduction + +In the past, there was only one open-source version of Clash, until some [improper uses and redistributions](https://github.com/Dreamacro/clash/issues/541#issuecomment-672029110) of Clash arose. From that, we decided to fork Clash and develop the more advanced features in a private GitHub repository. + +Don't worry just yet - the Premium core will stay free of charge, and the security is enforced with peer reviews from multiple credible developers. + +## What's the difference? + +The Premium core is a fork of the open-source Clash core with the addition of the following features: + +- [TUN Device](/premium/tun-device) with the support of `auto-redir` and `auto-route` +- [eBPF Redirect to TUN](/premium/ebpf) +- [Rule Providers](/premium/rule-providers) +- [Script](/premium/script) +- [Script Shortcuts](/premium/script-shortcuts) +- [Userspace Wireguard](/premium/userspace-wireguard) +- [The Profiling Engine](/premium/the-profiling-engine) + +## Obtaining a Copy + +You can download the latest Clash Premium binaries from [GitHub Releases](https://github.com/Dreamacro/clash/releases/tag/premium). diff --git a/docs/premium/rule-providers.md b/docs/premium/rule-providers.md new file mode 100644 index 0000000..300085e --- /dev/null +++ b/docs/premium/rule-providers.md @@ -0,0 +1,100 @@ +--- +sidebarTitle: "Feature: Rule Providers" +sidebarOrder: 4 +--- + +# Rule Providers + +Rule Providers are pretty much the same compared to Proxy Providers. It enables users to load rules from external sources and overall cleaner configuration. This feature is currently Premium core only. + +To define a Rule Provider, add the `rule-providers` field to the main configuration: + +```yaml +rule-providers: + apple: + behavior: "domain" # domain, ipcidr or classical (premium core only) + type: http + url: "url" + # format: 'yaml' # or 'text' + interval: 3600 + path: ./apple.yaml + microsoft: + behavior: "domain" + type: file + path: /microsoft.yaml + +rules: + - RULE-SET,apple,REJECT + - RULE-SET,microsoft,policy +``` + +There are three behavior types available: + +## `domain` + +yaml: + +```yaml +payload: + - '.blogger.com' + - '*.*.microsoft.com' + - 'books.itunes.apple.com' +``` + +text: + +```txt +# comment +.blogger.com +*.*.microsoft.com +books.itunes.apple.com +``` + +## `ipcidr` + +yaml + +```yaml +payload: + - '192.168.1.0/24' + - '10.0.0.0.1/32' +``` + +text: + +```txt +# comment +192.168.1.0/24 +10.0.0.0.1/32 +``` + +## `classical` + +yaml: + +```yaml +payload: + - DOMAIN-SUFFIX,google.com + - DOMAIN-KEYWORD,google + - DOMAIN,ad.com + - SRC-IP-CIDR,192.168.1.201/32 + - IP-CIDR,127.0.0.0/8 + - GEOIP,CN + - DST-PORT,80 + - SRC-PORT,7777 + # MATCH is not necessary here +``` + +text: + +```txt +# comment +DOMAIN-SUFFIX,google.com +DOMAIN-KEYWORD,google +DOMAIN,ad.com +SRC-IP-CIDR,192.168.1.201/32 +IP-CIDR,127.0.0.0/8 +GEOIP,CN +DST-PORT,80 +SRC-PORT,7777 +``` diff --git a/docs/premium/script-shortcuts.md b/docs/premium/script-shortcuts.md new file mode 100644 index 0000000..9b48959 --- /dev/null +++ b/docs/premium/script-shortcuts.md @@ -0,0 +1,38 @@ +--- +sidebarTitle: "Feature: Script Shortcuts" +sidebarOrder: 6 +--- + +# Script Shortcuts + +Clash Premium implements the Scripting feature powered by Python3, enableing users to programmatically select policies for the packets with dynamic flexibility. + +You can either controll the entire rule-matching engine with a single Python script, or define a number of shortcuts and use them in companion with the regular rules. This page refers to the latter feature, for the former, see [Script](./script.md). + +This feature enables the use of script in `rules` mode. By default, DNS resolution takes place for SCRIPT rules. `no-resolve` can be appended to the rule to prevent the resolution. (i.e.: `SCRIPT,quic,DIRECT,no-resolve`) + +**NOTE: ****`src_port`**** and ****`dst_port`**** are number** + +```yaml +mode: Rule + +script: + shortcuts: + quic: network == 'udp' and dst_port == 443 + curl: resolve_process_name() == 'curl' + # curl: resolve_process_path() == '/usr/bin/curl' + +rules: + - SCRIPT,quic,REJECT +``` + +## Function Definitions + +```ts +type resolve_ip = (host: string) => string // ip string +type in_cidr = (ip: string, cidr: string) => boolean // ip in cidr +type geoip = (ip: string) => string // country code +type match_provider = (name: string) => boolean // in rule provider +type resolve_process_name = () => string // find process name (curl .e.g) +type resolve_process_path = () => string // find process path (/usr/bin/curl .e.g) +``` diff --git a/docs/premium/script.md b/docs/premium/script.md new file mode 100644 index 0000000..6711d16 --- /dev/null +++ b/docs/premium/script.md @@ -0,0 +1,70 @@ +--- +sidebarTitle: "Feature: Script" +sidebarOrder: 5 +--- + +# Script + +Clash Premium implements the Scripting feature powered by Python3, enableing users to programmatically select policies for the packets with dynamic flexibility. + +You can either controll the entire rule-matching engine with a single Python script, or define a number of shortcuts and use them in companion with the regular rules. This page refers to the first feature, for the latter, see [Script Shortcuts](./script-shortcuts.md). + +## Scripting the entire rule-matching engine + +```yaml +mode: Script + +# https://lancellc.gitbook.io/clash/clash-config-file/script +script: + code: | + def main(ctx, metadata): + ip = metadata["dst_ip"] = ctx.resolve_ip(metadata["host"]) + if ip == "": + return "DIRECT" + + code = ctx.geoip(ip) + if code == "LAN" or code == "CN": + return "DIRECT" + + return "Proxy" # default policy for requests which are not matched by any other script +``` + +If you want to use ip rules (i.e.: IP-CIDR, GEOIP, etc), you will first need to manually resolve IP addresses and assign them to metadata: + +```python +def main(ctx, metadata): + # ctx.rule_providers["geoip"].match(metadata) return false + + ip = ctx.resolve_ip(metadata["host"]) + if ip == "": + return "DIRECT" + metadata["dst_ip"] = ip + + # ctx.rule_providers["iprule"].match(metadata) return true + + return "Proxy" +``` + +Interface definition for Metadata and Context: + +```ts +interface Metadata { + type: string // socks5、http + network: string // tcp + host: string + src_ip: string + src_port: string + dst_ip: string + dst_port: string +} + +interface Context { + resolve_ip: (host: string) => string // ip string + resolve_process_name: (metadata: Metadata) => string + resolve_process_path: (metadata: Metadata) => string + geoip: (ip: string) => string // country code + log: (log: string) => void + proxy_providers: Record> + rule_providers: Record boolean }> +} +``` diff --git a/docs/premium/the-profiling-engine.md b/docs/premium/the-profiling-engine.md new file mode 100644 index 0000000..87adaae --- /dev/null +++ b/docs/premium/the-profiling-engine.md @@ -0,0 +1,13 @@ +--- +sidebarTitle: "Feature: The Profiling Engine" +sidebarOrder: 8 +--- + +# The Profiling Engine + +https://github.com/Dreamacro/clash-tracing + +```yaml +profile: + tracing: true +``` diff --git a/docs/premium/tun-device.md b/docs/premium/tun-device.md new file mode 100644 index 0000000..49a8915 --- /dev/null +++ b/docs/premium/tun-device.md @@ -0,0 +1,65 @@ +--- +sidebarTitle: "Feature: TUN Device" +sidebarOrder: 2 +--- + +# TUN Device + +The Premium core has out-of-the-box support of TUN device. Being a Network layer device, it can be used to handle TCP, UDP, ICMP traffic. It has been extensively tested and used in production environments - you can even play competitive games with it. + +One of the biggest advantage of using Clash TUN is the built-in support of the *automagic* management of the route table, routing rules and nftable. You can enable it with the options `tun.auto-route` and `tun.auto-redir`. It's a drop-in replacement of the ancient configuration option `redir-port` (TCP) for the sake of easier configuration and better stability. + +::: tip +`tun.auto-route` and `tun.auto-redir` are only available on macOS, Windows, Linux and Android, and only receives IPv4 traffic. +::: + +There are two options of TCP/IP stack available: `system` or `gvisor`. In order to get the best performance available, we recommend that you always use `system` stack unless you have a specific reason or compatibility issue to use `gvisor`. If that's the case, do not hesitate to [submit an issue](https://github.com/Dreamacro/clash/issues/new/choose). + +## Technical Limitations + +* For Android, the control device is at `/dev/tun` instead of `/dev/net/tun`, you will need to create a symbolic link first (i.e. `ln -sf /dev/tun /dev/net/tun`) + +* DNS hijacking might result in a failure, if the system DNS is at a private IP address (since `auto-route` does not capture private network traffic). + +## Linux, macOS or Android + +This is an example configuration of the TUN feature: + +```yaml +interface-name: en0 # conflict with `tun.auto-detect-interface` + +tun: + enable: true + stack: system # or gvisor + # dns-hijack: + # - 8.8.8.8:53 + # - tcp://8.8.8.8:53 + # - any:53 + # - tcp://any:53 + auto-route: true # manage `ip route` and `ip rules` + auto-redir: true # manage nftable REDIRECT + auto-detect-interface: true # conflict with `interface-name` +``` + +Be advised, since the use of TUN device and manipulation of system route/nft settings, Clash will need superuser privileges to run. + +```shell +sudo ./clash +``` + +If your device already has some TUN device, Clash TUN might not work - you will have to check the route table and routing rules manually. In this case, `fake-ip-filter` may helpful as well. + +## Windows + +You will need to visit the [WinTUN website](https://www.wintun.net) and download the latest release. After that, copy `wintun.dll` into Clash home directory. Example configuration: + +```yaml +tun: + enable: true + stack: gvisor # or system + dns-hijack: + - 198.18.0.2:53 # when `fake-ip-range` is 198.18.0.1/16, should hijack 198.18.0.2:53 + auto-route: true # auto set global route for Windows + # It is recommended to use `interface-name` + auto-detect-interface: true # auto detect interface, conflict with `interface-name` +``` diff --git a/docs/premium/userspace-wireguard.md b/docs/premium/userspace-wireguard.md new file mode 100644 index 0000000..3c93e95 --- /dev/null +++ b/docs/premium/userspace-wireguard.md @@ -0,0 +1,25 @@ +--- +sidebarTitle: "Feature: Userspace Wireguard" +sidebarOrder: 7 +--- + +# Userspace Wireguard + +Due to the dependency on gvisor TCP/IP stack, Wireguard outbound is currently only available in the Premium core. + +```yaml +proxies: + - name: "wg" + type: wireguard + server: 127.0.0.1 + port: 443 + ip: 172.16.0.2 + # ipv6: your_ipv6 + private-key: eCtXsJZ27+4PbhDkHnB923tkUn2Gj59wZw5wFA75MnU= + public-key: Cr8hWlKvtDt7nrvf+f0brNQQzabAqrjfBvas9pmowjo= + # preshared-key: base64 + # remote-dns-resolve: true # remote resolve DNS with `dns` field, default is true + # dns: [1.1.1.1, 8.8.8.8] + # mtu: 1420 + udp: true +``` diff --git a/docs/runtime/external-controller.md b/docs/runtime/external-controller.md new file mode 100644 index 0000000..ebf4dc9 --- /dev/null +++ b/docs/runtime/external-controller.md @@ -0,0 +1,130 @@ +--- +sidebarTitle: The External Controller +sidebarOrder: 1 +--- + +# The External Controller + +## Introduction + +External Controller enables users to control Clash programmatically with the HTTP RESTful API. The third-party Clash GUIs are heavily based on this feature. Enable this feature by specifying an address in `external-controller`. + +## Authentication + +- External Controllers Accept `Bearer Tokens` as access authentication method. + - Use `Authorization: Bearer ` as your request header in order to pass credentials. + +## RESTful API Documentation + +### Logs + +- `/logs` + - Method: `GET` + - Full Path: `GET /logs` + - Description: Get real-time logs + +### Traffic + +- `/traffic` + - Method: `GET` + - Full Path: `GET /traffic` + - Description: Get real-time traffic data + +### Version + +- `/version` + - Method: `GET` + - Full Path: `GET /version` + - Description: Get clash version + +### Configs + +- `/configs` + - Method: `GET` + - Full Path: `GET /configs` + - Description: Get base configs + + - Method: `PUT` + - Full Path: `PUT /configs` + - Description: Reloading base configs + + - Method: `PATCH` + - Full Path: `PATCH /configs` + - Description: Update base configs + +### Proxies + +- `/proxies` + - Method: `GET` + - Full Path: `GET /proxies` + - Description: Get proxies information + +- `/proxies/:name` + - Method: `GET` + - Full Path: `GET /proxies/:name` + - Description: Get specific proxy information + + - Method: `PUT` + - Full Path: `PUT /proxies/:name` + - Description: Select specific proxy + +- `/proxies/:name/delay` + - Method: `GET` + - Full Path: `GET /proxies/:name/delay` + - Description: Get specific proxy delay test information + +### Rules + +- `/rules` + - Method: `GET` + - Full Path: `GET /rules` + - Description: Get rules information + +### Connections + +- `/connections` + - Method: `GET` + - Full Path: `GET /connections` + - Description: Get connections information + + - Method: `DELETE` + - Full Path: `DELETE /connections` + - Description: Close all connections + +- `/connections/:id` + - Method: `DELETE` + - Full Path: `DELETE /connections/:id` + - Description: Close specific connection + +### Providers + +- `/providers/proxies` + - Method: `GET` + - Full Path: `GET /providers/proxies` + - Description: Get all proxies information for all proxy-providers + +- `/providers/proxies/:name` + - Method: `GET` + - Full Path: `GET /providers/proxies/:name` + - Description: Get proxies information for specific proxy-provider + + - Method: `PUT` + - Full Path: `PUT /providers/proxies/:name` + - Description: Select specific proxy-provider + +- `/providers/proxies/:name/healthcheck` + - Method: `GET` + - Full Path: `GET /providers/proxies/:name/healthcheck` + - Description: Get proxies information for specific proxy-provider + +### DNS Query + +- `/dns/query` + - Method: `GET` + - Full Path: `GET /dns/query?name={name}[&type={type}]` + - Description: Get DNS query data for a specified name and type. + - Parameters: + - `name` (required): The domain name to query. + - `type` (optional): The DNS record type to query (e.g., A, MX, CNAME, etc.). Defaults to `A` if not provided. + + - Example: `GET /dns/query?name=example.com&type=A`