如何处理原始Python套接字中的SSL连接? [英] How to handle ssl connections in raw Python socket?

查看:41
本文介绍了如何处理原始Python套接字中的SSL连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个程序来下载给定的网页.由于某些限制,我只需要对所有连接使用原始python套接字.因此,我建立了到给定域(对象响应头中的Host字段)的套接字连接,然后在此上发送GET请求.现在,当该URL为https URL时,我认为我首先需要进行SSL握手(因为否则,我将从服务器收到非200 OK响应,以及提及P3P策略的其他错误响应).我检查了curl的响应,以检查它如何能够成功下载(而不是),结果发现curl首先进行了SSL握手(这就是全部).curl始终能够成功下载给定的对象,唯一的区别始终是它执行的SSL握手.

I'm writing a program to download a given webpage. I need to only use raw python sockets for all the connection due to some restriction. So I make a socket connection to a given domain (the Host field in the response header of an object) and then send the GET request on this. Now when the url is a https url, I think I need to first do the SSL handshake (because otherwise I'm getting non-200 OK responses from the server and other error responses mentioning P3P policies). I inspected curl's response to check how it's able to successfully download while I'm not, turns out curl first does the SSL handshake (that's all the difference). curl is always able to successfully download a given object, the only difference always being the SSL handshake it does.

所以我想知道如何在原始python套接字中进行SSL握手?基本上,我想要一个简单的解决方案,该解决方案除了使用原始套接字外,还可以使我做得最少.

So I'm wondering how to do the SSL handshake in raw python sockets? Basically I want as easy a solution which allows me to do the minimum besides using raw sockets.

推荐答案

以下是带有SLL的TCP客户端的示例.

Here is an example of a TCP client with SLL.

不确定是下载网页的最佳方法,但是它应该回答您的问题原始python套接字中的SSL握手".

Not sure if it's the best way to download a web page but it should answer your question "SSL handshake in raw python socket".

您可能必须改编struct.pack/unpack,但您会得到大致的认识:

You will probably have to adapt the struct.pack/unpack but you get the general idea:

import socket
import ssl
import struct
import binascii
import sys

class NotConnectedException(Exception):
    def __init__(self, message=None, node=None):
        self.message = message
        self.node = node

class DisconnectedException(Exception):
    def __init__(self, message=None, node=None):
        self.message = message
        self.node = node

class Connector:
    def __init__(self):
        pass

    def is_connected(self):
        return (self.sock and self.ssl_sock)

    def open(self, hostname, port, cacert):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.ssl_sock = ssl.wrap_socket(self.sock, ca_certs=cacert, cert_reqs=ssl.CERT_REQUIRED)

        if hostname == socket.gethostname():
            ipaddress = socket.gethostbyname_ex(hostname)[2][0]
            self.ssl_sock.connect((ipaddress, port))
        else:
            self.ssl_sock.connect((hostname, port))

        self.sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)

    def close(self):
        if self.sock: self.sock.close()
        self.sock = None
        self.ssl_sock = None

    def send(self, buffer):
        if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)")
        self.ssl_sock.sendall(struct.pack('L', len(buffer)))
        self.ssl_sock.sendall(buffer)

    def receive(self):
        if not self.ssl_sock: raise NotConnectedException("Not connected (SSL Socket is null)")
        data_size_buffer = self.ssl_sock.recv(4)

        if len(data_size_buffer) <= 0:
            raise DisconnectedException()

        data_size = struct.unpack('L', data_size_buffer)[0]
        received_size = 0
        data_buffer = ""

        while received_size < data_size:
            chunk = self.ssl_sock.recv(1024)
            data_buffer += chunk
            received_size += len(chunk)

        return data_buffer

然后您使用此类:

    connector = Connector.Connector()
    connector.open(server_ip, server_port, path_to_the_CA_cert.pem)
    connector.send(your_data)
    response = connector.receive()
    connector.close()

这篇关于如何处理原始Python套接字中的SSL连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆