optimize: disable send_redirects for Real Direct

This commit is contained in:
mzz2017
2023-02-26 05:07:42 +08:00
parent 5cf6dca509
commit 27d77d2b42
7 changed files with 71 additions and 14 deletions

View File

@ -64,25 +64,30 @@ Check them using command like:
(zcat /proc/config.gz || cat /boot/{config,config-$(uname -r)}) | grep -E 'CONFIG_(DEBUG_INFO_BTF|NET_CLS_ACT|NET_SCH_INGRESS|NET_INGRESS|NET_EGRESS)='
```
### Enable IP Forwarding
### Kernel Parameters
By default, any latest Linux distributions will 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 must need to enable forwarding. Do the followings to have `ip-forwarding` feature enabled:
If you set up dae as a router or other intermediate device, 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:
```shell
sudo tee /etc/sysctl.d/dae.conf<<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
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
net.ipv6.conf.$lan_ifname.send_redirects = 0
EOF
sudo sysctl --system
```
Please modify `docker0` to your LAN interface.
## Getting Started
Please refer to [Quick Start Guide](./docs/getting-started/README.md) to start using `dae` right away!
## Known Issues
1. If you setup dae and also a shadowsocks server (or any UDP servers) on the same machine in public network, such as a VPS, don't forget to add `l4proto(udp) && sport(your server ports) -> must_direct` rule for your UDP server port. Because states of UDP are hard to maintain, all outgoing UDP packets will potentially be proxied (depends on your routing), including traffic to your client. That is not what we want to see. `must_direct` makes all traffic from this port including DNS traffic direct.
1. If you setup dae and also a shadowsocks server (or any UDP servers) on the same machine in public network, such as a VPS, don't forget to add `l4proto(udp) && sport(your server ports) -> must_direct` rule for your UDP server port. Because states of UDP are hard to maintain, all outgoing UDP packets will potentially be proxied (depends on your routing), including traffic to your client. This behaviour is not what we want to see. `must_direct` makes all traffic from this port including DNS traffic direct.
## TODO

View File

@ -23,7 +23,8 @@ type Global struct {
CheckTolerance time.Duration `mapstructure:"check_tolerance" default:"0"`
DnsUpstream string `mapstructure:"dns_upstream" default:"<empty>"`
LanInterface []string `mapstructure:"lan_interface"`
LanNatDirect bool `mapstructure:"lan_nat_direct" default:"true"`
// Deprecated:
LanNatDirect bool `mapstructure:"lan_nat_direct" default:"false"`
WanInterface []string `mapstructure:"wan_interface"`
AllowInsecure bool `mapstructure:"allow_insecure" default:"false"`
DialMode string `mapstructure:"dial_mode" default:"domain"`

View File

@ -42,7 +42,7 @@ var GlobalDesc = Desc{
"check_interval": "Interval of connectivity check for TCP and UDP",
"check_tolerance": "Group will switch node only when new_latency <= old_latency - tolerance.",
"lan_interface": "The LAN interface to bind. Use it if you only want to proxy LAN instead of localhost.",
"lan_nat_direct": "SNAT for incoming connection to avoid MAC learning.\nAlways set it true if you are NOT using dae as a transparent bridge, but will reduce forwarding performance for direct traffic in LAN mode.\nThis option does not affect direct traffic performance of WAN.",
"lan_nat_direct": "[Deprecated] SNAT for incoming connection to avoid MAC learning.\nAlways set it true if you are NOT using dae as a transparent bridge, but will reduce forwarding performance for direct traffic in LAN mode.\nThis option does not affect direct traffic performance of WAN.",
"wan_interface": "The WAN interface to bind. Use it if you want to proxy localhost.",
"allow_insecure": "Allow insecure TLS certificates. It is not recommended to turn it on unless you have to.",
"dial_mode": `Optional values of dial_mode are:

View File

@ -15,6 +15,7 @@ type patch func(params *Config) error
var patches = []patch{
patchEmptyDns,
patchDeprecatedGlobalDnsUpstream,
patchDeprecatedLanNatDirect,
}
func patchEmptyDns(params *Config) error {
@ -34,3 +35,10 @@ func patchDeprecatedGlobalDnsUpstream(params *Config) error {
params.Global.DnsUpstream = ""
return nil
}
func patchDeprecatedLanNatDirect(params *Config) error {
if params.Global.LanNatDirect != false {
return fmt.Errorf("'global.lan_nat_direct' was deprecated; please remove it")
}
return nil
}

View File

@ -236,8 +236,10 @@ func (c *ControlPlaneCore) bindLan(ifname string) error {
if err != nil {
return err
}
err = CheckIpforward(ifname)
if err != nil {
if err = CheckIpforward(ifname); err != nil {
return err
}
if err = CheckSendRedirects(ifname); err != nil {
return err
}
/// Insert an elem into IfindexParamsMap.

View File

@ -69,12 +69,23 @@ func sendPktWithHdrWithFlag(data []byte, realFrom netip.AddrPort, lConn *net.UDP
}
b.Write(data)
//logrus.Debugln("sendPktWithHdrWithFlag: from", realFrom, "to", to)
if ipversion := consts.IpVersionFromAddr(to.Addr()); consts.IpVersionFromAddr(lConn.LocalAddr().(*net.UDPAddr).AddrPort().Addr()) != ipversion {
// ip versions unmatched.
if ipversion == consts.IpVersionStr_4 {
// 4 to 6
to = netip.AddrPortFrom(netip.AddrFrom16(to.Addr().As16()), to.Port())
} else {
// Shouldn't happen.
return fmt.Errorf("unmatched ipversions")
}
}
_, err := lConn.WriteToUDPAddrPort(b.Bytes(), to)
return err
}
// sendPkt uses bind first, and fallback to send hdr if addr is in use.
func sendPkt(data []byte, from netip.AddrPort, realTo, to netip.AddrPort, lConn *net.UDPConn, lanWanFlag consts.LanWanFlag) (err error) {
if lanWanFlag == consts.LanWanFlag_IsWan {
return sendPktWithHdrWithFlag(data, from, lConn, to, lanWanFlag)
}

View File

@ -87,12 +87,16 @@ func checkIpforward(ifname string, ipversion consts.IpVersionStr) error {
path := fmt.Sprintf("/proc/sys/net/ipv%v/conf/%v/forwarding", ipversion, ifname)
b, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
// Kernel does not support.
return nil
}
return err
}
if bytes.Equal(bytes.TrimSpace(b), []byte("1")) {
return nil
}
return fmt.Errorf("ipforward on %v is off: %v; see https://github.com/v2rayA/dae#enable-ip-forwarding", ifname, path)
return fmt.Errorf("ipforward on %v is off: %v; see https://github.com/v2rayA/dae#kernel-parameters", ifname, path)
}
func CheckIpforward(ifname string) error {
@ -105,6 +109,32 @@ func CheckIpforward(ifname string) error {
return nil
}
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)
if err != nil {
if os.IsNotExist(err) {
// Kernel does not support.
return nil
}
return err
}
if bytes.Equal(bytes.TrimSpace(b), []byte("0")) {
return nil
}
return fmt.Errorf("send_directs on %v is on: %v; see https://github.com/v2rayA/dae#kernel-parameters", ifname, path)
}
func CheckSendRedirects(ifname string) error {
if err := checkSendRedirects(ifname, consts.IpVersionStr_4); err != nil {
return err
}
if err := checkSendRedirects(ifname, consts.IpVersionStr_6); err != nil {
return err
}
return nil
}
func MagicNetwork(network string, mark uint32) string {
if mark == 0 {
return network