forked from doreamon-design/clash
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
1 parent
10dcb7a
commit ca42ca2
Showing
30 changed files
with
2,477 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.