Просмотр исходного кода

Merge pull request #451 from 9seconds/keepalive-config

Propagate keep alive settings from the config
tags/v2.2.8^2^2
Sergei Arkhipov 4 недель назад
Родитель
Сommit
ac40c94820
Аккаунт пользователя с таким Email не найден

+ 11
- 1
example.config.toml Просмотреть файл

204
 # define a global timeout on establishing of network connections. idle
204
 # define a global timeout on establishing of network connections. idle
205
 # means a timeout on pumping data between sockset when nothing is
205
 # means a timeout on pumping data between sockset when nothing is
206
 # happening.
206
 # happening.
207
-#
208
 [network.timeout]
207
 [network.timeout]
209
 tcp = "5s"
208
 tcp = "5s"
210
 http = "10s"
209
 http = "10s"
211
 idle = "5m"
210
 idle = "5m"
212
 handshake = "10s"
211
 handshake = "10s"
213
 
212
 
213
+# this defines a configuration for TCP keep alives. Default values are taken
214
+# from Golang default behavior.
215
+[network.keep-alive]
216
+disabled = false
217
+# idle means a time period after which we start sending TCP Keep Alive probes
218
+idle = "15s"
219
+# interval is a period between 2 consecutive probes
220
+interval = "15s"
221
+# if we miss that many probes, a connection will be considered as a dead one.
222
+count = 9
223
+
214
 # mtg has to mimic real websites. It does not mean domain fronting, it also
224
 # mtg has to mimic real websites. It does not mean domain fronting, it also
215
 # means that traffic characteristics should be similar to real world traffic.
225
 # means that traffic characteristics should be similar to real world traffic.
216
 # websites and applications behave differently, their traffic patterns are also
226
 # websites and applications behave differently, their traffic patterns are also

+ 6
- 0
internal/cli/doctor.go Просмотреть файл

97
 		conf.Network.Timeout.TCP.Get(10*time.Second),
97
 		conf.Network.Timeout.TCP.Get(10*time.Second),
98
 		conf.Network.Timeout.HTTP.Get(0),
98
 		conf.Network.Timeout.HTTP.Get(0),
99
 		conf.Network.Timeout.Idle.Get(0),
99
 		conf.Network.Timeout.Idle.Get(0),
100
+		net.KeepAliveConfig{
101
+			Enable:   !conf.Network.KeepAlive.Disabled.Get(false),
102
+			Idle:     conf.Network.KeepAlive.Idle.Get(0),
103
+			Interval: conf.Network.KeepAlive.Interval.Get(0),
104
+			Count:    int(conf.Network.KeepAlive.Count.Get(0)),
105
+		},
100
 	)
106
 	)
101
 
107
 
102
 	fmt.Println("Validate native network connectivity")
108
 	fmt.Println("Validate native network connectivity")

+ 6
- 0
internal/cli/run_proxy.go Просмотреть файл

50
 		conf.Network.Timeout.TCP.Get(0),
50
 		conf.Network.Timeout.TCP.Get(0),
51
 		conf.Network.Timeout.HTTP.Get(0),
51
 		conf.Network.Timeout.HTTP.Get(0),
52
 		conf.Network.Timeout.Idle.Get(0),
52
 		conf.Network.Timeout.Idle.Get(0),
53
+		net.KeepAliveConfig{
54
+			Enable:   !conf.Network.KeepAlive.Disabled.Get(false),
55
+			Idle:     conf.Network.KeepAlive.Idle.Get(0),
56
+			Interval: conf.Network.KeepAlive.Interval.Get(0),
57
+			Count:    int(conf.Network.KeepAlive.Count.Get(0)),
58
+		},
53
 	)
59
 	)
54
 
60
 
55
 	proxyDialers := make([]mtglib.Network, len(conf.Network.Proxies))
61
 	proxyDialers := make([]mtglib.Network, len(conf.Network.Proxies))

+ 6
- 0
internal/config/config.go Просмотреть файл

65
 			Idle      TypeDuration `json:"idle"`
65
 			Idle      TypeDuration `json:"idle"`
66
 			Handshake TypeDuration `json:"handshake"`
66
 			Handshake TypeDuration `json:"handshake"`
67
 		} `json:"timeout"`
67
 		} `json:"timeout"`
68
+		KeepAlive struct {
69
+			Disabled TypeBool        `json:"disabled"`
70
+			Idle     TypeDuration    `json:"idle"`
71
+			Interval TypeDuration    `json:"interval"`
72
+			Count    TypeConcurrency `json:"count"`
73
+		} `json:"keepAlive"`
68
 		DOHIP   TypeIP         `json:"dohIp"`
74
 		DOHIP   TypeIP         `json:"dohIp"`
69
 		DNS     TypeDNSURI     `json:"dns"`
75
 		DNS     TypeDNSURI     `json:"dns"`
70
 		Proxies []TypeProxyURL `json:"proxies"`
76
 		Proxies []TypeProxyURL `json:"proxies"`

+ 6
- 0
internal/config/parse.go Просмотреть файл

60
 			Idle      string `toml:"idle" json:"idle,omitempty"`
60
 			Idle      string `toml:"idle" json:"idle,omitempty"`
61
 			Handshake string `toml:"handshake" json:"handshake,omitempty"`
61
 			Handshake string `toml:"handshake" json:"handshake,omitempty"`
62
 		} `toml:"timeout" json:"timeout,omitempty"`
62
 		} `toml:"timeout" json:"timeout,omitempty"`
63
+		KeepAlive struct {
64
+			Disabled bool   `toml:"disabled" json:"disabled,omitempty"`
65
+			Idle     string `toml:"idle" json:"idle,omitempty"`
66
+			Interval string `toml:"interval" json:"interval,omitempty"`
67
+			Count    uint   `toml:"count" json:"count,omitempty"`
68
+		} `toml:"keep-alive" json:"keepAlive,omitempty"`
63
 		DOHIP   string   `toml:"doh-ip" json:"dohIp,omitempty"`
69
 		DOHIP   string   `toml:"doh-ip" json:"dohIp,omitempty"`
64
 		DNS     string   `toml:"dns" json:"dns,omitempty"`
70
 		DNS     string   `toml:"dns" json:"dns,omitempty"`
65
 		Proxies []string `toml:"proxies" json:"proxies,omitempty"`
71
 		Proxies []string `toml:"proxies" json:"proxies,omitempty"`

+ 1
- 1
network/v2/base_http_test.go Просмотреть файл

25
 }
25
 }
26
 
26
 
27
 func (suite *BaseHTTPTestSuite) SetupTest() {
27
 func (suite *BaseHTTPTestSuite) SetupTest() {
28
-	suite.client = network.New(nil, "mtg/1", 0, 0, 0).MakeHTTPClient(nil)
28
+	suite.client = network.New(nil, "mtg/1", 0, 0, 0, network.DefaultKeepAliveConfig).MakeHTTPClient(nil)
29
 }
29
 }
30
 
30
 
31
 func (suite *BaseHTTPTestSuite) TestGet() {
31
 func (suite *BaseHTTPTestSuite) TestGet() {

+ 1
- 1
network/v2/base_network_test.go Просмотреть файл

19
 func (suite *BaseNetworkTestSuite) SetupSuite() {
19
 func (suite *BaseNetworkTestSuite) SetupSuite() {
20
 	suite.EchoServerTestSuite.SetupSuite()
20
 	suite.EchoServerTestSuite.SetupSuite()
21
 
21
 
22
-	suite.net = network.New(nil, "agent", 0, 0, 0)
22
+	suite.net = network.New(nil, "agent", 0, 0, 0, network.DefaultKeepAliveConfig)
23
 }
23
 }
24
 
24
 
25
 func (suite *BaseNetworkTestSuite) TestDialUnknownNetwork() {
25
 func (suite *BaseNetworkTestSuite) TestDialUnknownNetwork() {

+ 22
- 2
network/v2/init.go Просмотреть файл

11
 
11
 
12
 import (
12
 import (
13
 	"errors"
13
 	"errors"
14
+	"net"
14
 	"time"
15
 	"time"
15
 )
16
 )
16
 
17
 
27
 	// DefaultTCPKeepAlivePeriod defines a time period between 2 consecuitive
28
 	// DefaultTCPKeepAlivePeriod defines a time period between 2 consecuitive
28
 	// probes.
29
 	// probes.
29
 	//
30
 	//
30
-	// Deprecated: use DefaultKeepAliveIdle and DefaultKeepAliveInterval instead.
31
+	// Deprecated: use DefaultKeepAliveConfig
31
 	DefaultTCPKeepAlivePeriod = 10 * time.Second
32
 	DefaultTCPKeepAlivePeriod = 10 * time.Second
32
 
33
 
33
 	// DefaultKeepAliveIdle is the time a connection must be idle before
34
 	// DefaultKeepAliveIdle is the time a connection must be idle before
34
 	// the first keepalive probe is sent.
35
 	// the first keepalive probe is sent.
36
+	//
37
+	// Deprecated: use DefaultKeepAliveConfig
35
 	DefaultKeepAliveIdle = 30 * time.Second
38
 	DefaultKeepAliveIdle = 30 * time.Second
36
 
39
 
37
 	// DefaultKeepAliveInterval is the time between consecutive keepalive
40
 	// DefaultKeepAliveInterval is the time between consecutive keepalive
38
 	// probes.
41
 	// probes.
42
+	//
43
+	// Deprecated: use DefaultKeepAliveConfig
39
 	DefaultKeepAliveInterval = 10 * time.Second
44
 	DefaultKeepAliveInterval = 10 * time.Second
40
 
45
 
41
 	// DefaultKeepAliveCount is the number of unacknowledged probes before
46
 	// DefaultKeepAliveCount is the number of unacknowledged probes before
42
 	// the connection is considered dead.
47
 	// the connection is considered dead.
48
+	//
49
+	// Deprecated: use DefaultKeepAliveConfig
43
 	DefaultKeepAliveCount = 3
50
 	DefaultKeepAliveCount = 3
44
 
51
 
45
 	// User Agent to use in HTTP client.
52
 	// User Agent to use in HTTP client.
50
 	tcpLingerTimeout = 1
57
 	tcpLingerTimeout = 1
51
 )
58
 )
52
 
59
 
53
-var ErrCannotDial = errors.New("cannot dial to any address")
60
+var (
61
+	ErrCannotDial = errors.New("cannot dial to any address")
62
+
63
+	// DefaultKeepAliveConfig defines a default configuration for
64
+	// keep alive settings. As per official documentation, if keep alive
65
+	// is enabled, then:
66
+	//
67
+	//  Idle = 15 * time.Second
68
+	//  Interval = 15 * time.Second
69
+	//  Count = 9
70
+	DefaultKeepAliveConfig = net.KeepAliveConfig{
71
+		Enable: true,
72
+	}
73
+)

+ 10
- 7
network/v2/network.go Просмотреть файл

14
 type network struct {
14
 type network struct {
15
 	net.Dialer
15
 	net.Dialer
16
 
16
 
17
-	httpTimeout time.Duration
18
-	idleTimeout time.Duration
19
-	userAgent   string
17
+	keepAliveConfig net.KeepAliveConfig
18
+	httpTimeout     time.Duration
19
+	idleTimeout     time.Duration
20
+	userAgent       string
20
 }
21
 }
21
 
22
 
22
 func (n *network) Dial(network, address string) (essentials.Conn, error) {
23
 func (n *network) Dial(network, address string) (essentials.Conn, error) {
37
 
38
 
38
 	tcpConn := conn.(*net.TCPConn)
39
 	tcpConn := conn.(*net.TCPConn)
39
 
40
 
40
-	return tcpConn, setCommonSocketOptions(tcpConn)
41
+	return tcpConn, setCommonSocketOptions(tcpConn, n.keepAliveConfig)
41
 }
42
 }
42
 
43
 
43
 func (n *network) MakeHTTPClient(
44
 func (n *network) MakeHTTPClient(
71
 	tcpTimeout,
72
 	tcpTimeout,
72
 	httpTimeout,
73
 	httpTimeout,
73
 	idleTimeout time.Duration,
74
 	idleTimeout time.Duration,
75
+	keepAliveConfig net.KeepAliveConfig,
74
 ) mtglib.Network {
76
 ) mtglib.Network {
75
 	if dnsResolver == nil {
77
 	if dnsResolver == nil {
76
 		dnsResolver = net.DefaultResolver
78
 		dnsResolver = net.DefaultResolver
86
 			Resolver:      dnsResolver,
88
 			Resolver:      dnsResolver,
87
 			FallbackDelay: -1,
89
 			FallbackDelay: -1,
88
 		},
90
 		},
89
-		userAgent:   userAgent,
90
-		idleTimeout: idleTimeout,
91
-		httpTimeout: httpTimeout,
91
+		userAgent:       userAgent,
92
+		idleTimeout:     idleTimeout,
93
+		httpTimeout:     httpTimeout,
94
+		keepAliveConfig: keepAliveConfig,
92
 	}
95
 	}
93
 }
96
 }

+ 2
- 7
network/v2/sockopts.go Просмотреть файл

5
 	"net"
5
 	"net"
6
 )
6
 )
7
 
7
 
8
-func setCommonSocketOptions(conn *net.TCPConn) error {
9
-	if err := conn.SetKeepAliveConfig(net.KeepAliveConfig{
10
-		Enable:   true,
11
-		Idle:     DefaultKeepAliveIdle,
12
-		Interval: DefaultKeepAliveInterval,
13
-		Count:    DefaultKeepAliveCount,
14
-	}); err != nil {
8
+func setCommonSocketOptions(conn *net.TCPConn, keepAliveConfig net.KeepAliveConfig) error {
9
+	if err := conn.SetKeepAliveConfig(keepAliveConfig); err != nil {
15
 		return fmt.Errorf("cannot configure TCP keepalive: %w", err)
10
 		return fmt.Errorf("cannot configure TCP keepalive: %w", err)
16
 	}
11
 	}
17
 
12
 

+ 4
- 4
network/v2/sockopts_test.go Просмотреть файл

65
 
65
 
66
 	tcpConn := accepted.(*net.TCPConn)
66
 	tcpConn := accepted.(*net.TCPConn)
67
 
67
 
68
-	err = setCommonSocketOptions(tcpConn)
68
+	err = setCommonSocketOptions(tcpConn, DefaultKeepAliveConfig)
69
 	require.NoError(t, err)
69
 	require.NoError(t, err)
70
 
70
 
71
 	rawConn, err := tcpConn.SyscallConn()
71
 	rawConn, err := tcpConn.SyscallConn()
78
 
78
 
79
 		idle, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, tcpKeepIdleOption())
79
 		idle, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, tcpKeepIdleOption())
80
 		require.NoError(t, err)
80
 		require.NoError(t, err)
81
-		require.Equal(t, int(DefaultKeepAliveIdle.Seconds()), idle, "keepalive idle should match DefaultKeepAliveIdle")
81
+		require.Equal(t, 15, idle, "keepalive idle should match DefaultKeepAliveIdle")
82
 
82
 
83
 		interval, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_KEEPINTVL)
83
 		interval, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_KEEPINTVL)
84
 		require.NoError(t, err)
84
 		require.NoError(t, err)
85
-		require.Equal(t, int(DefaultKeepAliveInterval.Seconds()), interval, "keepalive interval should match DefaultKeepAliveInterval")
85
+		require.Equal(t, 15, interval, "keepalive interval should match DefaultKeepAliveInterval")
86
 
86
 
87
 		count, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_KEEPCNT)
87
 		count, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_KEEPCNT)
88
 		require.NoError(t, err)
88
 		require.NoError(t, err)
89
-		require.Equal(t, DefaultKeepAliveCount, count, "keepalive count should match DefaultKeepAliveCount")
89
+		require.Equal(t, 9, count, "keepalive count should match DefaultKeepAliveCount")
90
 	})
90
 	})
91
 	require.NoError(t, err)
91
 	require.NoError(t, err)
92
 }
92
 }

+ 1
- 1
network/v2/socks_proxy_test.go Просмотреть файл

66
 	require.NoError(suite.T(), err)
66
 	require.NoError(suite.T(), err)
67
 	suite.authURL = parsed
67
 	suite.authURL = parsed
68
 
68
 
69
-	suite.baseNetwork = network.New(nil, "mtg", 0, 0, 0)
69
+	suite.baseNetwork = network.New(nil, "mtg", 0, 0, 0, network.DefaultKeepAliveConfig)
70
 }
70
 }
71
 
71
 
72
 func (suite *SocksProxyTestSuite) TestIncorrectSchema() {
72
 func (suite *SocksProxyTestSuite) TestIncorrectSchema() {

Загрузка…
Отмена
Сохранить