如何保护Python分布式计算层

mot*_*oku 4 python hash distributed-computing

这些模块旨在促进跨多台计算机的计算能力层.有哪些一种或多种经过验证的方法可以防止欺骗性数据包?如何最好地对传输的可调用引用的任何未包含的对象进行深层复制?函数对象是封装客户端作业的最佳方法吗?最后:这段代码可以改进吗?邮件脚本:请原谅我的最后一个问题.我需要兑现我的声誉.

sock.py

from socket import socket
from socket import AF_INET
from socket import SOCK_STREAM
from socket import gethostbyname
from socket import gethostname

class SocketServer:
  def __init__(self, port):
    self.sock = socket(AF_INET, SOCK_STREAM)
    self.port = port
  def send(self, tdata):
    self.sock.bind(("127.0.0.1", self.port))
    self.sock.listen(len(tdata))
    while tdata:
      s = self.sock.accept()[0]
      for x in tdata.pop(): s.send(x)
      s.close()
    self.sock.close()

class Socket:
  def __init__(self, host, port):
    self.sock = socket(AF_INET, SOCK_STREAM)
    self.sock.connect((host, port))
  def recv(self, size):
    return self.sock.recv(size)
  def close(self):
    self.sock.close()
Run Code Online (Sandbox Code Playgroud)

pack.py

#http://stackoverflow.com/questions/6234586/we-need-to-pickle-any-sort-of-callable
from marshal import dumps as marshal_dumps
from pickle import dumps as pickle_dumps
from struct import pack as struct_pack
from hashlib import sha224

class packer:
  def __init__(self):
    self.f = []
  def pack(self, what):
    if type(what) is type(lambda:None):
      self.f = []
      self.f.append(marshal_dumps(what.func_code))
      self.f.append(pickle_dumps(what.func_name))
      self.f.append(pickle_dumps(what.func_defaults))
      self.f.append(pickle_dumps(what.func_closure))
      self.f = pickle_dumps(self.f)
      return (struct_pack('Q', len(self.f)), self.f)
    return None
  def gethash(self):
    hash = sha224(self.f).hexdigest()
    return (struct_pack('Q', len(hash)), hash)
  def getwithhash(self, what):
    a, b = self.pack(what)
    c, d = self.gethash()
    return (a, b, c, d)
Run Code Online (Sandbox Code Playgroud)

unpack.py

from types import FunctionType
from pickle import loads as pickle_loads
from marshal import loads as marshal_loads
from struct import unpack as struct_unpack
from struct import calcsize
from hashlib import sha224

#http://stackoverflow.com/questions/6234586/we-need-to-pickle-any-sort-of-callable

class unpacker:
  def __init__(self):
    self.f = []
    self.fcompiled = lambda:None
    self.sizeofsize = calcsize('Q')
  def unpack(self, sock):
    size = struct_unpack('Q', sock.recv(self.sizeofsize))[0]
    self.f = sock.recv(size)
    size = struct_unpack('Q', sock.recv(self.sizeofsize))[0]
    hash0 = sock.recv(size)
    sock.close()
    hash1 = sha224(self.f).hexdigest()
    if hash0 != hash1: return None
    self.f = pickle_loads(self.f)
    a = marshal_loads(self.f[0])
    b = globals() # TODO
    c = pickle_loads(self.f[1])
    d = pickle_loads(self.f[2])
    e = pickle_loads(self.f[3])
    self.fcompiled = FunctionType(a, b, c, d, e)
    return self.fcompiled
Run Code Online (Sandbox Code Playgroud)

test.py

from unpack import unpacker
from pack import packer
from sock import SocketServer
from sock import Socket
from threading import Thread
from time import sleep

count = 2
port = 4446

def f():
  print 42

def server():
  ss = SocketServer(port)
  pack = packer()
  functions = [pack.getwithhash(f) for nothing in range(count)]
  ss.send(functions)

if __name__ == "__main__":
  Thread(target=server).start()
  sleep(1)
  unpack = unpacker()
  for nothing in range(count):
    print unpack.unpack(Socket("127.0.0.1", port))
Run Code Online (Sandbox Code Playgroud)

输出:

<function f at 0x0000000>
<function f at 0x0000000>
Run Code Online (Sandbox Code Playgroud)

sar*_*old 6

我现在仔细看看你的代码,我有一些评论:

  • 此代码看起来很容易防止在飞行过程中意外修改腌制对象.sha224是一种优秀的散列算法,很容易发现可能仍然通过TCP校验和的意外修改的数据包.
  • 此代码无法防止在飞行中对腌制对象进行恶意修改.无法保证数据包来自计算网络的受信任成员,也不保证数据包未被修改.(或完全掉下来.)

单独使用散列算法不能证明数据包的来源,也不能证明它们没有被恶意修改:攻击者可以在修改数据并重新发送数据包后简单地重新计算散列.

此问题有几种"常用方法":您可以使用共享密钥,即在参与网络的所有客户端之间共享的密钥.此密钥将用作密钥哈希的一部分,例如HMAC,数据收件人将使用共享密钥重新计算HMAC身份验证代码.它快速而简单(在某些司法管辖区内禁止加密软件是合法的)但如果任何一个系统的密钥泄露,共享密钥就是一个巨大的责任.(受损系统可能甚至不属于您的威胁模型.)

您还可以使用每个主机付费的共享机密.它的工作原理就像所有节点之间的共享密钥一样,但是在单个客户端密钥被泄露的情况下,只需要在所有其他系统上替换该客户端的密钥.

您还可以使用公钥加密来提供数据包的签名.每个客户端都有一个私钥和一个所有客户都知道的相应公钥.受损的私钥仍然会破坏系统,但它会大大减少您需要准备的密钥数量.(每个客户端只有一个,而不是每对客户端一个:O(N)vs O(N 2).)

公共密钥系统将自己写成学习经验很有趣,但尝试正确编程却很糟糕.防止重放攻击,选择性消息丢弃,消息切片/构建等需要大量聪明的协议设计.

因此,大多数人都部署了预先制定的传输安全方案,例如SSLv3或TLS.结合客户端证书,它可以轻松地保证两个端点都是他们所说的人(当然,直到受到攻击的密钥点)并且提供在受TLS保护的流中发送的数据以正确的顺序传递并且没有篡改.

TLS可以正常配置很多工作.使用更简单的工具(例如ssh)可能会取得很好的成功.库可用,因此您可以以编程方式控制连接,而不是依赖系统提供的ssh(1)客户端和sshd(8)服务器.