mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-14 17:59:57 +07:00
feat: support global.sniffing_timeout
This commit is contained in:
@ -9,6 +9,7 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ConnSniffer struct {
|
||||
@ -16,10 +17,10 @@ type ConnSniffer struct {
|
||||
*Sniffer
|
||||
}
|
||||
|
||||
func NewConnSniffer(conn net.Conn, snifferBufSize int) *ConnSniffer {
|
||||
func NewConnSniffer(conn net.Conn, snifferBufSize int, dataWaitingTimeout time.Duration) *ConnSniffer {
|
||||
s := &ConnSniffer{
|
||||
Conn: conn,
|
||||
Sniffer: NewStreamSniffer(conn, snifferBufSize),
|
||||
Sniffer: NewStreamSniffer(conn, snifferBufSize, dataWaitingTimeout),
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -11,16 +11,13 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
DataWaitingTimeout = 100 * time.Millisecond
|
||||
)
|
||||
|
||||
type Sniffer struct {
|
||||
// Stream
|
||||
stream bool
|
||||
r io.Reader
|
||||
dataReady chan struct{}
|
||||
dataError error
|
||||
stream bool
|
||||
r io.Reader
|
||||
dataReady chan struct{}
|
||||
dataError error
|
||||
dataWaitingTimeout time.Duration
|
||||
|
||||
// Common
|
||||
buf []byte
|
||||
@ -28,12 +25,13 @@ type Sniffer struct {
|
||||
readMu sync.Mutex
|
||||
}
|
||||
|
||||
func NewStreamSniffer(r io.Reader, bufSize int) *Sniffer {
|
||||
func NewStreamSniffer(r io.Reader, bufSize int, dataWaitingTimeout time.Duration) *Sniffer {
|
||||
s := &Sniffer{
|
||||
stream: true,
|
||||
r: r,
|
||||
buf: make([]byte, bufSize),
|
||||
dataReady: make(chan struct{}),
|
||||
stream: true,
|
||||
r: r,
|
||||
buf: make([]byte, bufSize),
|
||||
dataReady: make(chan struct{}),
|
||||
dataWaitingTimeout: dataWaitingTimeout,
|
||||
}
|
||||
return s
|
||||
}
|
||||
@ -82,7 +80,7 @@ func (s *Sniffer) SniffTcp() (d string, err error) {
|
||||
if s.dataError != nil {
|
||||
return "", s.dataError
|
||||
}
|
||||
case <-time.After(DataWaitingTimeout):
|
||||
case <-time.After(s.dataWaitingTimeout):
|
||||
return "", NotApplicableError
|
||||
}
|
||||
} else {
|
||||
|
@ -27,6 +27,7 @@ type Global struct {
|
||||
DialMode string `mapstructure:"dial_mode" default:"domain"`
|
||||
DisableWaitingNetwork bool `mapstructure:"disable_waiting_network" default:"false"`
|
||||
AutoConfigKernelParameter bool `mapstructure:"auto_config_kernel_parameter" default:"false"`
|
||||
SniffingTimeout time.Duration `mapstructure:"sniffing_timeout" default:"100ms"`
|
||||
}
|
||||
|
||||
type FunctionOrString interface{}
|
||||
|
@ -45,12 +45,13 @@ var GlobalDesc = Desc{
|
||||
"wan_interface": "The WAN interface to bind. Use it if you want to proxy localhost. Use \"auto\" to auto detect.",
|
||||
"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:
|
||||
1. "ip". Dial proxy using the IP from DNS directly. This allows your ipv4, ipv6 to choose the optimal path respectively, and makes the IP version requested by the application meet expectations. For example, if you use curl -4 ip.sb, you will request IPv4 via proxy and get a IPv4 echo. And curl -6 ip.sb will request IPv6. This may solve some wierd full-cone problem if your are be your node support that.
|
||||
1. "ip". Dial proxy using the IP from DNS directly. This allows your ipv4, ipv6 to choose the optimal path respectively, and makes the IP version requested by the application meet expectations. For example, if you use curl -4 ip.sb, you will request IPv4 via proxy and get a IPv4 echo. And curl -6 ip.sb will request IPv6. This may solve some wierd full-cone problem if your are be your node support that.Sniffing will be disabled in this mode.
|
||||
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.",
|
||||
"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.",
|
||||
"sniffing_timeout": "Timeout to waiting for first data sending for sniffing. It is always 0 if dial_mode is ip. Set it higher is useful in high latency LAN network.",
|
||||
}
|
||||
|
||||
var DnsDesc = Desc{
|
||||
|
@ -65,6 +65,8 @@ type ControlPlane struct {
|
||||
|
||||
wanInterface []string
|
||||
lanInterface []string
|
||||
|
||||
sniffingTimeout time.Duration
|
||||
}
|
||||
|
||||
func NewControlPlane(
|
||||
@ -325,6 +327,10 @@ func NewControlPlane(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sniffingTimeout := global.SniffingTimeout
|
||||
if dialMode == consts.DialMode_Ip {
|
||||
sniffingTimeout = 0
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
plane := &ControlPlane{
|
||||
@ -344,6 +350,7 @@ func NewControlPlane(
|
||||
realDomainSet: bloom.NewWithEstimates(2048, 0.001),
|
||||
lanInterface: global.LanInterface,
|
||||
wanInterface: global.WanInterface,
|
||||
sniffingTimeout: sniffingTimeout,
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
|
@ -29,7 +29,7 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
|
||||
defer lConn.Close()
|
||||
|
||||
// Sniff target domain.
|
||||
sniffer := sniffing.NewConnSniffer(lConn, TcpSniffBufSize)
|
||||
sniffer := sniffing.NewConnSniffer(lConn, TcpSniffBufSize, c.sniffingTimeout)
|
||||
// ConnSniffer should be used later, so we cannot close it now.
|
||||
defer sniffer.Close()
|
||||
domain, err := sniffer.SniffTcp()
|
||||
|
@ -37,7 +37,8 @@ global {
|
||||
# 1. "ip". Dial proxy using the IP from DNS directly. This allows your ipv4, ipv6 to choose the optimal path
|
||||
# respectively, and makes the IP version requested by the application meet expectations. For example, if you
|
||||
# use curl -4 ip.sb, you will request IPv4 via proxy and get a IPv4 echo. And curl -6 ip.sb will request IPv6.
|
||||
# This may solve some wierd full-cone problem if your are be your node support that.
|
||||
# This may solve some wierd full-cone problem if your are be your node support that. Sniffing will be disabled
|
||||
# in this mode.
|
||||
# 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.
|
||||
@ -55,6 +56,10 @@ global {
|
||||
# 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
|
||||
|
||||
# Timeout to waiting for first data sending for sniffing. It is always 0 if dial_mode is ip. Set it higher is useful
|
||||
# in high latency LAN network.
|
||||
sniffing_timeout: 100ms
|
||||
}
|
||||
|
||||
# Subscriptions defined here will be resolved as nodes and merged as a part of the global node pool.
|
||||
|
Reference in New Issue
Block a user