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

Merge pull request #770 from thesinakamali/master

Add alternative upstream device support to Inproxy
Rod Hynes 2 недель назад
Родитель
Сommit
b2ee778e30

+ 1 - 0
psiphon/common/inproxy/inproxy_disabled.go

@@ -61,6 +61,7 @@ type webRTCConn struct {
 type webRTCConfig struct {
 	Logger                      common.Logger
 	EnableDebugLogging          bool
+	ExcludeInterfaceName        string
 	WebRTCDialCoordinator       WebRTCDialCoordinator
 	ClientRootObfuscationSecret ObfuscationSecret
 	DoDTLSRandomization         bool

+ 5 - 0
psiphon/common/inproxy/proxy.go

@@ -138,6 +138,10 @@ type ProxyConfig struct {
 	// and the provider can select new parameters per connection as reqired.
 	MakeWebRTCDialCoordinator func() (WebRTCDialCoordinator, error)
 
+	// ExcludeInterfaceName specifies the network interface to omit from
+	// proxy WebRTC ICE interface enumeration.
+	ExcludeInterfaceName string
+
 	// HandleTacticsPayload is a callback that receives any tactics payload,
 	// provided by the broker in proxy announcement request responses.
 	// HandleTacticsPayload must return true when the tacticsPayload includes
@@ -1148,6 +1152,7 @@ func (p *Proxy) proxyOneClient(
 		&webRTCConfig{
 			Logger:                      p.config.Logger,
 			EnableDebugLogging:          p.config.EnableWebRTCDebugLogging,
+			ExcludeInterfaceName:        p.config.ExcludeInterfaceName,
 			WebRTCDialCoordinator:       webRTCCoordinator,
 			ClientRootObfuscationSecret: announceResponse.ClientRootObfuscationSecret,
 			DoDTLSRandomization:         announceResponse.DoDTLSRandomization,

+ 16 - 2
psiphon/common/inproxy/webrtc.go

@@ -152,6 +152,10 @@ type webRTCConfig struct {
 	// Logger at a Debug log level.
 	EnableDebugLogging bool
 
+	// ExcludeInterfaceName specifies the interface name to omit from ICE
+	// interface enumeration.
+	ExcludeInterfaceName string
+
 	// WebRTCDialCoordinator specifies specific WebRTC dial strategies and
 	// settings; WebRTCDialCoordinator also facilities dial replay by
 	// receiving callbacks when individual dial steps succeed or fail.
@@ -350,7 +354,10 @@ func newWebRTCConn(
 		config.EnableDebugLogging)
 
 	pionNetwork := newPionNetwork(
-		ctx, pionLoggerFactory.NewLogger("net"), config.WebRTCDialCoordinator)
+		ctx,
+		pionLoggerFactory.NewLogger("net"),
+		config.WebRTCDialCoordinator,
+		config.ExcludeInterfaceName)
 
 	udpMux := webrtc.NewICEUniversalUDPMux(
 		pionLoggerFactory.NewLogger("mux"), udpConn, TTL, pionNetwork)
@@ -3255,17 +3262,20 @@ type pionNetwork struct {
 	dialCtx               context.Context
 	logger                pion_logging.LeveledLogger
 	webRTCDialCoordinator WebRTCDialCoordinator
+	excludeInterfaceName  string
 }
 
 func newPionNetwork(
 	dialCtx context.Context,
 	logger pion_logging.LeveledLogger,
-	webRTCDialCoordinator WebRTCDialCoordinator) *pionNetwork {
+	webRTCDialCoordinator WebRTCDialCoordinator,
+	excludeInterfaceName string) *pionNetwork {
 
 	return &pionNetwork{
 		dialCtx:               dialCtx,
 		logger:                logger,
 		webRTCDialCoordinator: webRTCDialCoordinator,
+		excludeInterfaceName:  excludeInterfaceName,
 	}
 }
 
@@ -3327,6 +3337,10 @@ func (p *pionNetwork) Interfaces() ([]*transport.Interface, error) {
 	}
 
 	for _, netInterface := range netInterfaces {
+		if p.excludeInterfaceName != "" && netInterface.Name == p.excludeInterfaceName {
+			continue
+		}
+
 		// Note: don't exclude interfaces with the net.FlagPointToPoint flag,
 		// which is set for certain mobile networks
 		if (netInterface.Flags&net.FlagUp == 0) ||

+ 18 - 0
psiphon/config.go

@@ -31,6 +31,7 @@ import (
 	"path/filepath"
 	"reflect"
 	"regexp"
+	"runtime"
 	"strconv"
 	"strings"
 	"sync"
@@ -658,6 +659,16 @@ type Config struct {
 	// ephemeral key will be generated.
 	InproxyProxySessionPrivateKey string `json:",omitempty"`
 
+	// InproxyProxySplitUpstreamInterfaceName specifies a network interface
+	// that the in-proxy proxy will use for upstream destination dialing. The
+	// specified interface is also excluded from proxy ICE gathering. This is
+	// intended to support split interface setups with the proxy/client
+	// connection on the default interface and the proxy/server connection on
+	// the designated interface.
+	//
+	// Only supported on Linux,  and cannot be used with DeviceBinder.
+	InproxyProxySplitUpstreamInterfaceName string `json:",omitempty"`
+
 	// InproxyMaxClients specifies the maximum number of common in-proxy
 	// clients to be proxied concurrently. When InproxyEnableProxy is set,
 	// it can only be 0 when InProxyMaxPersonalClients is > 0.
@@ -1574,6 +1585,13 @@ func (config *Config) Commit(migrateFromLegacyFields bool) error {
 		return errors.TraceNew("invalid ObfuscatedSSHAlgorithms")
 	}
 
+	if config.InproxyProxySplitUpstreamInterfaceName != "" && runtime.GOOS != "linux" {
+		return errors.TraceNew("InproxyProxySplitUpstreamInterfaceName is only supported on Linux")
+	}
+	if config.InproxyProxySplitUpstreamInterfaceName != "" && config.DeviceBinder != nil {
+		return errors.TraceNew("InproxyProxySplitUpstreamInterfaceName cannot be used with DeviceBinder")
+	}
+
 	if config.InproxyEnableProxy {
 
 		if config.InproxyMaxCommonClients+config.InproxyMaxPersonalClients <= 0 {

+ 1 - 0
psiphon/controller.go

@@ -3368,6 +3368,7 @@ func (controller *Controller) runInproxyProxy() {
 		GetBrokerClient:                      controller.inproxyGetProxyBrokerClient,
 		GetBaseAPIParameters:                 controller.inproxyGetProxyAPIParameters,
 		MakeWebRTCDialCoordinator:            controller.inproxyMakeProxyWebRTCDialCoordinator,
+		ExcludeInterfaceName:                 controller.config.InproxyProxySplitUpstreamInterfaceName,
 		HandleTacticsPayload:                 controller.inproxyHandleProxyTacticsPayload,
 		MaxCommonClients:                     controller.config.InproxyMaxCommonClients,
 		MaxPersonalClients:                   controller.config.InproxyMaxPersonalClients,

+ 9 - 0
psiphon/inproxy.go

@@ -41,6 +41,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tun"
 	utls "github.com/Psiphon-Labs/utls"
 	"github.com/cespare/xxhash"
 )
@@ -2003,6 +2004,8 @@ func (w *InproxyWebRTCDialInstance) ProxyUpstreamDial(
 	// DNSResolverPreresolvedIPAddressCIDRs proxy tactics. In addition,
 	// replay the selected upstream dial tactics parameters.
 
+	splitUpstreamInterfaceName := w.config.InproxyProxySplitUpstreamInterfaceName
+
 	dialer := net.Dialer{
 		Control: func(_, _ string, c syscall.RawConn) error {
 			var controlErr error
@@ -2018,6 +2021,12 @@ func (w *InproxyWebRTCDialInstance) ProxyUpstreamDial(
 						controlErr = errors.Tracef("BindToDevice failed: %s", err)
 						return
 					}
+				} else if splitUpstreamInterfaceName != "" {
+					err := tun.BindToDevice(socketFD, splitUpstreamInterfaceName)
+					if err != nil {
+						controlErr = errors.Tracef("BindToDevice failed: %s", err)
+						return
+					}
 				}
 			})
 			if controlErr != nil {