From f44fbd1f164dae3ef5a8adec5eeb10f8e5bb326a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 9 Nov 2014 23:01:13 -0700 Subject: [PATCH] Option to allow console connections to any local IP address when using the local server. --- gns3server/main.py | 3 ++- gns3server/modules/dynamips/__init__.py | 4 ++-- gns3server/modules/dynamips/hypervisor_manager.py | 6 ++++-- gns3server/modules/iou/__init__.py | 3 ++- gns3server/modules/iou/iou_device.py | 12 ++++++------ gns3server/modules/qemu/__init__.py | 6 +++--- gns3server/modules/qemu/qemu_vm.py | 7 +++++-- gns3server/modules/virtualbox/__init__.py | 7 +++---- gns3server/modules/virtualbox/virtualbox_vm.py | 12 ++++++------ gns3server/modules/vpcs/__init__.py | 3 ++- gns3server/modules/vpcs/vpcs_device.py | 8 ++++---- gns3server/server.py | 14 +++++++++++--- 12 files changed, 50 insertions(+), 35 deletions(-) diff --git a/gns3server/main.py b/gns3server/main.py index 8f4e55c7..ac331df9 100644 --- a/gns3server/main.py +++ b/gns3server/main.py @@ -35,6 +35,7 @@ define("port", default=8000, help="run on the given port", type=int) define("ipc", default=False, help="use IPC for module communication", type=bool) define("version", default=False, help="show the version", type=bool) define("quiet", default=False, help="do not show output on stdout", type=bool) +define("console_bind_to_any", default=True, help="bind console ports to any local IP address", type=bool) def locale_check(): @@ -127,7 +128,7 @@ def main(): log.critical("the current working directory doesn't exist") return - server = Server(options.host, options.port, options.ipc) + server = Server(options.host, options.port, options.ipc, options.console_bind_to_any) server.load_modules() server.run() diff --git a/gns3server/modules/dynamips/__init__.py b/gns3server/modules/dynamips/__init__.py index 38595ef5..897a1b13 100644 --- a/gns3server/modules/dynamips/__init__.py +++ b/gns3server/modules/dynamips/__init__.py @@ -33,7 +33,6 @@ from gns3server.builtins.interfaces import get_windows_interfaces from .hypervisor import Hypervisor from .hypervisor_manager import HypervisorManager from .dynamips_error import DynamipsError -from ..attic import has_privileged_access # Nodes from .nodes.router import Router @@ -138,6 +137,7 @@ class Dynamips(IModule): self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir self._host = dynamips_config.get("host", kwargs["host"]) + self._console_host = dynamips_config.get("console_host", kwargs["console_host"]) if not sys.platform.startswith("win32"): #FIXME: pickle issues Windows @@ -282,7 +282,7 @@ class Dynamips(IModule): raise DynamipsError("Cannot write to working directory {}".format(workdir)) log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(workdir)) - self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host) + self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host, self._console_host) for name, value in self._hypervisor_manager_settings.items(): if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value: diff --git a/gns3server/modules/dynamips/hypervisor_manager.py b/gns3server/modules/dynamips/hypervisor_manager.py index a7451cb5..3106d98c 100644 --- a/gns3server/modules/dynamips/hypervisor_manager.py +++ b/gns3server/modules/dynamips/hypervisor_manager.py @@ -40,14 +40,16 @@ class HypervisorManager(object): :param path: path to the Dynamips executable :param working_dir: path to a working directory :param host: host/address for hypervisors to listen to + :param console_host: IP address to bind for console connections """ - def __init__(self, path, working_dir, host='127.0.0.1'): + def __init__(self, path, working_dir, host='127.0.0.1', console_host='0.0.0.0'): self._hypervisors = [] self._path = path self._working_dir = working_dir - self._host = host + self._console_host = console_host + self._host = console_host # FIXME: Dynamips must be patched to bind on a different address than the one used by the hypervisor. config = Config.instance() dynamips_config = config.get_section_config("DYNAMIPS") diff --git a/gns3server/modules/iou/__init__.py b/gns3server/modules/iou/__init__.py index 648223bf..aa36c9fd 100644 --- a/gns3server/modules/iou/__init__.py +++ b/gns3server/modules/iou/__init__.py @@ -92,6 +92,7 @@ class IOU(IModule): self._udp_start_port_range = iou_config.get("udp_start_port_range", 30001) self._udp_end_port_range = iou_config.get("udp_end_port_range", 35000) self._host = iou_config.get("host", kwargs["host"]) + self._console_host = iou_config.get("console_host", kwargs["console_host"]) self._projects_dir = kwargs["projects_dir"] self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir @@ -303,9 +304,9 @@ class IOU(IModule): iou_instance = IOUDevice(name, iou_path, self._working_dir, - self._host, iou_id, console, + self._console_host, self._console_start_port_range, self._console_end_port_range) diff --git a/gns3server/modules/iou/iou_device.py b/gns3server/modules/iou/iou_device.py index cef5c8c4..d12a7b45 100644 --- a/gns3server/modules/iou/iou_device.py +++ b/gns3server/modules/iou/iou_device.py @@ -49,9 +49,9 @@ class IOUDevice(object): :param name: name of this IOU device :param path: path to IOU executable :param working_dir: path to a working directory - :param host: host/address to bind for console and UDP connections :param iou_id: IOU instance ID :param console: TCP console port + :param console_host: IP address to bind for console connections :param console_start_port_range: TCP console port range start :param console_end_port_range: TCP console port range end """ @@ -63,9 +63,9 @@ class IOUDevice(object): name, path, working_dir, - host="127.0.0.1", - iou_id = None, + iou_id=None, console=None, + console_host="0.0.0.0", console_start_port_range=4001, console_end_port_range=4512): @@ -99,8 +99,8 @@ class IOUDevice(object): self._iouyap_stdout_file = "" self._ioucon_thead = None self._ioucon_thread_stop_event = None - self._host = host self._started = False + self._console_host = console_host self._console_start_port_range = console_start_port_range self._console_end_port_range = console_end_port_range @@ -127,7 +127,7 @@ class IOUDevice(object): try: self._console = find_unused_port(self._console_start_port_range, self._console_end_port_range, - self._host, + self._console_host, ignore_ports=self._allocated_console_ports) except Exception as e: raise IOUError(e) @@ -484,7 +484,7 @@ class IOUDevice(object): """ if not self._ioucon_thead: - telnet_server = "{}:{}".format(self._host, self.console) + telnet_server = "{}:{}".format(self._console_host, self.console) log.info("starting ioucon for IOU instance {} to accept Telnet connections on {}".format(self._name, telnet_server)) args = argparse.Namespace(appl_id=str(self._id), debug=False, escape='^^', telnet_limit=0, telnet_server=telnet_server) self._ioucon_thread_stop_event = threading.Event() diff --git a/gns3server/modules/qemu/__init__.py b/gns3server/modules/qemu/__init__.py index a1917d51..bfdb9258 100644 --- a/gns3server/modules/qemu/__init__.py +++ b/gns3server/modules/qemu/__init__.py @@ -71,6 +71,7 @@ class Qemu(IModule): self._udp_start_port_range = qemu_config.get("udp_start_port_range", 40001) self._udp_end_port_range = qemu_config.get("udp_end_port_range", 45500) self._host = qemu_config.get("host", kwargs["host"]) + self._console_host = qemu_config.get("console_host", kwargs["console_host"]) self._projects_dir = kwargs["projects_dir"] self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir @@ -214,6 +215,7 @@ class Qemu(IModule): self._host, qemu_id, console, + self._console_host, self._console_start_port_range, self._console_end_port_range) @@ -614,7 +616,6 @@ class Qemu(IModule): Gets QEMU binaries list. Response parameters: - - Server address/host - List of Qemu binaries """ @@ -642,8 +643,7 @@ class Qemu(IModule): log.warn("Could not find QEMU version for {}: {}".format(path, e)) continue - response = {"server": self._host, - "qemus": qemus} + response = {"qemus": qemus} self.send_response(response) @IModule.route("qemu.echo") diff --git a/gns3server/modules/qemu/qemu_vm.py b/gns3server/modules/qemu/qemu_vm.py index ce341780..6cb2efa1 100644 --- a/gns3server/modules/qemu/qemu_vm.py +++ b/gns3server/modules/qemu/qemu_vm.py @@ -44,6 +44,7 @@ class QemuVM(object): :param host: host/address to bind for console and UDP connections :param qemu_id: QEMU VM instance ID :param console: TCP console port + :param console_host: IP address to bind for console connections :param console_start_port_range: TCP console port range start :param console_end_port_range: TCP console port range end """ @@ -58,6 +59,7 @@ class QemuVM(object): host="127.0.0.1", qemu_id=None, console=None, + console_host="0.0.0.0", console_start_port_range=5001, console_end_port_range=5500): @@ -84,6 +86,7 @@ class QemuVM(object): self._started = False self._process = None self._stdout_file = "" + self._console_host = console_host self._console_start_port_range = console_start_port_range self._console_end_port_range = console_end_port_range @@ -113,7 +116,7 @@ class QemuVM(object): try: self._console = find_unused_port(self._console_start_port_range, self._console_end_port_range, - self._host, + self._console_host, ignore_ports=self._allocated_console_ports) except Exception as e: raise QemuError(e) @@ -681,7 +684,7 @@ class QemuVM(object): def _serial_options(self): if self._console: - return ["-serial", "telnet:{}:{},server,nowait".format(self._host, self._console)] + return ["-serial", "telnet:{}:{},server,nowait".format(self._console_host, self._console)] else: return [] diff --git a/gns3server/modules/virtualbox/__init__.py b/gns3server/modules/virtualbox/__init__.py index 9742bc3b..4deafe11 100644 --- a/gns3server/modules/virtualbox/__init__.py +++ b/gns3server/modules/virtualbox/__init__.py @@ -96,6 +96,7 @@ class VirtualBox(IModule): self._udp_start_port_range = vbox_config.get("udp_start_port_range", 35001) self._udp_end_port_range = vbox_config.get("udp_end_port_range", 35500) self._host = vbox_config.get("host", kwargs["host"]) + self._console_host = vbox_config.get("console_host", kwargs["console_host"]) self._projects_dir = kwargs["projects_dir"] self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir @@ -251,9 +252,9 @@ class VirtualBox(IModule): vmname, linked_clone, self._working_dir, - self._host, vbox_id, console, + self._console_host, self._console_start_port_range, self._console_end_port_range) @@ -755,9 +756,7 @@ class VirtualBox(IModule): if not extra_data == "Value: yes": vms.append(vmname) - response = {"server": self._host, - "vms": vms} - + response = {"vms": vms} self.send_response(response) @IModule.route("virtualbox.echo") diff --git a/gns3server/modules/virtualbox/virtualbox_vm.py b/gns3server/modules/virtualbox/virtualbox_vm.py index 28260912..eb419986 100644 --- a/gns3server/modules/virtualbox/virtualbox_vm.py +++ b/gns3server/modules/virtualbox/virtualbox_vm.py @@ -52,9 +52,9 @@ class VirtualBoxVM(object): :param vmname: name of this VirtualBox VM in VirtualBox itself :param linked_clone: flag if a linked clone must be created :param working_dir: path to a working directory - :param host: host/address to bind for console and UDP connections :param vbox_id: VirtalBox VM instance ID :param console: TCP console port + :param console_host: IP address to bind for console connections :param console_start_port_range: TCP console port range start :param console_end_port_range: TCP console port range end """ @@ -68,9 +68,9 @@ class VirtualBoxVM(object): vmname, linked_clone, working_dir, - host="127.0.0.1", vbox_id=None, console=None, + console_host="0.0.0.0", console_start_port_range=4512, console_end_port_range=5000): @@ -93,10 +93,10 @@ class VirtualBoxVM(object): self._name = name self._linked_clone = linked_clone self._working_dir = None - self._host = host self._command = [] self._vboxmanage_path = vboxmanage_path self._started = False + self._console_host = console_host self._console_start_port_range = console_start_port_range self._console_end_port_range = console_end_port_range @@ -125,7 +125,7 @@ class VirtualBoxVM(object): try: self._console = find_unused_port(self._console_start_port_range, self._console_end_port_range, - self._host, + self._console_host, ignore_ports=self._allocated_console_ports) except Exception as e: raise VirtualBoxError(e) @@ -810,7 +810,7 @@ class VirtualBoxVM(object): self._serial_pipe = open(pipe_name, "a+b") except OSError as e: raise VirtualBoxError("Could not open the pipe {}: {}".format(pipe_name, e)) - self._telnet_server_thread = TelnetServer(self._vmname, msvcrt.get_osfhandle(self._serial_pipe.fileno()), self._host, self._console) + self._telnet_server_thread = TelnetServer(self._vmname, msvcrt.get_osfhandle(self._serial_pipe.fileno()), self._console_host, self._console) self._telnet_server_thread.start() else: try: @@ -818,7 +818,7 @@ class VirtualBoxVM(object): self._serial_pipe.connect(pipe_name) except OSError as e: raise VirtualBoxError("Could not connect to the pipe {}: {}".format(pipe_name, e)) - self._telnet_server_thread = TelnetServer(self._vmname, self._serial_pipe, self._host, self._console) + self._telnet_server_thread = TelnetServer(self._vmname, self._serial_pipe, self._console_host, self._console) self._telnet_server_thread.start() def stop(self): diff --git a/gns3server/modules/vpcs/__init__.py b/gns3server/modules/vpcs/__init__.py index b88324a4..adb121a6 100644 --- a/gns3server/modules/vpcs/__init__.py +++ b/gns3server/modules/vpcs/__init__.py @@ -87,6 +87,7 @@ class VPCS(IModule): self._udp_start_port_range = vpcs_config.get("udp_start_port_range", 20501) self._udp_end_port_range = vpcs_config.get("udp_end_port_range", 21000) self._host = vpcs_config.get("host", kwargs["host"]) + self._console_host = vpcs_config.get("console_host", kwargs["console_host"]) self._projects_dir = kwargs["projects_dir"] self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir @@ -237,9 +238,9 @@ class VPCS(IModule): vpcs_instance = VPCSDevice(name, self._vpcs, self._working_dir, - self._host, vpcs_id, console, + self._console_host, self._console_start_port_range, self._console_end_port_range) diff --git a/gns3server/modules/vpcs/vpcs_device.py b/gns3server/modules/vpcs/vpcs_device.py index d5ad8c09..cd89b00e 100644 --- a/gns3server/modules/vpcs/vpcs_device.py +++ b/gns3server/modules/vpcs/vpcs_device.py @@ -45,9 +45,9 @@ class VPCSDevice(object): :param name: name of this VPCS device :param path: path to VPCS executable :param working_dir: path to a working directory - :param host: host/address to bind for console and UDP connections :param vpcs_id: VPCS instance ID :param console: TCP console port + :param console_host: IP address to bind for console connections :param console_start_port_range: TCP console port range start :param console_end_port_range: TCP console port range end """ @@ -59,9 +59,9 @@ class VPCSDevice(object): name, path, working_dir, - host="127.0.0.1", vpcs_id=None, console=None, + console_host="0.0.0.0", console_start_port_range=4512, console_end_port_range=5000): @@ -89,7 +89,7 @@ class VPCSDevice(object): self._path = path self._console = console self._working_dir = None - self._host = host + self._console_host = console_host self._command = [] self._process = None self._vpcs_stdout_file = "" @@ -114,7 +114,7 @@ class VPCSDevice(object): try: self._console = find_unused_port(self._console_start_port_range, self._console_end_port_range, - self._host, + self._console_host, ignore_ports=self._allocated_console_ports) except Exception as e: raise VPCSError(e) diff --git a/gns3server/server.py b/gns3server/server.py index e89740ea..e178c9f9 100644 --- a/gns3server/server.py +++ b/gns3server/server.py @@ -33,7 +33,7 @@ import tornado.ioloop import tornado.web import tornado.autoreload import pkg_resources -from os.path import expanduser +import ipaddress import base64 import uuid @@ -58,13 +58,21 @@ class Server(object): (r"/upload", FileUploadHandler), (r"/login", LoginHandler)] - def __init__(self, host, port, ipc): + def __init__(self, host, port, ipc, console_bind_to_any): self._host = host self._port = port self._router = None self._stream = None + if console_bind_to_any: + if ipaddress.ip_address(self._host).version == 6: + self._console_host = "::" + else: + self._console_host = "0.0.0.0" + else: + self._console_host = self._host + if ipc: self._zmq_port = 0 # this forces to use IPC for communications with the ZeroMQ server else: @@ -132,6 +140,7 @@ class Server(object): "127.0.0.1", # ZeroMQ server address self._zmq_port, # ZeroMQ server port host=self._host, # server host address + console_host=self._console_host, projects_dir=self._projects_dir, temp_dir=self._temp_dir) @@ -141,7 +150,6 @@ class Server(object): JSONRPCWebSocket.register_destination(destination, instance.name) instance.start() # starts the new process - def run(self): """ Starts the Tornado web server and ZeroMQ server.