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

* refactor(/docs): rework documentation structure layout

* refactor(/docs): update file reference paths

* feat(/docs): add English version of other-proxy-protocol.md

* refacotr: move docs/templates/ docs/sync/ to hack/

* fix(example.dae|readme): update ref link to adopt new file structure

* refactor: rename other-proxy-protocol.md -> proxy-protocols.md

* docs(readme): add ref to proxy-protocols.md

* feat(/docs): add English version of how-it-works.md

* refactor: rename how-it-works; add nav links

* fix: fix linting errors

* fix: fix linting errors

---------

Co-authored-by: earrmouth <43926351+earrmouth@users.noreply.github.com>
This commit is contained in:
Kevin Yu
2023-07-09 17:31:47 +08:00
committed by GitHub
parent d12c79ec44
commit e39ec7fc05
24 changed files with 163 additions and 53 deletions

212
docs/en/README.md Normal file
View File

@ -0,0 +1,212 @@
# Quick Start Guide
[**简体中文**](../zh/README.md) | [**English**](README.md)
## Linux Kernel Requirement
## Kernel Version
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**](user-guide/kernel-upgrade.md) to upgrade the kernel to the minimum required version.
`Bind to LAN: >= 5.8`
You need bind dae to LAN interface, if you want to provide network service for LAN as an intermediate device.
This feature requires the kernel version of machine on which dae install >= 5.8.
Note that if you bind dae to LAN only, dae only provide network service for traffic from LAN, and not impact local programs.
`Bind to WAN: >= 5.8`
You need bind dae to WAN interface, if you want dae to provide network service for local programs.
This feature requires kernel version of the machine >= 5.8.
Note that if you bind dae to WAN only, dae only provide network service for local programs and not impact traffic coming in from other interfaces.
## Kernel Configurations
Usually, mainstream desktop distributions have these items turned on. But in order to reduce kernel size, some items are turned off by default on embedded device distributions like OpenWRT, Armbian, etc.
Use following command to show kernel configuration items on your machine.
```shell
zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}
```
dae needs:
```
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_CGROUPS=y
CONFIG_KPROBES=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BPF=m
CONFIG_NET_CLS_ACT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
```
Check them using command like:
```shell
(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**](user-guide/kernel-upgrade.md) to upgrade the kernel to meet the kernel configuration requirement.
## Installation
### Archlinux/Manjaro
dae has been released on [AUR](https://aur.archlinux.org/packages/dae).
```shell
# yay -S dae
pacman -S --needed git base-devel
git clone https://aur.archlinux.org/dae.git
cd dae
makepkg -si
```
After installation, use systemctl to control it.
```shell
# start dae
sudo systemctl start dae
# auto start dae at boot
sudo systemctl enable dae
```
### Gentoo Linux
dae has been released on [gentoo-zh](https://github.com/microcai/gentoo-zh)
use `app-eselect/eselect-repository` to enable this overlay:
```shell
eselect repository enable gentoo-zh
emaint sync -r gentoo-zh
emerge -a net-proxy/dae
```
### macOS
We provide a hacky way to run dae on your macOS. See [run on macOS](tutorials/run-on-macos.md).
### Docker
Pre-built image and related docs can be found at <https://hub.docker.com/r/daeuniverse/dae>.
Alternatively, you can use `docker compose`:
```shell
git clone --depth=1 https://github.com/daeuniverse/dae
docker compose up -d --build
```
## Manual installation
> **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](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](user-guide/build-by-yourself.md).
## Minimal Configuration
For minimal bootable config:
```shell
global{}
routing{}
```
However, this config leaves dae no-load state. If you want dae to be in working state, following is a best practice for small config:
```shell
global {
# Bind to LAN and/or WAN as you want. Replace the interface name to your own.
#lan_interface: docker0
wan_interface: auto # Use "auto" to auto detect WAN interface.
log_level: info
allow_insecure: false
auto_config_kernel_parameter: true
}
subscription {
# Fill in your subscription links here.
}
# 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'
alidns: 'udp://dns.alidns.com:53'
}
routing {
request {
fallback: alidns
}
response {
upstream(googledns) -> accept
!qname(geosite:cn) && ip(geoip:private) -> googledns
fallback: accept
}
}
}
group {
proxy {
#filter: name(keyword: HK, keyword: SG)
policy: min_moving_avg
}
}
# 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
### Write your rules below.
dip(geoip:private) -> direct
dip(geoip:cn) -> direct
domain(geosite:cn) -> direct
fallback: proxy
}
```
See more at [example.dae](https://github.com/daeuniverse/dae/blob/main/example.dae).
If you use PVE, refer to [#37](https://github.com/daeuniverse/dae/discussions/37).
## Reload and suspend
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](user-guide/reload-and-suspend.md).
## Troubleshooting
See [Troubleshooting](troubleshooting.md).

View File

@ -0,0 +1,121 @@
# DNS
dae will intercept all UDP traffic to port 53 and sniff DNS. Here gives some examples and templates for DNS configuration.
## Examples
```shell
dns {
# For example, if ipversion_prefer is 4 and the domain name has both type A and type AAAA records, the dae will only
# respond to type A queries and response empty answer to type AAAA queries.
ipversion_prefer: 4
# Give a fixed ttl for domains. Zero means that dae will request to upstream every time and not cache DNS results
# for these domains.
fixed_domain_ttl {
ddns.example.org: 10
test.example.org: 3600
}
upstream {
# Value can be scheme://host:port.
# Scheme list: tcp, udp, tcp+udp. Ongoing: https, tls, quic.
# If host is a domain and has both IPv4 and IPv6 record, dae will automatically choose
# IPv4 or IPv6 to use according to group policy (such as min latency policy).
# Please make sure DNS traffic will go through and be forwarded by dae, which is REQUIRED for domain routing.
# If dial_mode is "ip", the upstream DNS answer SHOULD NOT be polluted, so domestic public DNS is not recommended.
alidns: 'udp://dns.alidns.com:53'
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/en/configuration/routing.md
routing {
# According to the request of dns query, decide to use which DNS upstream.
# Match rules from top to bottom.
request {
# Built-in outbounds in 'request': asis, reject.
# You can also use user-defined upstreams.
# Available functions: qname, qtype.
# DNS request name (omit suffix dot '.').
qname(geosite:category-ads-all) -> reject
qname(geosite:google@cn) -> alidns # Also see: https://github.com/v2fly/domain-list-community#attributes
qname(suffix: abc.com, keyword: google) -> googledns
qname(full: ok.com, regex: '^yes') -> googledns
# DNS request type
qtype(a, aaaa) -> alidns
qtype(cname) -> googledns
# If no match, fallback to this upstream.
fallback: asis
}
# According to the response of dns query, decide to accept or re-lookup using another DNS upstream.
# Match rules from top to bottom.
response {
# Built-in outbounds in 'response': accept, reject.
# You can use user-defined upstreams.
# Available functions: qname, qtype, upstream, ip.
# Accept the response if the request is sent to upstream 'googledns'. This is useful to avoid loop.
upstream(googledns) -> accept
# If DNS request name is not in CN and response answers include private IP, which is most likely polluted
# in China mainland. Therefore, resend DNS request to 'googledns' to get correct result.
!qname(geosite:cn) && ip(geoip:private) -> googledns
fallback: accept
}
}
}
```
## Templates
```shell
# Use alidns for China mainland domains and googledns for others.
dns {
upstream {
googledns: 'tcp+udp://dns.google.com:53'
alidns: 'udp://dns.alidns.com:53'
}
routing {
# According to the request of dns query, decide to use which DNS upstream.
# Match rules from top to bottom.
request {
# Lookup China mainland domains using alidns, otherwise googledns.
qname(geosite:cn) -> alidns
# fallback is also called default.
fallback: googledns
}
}
}
```
```shell
# Use alidns for all DNS queries and fallback to googledns if pollution result detected.
dns {
upstream {
googledns: 'tcp+udp://dns.google.com:53'
alidns: 'udp://dns.alidns.com:53'
}
routing {
# According to the request of dns query, decide to use which DNS upstream.
# Match rules from top to bottom.
request {
# fallback is also called default.
fallback: alidns
}
# According to the response of dns query, decide to accept or re-lookup using another DNS upstream.
# Match rules from top to bottom.
response {
# Trusted upstream. Always accept its result.
upstream(googledns) -> accept
# Possibly polluted, re-lookup using googledns.
!qname(geosite:cn) && ip(geoip:private) -> googledns
# fallback is also called default.
fallback: accept
}
}
}
```

View File

@ -0,0 +1,98 @@
# Use External DNS
> **Note**
> DNS request should be forwarded by dae for domain based traffic split. This guide will show you how to configure dae with external DNS.
If you use a external DNS like AdguardHome, you could refer to the following guide.
## External DNS on localhost
If you set up an external DNS on localhost, you may want to let the DNS queries to `dns.google.com` proxied. For example, if you have the following configuration in AdguardHome:
```
Listen on: the same machine with dae, port 53.
China mainland: udp://223.5.5.5:53
Others: https://dns.google.com/dns-query
```
You should configure dae as follows:
1. Complete `wan_interface` in "global" section to proxy requests of AdguardHome.
2. Insert following rule as the first line of "routing" section to avoid loops.
```python
pname(AdGuardHome) && l4proto(udp) && dport(53) -> must_direct
```
And make sure domain `dns.google.com` will be proxied in routing rules.
3. Add upstream and request to section "dns".
```
dns {
upstream {
adguardhome: 'udp://127.0.0.1:53'
}
routing {
request {
fallback: adguardhome
}
}
}
```
4. If you bind to WAN, make sure your `/etc/resolv.conf` does NOT use your local external DNS directly. For example, you can set it as `nameserver 119.29.29.29`, and then DNS traffic will be hijacked by dae when the packets are sent through NIC. Most of the time, `/etc/resolv.conf` will be modified back by your DNS service like dnsmasq after rebooting, which is hard to deal with. We recommended you to uninstall them or give `sudo chattr +i /etc/resolv.conf` if you encounter such situation.
5. If you bind to LAN, make sure your DHCP server will distribute dae as the DNS server (DNS request should be forwarded by dae for domain based traffic split).
6. If there is still a DNS issue and there are no warn/error logs, you have to change your listening port of external DNS (here is AdGuardHome) from 53 to non-53 port. See [#31](https://github.com/daeuniverse/dae/issues/31#issuecomment-1467358364).
7. If you use PVE, refer to [#37](https://github.com/daeuniverse/dae/discussions/37).
## External DNS on another machine in LAN
If you set up a external DNS on another machine in LAN, you may want to let the DNS queries to `dns.google.com` proxied. For example, if you have following configuration in `AdguardHome`:
```
Listen on: 192.168.30.3:53 (mac address: 8c:16:45:36:1c:5a)
China mainland: udp://223.5.5.5:53
Others: https://dns.google.com/dns-query
```
You should configure dae as follows:
1. Fill in `lan_interface` in "global" section to proxy requests of AdguardHome.
2. Insert following rule as the first line of "routing" section to avoid loops.
```python
sip(192.168.30.3) && l4proto(udp) && dport(53) -> must_direct
# Or use MAC address if in the same link:
# mac(8c:16:45:36:1c:5a) && l4proto(udp) && dport(53) -> must_direct
```
And make sure domain `dns.google.com` will be proxied in routing rules.
3. Add upstream and request to section "dns".
```
dns {
upstream {
adguardhome: 'udp://192.168.30.3:53'
}
routing {
request {
fallback: adguardhome
}
}
}
```
4. If you bind to LAN, make sure your DHCP server will distribute dae as the DNS server (DNS request should be forwarded by dae for domain based traffic split).
5. If there is still a DNS issue and there are no warn/error logs, you have to change your listening port of external DNS (here is AdGuardHome) from 53 to non-53 port. See [#31](https://github.com/daeuniverse/dae/issues/31#issuecomment-1467358364).
6. If you use PVE, refer to [#37](https://github.com/daeuniverse/dae/discussions/37).

View File

@ -0,0 +1,109 @@
# Routing
## Examples
```shell
### Built-in outbounds: block, direct, must_rules
# must_rules means no redirecting DNS traffic to dae and continue to matching.
# For single rule, the difference between "direct" and "must_direct" is that "direct" will hijack and process DNS request
# (for traffic split use), but "must_direct" will not. "must_direct" is useful when there are traffic loops of DNS requests.
# "must_direct" can also be written as "direct(must)".
# Similarly, "must_groupname" is also supported to NOT hijack and process DNS traffic, which equals to "groupname(must)".
### fallback outbound
# If no rule matches, traffic will go through the outbound defined by fallback.
fallback: my_group
### Domain rule
domain(suffix: v2raya.org) -> my_group
# equals to domain(v2raya.org) -> my_group
domain(full: dns.google.com) -> my_group
domain(keyword: facebook) -> my_group
domain(regex: '\.goo.*\.com$') -> my_group
domain(geosite:category-ads) -> block
domain(geosite:cn)->direct
### Dest IP rule
dip(8.8.8.8) -> direct
dip(101.97.0.0/16) -> direct
dip(geoip:private) -> direct
### Source IP rule
sip(192.168.0.0/24) -> my_group
sip(192.168.50.0/24) -> direct
### Dest port rule
dport(80) -> direct
dport(10080-30000) -> direct
### Source port rule
sport(38563) -> direct
sport(10080-30000) -> direct
### Level 4 protocol rule:
l4proto(tcp) -> my_group
l4proto(udp) -> direct
### IP version rule:
ipversion(4) -> block
ipversion(6) -> ipv6_group
### Source MAC rule
mac('02:42:ac:11:00:02') -> direct
### Process Name rule (only support localhost process when binding to WAN)
pname(curl) -> direct
### Multiple domains rule
domain(keyword: google, suffix: www.twitter.com, suffix: v2raya.org) -> my_group
### Multiple IP rule
dip(geoip:cn, geoip:private) -> direct
dip(9.9.9.9, 223.5.5.5) -> direct
sip(192.168.0.6, 192.168.0.10, 192.168.0.15) -> direct
### 'And' rule
dip(geoip:cn) && dport(80) -> direct
dip(8.8.8.8) && l4proto(tcp) && dport(1-1023, 8443) -> my_group
dip(1.1.1.1) && sip(10.0.0.1, 172.20.0.0/16) -> direct
### 'Not' rule
!domain(geosite:google-scholar,
geosite:category-scholar-!cn,
geosite:category-scholar-cn
) -> my_group
### Little more complex rule
domain(geosite:geolocation-!cn) &&
!domain(geosite:google-scholar,
geosite:category-scholar-!cn,
geosite:category-scholar-cn
) -> my_group
### Customized DAT file
domain(ext:"yourdatfile.dat:yourtag")->direct
dip(ext:"yourdatfile.dat:yourtag")->direct
### Set fwmark
# Mark is useful when you want to redirect traffic to specific interface (such as wireguard) or for other advanced uses.
# An example of redirecting Disney traffic to wg0 is given here.
# You need set ip rule and ip table like this:
# 1. Set all traffic with mark 0x800/0x800 to use route table 1145:
# >> ip rule add fwmark 0x800/0x800 table 1145
# >> ip -6 rule add fwmark 0x800/0x800 table 1145
# 2. Set default route of route table 1145:
# >> ip route add default dev wg0 scope global table 1145
# >> ip -6 route add default dev wg0 scope global table 1145
# Notice that interface wg0, mark 0x800, table 1145 can be set by preferences, but cannot conflict.
# 3. Set routing rules in dae config file.
domain(geosite:disney) -> direct(mark: 0x800)
### Must rules
# For following rules, DNS requests will be forcibly redirected to dae except from mosdns.
# Different from must_direct/must_my_group, traffic from mosdns will continue to match other rules.
pname(mosdns) -> must_rules
ip(geoip:cn) -> direct
domain(geosite:cn) -> direct
fallback: my_group
```

View File

@ -0,0 +1,81 @@
# Semantic Commit Messages
## The reasons for these conventions
- automatic generating of the changelog
- simple navigation through Git history (e.g. ignoring the style changes)
See how a minor change to your commit message style can make you a better developer.
## Format
```
`<type>(<scope>): <subject>`
`<scope>` is optional
```
## Example
```
feat: add hat wobble
^--^ ^------------^
| |
| +-> Summary in present tense.
|
+-------> Type: chore, docs, feat, fix, refactor, style, or test.
```
Example `<type>` values:
- `feat`: (new feature for the user, not a new feature for build script)
- `fix`: (bug fix for the user, not a fix to a build script)
- `docs`: (changes to the documentation)
- `style`: (formatting, missing semi colons, etc; no production code change)
- `refactor`: (refactoring production code, eg. renaming a variable)
- `test`: (adding missing tests, refactoring tests; no production code change)
- `chore`: (updating grunt tasks etc; no production code change, e.g. dependencies upgrade)
- `perf`: (perfomance improvement change, e.g. better concurrency performance)
- `ci`: (updating CI configuration files and scripts e.g. `.gitHub/workflows/*.yml` )
Example `<Scope>` values:
- `init`
- `runner`
- `watcher`
- `config`
- `web-server`
- `proxy`
The `<scope>` can be empty (e.g. if the change is a global or difficult to assign to a single component), in which case the parentheses are omitted. In smaller projects such as Karma plugins, the `<scope>` is empty.
## Message Subject (First Line)
The first line cannot be longer than `72` characters and should be followed by a blank line. The type and scope should always be lowercase as shown below
## Message Body
use as in the `<subject>`, use the imperative, present tense: "change" not "changed" nor "changes". Message body should include motivation for the change and contrasts with previous behavior.
## Message footer
### Referencing issues
Closed issues should be listed on a separate line in the footer prefixed with "Closes" keyword as the following:
```
Closes #234
```
or in the case of multiple issues:
```
Closes #123, #245, #992
```
## References
- <https://www.conventionalcommits.org/>
- <https://seesparkbox.com/foundry/semantic_commit_messages>
- <http://karma-runner.github.io/1.0/dev/git-commit-msg.html>
- <https://wadehuanglearning.blogspot.com/2019/05/commit-commit-commit-why-what-commit.html>

View File

@ -0,0 +1,50 @@
# 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 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
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
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
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
pip3 install pre-commit
# install pre-commit hooks
pre-commit install
```
## 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`.
- 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`.
- Implement/fix your feature, comment your code.
- Follow the code style of the project, including indentation.
- 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`.
- 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
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
docs/en/how-it-works.md Normal file
View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,80 @@
# Troubleshooting
## Unknown bpf_trace_printk
```console
invalid argument: unknown func bpf_trace_printk
```
Solution:
Compile dae with CFLAG `-D__REMOVE_BPF_PRINTK`. See [build-by-yourself](user-guide/build-by-yourself.md).
## No network after `dae suspend`
Do not set dae as the DNS in DHCP setting. For example, you can set `223.5.5.5` as DNS in your DHCP setting.
Because dae will not hijack any DNS request if it was suspended.
## PVE related
- [PVE NIC Hardware passthrough](https://github.com/daeuniverse/dae/issues/43)
## Binding to WAN but no network
### Troubleshoot local DNS service
If you use `adguardhome`, `mosdns` in `dns` section, refer to [external-dns](configuration/external-dns.md).
### Troubleshoot firewall
If you bind to wan, make sure firewall is stopped or `12345` is allowed by firewall. Don't worry about the security of this port because this port has its own firewall rule.
Usual firewalls on Linux:
```bash
ufw
firewalld
```
### Troubleshoot PPPoE
dae does not support PPPoE yet. We are working on it. However, binding to LAN for other machines should work fine.
## Binding to LAN but bad DNS in other machines
### Troubleshoot config of dae
Make sure you have bind to the correct LAN interfaces.
For example, if your use the same interface eth1 for WAN and LAN, write it as `wan_interface: eth1` and also in `lan_interface: eth1`. If the LAN interfaces you want to proxy are eth1 and docker0, write them both as `lan_interface: eth1,docker0`.
### Troubleshoot DNS
To verify on another machine in LAN:
```bash
curl -i 1.1.1.1
curl -i google.com
```
If the first line has a response and the second line doesn't, check whether port `53` is occupied by others on dae's machine.
```bash
netstat -ulpen|grep 53
# or
# lsof -i:53 -n
```
If does, stop the service process or change its listening port from 53 to others. Do not forget to modify `/etc/resolv.conf` to make DNS accessible (for example, with content `nameserver 223.5.5.5`, but do not use `nameserver 127.0.0.1`).
## Fail to load eBPF objects
> FATA[0022] load eBPF objects: field TproxyWanEgress: program tproxy_wan_egress: load program: argument list too long: 1617: (bf) r2 = r6: 1618: (85) call bpf_map_loo (truncated, 992 line(s) omitted)
If you use `clang-13` to compile dae, you may encounter this problem.
There are ways to resolve it:
1. Method 1: Use `clang-15` or higher versions to compile dae. Or just download dae from [releases](https://github.com/daeuniverse/dae/releases).
2. Method 2: Add CFLAGS `-D__UNROLL_ROUTE_LOOP` while compiling. However, it will increse memory occupation (or swap space) at the eBPF loading stage (about 180MB). For example, compile dae to ARM64 using `make CGO_ENABLED=0 GOARCH=arm64 CFLAGS="-D__UNROLL_ROUTE_LOOP -D__REMOVE_BPF_PRINTK"`.

View File

@ -0,0 +1,261 @@
# Run on macOS
## Install brew
### For x86
You can install brew referring to official docs <https://docs.brew.sh/Installation>:
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
### For ARM64
To install ARM64 architecture packages, homebrew should be installed in `/opt/homebrew`:
```shell
cd /opt
sudo mkdir homebrew
sudo chown $(whoami):admin homebrew
curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
```
## Lima
### Setup
This section intruduces how to use [lima](https://github.com/lima-vm/lima) virtual machine to run dae, and proxy whole macOS host network.
First, we should install `lima` and `socket_vmnet`.
```shell
# Install lima for VM and socket_vmnet for bridge.
brew install lima socket_vmnet
# Set up the sudoers file for launching socket_vmnet from Lima
limactl sudoers >etc_sudoers.d_lima
sudo install -o root etc_sudoers.d_lima /etc/sudoers.d/lima
```
Then, configure lima configuration and dae VM configuration.
```shell
# Configure lima networks.
socket_vmnet_bin=$(readlink -f ${HOMEBREW_PREFIX}/opt/socket_vmnet)/bin/socket_vmnet
sed -ir "s#^ *socketVMNet:.*# socketVMNet: \"${socket_vmnet_bin}\"#" ~/.lima/_config/networks.yaml
```
```shell
# Configure dae vm.
mkdir ~/.lima/dae/
cat << 'EOF' | tee ~/.lima/dae/lima.yaml
images:
- location: "https://cloud.debian.org/images/cloud/bookworm/daily/20230416-1352/debian-12-generic-amd64-daily-20230416-1352.qcow2"
arch: "x86_64"
digest: "sha512:8dcb07f213bbe7436744ce310252f53eb06d8d0a85378e4bdeb297e29d7f8b8af82b038519fabca84a75f188aa4e5586d21856d1bb09ab89aca70fd39be7c06b"
- location: "https://cloud.debian.org/images/cloud/bookworm/daily/20230416-1352/debian-12-generic-arm64-daily-20230416-1352.qcow2"
arch: "aarch64"
digest: "sha512:88020fbde570e4bc773d6b05d810150b64fea007a2a18dfee835f1d73025bd2872300352e5cb1acb0bb4784c3c6765be1007880177f5319385d4fdf1d75e3ccf"
mounts:
networks:
- lima: bridged
interface: "lima0"
memory: "1GB"
disk: "3GiB"
EOF
```
Start dae VM and configure it.
```shell
# Start dae VM.
limactl start dae
```
```shell
# Enter the dae VM.
limactl shell dae
# Manually configure network.
cat << 'EOF' | sudo tee /etc/netplan/99-override.yaml
network:
ethernets:
eth0:
dhcp4: true
dhcp4-overrides:
route-metric: 200
lima0:
dhcp4: true
dhcp6: true
version: 2
EOF
# Apply netplan.
sudo netplan apply
# Install requirements.
sudo apt-get install jq
# Install dae.
sudo bash -c "$(curl -s https://hubmirror.v2raya.org/raw/daeuniverse/dae-installer/main/installer.sh)" @ install
# Configure config.dae.
cat << 'EOF' | sudo tee /usr/local/etc/dae/config.dae
global {
lan_interface: lima0
wan_interface: lima0
log_level: info
allow_insecure: false
auto_config_kernel_parameter: true
}
subscription {
# Fill in your subscription links here.
}
# 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'
alidns: 'udp://dns.alidns.com:53'
}
routing {
request {
fallback: alidns
}
response {
upstream(googledns) -> accept
!qname(geosite:cn) && ip(geoip:private) -> googledns
fallback: accept
}
}
}
group {
proxy {
#filter: name(keyword: HK, keyword: SG)
policy: min_moving_avg
}
}
# 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
### Write your rules below.
dip(geoip:private) -> direct
dip(geoip:cn) -> direct
domain(geosite:cn) -> direct
fallback: proxy
}
EOF
sudo chmod 0600 /usr/local/etc/dae/config.dae
# Do not forget to add your subscriptions and nodes.
sudo vim /usr/local/etc/dae/config.dae
# Enable and start dae.
sudo systemctl enable --now dae.service
# Exit dae vm.
exit
```
Set default route of macOS to dae VM.
> **Note**
> You may need to execute this command every time you connect to network.
>
> Refer to [Auto set route and DNS](#auto-set-route-and-dns) if you want to auto execute it.
```shell
# Get IP of dae VM.
dae_ip=$(limactl shell dae ip --json addr | limactl shell dae jq -cr '.[] | select( .ifname == "lima0" ).addr_info | .[] | select( .family == "inet" ).local')
# Set gateway of macOS host to dae VM.
sudo route delete default; sudo route add default $dae_ip
# Set DNS of macOS host to dae VM.
networksetup -setdnsservers Wi-Fi $dae_ip
```
Verify that we were successful.
```shell
# Verify.
curl -v ipinfo.io
```
### Auto set route and DNS
Write a script to execute.
```shell
# The script to execute.
mkdir -p /Users/Shared/bin
cat << 'EOF' > /Users/Shared/bin/dae-network-update.sh
#!/bin/sh
set -ex
export PATH=$PATH:/opt/local/bin/:/opt/homebrew/bin/
dae_ip=$(limactl shell dae ip --json addr | limactl shell dae jq -cr '.[] | select( .ifname == "lima0" ).addr_info | .[] | select( .family == "inet" ).local')
current_gateway=$(route -n get default|grep gateway|rev|cut -d' ' -f1|rev)
networksetup -getdnsservers Wi-Fi | cut -d" " -f1 | grep -E '\.|:' && dns_override=1
[ ! -z "$dae_ip" ] && ping -c 1 -t 1 -n "$dae_ip" && dae_ready=1
[ -z "$dae_ready" ] && [ ! -z "$dns_override" ] && (networksetup -setmanual Wi-Fi 1.1.1.1 1.1.1.1/32 1.1.1.1; networksetup -setdhcp Wi-Fi; networksetup -setdnsservers Wi-Fi "Empty"; exit 1)
[ "$current_gateway" != "$dae_ip" ] && (sudo route delete default; sudo route add default $dae_ip)
networksetup -setdnsservers Wi-Fi $dae_ip
exit 0
EOF
# Give executable permission.
chmod +x /Users/Shared/bin/dae-network-update.sh
```
Give no-password permission for route.
```shell
if [ $(id -u) -eq "0" ]; then echo 'Do not use root!!'; else echo "$(whoami) ALL=(ALL) NOPASSWD: $(which route)" | sudo tee /etc/sudoers.d/"$(whoami)"-route; fi
```
Write a plist service file.
```shell
cat << 'EOF' > ~/Library/LaunchAgents/org.v2raya.dae.networkchanging.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.v2raya.dae.networkchanging</string>
<key>LowPriorityIO</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/Users/Shared/bin/dae-network-update.sh</string>
</array>
<key>WatchPaths</key>
<array>
<string>/etc/resolv.conf</string>
<string>/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist</string>
<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
```
Load the plist service.
```shell
launchctl load ~/Library/LaunchAgents/org.v2raya.dae.networkchanging.plist
```

View File

@ -0,0 +1,65 @@
# Build Guide
## Build
### Make Dependencies
```shell
clang >= 10
llvm >= 10 (optional)
golang >= 1.18
make
```
### Compilation
```shell
git clone https://github.com/daeuniverse/dae.git
cd dae
git submodule update --init
## Minimal dependency build
make GOFLAGS="-buildvcs=false" \
CFLAGS="-D__REMOVE_BPF_PRINTK" \
CC=clang
## Normal build
#make
## Cross compile
# To armv7 CPU architect:
#make CGO_ENABLED=0 GOARCH=arm GOARM=7
# To mips CPU architect:
#make CGO_ENABLED=0 GOARCH=mips
```
## Run
### Runtime Dependencies
For traffic splitting, dae relies on the following data sources, [geoip.dat](https://github.com/v2fly/geoip/releases/latest) and [geosite.dat](https://github.com/v2fly/domain-list-community/releases/latest).
```shell
mkdir -p /usr/local/share/dae/
pushd /usr/local/share/dae/
curl -L -o geoip.dat https://github.com/v2fly/geoip/releases/latest/download/geoip.dat
curl -L -o geosite.dat https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat
popd
```
### Run
Download the example config file:
```shell
curl -L -o example.dae https://github.com/daeuniverse/dae/raw/main/example.dae
```
See [example.dae](https://github.com/daeuniverse/dae/blob/main/example.dae).
After fine tuning, run dae:
```shell
./dae run -c example.dae
```
> **Note**: Alternatively, you may run dae as a daemon (systemd) service. Check out more details [HERE](run-as-daemon.md).

View File

@ -0,0 +1,28 @@
# Configure Kernel Parameters
> **Note**
> Parameters will be automatically configured if `global.auto_config_kernel_parameter` is `true`.
If you set up dae as a router or other intermediate device and bind it to LAN interfaces, you need to adjust some Linux kernel parameters to make everything work fine. By default, the latest Linux distributions have IP Forwarding `disabled`. In the case where we need to up a Linux router/gateway or a VPN server or simply a plain dial-in server, then we need to enable forwarding. Moreover, in order to keep our gateway position and keep correct downstream route table, we should disable `send-redirects`. Do the followings to adjust Linux kernel parameters:
For every LAN interfaces you want to proxy:
```shell
export lan_ifname=docker0
sudo tee /etc/sysctl.d/60-dae-$lan_ifname.conf << EOF
net.ipv4.conf.$lan_ifname.forwarding = 1
net.ipv6.conf.$lan_ifname.forwarding = 1
net.ipv4.conf.$lan_ifname.send_redirects = 0
EOF
sudo sysctl --system
```
It is also recommended to enable IPv4 forward to avoid weird situations:
```shell
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/60-ip-forward.conf
sudo sysctl --system
```
Please modify `docker0` to your LAN interface.

View File

@ -0,0 +1,125 @@
# Kernel Upgrade Guide
A `kernel` is the core of any operating system. Before you start calling Linux an operating system, you need to know the basic concept and Linuxs birth history. **_Linux is not an operating system; mainly, Linux is a kernel_**.
## How To Upgrade Linux Kernel On Various Distributions
### Disclaimer
Upgrading the Linux kernel is not easy; you must do this only if you find security errors or hardware interaction issues. If your system crashes, you might have to recover the whole system. Mostly, Linux distributions come with the most upgraded kernel. Upgrading the Linux kernel doesnt delete or remove the previous kernel; it is kept inside the system.
> **Note**: You should not upgrade your kernel manually unless you want some specific driver support. You can roll back to the older kernel from the recovery menu of your Linux system. However, you may need to upgrade the kernel for hardware issues or security issues.
### Preparation
Before you start upgrading your Linux kernel, you must know the Kernels `current version` running inside your host machine. You may do so by `uname -r`. In case of `eBPF`, the minimum required version is `>= 5.8`
Various Linux distributions have different methods to upgrade the Linux kernel. This guide convers ways to upgrade the kernel to a desired version for most `Armbian Linux`, `Debian-based Linux`, `RedHat, Fedora based Linux`, and `Arch-based Linux` distributions.
> **Note**: Since `dae` is builts with `eBPF`, your host must meet the minimum Kernel version, `>= 5.8` for dae to properly running.
### Upgrade to BTF Kernel on Armbian Linux
For Armbian users, we have compiled kernels with BTF on.
See [daeuniverse/armbian-btf-kernel](https://github.com/daeuniverse/armbian-btf-kernel).
### Upgrade Kernel on Debian-based Linux
Debian-based distributions like armbian can install a specific version of Kernel on their system. You can run the following command-line on your Linux terminal to install any specific version kernel on your Linux system. After the installation is done, reboot your system to get the desired kernel on your Linux system.
```shell
# Sync databases.
sudo apt update
# Search available kernel versions.
apt-cache search ^linux-image
# Install specific image.
sudo apt install <specific-linux-image>
```
Reboot to take effect:
```shell
sudo reboot
uname -r
```
(Debian ONLY): If you would like to upgrade to the latest Kernel (AGGRESSIVE UPGRADE), follow the commands below:
> **Warning**: The latest Kernel that Debian officially supports is available in the `unstable release`. Debian Unstable (also known by its codename "SID") is not strictly a release, but rather a rolling development version of the Debian distribution containing the latest packages that have been introduced into Debian. Upgrading to the latest Kernel might potentially introduce breaking changes to your system, so please do at your own risk.
Reference: [https://www.itsfoss.net/installing-linux-5-14-kernel-on-debian-11/](https://www.itsfoss.net/installing-linux-5-14-kernel-on-debian-11)
> **Note**: Please modify the following line if your system is NOT on Debian11: `Pin: release a=bullseye` - e.g. `Pin: release a=buster` (Debian10)
```shell
# Sync databases.
sudo apt update
# Add unstable source
cat <<EOF | sudo tee -a /etc/apt/sources.list/
deb http://deb.debian.org/debian unstable main contrib non-free
deb-src http://deb.debian.org/debian unstable main contrib non-free
EOF
# Create apt preferences
cat <<EOF | sudo tee /etc/apt/preferences
Package: *
Pin: release a=bullseye
Pin-Priority: 500
Package: linux-image-amd64
Pin: release a=unstable
Pin-Priority: 1000
Package: *
Pin: release a=unstable
Pin-Priority: 100
EOF
# Perform full dist-upgrade
sudo apt dist-upgrade
```
Reboot to take effect:
```shell
sudo reboot
uname -r
```
### Upgrade kernel on RedHat and Fedora Linux
Fedora, RedHat, and RedHat-based Linux distribution users can upgrade their Linux kernel manually by downloading the kernel from the repository.
Fedora and RedHat Linux users can install a specific version of Kernel on their system. You can run the following command-line on your Linux terminal to install any specific version kernel on your Linux system. After the installation is done, reboot your system to get the desired kernel on your Linux system.
```bash
sudo yum install kernel
```
Reboot to take effect:
```bash
sudo reboot
uname -r
```
### Upgrade kernel on Arch-based Linux
Arch and Arch-based Linux distributions have a `dynamic` variety of Linux kernel. Arch Linux updates its security patch regularly; thats why you will see notable kernel and patch updates are available on Arch Linux. Here, I will describe two methods to upgrade the kernel on Arch Linux.
Manjaro and other Arch Linux distributions often offer kernel updates and upgrades via the conventional update manager. When you run the system updater on the Linux system, it checks for the latest kernels. You can use the following `pacman` command to check for the latest kernel on Arch Linux distributions.
```bash
# Search available kernel images.
pacman -Ss ^linux$
# Install specific kernel image.
pacman -S <specific-linux-image>
```
Once you agree to install, reboot your system after the installation is finished. Then, you can check the kernel version to ensure whether the kernel is upgraded or not.
```bash
sudo reboot
uname -r
```

View File

@ -0,0 +1,29 @@
# Reload and Suspend
dae supports configuration reloading and program suspending, which can help you save a lot of time when modifying the configuration or temporarily suspend dae.
## Reload
Generally, dae won't interrupt connections when reloading configuration. And reloading is much faster than restarting.
Usage:
```shell
dae reload
```
## Suspend
It will be useful if you want to suspend dae temporarily and recover it later.
## Usage
```shell
dae suspend
```
If you want to recover, use reload:
```shell
dae reload
```

View File

@ -0,0 +1,68 @@
# Run dae as a Daemon Service
[systemd](https://wiki.debian.org/systemd) allows you to create and manage services in extremely powerful and flexible ways.
> **Note**: (Prerequisites) If your distribution's service manager is provided by systemd.
dae can run as a daemon (systemd) service so that it can run at boot.
## Prerequisites
### Optional Geo Data Files
For more convenient traffic split, dae relies on the following data sources, [geoip.dat](https://github.com/v2fly/geoip/releases/latest) and [geosite.dat](https://github.com/v2fly/domain-list-community/releases/latest).
```shell
mkdir -p /usr/local/share/dae/
pushd /usr/local/share/dae/
curl -L -o geoip.dat https://github.com/v2fly/geoip/releases/latest/download/geoip.dat
curl -L -o geosite.dat https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat
popd
```
### Configuration File
> **Note**: The config file is recommended to save under `/etc/dae`
Download the sample config file:
```bash
mkdir -p /etc/dae
curl -L -o /etc/dae/config.dae https://github.com/daeuniverse/dae/raw/main/example.dae
```
## Download pre-compiled binaries
Releases are available in <https://github.com/daeuniverse/daed/releases>
> **Note**: If you would like to get a taste of new features, there are nightly (latest) builds available. Most of the time, newly proposed changes will be included in `PRs` and will be exported as cross-platform executable binaries in builds (GitHub Action Workflow Build). Noted that newly introduced features are sometimes buggy, do it at your own risk. However, we still highly encourage you to check out our latest builds as it may help us further analyze features stability and resolve potential bugs accordingly.
Nightly builds are available in <https://github.com/daeuniverse/dae/actions/workflows/build-nightly.yml>
```bash
sudo chmod +x ./dae
sudo install -Dm755 dae /usr/bin/
# helper
dae [-h,--help]
# check version
dae version
```
## Setup
```bash
# download the sample systemd.service
sudo curl -L -o /etc/systemd/system/dae.service https://github.com/daeuniverse/dae/raw/main/install/dae.service
# reload and restart daemon to take effect
sudo systemctl daemon-reload
sudo systemctl enable dae --now
sudo systemctl status dae
```
## Check System Logs
```bash
sudo journalctl -xefu dae
```