【问题标题】:How to connect a client to a server through an HTTP proxy in Python?如何通过 Python 中的 HTTP 代理将客户端连接到服务器?
【发布时间】:2016-10-09 20:57:10
【问题描述】:

我对使用套接字进行编码真的很陌生。

我喜欢 socket 库,我了解了我的程序中发生的大部分事情,所以我不介意我想坚持下去。

正如标题所说,我有一个基于套接字的客户端和服务器,我想通过 HTTP 代理交换内容(我使用的是 Squid 代理)。这段小代码应该绕过我校园中的代理来模拟校园网络上的聊天。这是完全合法的,因为我询问了在那里工作的 IT 人员。

这是交易,我可以通过代理向我的服务器发送一个 POST 请求,该服务器接收它并将其发送回客户端 1,但是当我尝试向代理发送更多请求时,它们都没有到达服务器所以我认为连接已断开,但问题是,当我从直接连接到服务器的客户端 2 发送消息时,服务器和客户端 1 会接收它们。

import socket
from _thread import *

def sender(server,h):
    b=input("<<--Send--")
    b=h
    server.send(b.encode())

PROXY_IP="127.0.0.1"
PROXY_PORT=3128
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.settimeout(0.05)
server.connect((PROXY_IP,PROXY_PORT))

header="""POST http://127.0.0.1:3001 HTTP/1.1\r\n
Host: 127.0.0.1:3001\r\n
Proxy-Connection: keep-alive\r\n
Content-Length: 5 \r\n\r\n
hello\r\n"""

server.send(header.encode())

while 1:
    try:
        start_new_thread(sender,(server,header))
        a=server.recv(1024)
        print("-->>{}".format(a.decode()))
    except KeyboardInterrupt:
        break
    except:
        pass

server.close()

我已经尝试过完美运行的 CONNECT 方法,但在我的校园网络代理中不允许使用它。 我究竟做错了什么 ? 关于如何通过代理重新发送内容,我应该知道些什么? 感谢您的宝贵时间,请多多包涵。

这是我在向代理发送请求的客户端上得到的:

~#Sent : POST http://127.0.0.1:3001 HTTP/1.1
Host: 127.0.0.1:3001
Proxy-Connection: keep-alive
Content-Length: 5 

hello

#Received : HTTP/1.1 200 OK
Server: squid/3.5.19
Mime-Version: 1.0
Date: Mon, 10 Oct 2016 00:46:39 GMT
X-Transformed-From: HTTP/0.9
X-Cache: MISS from kali
X-Cache-Lookup: MISS from kali:3128
Transfer-Encoding: chunked
Via: 1.1 kali (squid/3.5.19)
Connection: keep-alive


#Received : B2
POST / HTTP/1.1
Content-Length: 5
Host: 127.0.0.1:3001
Via: 1.1 kali (squid/3.5.19)
X-Forwarded-For: 127.0.0.1
Cache-Control: max-age=259200
Connection: keep-alive

hello


#Sent : POST http://127.0.0.1:3001 HTTP/1.1
Host: 127.0.0.1:3001
Proxy-Connection: keep-alive
Content-Length: 5 

hello

在这之后没有收到任何东西..

【问题讨论】:

  • 几个问题:1) 为什么不使用代理感知的http.client? 2) 您能否在同一个套接字上向源提供两个请求,而第二个请求无法通过代理?
  • 感谢您这么快回复!就像我说的那样,我真的很想坚持使用套接字库,以了解我在做什么,然后再转向更复杂的库。我用你问的内容编辑了这篇文章,希望这能让事情变得更清楚..
  • 您示例中的第二个请求看起来错误。代理请求必须在请求的第一行包含完整的 URL。 IE。 POST http://127.0.0.1:3001/ HTTP/1.1 而不是 POST / HTTP/1.1
  • 第二个是从代理发送到服务器并发送回客户端的那个(收到的回复有一个“已接收:”)第一个请求与最后一个请求相同并在开始时自动完成以建立与 te 代理的连接

标签: python sockets proxy server client


【解决方案1】:
POST http://127.0.0.1:3001 HTTP/1.1\r\n
Host: 127.0.0.1:3001\r\n
Proxy-Connection: keep-alive\r\n
Content-Length: 5 \r\n\r\n
hello\r\n

您的 HTTP 响应正文由 7 个字节组成,而不是您在 Content-length 中所述的 5 个字节。 5 字节后的\r\n 仍然属于响应体。提供错误的大小可能会混淆请求处理,即代理期待一个新请求,但实际上得到了\r\n,即您的 5 个字节之后的 2 个字节Content-length

除此之外,从代理的角度来看,路径和Host 标头都必须包含目标的名称。使用 127.0.0.1。就像在您的示例中一样,意味着您尝试访问代理的同一主机上的服务器,即从代理的角度来看 localhost。这可能不是您想要的。

...
X-Transformed-From: HTTP/0.9

代理响应中的此标头表明您的服务器不能正确使用 HTTP/1.x。它没有发送 HTTP 标头和正文,而是将有效负载发送回来,没有任何 HTTP 标头,就像在 20 年前已过时的 HTTP 0.9 协议中所做的那样。对于 HTTP 0.9,响应将始终仅在 TCP 连接结束时结束。这意味着在同一个 TCP 连接中不能有多个请求。

我对使用套接字进行编码真的很陌生。

问题不是由于错误使用套接字引起的,而是由于应用程序协议的错误实现,即数据通过套接字发送。如果您确实需要实现 HTTP,请研究标准,即RFC 7230 及以下。如果您不想这样做,请使用现有的和经过测试的 HTTP 库,而不是自己编写。

【讨论】:

  • 非常感谢您的建议和帮助!我刚刚在服务器响应中添加了一个响应标头 HTTP/1.1 200 OK,然后是 Content-Length,它神奇地工作。虽然旧连接已关闭并创建了一个新连接(使用服务器)。这是正常的吗?而且我无法收到来自客户端 2 的消息(它从客户端 1 获取消息)(代理和服务器只是为了测试而在本地运行)
  • @shirohige:我认为您应该将此问题与当前代码和有关行为的更多详细信息一起放在一个新问题中,而不是在评论中询问此后续问题。从这个简短的描述中不可能说出你真正在做什么。
猜你喜欢
  • 2017-05-08
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
相关资源
最近更新 更多