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

Merge pull request #123 from Psiphon-Labs/network-interface-changes

Network interface changes
Rod Hynes 10 лет назад
Родитель
Сommit
705afd534f
6 измененных файлов с 110 добавлено и 6 удалено
  1. 7 0
      ConsoleClient/psiphonClient.go
  2. 7 0
      psiphon/config.go
  3. 8 2
      psiphon/controller.go
  4. 3 2
      psiphon/httpProxy.go
  5. 79 0
      psiphon/networkInterface.go
  6. 6 2
      psiphon/socksProxy.go

+ 7 - 0
ConsoleClient/psiphonClient.go

@@ -47,6 +47,9 @@ func main() {
 	var profileFilename string
 	var profileFilename string
 	flag.StringVar(&profileFilename, "profile", "", "CPU profile output file")
 	flag.StringVar(&profileFilename, "profile", "", "CPU profile output file")
 
 
+	var interfaceName string
+	flag.StringVar(&interfaceName, "listenInterface", "", "Interface Name")
+
 	flag.Parse()
 	flag.Parse()
 
 
 	// Initialize default Notice output (stderr)
 	// Initialize default Notice output (stderr)
@@ -153,6 +156,10 @@ func main() {
 		}
 		}
 	}
 	}
 
 
+	if interfaceName != "" {
+		config.ListenInterface = interfaceName
+	}
+
 	// Run Psiphon
 	// Run Psiphon
 
 
 	controller, err := psiphon.NewController(config)
 	controller, err := psiphon.NewController(config)

+ 7 - 0
psiphon/config.go

@@ -144,6 +144,13 @@ type Config struct {
 	// the controller will keep trying indefinitely.
 	// the controller will keep trying indefinitely.
 	EstablishTunnelTimeoutSeconds *int
 	EstablishTunnelTimeoutSeconds *int
 
 
+	// ListenInterface specifies which interface to listen on.  If no interface
+	// is provided then listen on 127.0.0.1.
+	// If an invalid interface is provided then listen on localhost (127.0.0.1).
+	// If 'any' is provided then use 0.0.0.0.
+	// If there are multiple IP addresses on an interface use the first IPv4 address.
+	ListenInterface string
+
 	// LocalSocksProxyPort specifies a port number for the local SOCKS proxy
 	// LocalSocksProxyPort specifies a port number for the local SOCKS proxy
 	// running at 127.0.0.1. For the default value, 0, the system selects a free
 	// running at 127.0.0.1. For the default value, 0, the system selects a free
 	// port (a notice reporting the selected port is emitted).
 	// port (a notice reporting the selected port is emitted).

+ 8 - 2
psiphon/controller.go

@@ -136,7 +136,13 @@ func (controller *Controller) Run(shutdownBroadcast <-chan struct{}) {
 
 
 	// Start components
 	// Start components
 
 
-	socksProxy, err := NewSocksProxy(controller.config, controller)
+	listenIP, err := GetInterfaceIPAddress(controller.config.ListenInterface)
+	if err != nil {
+		NoticeError("error getting listener IP: %s", err)
+		return
+	}
+
+	socksProxy, err := NewSocksProxy(controller.config, controller, listenIP)
 	if err != nil {
 	if err != nil {
 		NoticeAlert("error initializing local SOCKS proxy: %s", err)
 		NoticeAlert("error initializing local SOCKS proxy: %s", err)
 		return
 		return
@@ -144,7 +150,7 @@ func (controller *Controller) Run(shutdownBroadcast <-chan struct{}) {
 	defer socksProxy.Close()
 	defer socksProxy.Close()
 
 
 	httpProxy, err := NewHttpProxy(
 	httpProxy, err := NewHttpProxy(
-		controller.config, controller.untunneledDialConfig, controller)
+		controller.config, controller.untunneledDialConfig, controller, listenIP)
 	if err != nil {
 	if err != nil {
 		NoticeAlert("error initializing local HTTP proxy: %s", err)
 		NoticeAlert("error initializing local HTTP proxy: %s", err)
 		return
 		return

+ 3 - 2
psiphon/httpProxy.go

@@ -71,10 +71,11 @@ var _HTTP_PROXY_TYPE = "HTTP"
 func NewHttpProxy(
 func NewHttpProxy(
 	config *Config,
 	config *Config,
 	untunneledDialConfig *DialConfig,
 	untunneledDialConfig *DialConfig,
-	tunneler Tunneler) (proxy *HttpProxy, err error) {
+	tunneler Tunneler,
+	listenIP string) (proxy *HttpProxy, err error) {
 
 
 	listener, err := net.Listen(
 	listener, err := net.Listen(
-		"tcp", fmt.Sprintf("127.0.0.1:%d", config.LocalHttpProxyPort))
+		"tcp", fmt.Sprintf("%s:%d", listenIP, config.LocalHttpProxyPort))
 	if err != nil {
 	if err != nil {
 		if IsAddressInUseError(err) {
 		if IsAddressInUseError(err) {
 			NoticeHttpProxyPortInUse(config.LocalHttpProxyPort)
 			NoticeHttpProxyPortInUse(config.LocalHttpProxyPort)

+ 79 - 0
psiphon/networkInterface.go

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package psiphon
+
+import (
+	"net"
+)
+
+// Take in an interface name ("lo", "eth0", "any") passed from either
+// a config setting or by -interface command line flag and return the IP
+// address associated with it.
+// If no interface is provided use the default loopback interface (127.0.0.1).
+// If "any" is passed then listen on 0.0.0.0
+func GetInterfaceIPAddress(listenInterface string) (string, error) {
+	var ip net.IP
+
+	if listenInterface == "" {
+		ip = net.ParseIP("127.0.0.1")
+	} else if listenInterface == "any" {
+		ip = net.ParseIP("0.0.0.0")
+	} else {
+		//Get a list of interfaces
+		availableInterfaces, err := net.Interfaces()
+		if err != nil {
+			return "", ContextError(err)
+		}
+
+		var selectedInterface net.Interface
+		found := false
+		for _, networkInterface := range availableInterfaces {
+			if listenInterface == networkInterface.Name {
+				NoticeInfo("Using interface: %s", networkInterface.Name)
+				selectedInterface = networkInterface
+				found = true
+				break
+			}
+		}
+		if !found {
+			NoticeAlert("Interface not found: %s", listenInterface)
+			ip = net.ParseIP("127.0.0.1")
+		} else {
+			netAddrs, err := selectedInterface.Addrs()
+			if err != nil {
+				return "", ContextError(err)
+			}
+
+			for _, ipAddr := range netAddrs {
+				ip, _, err = net.ParseCIDR(ipAddr.String())
+				if err != nil {
+					return "", ContextError(err)
+				}
+				if ip.To4() != nil {
+					break
+				}
+			}
+		}
+	}
+
+	NoticeInfo("Listening on IP address: %s", ip.String())
+
+	return ip.String(), nil
+}

+ 6 - 2
psiphon/socksProxy.go

@@ -44,9 +44,13 @@ var _SOCKS_PROXY_TYPE = "SOCKS"
 // NewSocksProxy initializes a new SOCKS server. It begins listening for
 // NewSocksProxy initializes a new SOCKS server. It begins listening for
 // connections, starts a goroutine that runs an accept loop, and returns
 // connections, starts a goroutine that runs an accept loop, and returns
 // leaving the accept loop running.
 // leaving the accept loop running.
-func NewSocksProxy(config *Config, tunneler Tunneler) (proxy *SocksProxy, err error) {
+func NewSocksProxy(
+	config *Config,
+	tunneler Tunneler,
+	listenIP string) (proxy *SocksProxy, err error) {
+
 	listener, err := socks.ListenSocks(
 	listener, err := socks.ListenSocks(
-		"tcp", fmt.Sprintf("127.0.0.1:%d", config.LocalSocksProxyPort))
+		"tcp", fmt.Sprintf("%s:%d", listenIP, config.LocalSocksProxyPort))
 	if err != nil {
 	if err != nil {
 		if IsAddressInUseError(err) {
 		if IsAddressInUseError(err) {
 			NoticeSocksProxyPortInUse(config.LocalSocksProxyPort)
 			NoticeSocksProxyPortInUse(config.LocalSocksProxyPort)