From: Claudio-Daniel Freire Date: Tue, 9 Aug 2011 17:21:12 +0000 (+0200) Subject: Configurable cipher for tunnelling X-Git-Tag: nepi-3.0.0~313 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=01b6b435937516a8f37c64e19d307f535ad14029;p=nepi.git Configurable cipher for tunnelling --- diff --git a/src/nepi/core/metadata.py b/src/nepi/core/metadata.py index 0dfc0dac..7f8e7815 100644 --- a/src/nepi/core/metadata.py +++ b/src/nepi/core/metadata.py @@ -432,6 +432,21 @@ class Metadata(object): Attribute.Metadata, "validation_function" : validation.is_integer, }), + "tun_cipher" : dict({ + "name" : "tun_cipher", + "help" : "Cryptographic cipher used for tunnelling", + "type" : Attribute.ENUM, + "value" : "AES", + "allowed" : [ + "AES", + "Blowfish", + "DES3", + "DES", + "PLAIN", + ], + "flags" : Attribute.ExecImmutable, + "validation_function" : validation.is_enum, + }), ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP : dict({ "name" : ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP, "help" : "Commands to set up the environment needed to run NEPI testbeds", diff --git a/src/nepi/testbeds/netns/metadata.py b/src/nepi/testbeds/netns/metadata.py index d6361b36..c4ddc610 100644 --- a/src/nepi/testbeds/netns/metadata.py +++ b/src/nepi/testbeds/netns/metadata.py @@ -535,7 +535,7 @@ factories_info = dict({ "other TAP interfaces supporting the NEPI tunneling protocol.", "connector_types": ["->fd", "udp", "tcp"], "allow_addresses": False, - "box_attributes": ["tun_proto", "tun_addr", "tun_port", "tun_key"], + "box_attributes": ["tun_proto", "tun_addr", "tun_port", "tun_key", "tun_cipher"], "tags": [tags.TUNNEL], }), }) diff --git a/src/nepi/testbeds/ns3/factories_metadata.py b/src/nepi/testbeds/ns3/factories_metadata.py index adda876a..ace0f271 100644 --- a/src/nepi/testbeds/ns3/factories_metadata.py +++ b/src/nepi/testbeds/ns3/factories_metadata.py @@ -1062,7 +1062,7 @@ factories_info = dict({ "other TAP interfaces supporting the NEPI tunneling protocol.", "connector_types": ["fd->", "udp", "tcp"], "allow_addresses": False, - "box_attributes": ["tun_proto", "tun_addr", "tun_port", "tun_key"], + "box_attributes": ["tun_proto", "tun_addr", "tun_port", "tun_key","tun_cipher"], "tags": [tags.TUNNEL], }), diff --git a/src/nepi/testbeds/planetlab/interfaces.py b/src/nepi/testbeds/planetlab/interfaces.py index 4f9c69be..5b4e3a16 100644 --- a/src/nepi/testbeds/planetlab/interfaces.py +++ b/src/nepi/testbeds/planetlab/interfaces.py @@ -88,10 +88,11 @@ class NodeIface(object): class _CrossIface(object): - def __init__(self, proto, addr, port): + def __init__(self, proto, addr, port, cipher): self.tun_proto = proto self.tun_addr = addr self.tun_port = port + self.tun_cipher = cipher # Cannot access cross peers self.peer_proto_impl = None @@ -101,7 +102,8 @@ class _CrossIface(object): self.__class__.__name__, ( self.tun_proto, self.tun_addr, - self.tun_port ) + self.tun_port, + self.tun_cipher ) ) __repr__ = __str__ @@ -140,6 +142,7 @@ class TunIface(object): # They're part of the TUN standard attribute set self.tun_port = None self.tun_addr = None + self.tun_cipher = "AES" # These get initialized when the iface is connected to its peer self.peer_iface = None @@ -247,7 +250,8 @@ class TunIface(object): self.peer_iface = _CrossIface( self.peer_proto, self.peer_addr, - self.peer_port) + self.peer_port, + self.peer_cipher) if self.peer_iface: if not self.peer_proto_impl: self.peer_proto_impl = self._impl_instance(home_path, listening) diff --git a/src/nepi/testbeds/planetlab/metadata.py b/src/nepi/testbeds/planetlab/metadata.py index 203b22d4..9a4a87bd 100644 --- a/src/nepi/testbeds/planetlab/metadata.py +++ b/src/nepi/testbeds/planetlab/metadata.py @@ -113,6 +113,7 @@ def crossconnect_tun_iface_peer_init(proto, testbed_instance, iface_guid, peer_i iface.peer_addr = peer_iface_data.get("tun_addr") iface.peer_proto = peer_iface_data.get("tun_proto") or proto iface.peer_port = peer_iface_data.get("tun_port") + iface.peer_cipher = peer_iface_data.get("tun_cipher") iface.tun_key = min(iface.tun_key, peer_iface_data.get("tun_key")) iface.tun_proto = proto @@ -124,6 +125,7 @@ def crossconnect_tun_iface_peer_compl(proto, testbed_instance, iface_guid, peer_ iface.peer_addr = peer_iface_data.get("tun_addr") iface.peer_proto = peer_iface_data.get("tun_proto") or proto iface.peer_port = peer_iface_data.get("tun_port") + iface.peer_cipher = peer_iface_data.get("tun_cipher") postconfigure_tuniface(testbed_instance, iface_guid) @@ -1076,7 +1078,7 @@ factories_info = dict({ "box_attributes": [ "up", "device_name", "mtu", "snat", "pointopoint", "txqueuelen", - "tun_proto", "tun_addr", "tun_port", "tun_key" + "tun_proto", "tun_addr", "tun_port", "tun_key", "tun_cipher", ], "traces": ["packets", "pcap"], "connector_types": ["node","udp","tcp","fd->","gre"], @@ -1092,7 +1094,7 @@ factories_info = dict({ "box_attributes": [ "up", "device_name", "mtu", "snat", "pointopoint", "txqueuelen", - "tun_proto", "tun_addr", "tun_port", "tun_key" + "tun_proto", "tun_addr", "tun_port", "tun_key", "tun_cipher", ], "traces": ["packets", "pcap"], "connector_types": ["node","udp","tcp","fd->","gre"], diff --git a/src/nepi/testbeds/planetlab/node.py b/src/nepi/testbeds/planetlab/node.py index 1101bfe8..8ab312f1 100644 --- a/src/nepi/testbeds/planetlab/node.py +++ b/src/nepi/testbeds/planetlab/node.py @@ -463,8 +463,10 @@ class Node(object): (out,err),proc = server.popen_ssh_command( # Some apps need two kills - "sudo -S killall -u %(slicename)s ; sudo -S killall -u root ; " - "sudo -S killall -u %(slicename)s ; sudo -S killall -u root" % { + "sudo -S killall -u %(slicename)s ; " + "sudo -S killall -u %(slicename)s ; " + "sudo -S killall -u root ; " + "sudo -S killall -u root " % { 'slicename' : self.slicename , }, host = self.hostname, diff --git a/src/nepi/testbeds/planetlab/scripts/tun_connect.py b/src/nepi/testbeds/planetlab/scripts/tun_connect.py index 0eb46e39..84934aeb 100644 --- a/src/nepi/testbeds/planetlab/scripts/tun_connect.py +++ b/src/nepi/testbeds/planetlab/scripts/tun_connect.py @@ -102,6 +102,10 @@ parser.add_option( default = None, help = "Specify a demultiplexing 32-bit numeric key for GRE." ) +parser.add_option( + "-C", "--cipher", dest="cipher", metavar="CIPHER", + default = 'AES', + help = "One of PLAIN, AES, Blowfish, DES, DES3. " ) parser.add_option( "-N", "--no-capture", dest="no_capture", action = "store_true", @@ -116,6 +120,13 @@ parser.add_option( (options, remaining_args) = parser.parse_args(sys.argv[1:]) +options.cipher = { + 'aes' : 'AES', + 'des' : 'DES', + 'des3' : 'DES3', + 'blowfish' : 'Blowfish', + 'plain' : None, +}[options.cipher.lower()] ETH_P_ALL = 0x00000003 ETH_P_IP = 0x00000800 @@ -426,7 +437,8 @@ def tun_fwd(tun, remote, reconnect = None): stderr = None, reconnect = reconnect, tunqueue = tunqueue, - tunkqueue = tunkqueue + tunkqueue = tunkqueue, + cipher = options.cipher ) diff --git a/src/nepi/testbeds/planetlab/tunproto.py b/src/nepi/testbeds/planetlab/tunproto.py index d3cf6b83..00bfb834 100644 --- a/src/nepi/testbeds/planetlab/tunproto.py +++ b/src/nepi/testbeds/planetlab/tunproto.py @@ -162,6 +162,7 @@ class TunProtoBase(object): peer_port = peer.tun_port peer_addr = peer.tun_addr peer_proto= peer.tun_proto + peer_cipher=peer.tun_cipher local_port = self.port local_cap = local.capture @@ -170,6 +171,7 @@ class TunProtoBase(object): local_snat = local.snat local_txq = local.txqueuelen local_p2p = local.pointopoint + local_cipher=local.tun_cipher if not local_p2p and hasattr(peer, 'address'): local_p2p = peer.address @@ -177,16 +179,23 @@ class TunProtoBase(object): if check_proto != peer_proto: raise RuntimeError, "Peering protocol mismatch: %s != %s" % (check_proto, peer_proto) + if local_cipher != peer_cipher: + raise RuntimeError, "Peering cipher mismatch: %s != %s" % (local_cipher, peer_cipher) + if not listen and ((peer_proto != 'fd' and not peer_port) or not peer_addr): raise RuntimeError, "Misconfigured peer: %s" % (peer,) if listen and ((peer_proto != 'fd' and not local_port) or not local_addr or not local_mask): raise RuntimeError, "Misconfigured TUN: %s" % (local,) + + if check_proto == 'gre' and local_cipher.lower() != 'plain': + raise RuntimeError, "Misconfigured TUN: %s - GRE tunnels do not support encryption. Got %s, you MUST use PLAIN" % (local, local_cipher,) args = ["python", "tun_connect.py", "-m", str(self.mode), "-A", str(local_addr), - "-M", str(local_mask)] + "-M", str(local_mask), + "-C", str(local_cipher)] if check_proto == 'fd': passfd_arg = str(peer_addr) @@ -335,7 +344,7 @@ class TunProtoBase(object): self._logger.debug("if_name: %r does not match expected pattern", out) time.sleep(1) else: - pself._logger.warn("if_name: Could not get interface name") + self._logger.warn("if_name: Could not get interface name") return self._if_name def async_launch(self, check_proto, listen, extra_args=[]): diff --git a/src/nepi/util/tunchannel_impl.py b/src/nepi/util/tunchannel_impl.py index bfc0ce5f..cecd7297 100644 --- a/src/nepi/util/tunchannel_impl.py +++ b/src/nepi/util/tunchannel_impl.py @@ -18,13 +18,13 @@ class TunChannel(object): testbed controller process. It takes several parameters that can be given by directly setting attributes: - tun_port/addr/proto: information about the local endpoint. + tun_port/addr/proto/cipher: information about the local endpoint. The addresses here should be externally-reachable, since when listening or when using the UDP protocol, connections to this address/port will be attempted by remote endpoitns. - peer_port/addr/proto: information about the remote endpoint. + peer_port/addr/proto/cipher: information about the remote endpoint. Usually, you set these when the cross connection initializer/completion functions are invoked (both). @@ -65,11 +65,13 @@ class TunChannel(object): # They're part of the TUN standard attribute set self.tun_port = None self.tun_addr = None + self.tun_cipher = None # These get initialized when the channel is connected to its peer self.peer_proto = None self.peer_addr = None self.peer_port = None + self.peer_cipher = None # These get initialized when the channel is connected to its iface self.tun_socket = None @@ -98,12 +100,13 @@ class TunChannel(object): def __str__(self): - return "%s<%s %s:%s %s %s:%s>" % ( + return "%s<%s %s:%s %s %s:%s %s>" % ( self.__class__.__name__, self.tun_proto, self.tun_addr, self.tun_port, self.peer_proto, self.peer_addr, self.peer_port, + self.tun_cipher, ) def Prepare(self): @@ -166,10 +169,12 @@ class TunChannel(object): peer_port = self.peer_port peer_addr = self.peer_addr peer_proto= self.peer_proto + peer_cipher=self.peer_cipher local_port = self.tun_port local_addr = self.tun_addr local_proto = self.tun_proto + local_cipher= self.tun_cipher stderr = self.stderr ether_mode = self.ethernet_mode @@ -177,6 +182,9 @@ class TunChannel(object): if local_proto != peer_proto: raise RuntimeError, "Peering protocol mismatch: %s != %s" % (local_proto, peer_proto) + + if local_cipher != peer_cipher: + raise RuntimeError, "Peering cipher mismatch: %s != %s" % (local_cipher, peer_cipher) udp = local_proto == 'udp' listen = self.listen @@ -249,7 +257,8 @@ class TunChannel(object): cipher_key = cipher_key, udp = udp, TERMINATE = TERMINATE, - stderr = stderr + stderr = stderr, + cipher = local_cipher ) tun.close() @@ -340,6 +349,7 @@ def crossconnect_tunchannel_peer_init(proto, testbed_instance, tun_guid, peer_da tun.peer_addr = peer_data.get("tun_addr") tun.peer_proto = peer_data.get("tun_proto") or proto tun.peer_port = peer_data.get("tun_port") + tun.peer_cipher = peer_data.get("tun_cipher") tun.tun_key = min(tun.tun_key, peer_data.get("tun_key")) tun.tun_proto = proto @@ -362,6 +372,7 @@ def crossconnect_tunchannel_peer_compl(proto, testbed_instance, tun_guid, peer_d tun.peer_addr = peer_data.get("tun_addr") tun.peer_proto = peer_data.get("tun_proto") or proto tun.peer_port = peer_data.get("tun_port") + tun.peer_cipher = peer_data.get("tun_cipher") postconfigure_tunchannel(testbed_instance, tun_guid)