Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(/docs): rework documentation structure layout #179

Merged
merged 12 commits into from
Jul 9, 2023
Merged
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ As a successor of [v2rayA](https://github.com/v2rayA/v2rayA), dae abandoned v2ra
- [x] Support to automatically switch nodes according to policy. That is to say, support to automatically test independent TCP/UDP/IPv4/IPv6 latencies, and then use the best nodes for corresponding traffic according to user-defined policy.
- [x] Support advanced DNS resolution process.
- [x] Support full-cone NAT for shadowsocks, trojan(-go) and socks5 (no test).
- [x] Support various trending proxy protocols, seen in [proxy-protocols.md](./docs/en/proxy-protocols.md).

## Getting Started

Please refer to [Quick Start Guide](./docs/getting-started) to start using `dae` right away!
Please refer to [Quick Start Guide](./docs/en/README.md) to start using `dae` right away!

Documentation: <https://dae.v2raya.org>

Expand All @@ -40,7 +41,7 @@ Documentation: <https://dae.v2raya.org>

## How it works

See [How it works](docs/how_it_works_zh.md).
See [How it works](./docs/en/how-it-works.md).

## TODO

Expand All @@ -53,7 +54,7 @@ See [How it works](docs/how_it_works_zh.md).

## Contributors

Special thanks goes to all [contributors](https://github.com/daeuniverse/dae/graphs/contributors). If you would like to contribute, please see the [instructions](./CONTRIBUTING.md). Also, it is recommended following the [commit-msg-guide](./docs/commit-msg-guide.md).
Special thanks goes to all [contributors](https://github.com/daeuniverse/dae/graphs/contributors). If you would like to contribute, please see the [instructions](./docs/en/development/contribute.md). Also, it is recommended following the [commit-msg-guide](./docs/en/development/commit-msg-guide.md).

## License

Expand Down
18 changes: 9 additions & 9 deletions docs/getting-started/README.md → docs/en/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Quick Start Guide

[**简体中文**](README_zh.md) | [**English**](README.md)
[**简体中文**](../zh/README.md) | [**English**](README.md)

## Linux Kernel Requirement

Expand All @@ -9,7 +9,7 @@
Use `uname -r` to check the kernel version on your machine.

> **Note**
> If you find your kernel version is `< 5.8`, follow the [**Upgrade Guide**](./kernel-upgrade.md) to upgrade the kernel to the minimum required version.
> If you find your kernel version is `< 5.8`, follow the [**Upgrade Guide**](user-guide/kernel-upgrade.md) to upgrade the kernel to the minimum required version.

`Bind to LAN: >= 5.8`

Expand Down Expand Up @@ -64,7 +64,7 @@ Check them using command like:
(zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}) | grep -E 'CONFIG_(DEBUG_INFO|DEBUG_INFO_BTF|KPROBES|KPROBE_EVENTS|BPF|BPF_SYSCALL|BPF_JIT|BPF_STREAM_PARSER|NET_CLS_ACT|NET_SCH_INGRESS|NET_INGRESS|NET_EGRESS|NET_CLS_BPF|BPF_EVENTS|CGROUPS)=|# CONFIG_DEBUG_INFO_REDUCED is not set'
```

> **Note**: `Armbian` users can follow the [**Upgrade Guide**](./kernel-upgrade.md) to upgrade the kernel to meet the kernel configuration requirement.
> **Note**: `Armbian` users can follow the [**Upgrade Guide**](user-guide/kernel-upgrade.md) to upgrade the kernel to meet the kernel configuration requirement.

## Installation

Expand Down Expand Up @@ -104,7 +104,7 @@ emerge -a net-proxy/dae

### macOS

We provide a hacky way to run dae on your macOS. See [run on macOS](run-on-macos.md).
We provide a hacky way to run dae on your macOS. See [run on macOS](tutorials/run-on-macos.md).

### Docker

Expand All @@ -121,15 +121,15 @@ docker compose up -d --build

> **Note**: This approach is **ONLY** recommended for `advanced` users. With this approach, users may have flexibility to test various versions of dae. Noted that newly introduced features are sometimes buggy, do it at your own risk.

dae can run as a daemon (systemd) service. See [run-as-daemon](run-as-daemon.md)
dae can run as a daemon (systemd) service. See [run-as-daemon](user-guide/run-as-daemon.md)

### Installation Script

See [daeuniverse/dae-installer](https://github.com/daeuniverse/dae-installer) (or [mirror](https://hubmirror.v2raya.org/daeuniverse/dae-installer)).

### Build from scratch

See [Build Guide](build-by-yourself.md).
See [Build Guide](user-guide/build-by-yourself.md).

## Minimal Configuration

Expand Down Expand Up @@ -157,7 +157,7 @@ subscription {
# Fill in your subscription links here.
}

# See https://github.com/daeuniverse/dae/blob/main/docs/dns.md for full examples.
# See https://github.com/daeuniverse/dae/blob/main/docs/en/configuration/dns.md for full examples.
dns {
upstream {
googledns: 'tcp+udp://dns.google.com:53'
Expand All @@ -182,7 +182,7 @@ group {
}
}

# See https://github.com/daeuniverse/dae/blob/main/docs/routing.md for full examples.
# See https://github.com/daeuniverse/dae/blob/main/docs/en/configuration/routing.md for full examples.
routing {
pname(NetworkManager) -> direct
dip(224.0.0.0/3, 'ff00::/8') -> direct
Expand All @@ -205,7 +205,7 @@ If you use PVE, refer to [#37](https://github.com/daeuniverse/dae/discussions/37

When the configuration changes, it is convenient to use command to hot reload the configuration, and the existing connection will not be interrupted in the process. When you want to suspend dae, you can use command to pause.

See [Reload and suspend](reload-and-suspend.md).
See [Reload and suspend](user-guide/reload-and-suspend.md).

## Troubleshooting

Expand Down
2 changes: 1 addition & 1 deletion docs/dns.md → docs/en/configuration/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dns {
googledns: 'tcp+udp://dns.google.com:53'
}
# The routing format of 'request' and 'response' is similar with section 'routing'.
# See https://github.com/daeuniverse/dae/blob/main/docs/routing.md
# See https://github.com/daeuniverse/dae/blob/main/docs/en/configuration/routing.md
routing {
# According to the request of dns query, decide to use which DNS upstream.
# Match rules from top to bottom.
Expand Down
File renamed without changes.
File renamed without changes.
24 changes: 12 additions & 12 deletions CONTRIBUTING.md → docs/en/development/contribute.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# Contribute

If you want to contribute to a project and make it better, your help is very welcome. Contributing is also a great way to learn more about social coding on Github, new technologies and and their ecosystems and how to make constructive, helpful bug reports, feature requests and the noblest of all contributions: a good, clean pull request.
If you want to contribute to a project and make it better, your help is very welcome. Contributing is also a great way to learn more about social coding on GitHub, new technologies and their ecosystems and how to make constructive, helpful bug reports, feature requests and the noblest of all contributions: a good, clean pull request.

### Bug Reports and Feature Requests
## Bug Reports and Feature Requests

If you have found a `bug` or have a `feature request`, please use the search first in case a similar issue already exists. If not, please create an [issue](https://github.com/daeuniverse/dae/issues/new) in this repository

### Code
## Code

If you would like to fix a bug or implement a feature, please `fork` the repository and `create a Pull Request`.

Before you start any Pull Request, `it is recommended that you create an issue` to discuss first if you have any doubts about requirement or implementation. That way you can be sure that the maintainer(s) agree on what to change and how, and you can hopefully get a quick merge afterwards.

`Pull Requests` can only be merged once all status checks are green.

### Pre-commit Hook
## Pre-commit Hook

This repo uses [pre-commit hook](https://github.com/pre-commit/pre-commit-hooks) to apply linting check prior to writing commit to local git history. To set up pre-commit, do the followings:
This repo uses [pre-commit hook](https://github.com/pre-commit/pre-commit-hooks) to apply linting check prior to writing commit to local Git history. To set up pre-commit, do the followings:

```bash
# install pre-commit
Expand All @@ -25,10 +25,10 @@ pip3 install pre-commit
pre-commit install
```

### How to make a clean pull request
## How to make a clean pull request

- Create a `personal fork` of the project on Github.
- Clone the fork on your local machine. Your remote repo on Github is called `origin`.
- Create a `personal fork` of the project on GitHub.
- Clone the fork on your local machine. Your remote repo on GitHub is called `origin`.
- Add the original repository as a remote called `upstream`.
- If you created your fork a while ago be sure to pull upstream changes into your local repository.
- Create a new branch to work on! Branch from `develop` if it exists, else from `master`.
Expand All @@ -37,14 +37,14 @@ pre-commit install
- If the project has tests run them!
- Write or adapt tests as needed.
- Add or change the documentation as needed.
- Squash your commits into a single commit with git's [interactive rebase](https://help.github.com/articles/interactive-rebase). Create a new branch if necessary.
- Push your branch to your fork on Github, the remote `origin`.
- Squash your commits into a single commit with Git's [interactive rebase](https://help.github.com/articles/interactive-rebase). Create a new branch if necessary.
- Push your branch to your fork on GitHub, the remote `origin`.
- From your fork open a pull request in the correct branch. Target the project's `develop` branch if there is one, else go for `master`!
- Once the pull request is approved and merged you can pull the changes from `upstream` to your local repo and delete
your extra branch(es).

And last but not least: Always write your commit messages in the present tense. Your commit message should describe what the commit, when applied, does to the code – not what you did to the code.

### Re-requesting a review
## Re-requesting a review

Please do not ping your reviewer(s) by mentioning them in a new comment. Instead, use the re-request review functionality. Read more about this in the [ GitHub docs, Re-requesting a review ](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request#re-requesting-a-review).
Please do not ping your reviewer(s) by mentioning them in a new comment. Instead, use the re-request review functionality. Read more about this in the [GitHub docs, Re-requesting a review](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request#re-requesting-a-review).
61 changes: 61 additions & 0 deletions docs/en/how-it-works.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Working Principle of dae

[**简体中文**](../zh/how-it-works.md) | [**English**](./how-it-works.md)

dae operates by loading a program into the tc (traffic control) mount point in the Linux kernel using [eBPF](https://en.wikipedia.org/wiki/EBPF). This program performs traffic splitting before the traffic enters the TCP/IP network stack. The position of tc in the Linux network protocol stack is shown in the diagram below (the diagram illustrates the receiving path, while the sending path is in the opposite direction), where netfilter represents the location of iptables/nftables.

![](../netstack-path.webp)

## Traffic Splitting Principle

### Splitting Information

dae supports traffic splitting based on domain name, source IP, destination IP, source port, destination port, TCP/UDP, IPv4/IPv6, process name, MAC address, and other factors.

Among them, source IP, destination IP, source port, destination port, TCP/UDP, IPv4/IPv6, and MAC address can be obtained by parsing MACv2 frames.

The **process name** is obtained by listening to local process socket, connect, and sendmsg system calls in the cgroupv2 mount point and reading and parsing the command line from the process control block. This method is much faster than user-space programs like Clash that scan the entire procfs to obtain process information (the latter may take even tens of milliseconds).

The **domain name** is obtained by intercepting DNS requests and associating the requested domain name with the corresponding IP address. Although this method has some issues:

1. It may lead to misjudgment. For example, if two websites, one domestic and one foreign, share the same IP address and are accessed simultaneously within a short period of time, or if the browser has DNS caching.
2. The user's DNS requests must go through dae. For example, setting dae as the DNS server or using public DNS while dae is acting as the gateway.

However, compared to other solutions, this approach is already an optimal solution. For example, the Fake IP approach cannot perform IP-based splitting and suffers from severe cache pollution issues, while the domain sniffing approach can only sniff traffic such as TLS/HTTP. In fact, using SNI sniffing for traffic splitting is indeed a better choice, but due to eBPF's limitations on program complexity and its lack of friendly support for loops, we cannot implement domain sniffing in the kernel space.

Therefore, when DNS requests cannot go through dae, domain-based splitting will fail.

> To reduce DNS pollution and achieve better CDN connection speed, dae implements domain sniffing in user space. When `dial_mode` is set to "domain" or its variants and the traffic needs to be proxied, dae sends the sniffed domain to the proxy server instead of sending the IP address. This way, the proxy server will re-resolve the domain and connect using the optimal IP, thereby solving the problem of DNS pollution and achieving better CDN connection speed.
>
> At the same time, for advanced users who have already used other splitting solutions and do not want to route DNS requests through dae but still want the part of the traffic to be split based on domain (e.g., splitting some traffic to Netflix nodes and some to download nodes based on the target domain, of course, some can be directly connected via the core), they can force the use of sniffed domain for splitting by setting `dial_mode: domain++`.

dae performs traffic splitting by redirecting the traffic using the program in the tc mount point. The redirection is based on the splitting result, either redirecting the traffic to dae's tproxy port or allowing it to bypass dae and go directly.

### Proxy Principle

The proxy principle of dae is similar to other programs. The difference is that when binding to the LAN interface, dae uses eBPF to directly associate the socket buffer of the traffic to be proxied in the tc mount point with the socket of dae's tproxy listening port. When binding to the WAN interface, dae moves the socket buffer of the traffic to be proxied from the egress queue of the network card to the ingress queue, disables its checksum, and modifies the destination address to the tproxy listening port.

In terms of benchmarking, dae's proxy performance is slightly better than other proxy programs, but not by much.

### Direct Connection Principle

Traditionally, in order to perform traffic splitting, the traffic needs to go through a proxy program, go through the splitting module, and then decide whether to go through a proxy or be directly connected. This involves parsing, processing, and copying the traffic through the network stack, passing it to the proxy program, and then copying, processing, and encapsulating it through the network stack before sending it out, which consumes a significant amount of resources. Especially for scenarios like BitTorrent downloads, even if direct connection is set, it still consumes a large number of connections, ports, memory, and CPU resources. It can even affect NAT type in gaming scenarios due to improper handling by the proxy program, resulting in connection errors.

dae performs traffic splitting at an earlier stage in the kernel, and directly connected traffic is forwarded through layer 3 routing, saving a significant amount of overhead from transitioning between kernel and user space. At this stage, Linux behaves like a pure switch or router.

> To make direct connection effective, for users with advanced topologies, please ensure that after configuring the [kernel parameters](user-guide/kernel-parameters.md) and **disabling** dae, other devices can access the network normally when the device where dae is located is set as the gateway. For example, accessing 223.5.5.5 should receive a "UrlPathError" response, and when performing tcpdump on the device where dae is located, you should be able to see the request packets from client devices.

Therefore, for directly connected traffic, dae does not perform SNAT. For users with a "side-router" setup, this will result in asymmetric routing, where traffic from client devices is sent through dae to the gateway when being sent out, but is directly sent from the gateway to the client devices when being received, bypassing dae.

> Here, "side-router" is defined as: 1) acting as the gateway, 2) performing SNAT on TCP/UDP, and 3) having the LAN interface and WAN interface in the same network segment.
>
> For example, if the laptop is at 192.168.0.3, the side-router is at 192.168.0.2, and the router is at 192.168.0.1, the logical three-layer topology would be: laptop -> side-router -> router. On the router side, only TCP/UDP traffic with a source IP of 192.168.0.2 can be seen, and there will be no TCP/UDP traffic with a source IP of 192.168.0.3.
>
> As far as we know, we are the first to define "side-router" like this (laughs).

Asymmetric routing brings one advantage and one potential issue:

1. It can improve performance. Since the return traffic does not pass through dae, the direct connection performance becomes as fast as without a side-router, as the path is reduced.
2. It may cause the failure of stateful firewall's state maintenance and result in packet loss (e.g., Sophos Firewall). However, this issue generally does not occur in home networks

From a benchmark perspective, the direct connectivity performance of dae is like a beast compared to other proxy.
48 changes: 48 additions & 0 deletions docs/en/proxy-protocols.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Proxy Protocols

> **Note**: dae currently supports the following proxy protocols

- [x] HTTP(S), naiveproxy
- [x] Socks
- [x] Socks4
- [x] Socks4a
- [x] Socks5
- [x] VMess(AEAD, alterID=0) / VLESS
- [x] TCP
- [x] WS
- [x] TLS
- [x] gRPC
- [x] Shadowsocks
- [x] AEAD Ciphers
- [x] Stream Ciphers
- [x] simple-obfs
- [ ] v2ray-plugin
- [x] ShadowsocksR
- [x] Trojan
- [x] Trojan-gfw
- [x] Trojan-go
- [x] Tuic (v5)

For other requirements, one way to expand protocol support is by using external proxy programs. Below is an example of using the external naiveproxy.

Although dae and other proxy programs support the HTTPS protocol, using them does not utilize the chromium networking stack, which weakens the camouflage effect of naiveproxy. Therefore, using an external naiveproxy program is recommended.

1. Start naiveproxy:

Since the socks implementation of naiveproxy may have some issues and cannot be used by curl and dae, the example uses naiveproxy to open an HTTP listening port. Note that HTTP proxy does not support proxying UDP traffic, so if you are using an external proxy program, it is advisable to prioritize using the socks5 port.

```bash
naiveproxy --listen=http://127.0.0.1:1090 --proxy=https://yourlink
```

2. In the section of dae's configuration related to nodes, add the following line: `http://127.0.0.1:1090`, and remember to use this node in the group you are using.

3. If you have bound the WAN interface, meaning you have filled in the `global.wan_interface` field, make sure to add the following line near the top in the routing section to prevent traffic from flowing back to dae after passing through naiveproxy, causing a loop:

```shell
pname(naiveproxy) -> must_direct
```

Here, `pname` refers to the process name. You can determine the process name of naiveproxy by examining the command used to start it, running the `ps -ef` command at runtime, or observing the dae logs. The meaning of `must_direct` is to allow all traffic, including DNS queries, to pass through directly without redirecting to dae.

Users who only bind the LAN interface do not need to perform this step.
Loading