diff --git a/config/config.go b/config/config.go index 1d97b7f..e1daa36 100644 --- a/config/config.go +++ b/config/config.go @@ -17,15 +17,16 @@ type Global struct { LogLevel string `mapstructure:"log_level" default:"info"` // We use DirectTcpCheckUrl to check (tcp)*(ipv4/ipv6) connectivity for direct. //DirectTcpCheckUrl string `mapstructure:"direct_tcp_check_url" default:"http://www.qualcomm.cn/generate_204"` - TcpCheckUrl string `mapstructure:"tcp_check_url" default:"http://keep-alv.google.com/generate_204"` - UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google:53"` - CheckInterval time.Duration `mapstructure:"check_interval" default:"30s"` - CheckTolerance time.Duration `mapstructure:"check_tolerance" default:"0"` - LanInterface []string `mapstructure:"lan_interface"` - WanInterface []string `mapstructure:"wan_interface"` - AllowInsecure bool `mapstructure:"allow_insecure" default:"false"` - DialMode string `mapstructure:"dial_mode" default:"domain"` - DisableWaitingNetwork bool `mapstructure:"disable_waiting_network" default:"false"` + TcpCheckUrl string `mapstructure:"tcp_check_url" default:"http://keep-alv.google.com/generate_204"` + UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google:53"` + CheckInterval time.Duration `mapstructure:"check_interval" default:"30s"` + CheckTolerance time.Duration `mapstructure:"check_tolerance" default:"0"` + LanInterface []string `mapstructure:"lan_interface"` + WanInterface []string `mapstructure:"wan_interface"` + AllowInsecure bool `mapstructure:"allow_insecure" default:"false"` + DialMode string `mapstructure:"dial_mode" default:"domain"` + DisableWaitingNetwork bool `mapstructure:"disable_waiting_network" default:"false"` + AutoConfigKernelParameter bool `mapstructure:"auto_config_kernel_parameter" default:"false"` } type FunctionOrString interface{} diff --git a/config/desc.go b/config/desc.go index 2679129..7a38cb5 100644 --- a/config/desc.go +++ b/config/desc.go @@ -49,7 +49,8 @@ var GlobalDesc = Desc{ 2. "domain". Dial proxy using the domain from sniffing. This will relieve DNS pollution problem to a great extent if have impure DNS environment. Generally, this mode brings faster proxy response time because proxy will re-resolve the domain in remote, thus get better IP result to connect. This policy does not impact routing. That is to say, domain rewrite will be after traffic split of routing and dae will not re-route it. 3. "domain+". Based on domain mode but do not check the reality of sniffed domain. It is useful for users whose DNS requests do not go through dae but want faster proxy response time. Notice that, if DNS requests do not go through dae, dae cannot split traffic by domain. 4. "domain++". Based on domain+ mode but force to re-route traffic using sniffed domain to partially recover domain based traffic split ability. It doesn't work for direct traffic and consumes more CPU resources.`, - "disable_waiting_network": "Disable waiting for network before pulling subscriptions.", + "disable_waiting_network": "Disable waiting for network before pulling subscriptions.", + "auto_config_kernel_parameter": "Automatically configure Linux kernel parameters like ip_forward and send_redirects. Check out https://github.com/daeuniverse/dae/blob/main/docs/getting-started/kernel-parameters.md to see what will dae do.", } var DnsDesc = Desc{ diff --git a/control/control_plane.go b/control/control_plane.go index 6646a19..fb1b824 100644 --- a/control/control_plane.go +++ b/control/control_plane.go @@ -188,8 +188,15 @@ func NewControlPlane( if err = core.setupRoutingPolicy(); err != nil { return nil, err } + if global.AutoConfigKernelParameter { + _ = SetIpv4forward("1") + } global.LanInterface = common.Deduplicate(global.LanInterface) for _, ifname := range global.LanInterface { + if global.AutoConfigKernelParameter { + SetSendRedirects(ifname, "0") + SetForwarding(ifname, "1") + } if err = core.bindLan(ifname); err != nil { return nil, fmt.Errorf("bindLan: %v: %w", ifname, err) } diff --git a/control/utils.go b/control/utils.go index 28aba01..21f2359 100644 --- a/control/utils.go +++ b/control/utils.go @@ -10,9 +10,9 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "github.com/mzz2017/softwind/netproxy" "github.com/daeuniverse/dae/common" "github.com/daeuniverse/dae/common/consts" + "github.com/mzz2017/softwind/netproxy" "golang.org/x/sys/unix" "net/netip" "os" @@ -105,6 +105,28 @@ func CheckIpforward(ifname string) error { return nil } +func setForwarding(ifname string, ipversion consts.IpVersionStr, val string) error { + path := fmt.Sprintf("/proc/sys/net/ipv%v/conf/%v/forwarding", ipversion, ifname) + err := os.WriteFile(path, []byte(val), 0644) + if err != nil { + return err + } + return nil +} + +func SetIpv4forward(val string) error { + err := os.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte(val), 0644) + if err != nil { + return err + } + return nil +} + +func SetForwarding(ifname string, val string) { + _ = setForwarding(ifname, consts.IpVersionStr_4, val) + _ = setForwarding(ifname, consts.IpVersionStr_6, val) +} + func checkSendRedirects(ifname string, ipversion consts.IpVersionStr) error { path := fmt.Sprintf("/proc/sys/net/ipv%v/conf/%v/send_redirects", ipversion, ifname) b, err := os.ReadFile(path) @@ -124,6 +146,19 @@ func CheckSendRedirects(ifname string) error { return nil } +func setSendRedirects(ifname string, ipversion consts.IpVersionStr, val string) error { + path := fmt.Sprintf("/proc/sys/net/ipv%v/conf/%v/send_redirects", ipversion, ifname) + err := os.WriteFile(path, []byte(val), 0644) + if err != nil { + return err + } + return nil +} + +func SetSendRedirects(ifname string, val string) { + _ = setSendRedirects(ifname, consts.IpVersionStr_4, val) +} + func MagicNetwork(network string, mark uint32) string { if mark == 0 { return network diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index ff926c0..764f8ef 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -54,31 +54,6 @@ Check them using command like: > **Note** > `Armbian` users can follow the [**Upgrade Guide**](./kernel-upgrade.md) to upgrade the kernel to meet the kernel configuration requirement. -## Kernel Parameters - -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-foward.conf -sudo sysctl --system -``` - -Please modify `docker0` to your LAN interface. - ## Installation ### Archlinux/Manjaro @@ -137,6 +112,7 @@ global { log_level: info allow_insecure: false + auto_config_kernel_parameter: true } subscription { diff --git a/docs/getting-started/kernel-parameters.md b/docs/getting-started/kernel-parameters.md new file mode 100644 index 0000000..d654df5 --- /dev/null +++ b/docs/getting-started/kernel-parameters.md @@ -0,0 +1,24 @@ +# Configure Kernel Parameters + +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. diff --git a/example.dae b/example.dae index 55561b3..54ab7bf 100644 --- a/example.dae +++ b/example.dae @@ -50,6 +50,10 @@ global { # Disable waiting for network before pulling subscriptions. disable_waiting_network: false + + # Automatically configure Linux kernel parameters like ip_forward and send_redirects. Check out + # https://github.com/daeuniverse/dae/blob/main/docs/getting-started/kernel-parameters.md to see what will dae do. + auto_config_kernel_parameter: true } # Subscriptions defined here will be resolved as nodes and merged as a part of the global node pool.