【问题标题】:got stuck programming https proxy - what to do next?卡住编程 https 代理 - 下一步该怎么做?
【发布时间】:2014-06-20 10:39:21
【问题描述】:

我目前正在制作一个位于浏览器和网络之间的代理。一切正常,除了 https。我在理解它的某些段落时遇到了麻烦,并且在网络上没有找到很多资源。所以我被困住了。

我使用的代码是:

conn, addr = server.accept()
request = conn.recv(9999) #get a CONNECT request
conn.send(b'HTTP/1.1 200 Connection estabilished\n\n')
enc_req = conn.recv(9999) #this gets an encrypted request
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #plaintext client 
client.connect((host, 443)) #connect to chosen host 
client.send(enc_req)
resp1 = client.recv(9999) #this gets something unreadable (encrypted?)
#could it be the certificate?

#now what?

resp1 我得到证书了吗?在那之后我需要做什么? (或者,同理,https接下来通常会发生什么?)

附:我知道这个问题有点笼统,但请不要太严厉地评判我。我曾尝试在网上进行研究,但我一直在寻找的只是用于 ssl 的加密方法。我真的不知道该怎么做。

【问题讨论】:

  • HTTPS (SSL) 连接是端到端加密的,代理所能做的就是在客户端和服务器之间传递数据,仅此而已。
  • 这正是我想要完成的,但我不确定如何。
  • @Martijn - SSL/TLS 不提供端到端加密(尽管我们经常希望如此)。 Trustwave 展示了如何没有兑现承诺。有一整类代理被用来打破预期,它们带来了自己的一系列问题,使得组织的攻击面经常增加。见SSL/TLS Interception Proxies and Transitive Trust
  • @jww,该问题主要是由于 CA 管理不善。 SSL/TLS 配置正确时,确实提供端到端加密。拥有主流操作系统/浏览器证书的 CA 绝不应该这样做,但公司很可能拥有自己的 CA 来做到这一点。
  • @Bruno - SSL/TLS 在理论上是端到端的,而不是在实践中。理论上,我们应该通过机会加密(ADH 或自签名证书)实现端到端的安全性。但是我们不能丢弃威胁和漏洞以适应我们的定义:)

标签: python sockets ssl


【解决方案1】:

我还没有测试过这段代码(它主要是伪代码),但这应该让你知道你需要做什么。

conn, addr = server.accept()
request = conn.recv(9999) #get a CONNECT request
# Here, parse the CONNECT string and get the host and port (not sure if you were doing that already.

# Then, try to connect *before* you tell the client the connection was established (in case it fails)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #plaintext client 
client.connect((host, 443)) #connect to chosen host 

conn.send(b'HTTP/1.1 200 Connection estabilished\n\n')

# Then loop until the connections are closed.
while True:
    # Read from the client, send the data to the server.
    enc_req = conn.recv(9999) #this gets an encrypted request
    client.send(enc_req)

    # Read from the server, send the data to the client.
    resp1 = client.recv(9999) #this gets something unreadable (encrypted?)
    #could it be the certificate?
    #now what?
    # The first time it's certainly the Client Hello message, not encrypted, but in a binary format indeed.
    # Just send everything you've just read to the server.
    conn.send(resp1)

这只是对您需要编写的循环概念的快速概述。实际上,您可能能够同时处理两者。您还希望在关闭连接时更加小心(允许它以任何顺序发生,同时仍中继任何一方发送的最后数据)。

【讨论】:

  • 感谢您的帮助,我已经对此进行了一些修改,并且可以正常工作!我的代码也主要是伪代码;)
【解决方案2】:

如 cmets 中所述,处理加密的端到端流量的代理只能将其传递。

这是一个使用 circuits 编写的完全工作的代理,它已经通过传递和代理 SSH 流量进行了全面测试,因此即使涉及 SSL,它也应该与传递 TCP 代理一样工作:

#!/usr/bin/env python

from uuid import uuid4 as uuid

from circuits import Component
from circuits.net.events import close, connect, write
from circuits.net.sockets import TCPClient, TCPServer


class Client(Component):

    channel = "client"

    def init(self, sock, host, port, channel=channel):
        self.sock = sock
        self.host = host
        self.port = port

        TCPClient(channel=self.channel).register(self)

    def ready(self, *args):
        self.fire(connect(self.host, self.port))

    def disconnect(self, *args):
        self.fire(close(self.sock), self.parent.channel)

    def read(self, data):
        self.fire(write(self.sock, data), self.parent.channel)


class Proxy(Component):

    channel = "server"

    def init(self, bind, host, port):
        self.bind = bind
        self.host = host
        self.port = port

        self.clients = dict()

        TCPServer(self.bind).register(self)

    def connect(self, sock, host, port):
        channel = uuid()

        client = Client(
            sock, self.host, self.port, channel=channel
        ).register(self)

        self.clients[sock] = client

    def disconnect(self, sock):
        client = self.clients.get(sock)
        if client is not None:
            client.unregister()
            del self.clients[sock]

    def read(self, sock, data):
        client = self.clients[sock]
        self.fire(write(data), client.channel)


app = Proxy(("0.0.0.0", 3333), "127.0.0.1", 22)

from circuits import Debugger
Debugger().register(app)

app.run()

【讨论】:

  • 我试图在这个答案中说明的一点是为这类问题使用合适的框架。我会很容易地提倡Twisted,它也有类似的例子准备好了。
  • 其实我是为了教育目的而尝试在较低的层次上解决它,我没有任何压力来快速完成工作。
  • 这完全没问题,但最终你会想要使用 AsyncIO、Twisted、电路或 Tornado 之类的东西。
猜你喜欢
  • 2019-04-15
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 2020-08-02
相关资源
最近更新 更多