阅读 369

Python 之构建代理服务器

奇葩需求

用户有个内部系统,提供基础数据,用户想在不改造改内部系统的前提下将数据文件(txt)内容进行加密,然后copy到我们系统

思路

思来想去只能搞一个代理服务器拦截用户的下载请求,解析内容后返回加密后文件

参考

www.cnblogs.com/yyds/p/7072…

具体实现代码

import logging;

logging.basicConfig(level=logging.INFO)
import socket, select
import _thread
from io import BytesIO
from Cryptodome.Cipher import AES

class Proxy(object):
    def __init__(self, soc):
        self.client, _ = soc.accept()
        self.target = None
        self.is_export = False
        self.BUFSIZE = 1024
        self.method = None
        self.targetHost = None
        self.s = None

    # 解析请求
    def getClientRequest(self):
        request = self.client.recv(self.BUFSIZE).decode()
        if not request:
            return None
        cn = request.find('\n')
        firstLine = request[:cn]
        line = firstLine.split()
        self.method = line[0]
        self.targetHost = line[1]
        return request

    # 拦截正常请求
    def commonMethod(self, request):
        tmp = self.targetHost.split('/')
        logging.info(tmp)
        targetAddr = self.getTargetInfo(tmp[2])
        if len(tmp) > 5 and tmp[5].find('export_delivery') >= 0:
            self.is_export = True
        else:
            self.is_export = False
        try:
            (fam, _, _, _, addr) = socket.getaddrinfo(targetAddr[0], targetAddr[1])[0]
        except Exception as e:
            print(e)
            return
        self.target = socket.socket(fam)
        self.target.connect(addr)
        self.target.send(request.encode())
        self.nonblocking()

    def connectMethod(self, request):
        print('建立连接')
        pass

    # 启动方法
    def run(self):
        request = self.getClientRequest()
        if request:
            if self.method in ['GET', 'POST', 'PUT', 'DELETE', 'HAVE']:
                self.commonMethod(request)
            elif self.method == 'CONNECT':
                self.connectMethod(request)

    # 分析数据
    def nonblocking(self):
        inputs = [self.client, self.target]
        break_flag = False
        if (self.is_export == True):
            self.s = BytesIO()
        while True:
            if break_flag == True:
                break
            readable, writeable, errs = select.select(inputs, [], inputs, 3)
            if errs:
                print('nonblocking errs')
                break
            for soc in readable:
                data = soc.recv(self.BUFSIZE)
                if data:
                    if soc is self.client:
                        self.target.send(data)
                    elif soc is self.target:
                        if (self.is_export == True):
                            self.s.write(data)
                        else:
                            self.client.send(data)
                else:
                    break_flag = True
                    break
        if (self.is_export == True):
            self.parseRequest()
        self.client.close()
        self.target.close()

    # 解析文件内容并加密
    def parseRequest(self):
        try:
            _res = self.s.getvalue().decode("gb2312")
            tmp = _res.split('octet-stream\r\n\r\n')
            _h = tmp[0] + 'octet-stream\r\n\r\n'
            _b = tmp[1]
            nb = BytesIO()
            nb.write(_h.encode('utf8'))
            secret_key = "ThisIs SecretKey"
            iv_param = 'This is an IV456'
            aes1 = AES.new(secret_key.encode("gb2312"), AES.MODE_CFB, iv_param.encode("gb2312"))
            cipher_data = aes1.encrypt(_b.encode("gb2312"))
            nb.write(cipher_data)
            self.client.send(nb.getvalue())
        except Exception as e:
            print('Error:', e)
            self.client.send(self.s.getvalue())

    def getTargetInfo(self, host):
        port = 0
        site = None
        if ':' in host:
            tmp = host.split(':')
            site = tmp[0]
            port = int(tmp[1])
        else:
            site = host
            port = 80
        return site, port


if __name__ == '__main__':
    host = '127.0.0.1'
    port = 8083
    backlog = 5
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind((host, port))
    server.listen(backlog)
    while True:
        # 多线程
        # t = Process(target=Proxy(server).run)
        # t.start()
        # 单线程
        _thread.start_new_thread(Proxy(server).run, ())
复制代码
关注下面的标签,发现更多相似文章
评论