繁体   English   中英

具有 python 的代理服务器

[英]proxy server with python

我有一个 python 的大学项目,我必须编写一个代理服务器来等待来自客户端的请求,然后将客户端连接到服务器。 我在网上搜索并从该站点找到了一个已经编写的代码:
https://www.geeksforgeeks.org/creating-a-proxy-webserver-in-python-set-1/
所以我使用它并对代码进行了一些更改并将公共服务器和端口添加到它但是当我运行它时出现此错误:

第 33 行,主要
请求 = conn.recv(4096)
NameError:名称“conn”未定义

所以我对 sockets 和 python 不是很熟悉,所以如果代码中有明显的错误,如果你们能以非常基本的方式解释它们,我会很高兴,所以我的业余屁股会理解它,哈哈
这是代码:

import signal
import socket
import threading

class Proxy:
    def __init__(self):
        # creating a tcp socket
        self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # reuse the socket
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.ip = 'localhost'
        self.port = 8080
        self.serverSocket.bind((self.ip, self.port))
        self.serverSocket.listen(10)
        self.__clients = {}

    def shutdown(self):
        # shutdown on cntrl c
        signal.signal(signal.SIGINT, self.shutdown)

    def multirequest (self):

        while True:
            # establish the connection
            (clientSocket, client_address) = self.serverSocket.accept()

            d = threading.Thread(name=self._getclientname(client_address),
                                 target=self.proxy_thread,
                                 args=(clientSocket, client_address))
            d.setDaemon(True)
            d.start()

    def main(self, conn):
        # get the request from browser
        request = conn.recv(4096)

        # parse the first line
        first_line = request.split('\n')[0]

        # get url
        url = first_line.split(' ')[1]

        http_pos = url.find("://")
        if http_pos == -1:
            temp = url
        else:
            temp = url[(http_pos + 3):]

        webserver = ""
        port = -1
        port_pos = temp.find(":")

        # find end of web server

        webserver_pos = temp.find("/")
        if webserver_pos == -1:
            webserver_pos = len(temp)

        if port_pos == -1 or webserver_pos < port_pos:

            # default port
            port = 80
            webserver = temp[:webserver_pos]

        else:  # specific port
            port = int((temp[(port_pos + 1):])[:webserver_pos - port_pos - 1])
            webserver = temp[:port_pos]

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(1)
        s.connect((webserver, port))
        s.sendall(request)

        while 1:
            # receive data from web server
            data = s.recv(4096)

            if len(data) > 0:
                conn.send(data)  # send to browser/client

            else:
                break
p = Proxy()
p.main()

在python中,可执行文件的常见模式是这样的:


def main():  # Or whatever name you want to use
   """Your code here"""

# If you are importing the code, the condition will evaluate to false.
if __name__ == "__main__":
    main()

请记住,您可以使用任何您想要的函数名称。

您需要将代码放在这样的类中。 您计划通过代码使用的任何变量,在__init__方法内部定义,例如您的self.serverSocket 、ip、端口号等。

init 方法设计为运行一次,一旦您创建了类的实例,它通常会存储变量。 主要方法或您定义的任何其他方法将是您放置其余代码的地方。

import signal
import socket
import threading

class proxy():
    def __init__(self):
        # creating a tcp socket
        self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # reuse the socket
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.your_ip = "127.0.0.1" # loop back address
        self.your_port = 80 # use a port thats open like port 80

    def shutdown(self):
        # add your signal shutdown code here
        pass

    def main(self):
        # shutdown on cntrl c
        signal.signal(signal.SIGINT, self.shutdown)

        self.serverSocket.bind((self.your_ip, self.your_port))

        self.serverSocket.listen(10)
        self.__clients = {}

        while True:
            # establish the connection
            (clientSocket, client_address) = self.serverSocket.accept()

            d = threading.Thread(name=self._getClientName(client_address),
                                 target=self.proxy_thread,
                                 args=(clientSocket, client_address))
            d.setDaemon(True)
            d.start()

        # get the request from browser
        request = conn.recv(4096)

        # parse the first line
        first_line = request.split('\n')[0]

        # get url
        url = first_line.split(' ')[1]

        http_pos = url.find("://")
        if http_pos == -1:
            temp = url
        else:
            temp = url[(http_pos + 3):]

        port_pos = temp.find(":")

        # find end of web server
        webserver_pos = temp.find("/")
        if webserver_pos == -1:
            webserver_pos = len(temp)

        webserver = ""
        port = -1

        if port_pos == -1 or webserver_pos < port_pos:

            # default port
            port = 80
            webserver = temp[:webserver_pos]

        else:  # specific port
            port = int((temp[(port_pos + 1):])[:webserver_pos - port_pos - 1])
            webserver = temp[:port_pos]

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(1)
        s.connect((webserver, port))
        s.sendall(request)

        while 1:
            # receive data from web server
            data = s.recv(4096)

            if len(data) > 0:
                conn.send(data)  # send to browser/client

            else:
                break

p = proxy()
p.main()

好的,你的代码是 class 中的“def main(self,arg1)”,所以你需要一个 arg1。我修改了代码让他可以允许,但是只能http不能https,因为我不选择允许,可能你可以参考: Python 插座模块。 连接到 HTTP 代理,然后对外部资源执行 GET 请求

你可以使用这个http链接进行下面的代码测试: http://serenecalmwholelight.neverssl.com/online/

import ssl
import socket
import threading

class Proxy:
    def __init__(self):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # creating a tcp socket
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # reuse the socket
        self.ip = "127.0.0.1"
        self.port = 8080
#        self.host = socket.gethostbyname(socket.gethostname())+":%s"%self.port
#        self.context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
#        self.context.load_cert_chain(certfile="host.cert", keyfile="host.key")
        self.server.bind((self.ip, self.port))
        self.server.listen(10)
        self.multirequest()
    
    def multirequest(self):
        while True:
            (clientSocket, client_address) = self.server.accept() # establish the connection
            d = threading.Thread(target=self.main, args=(clientSocket, client_address))
            d.setDaemon(True)
            d.start()
            
    def main(self, conn, addr):
        origin_request = conn.recv(4096) # bytes
        request = origin_request.decode(encoding="utf-8") # get the request from browser
        first_line = request.split("\r\n")[0] # parse the first line
        url = first_line.split(" ")[1] # get url
        http_pos = url.find("://")
        if http_pos == -1:
            temp = url
        else:
            temp = url[(http_pos + 3):]
        webserver = ""
        port = -1
        port_pos = temp.find(":")
        # find end of web server
        webserver_pos = temp.find("/")
        if webserver_pos == -1:
            webserver_pos = len(temp)
        if port_pos == -1 or webserver_pos < port_pos: # default port
            port = 80
            webserver = temp[:webserver_pos]
        else: # specific port
            port = int(temp[(port_pos + 1):])
            webserver = temp[:port_pos]
        if port==443:
            print("WE CAN'T HANDLE HTTPS :)")
            return
#             s = self.context.wrap_socket(s)
        print("Connected by", addr)
        print("ClientSocket", conn)
        print("Browser Request:")
        print(request)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(1000)
        s.connect((webserver, port))
        s.sendall(origin_request)
        print("Website Host Result:")
        while 1:
            # receive data from web server
            data = s.recv(4096)
            try:
                print(data.decode(encoding="utf-8"))
            except:
                print(data)
            if len(data) > 0:
                conn.send(data)  # send to browser/client
            else:
                conn.send(b"")
                break
        s.shutdown(socket.SHUT_RDWR)
        s.close()
        conn.close()
Proxy()

记得到设定代理,

此代码 output:

WE CAN'T HANDLE HTTPS :)
WE CAN'T HANDLE HTTPS :)
Connected by ('127.0.0.1', 55225)
ClientSocket <socket.socket fd=1324, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 55225)>
Browser Request:
GET http://serenecalmwholelight.neverssl.com/online/ HTTP/1.1
Host: serenecalmwholelight.neverssl.com
Proxy-Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.42
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://neverssl.com/
Accept-Encoding: gzip, deflate
Accept-Language: zh-TW,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6


Website Host Result:
b'HTTP/1.1 200 OK\r\nDate: Mon, 26 Sep 2022 08:06:41 GMT\r\nServer: Apache/2.4.53 ()\r\nUpgrade: h2,h2c\r\nConnection: Upgrade\r\nLast-Modified: Wed, 29 Jun 2022 00:23:22 GMT\r\nETag: "8be-5e28b29291e10-gzip"\r\nAccept-Ranges: bytes\r\nVary: Accept-Encoding\r\nContent-Encoding: gzip\r\nContent-Length: 1173\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03uVQo\xdb6\x10~\x96~\xc5\xcd{\xe8\x06X\xb2\xe3,i\xe3\xba\xde\xda\x0eY\x07\xb4\xc5\x00\x1b(\xf6T\x9c$J\xe2L\x91\x02IEU\x87\xfd\xf7\xddQ\x92\xe3\xac\x98\x81@\x14y\xfc\xee\xee\xbb\xefN\xd9\xd5\xbeQ\xfb8\xda\xd5\x02\x0bzF;/\xbd\x12\xfb\x8f\xe2A\xd8\xc3\xe1=$P\x0b\xd5J]\xc1`:\xa8\x84\x07\xa3\x95\xd4b\xb7\x1a\rc\xbe\xe3\xfc\xc0\xcb(\xcaL1\xc0\xdf\xb4\x88J\xa3}Rb#\xd5\xb0\x85\x0f\xf4\xe2\x84\xb5\xe8\x97\x0c\xf7 \xbc\xccq\th%\xaa%8\xd4.\xa1cY\xbe\x84\xf3U\'\xbf\x8a-\\\xdd~y\xc9[\xb9Q\xc6n\xe1\xfb\x9f\xc2/l5h+\xa9\xb7\xb0\xe6\xb7\x7f\xe8\xaf\xde\\x\xee\x85\xacj\xbf\x85\xe7\xebp\xfe\x043\xbd\x15\xcd\x05D\xe2M\xbb\x85\xebu\xfbeFjG N3\xa9\'\xa0\xf3-6Hs\x82C:\xb6\xa3e\x83_\x92^\x16\xbe\xde\xc2\xed\xcd\x04t\x0epC\x1b\x80\x9d7\x8f\xabp\xdebQ\x10\xaf\x89\x12%\xe3\xdfL\xd7\xe6m;\xf9\xa5\xfd\xd9+\xd7hv\x99a~\xaa\xac\xe9t\x91\x9c\xc9\xd9\xbc]\xdf\xff\xfa\x84\xaf\xfb\xf0\xbb\xc4%D\x8eb==\xfeK\xce&\xdd<\xa6\xb9\xfb.I\xe0\xed\xe1\x00\xa55\r|@{\x82O"s\x9eb\xa8\xbdo\xddv\xb5\xaa\xa4\xf3i%}\xddeDJ\xb3\xa2\xa4Oy?\x1a\xad\xee\xb2\xa2\xbc^\xdf\xde\xdc\xe4Eq\xb3y~\x97aqu}ww\x8d\xf9\x8b\xe7\xf9\x8b\x9b\x02\x92$Hn5\xebg\xb7\x9ad\xb8c!\xb1\xb6v\x85|\x80\\\xa1s\xaf\x16c\xfa\x8bp\xe5b\xfb\\\x8b\xf1\xa4\xbe:\x8b\x97\xe0\xaeF\x07d\x1e\xe0\xc7g\xfc\xcd}\xa1=\xdf\xfe?X\xee\x8f\xcd\xfeS\x8d\xfeg\xc2\xdc\xb0e\xbb?\xd6\xd2\x01\xa7*\xbd\x00Z\x96\xc6B_\x0b\x1d\x1a\xc5\xdb\x01\xa8\xe2\xa6\xa5\xf7{\xccEf\xcci\t\xbf\x19S)\xb1\x84\xd7\r~5z\t\xc2\xe7qd4 \xf4\xb2\x94\xa0\x85\xef\x8d%;\xd4\x05h\xe3kn\xbb\x1a[\x02q)\x1c\x87V\xc0\x82\x89\'\xde5\xa7\xe8\x9cb\xd2\x17q$59#\xbf\x162kz\xea\xa5g\x0e:\xab C;\xa2\xd1\xd93E\xef\x020S\x82CS\xa6\xa2VNw\xabv\xce\xef\x9d\xe9/\xd2\xbb\xf4@\xe1\xd1\xe5\xb0\x03\x9d\x13\xc0\x83\xe1\x07T\xce\xc0I\x9b\x9e\xe2wp|\x7f\xf81\x85\x8f&\x8e\x84\xce\xed\xd0z\xc9\tj\x03\xce[Ci\x90\xec\x89\x1b\xee\xfb\xf3\xc9\x0e\xe3\xa8\xb6\xa2|\xb5\x98\xd5$t\xda\xcb\x93lE!15\xb6Z\xf1\xdb\xea\xdd\xf1\xf8\xc7\xe7\x83\xb72\xf7\x9f\x8f\x96\x86Ek\xac\xff|\x10yg\xa5\x1f\x16\xfbw\x87\xe3a\xb7\xc2\xfd2\x8e\x08\x95\xadW\x9bt\xbd\x84\xbf:\xe7\xa1UTD0\xaa\x80NO\x91\x89"\x18\x05^\xa8h!+\xe7\xbb\xfc\x04dIQBA"\x8e#\xac\x84\x03S\xd2&i\x99J\x03n\xf2\x188\x83\xb3(\x86\x0b\xd2>\x1a\xdb\xa0R\xc3\x92p\xd0S\x11\x90JP\x80,\x04\xa6\xf0\'\xe9\xc2\xd5\xa6\xa3XP\xf58\xb83\x97\x1cI@\x17\x97\xf4\x8djj\x8ds\x92j\x96\xc2\xef\x1aJ\xcci\x84JFv]^_\xc0\x07\x87\xd0\x18Jy\xd2\xa4\xa3\x14\xac \xa2{\xf2\x13\x94\xc4,C6@!J\xec\x94\x1fk\x1f\x85\xc0_S\x04S\xc8\x95\x15<\xa7\xb3\xce\x93#\x08Un\x04\xb1>z\x90e\xd0\x12\x01[\xa1\x06\x865:\x8eZc\xac\x1a\x92L\xd4\xf8@\xf4^\xaa\xd9q\xbc\x90\xa3f\xf1\xd5h\x0b\x16\xdf\xe3w$\x058L\x99O\xd2u\x81\x8e9\x89\'\xb17x\x12\x8c&\x9b\x99\x95\xd0u\xbe6D$;%\x05L^\xd9\x8b\x13\xa3\xf2y\x8d,xV\x82\x85\x16\x87\x86\xa4H\xcf\x8a\xdc\xbfAG\xa2\x9cj\xc683B\x1cQ\xd0\xcf<xl\xe1\xb1\xbfh,h\x91\x87\xf2\x04})I!\xa1\xf74\x8e9\xf4p%\xa5\x0f\x1eM*=7\xe3T\t"\xb22f\xe4\x99u6\x04V\xachD\x93\x89iv\xe0y\xa2\xb8\xaee\x9d;\xb8\x10\x04\x11C\x02y \xbb\xb1\x0c\xe0y&L\xaa\x9d/jl\xc42\xe0s\xc7\xb3\xc4\x02y\x8f\xaa\x1d\xabM\x08|k\xcavjnK\x9dg)=7\xd3\xe6y\xc81QK\xc2\'8\x1cO(\xf08r\x82v\'1\xd0\xb4\x82F\xbaP\xab\x86\x94y\x9e+\x08O[\xdc\xf7\xd2S?\x85\x8f\xc5<b\x16\xfb{\xa3\x14\xe9\xf4\x97y\x87\xdb9\x8e\xbf\x19\xdc\xbb\xd5\xf8]\xa0\x86\x0b\xff\xb6\xfc\x0b\x05yD\xe5\xbe\x08\x00\x00'
WE CAN'T HANDLE HTTPS :)

Connected by ('127.0.0.1', 55226)
ClientSocket <socket.socket fd=1364, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 55226)>
Browser Request:
GET http://serenecalmwholelight.neverssl.com/favicon.ico HTTP/1.1
Host: serenecalmwholelight.neverssl.com
Proxy-Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.42
Accept: image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://serenecalmwholelight.neverssl.com/online/
Accept-Encoding: gzip, deflate
Accept-Language: zh-TW,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6


Website Host Result:
b'HTTP/1.1 200 OK\r\nDate: Mon, 26 Sep 2022 08:06:46 GMT\r\nServer: Apache/2.4.53 ()\r\nUpgrade: h2,h2c\r\nConnection: Upgrade\r\nLast-Modified: Wed, 29 Jun 2022 00:26:43 GMT\r\nETag: "7c-5e28b351ffe27"\r\nAccept-Ranges: bytes\r\nContent-Length: 124\r\nContent-Type: image/vnd.microsoft.icon\r\n\r\n\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x010\x00\x00\x010\x01\x03\x00\x00\x00\n5\xbf\xb0\x00\x00\x00\x06PLTE\xff\xff\xffB\xc0\xfd.*\xd3?\x00\x00\x001IDATh\xde\xed\xca1\r\x00\x00\x08\x030\xfc\x9b\x06\x0b${v\xb4wg_4M\xd34M\xd34M\xd34M\xd3\xb4\xa8\x01\x00\x00\x00\x00\x00\x00\xf49\x04\x0f\x01\xee\x060\xdcP\x00\x00\x00\x00IEND\xaeB`\x82'

我通过套接字模块成功创建了本地 python 代理。

它可以运行 http 和 https 请求。

链接在这里。

https://github.com/wayne931121/Python_Proxy_Server/blob/main/Proxy.py

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM