Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,23 @@ proxies = [
# define a global timeout on establishing of network connections. idle
# means a timeout on pumping data between sockset when nothing is
# happening.
#
[network.timeout]
tcp = "5s"
http = "10s"
idle = "5m"
handshake = "10s"

# this defines a configuration for TCP keep alives. Default values are taken
# from Golang default behavior.
[network.keep-alive]
disabled = false
# idle means a time period after which we start sending TCP Keep Alive probes
idle = "15s"
# interval is a period between 2 consecutive probes
interval = "15s"
# if we miss that many probes, a connection will be considered as a dead one.
count = 9

# mtg has to mimic real websites. It does not mean domain fronting, it also
# means that traffic characteristics should be similar to real world traffic.
# websites and applications behave differently, their traffic patterns are also
Expand Down
6 changes: 6 additions & 0 deletions internal/cli/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ func (d *Doctor) Run(cli *CLI, version string) error {
conf.Network.Timeout.TCP.Get(10*time.Second),
conf.Network.Timeout.HTTP.Get(0),
conf.Network.Timeout.Idle.Get(0),
net.KeepAliveConfig{
Enable: !conf.Network.KeepAlive.Disabled.Get(false),
Idle: conf.Network.KeepAlive.Idle.Get(0),
Interval: conf.Network.KeepAlive.Interval.Get(0),
Count: int(conf.Network.KeepAlive.Count.Get(0)),
},
)

fmt.Println("Validate native network connectivity")
Expand Down
6 changes: 6 additions & 0 deletions internal/cli/run_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ func makeNetwork(conf *config.Config, version string) (mtglib.Network, error) {
conf.Network.Timeout.TCP.Get(0),
conf.Network.Timeout.HTTP.Get(0),
conf.Network.Timeout.Idle.Get(0),
net.KeepAliveConfig{
Enable: !conf.Network.KeepAlive.Disabled.Get(false),
Idle: conf.Network.KeepAlive.Idle.Get(0),
Interval: conf.Network.KeepAlive.Interval.Get(0),
Count: int(conf.Network.KeepAlive.Count.Get(0)),
},
)

proxyDialers := make([]mtglib.Network, len(conf.Network.Proxies))
Expand Down
6 changes: 6 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ type Config struct {
Idle TypeDuration `json:"idle"`
Handshake TypeDuration `json:"handshake"`
} `json:"timeout"`
KeepAlive struct {
Disabled TypeBool `json:"disabled"`
Idle TypeDuration `json:"idle"`
Interval TypeDuration `json:"interval"`
Count TypeConcurrency `json:"count"`
} `json:"keepAlive"`
DOHIP TypeIP `json:"dohIp"`
DNS TypeDNSURI `json:"dns"`
Proxies []TypeProxyURL `json:"proxies"`
Expand Down
6 changes: 6 additions & 0 deletions internal/config/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ type tomlConfig struct {
Idle string `toml:"idle" json:"idle,omitempty"`
Handshake string `toml:"handshake" json:"handshake,omitempty"`
} `toml:"timeout" json:"timeout,omitempty"`
KeepAlive struct {
Disabled bool `toml:"disabled" json:"disabled,omitempty"`
Idle string `toml:"idle" json:"idle,omitempty"`
Interval string `toml:"interval" json:"interval,omitempty"`
Count uint `toml:"count" json:"count,omitempty"`
} `toml:"keep-alive" json:"keepAlive,omitempty"`
DOHIP string `toml:"doh-ip" json:"dohIp,omitempty"`
DNS string `toml:"dns" json:"dns,omitempty"`
Proxies []string `toml:"proxies" json:"proxies,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion network/v2/base_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (suite *BaseHTTPTestSuite) SetupSuite() {
}

func (suite *BaseHTTPTestSuite) SetupTest() {
suite.client = network.New(nil, "mtg/1", 0, 0, 0).MakeHTTPClient(nil)
suite.client = network.New(nil, "mtg/1", 0, 0, 0, network.DefaultKeepAliveConfig).MakeHTTPClient(nil)
}

func (suite *BaseHTTPTestSuite) TestGet() {
Expand Down
2 changes: 1 addition & 1 deletion network/v2/base_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type BaseNetworkTestSuite struct {
func (suite *BaseNetworkTestSuite) SetupSuite() {
suite.EchoServerTestSuite.SetupSuite()

suite.net = network.New(nil, "agent", 0, 0, 0)
suite.net = network.New(nil, "agent", 0, 0, 0, network.DefaultKeepAliveConfig)
}

func (suite *BaseNetworkTestSuite) TestDialUnknownNetwork() {
Expand Down
24 changes: 22 additions & 2 deletions network/v2/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package network

import (
"errors"
"net"
"time"
)

Expand All @@ -27,19 +28,25 @@ const (
// DefaultTCPKeepAlivePeriod defines a time period between 2 consecuitive
// probes.
//
// Deprecated: use DefaultKeepAliveIdle and DefaultKeepAliveInterval instead.
// Deprecated: use DefaultKeepAliveConfig
DefaultTCPKeepAlivePeriod = 10 * time.Second

// DefaultKeepAliveIdle is the time a connection must be idle before
// the first keepalive probe is sent.
//
// Deprecated: use DefaultKeepAliveConfig
DefaultKeepAliveIdle = 30 * time.Second

// DefaultKeepAliveInterval is the time between consecutive keepalive
// probes.
//
// Deprecated: use DefaultKeepAliveConfig
DefaultKeepAliveInterval = 10 * time.Second

// DefaultKeepAliveCount is the number of unacknowledged probes before
// the connection is considered dead.
//
// Deprecated: use DefaultKeepAliveConfig
DefaultKeepAliveCount = 3

// User Agent to use in HTTP client.
Expand All @@ -50,4 +57,17 @@ const (
tcpLingerTimeout = 1
)

var ErrCannotDial = errors.New("cannot dial to any address")
var (
ErrCannotDial = errors.New("cannot dial to any address")

// DefaultKeepAliveConfig defines a default configuration for
// keep alive settings. As per official documentation, if keep alive
// is enabled, then:
//
// Idle = 15 * time.Second
// Interval = 15 * time.Second
// Count = 9
DefaultKeepAliveConfig = net.KeepAliveConfig{
Enable: true,
}
)
17 changes: 10 additions & 7 deletions network/v2/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import (
type network struct {
net.Dialer

httpTimeout time.Duration
idleTimeout time.Duration
userAgent string
keepAliveConfig net.KeepAliveConfig
httpTimeout time.Duration
idleTimeout time.Duration
userAgent string
}

func (n *network) Dial(network, address string) (essentials.Conn, error) {
Expand All @@ -37,7 +38,7 @@ func (n *network) DialContext(ctx context.Context, network, address string) (ess

tcpConn := conn.(*net.TCPConn)

return tcpConn, setCommonSocketOptions(tcpConn)
return tcpConn, setCommonSocketOptions(tcpConn, n.keepAliveConfig)
}

func (n *network) MakeHTTPClient(
Expand Down Expand Up @@ -71,6 +72,7 @@ func New(
tcpTimeout,
httpTimeout,
idleTimeout time.Duration,
keepAliveConfig net.KeepAliveConfig,
) mtglib.Network {
if dnsResolver == nil {
dnsResolver = net.DefaultResolver
Expand All @@ -86,8 +88,9 @@ func New(
Resolver: dnsResolver,
FallbackDelay: -1,
},
userAgent: userAgent,
idleTimeout: idleTimeout,
httpTimeout: httpTimeout,
userAgent: userAgent,
idleTimeout: idleTimeout,
httpTimeout: httpTimeout,
keepAliveConfig: keepAliveConfig,
}
}
9 changes: 2 additions & 7 deletions network/v2/sockopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@ import (
"net"
)

func setCommonSocketOptions(conn *net.TCPConn) error {
if err := conn.SetKeepAliveConfig(net.KeepAliveConfig{
Enable: true,
Idle: DefaultKeepAliveIdle,
Interval: DefaultKeepAliveInterval,
Count: DefaultKeepAliveCount,
}); err != nil {
func setCommonSocketOptions(conn *net.TCPConn, keepAliveConfig net.KeepAliveConfig) error {
if err := conn.SetKeepAliveConfig(keepAliveConfig); err != nil {
return fmt.Errorf("cannot configure TCP keepalive: %w", err)
}

Expand Down
8 changes: 4 additions & 4 deletions network/v2/sockopts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestSetCommonSocketOptionsKeepAlive(t *testing.T) {

tcpConn := accepted.(*net.TCPConn)

err = setCommonSocketOptions(tcpConn)
err = setCommonSocketOptions(tcpConn, DefaultKeepAliveConfig)
require.NoError(t, err)

rawConn, err := tcpConn.SyscallConn()
Expand All @@ -78,15 +78,15 @@ func TestSetCommonSocketOptionsKeepAlive(t *testing.T) {

idle, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, tcpKeepIdleOption())
require.NoError(t, err)
require.Equal(t, int(DefaultKeepAliveIdle.Seconds()), idle, "keepalive idle should match DefaultKeepAliveIdle")
require.Equal(t, 15, idle, "keepalive idle should match DefaultKeepAliveIdle")

interval, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_KEEPINTVL)
require.NoError(t, err)
require.Equal(t, int(DefaultKeepAliveInterval.Seconds()), interval, "keepalive interval should match DefaultKeepAliveInterval")
require.Equal(t, 15, interval, "keepalive interval should match DefaultKeepAliveInterval")

count, err := unix.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_KEEPCNT)
require.NoError(t, err)
require.Equal(t, DefaultKeepAliveCount, count, "keepalive count should match DefaultKeepAliveCount")
require.Equal(t, 9, count, "keepalive count should match DefaultKeepAliveCount")
})
require.NoError(t, err)
}
2 changes: 1 addition & 1 deletion network/v2/socks_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (suite *SocksProxyTestSuite) SetupSuite() {
require.NoError(suite.T(), err)
suite.authURL = parsed

suite.baseNetwork = network.New(nil, "mtg", 0, 0, 0)
suite.baseNetwork = network.New(nil, "mtg", 0, 0, 0, network.DefaultKeepAliveConfig)
}

func (suite *SocksProxyTestSuite) TestIncorrectSchema() {
Expand Down
Loading