Skip to content

Commit 1443352

Browse files
committed
fix http connect issue
1 parent 3ba4020 commit 1443352

3 files changed

Lines changed: 16 additions & 14 deletions

File tree

pproxy/__doc__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
__title__ = "pproxy"
2-
__version__ = "2.2.2"
2+
__version__ = "2.2.3"
33
__license__ = "MIT"
44
__description__ = "Proxy server that can tunnel among remote servers by regex rules."
55
__keywords__ = "proxy socks http shadowsocks shadowsocksr ssr redirect pf tunnel cipher ssl udp"

pproxy/proto.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ async def parse(self, header, reader, auth, authtable, **kw):
7474
authtable.set_authed()
7575
header = await reader.read_n(1)
7676
host_name, port, data = await socks_address_stream(reader, header[0])
77-
return host_name, port, b''
77+
return host_name, port
7878
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
7979
writer_remote.write(rauth + b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
8080

@@ -128,7 +128,7 @@ async def parse(self, header, reader, auth, authtable, reader_cipher, **kw):
128128
checksum = hmac.new(reader_cipher.iv+reader_cipher.key, header+data, hashlib.sha1).digest()
129129
assert checksum[:10] == await reader.read_n(10), 'Unknown OTA checksum'
130130
self.patch_ota_reader(reader_cipher, reader)
131-
return host_name, port, b''
131+
return host_name, port
132132
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, writer_cipher_r, **kw):
133133
writer_remote.write(rauth)
134134
if writer_cipher_r and writer_cipher_r.ota:
@@ -174,7 +174,7 @@ async def parse(self, reader, writer, auth, authtable, **kw):
174174
raise Exception(f'Unauthorized SOCKS {auth}')
175175
authtable.set_authed()
176176
writer.write(b'\x00\x5a' + port.to_bytes(2, 'big') + ip)
177-
return socket.inet_ntoa(ip), port, b''
177+
return socket.inet_ntoa(ip), port
178178
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
179179
ip = socket.inet_aton((await asyncio.get_event_loop().getaddrinfo(host_name, port, family=socket.AF_INET))[0][4][0])
180180
writer_remote.write(b'\x04\x01' + port.to_bytes(2, 'big') + ip + rauth + b'\x00')
@@ -202,7 +202,7 @@ async def parse(self, reader, writer, auth, authtable, **kw):
202202
header = await reader.read_n(1)
203203
host_name, port, data = await socks_address_stream(reader, header[0])
204204
writer.write(b'\x05\x00\x00' + header + data)
205-
return host_name, port, b''
205+
return host_name, port
206206
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
207207
writer_remote.write((b'\x05\x01\x02\x01' + b''.join(packstr(i) for i in rauth.split(b':', 1)) if rauth else b'\x05\x01\x00') + b'\x05\x01\x00\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
208208
await reader_remote.read_until(b'\x00\x05\x00\x00')
@@ -250,14 +250,13 @@ async def parse(self, header, reader, writer, auth, authtable, httpget=None, **k
250250
if method == 'CONNECT':
251251
host_name, port = path.split(':', 1)
252252
port = int(port)
253-
writer.write(f'{ver} 200 OK\r\nConnection: close\r\n\r\n'.encode())
254-
return host_name, port, b''
253+
return host_name, port, f'{ver} 200 OK\r\nConnection: close\r\n\r\n'.encode()
255254
else:
256255
url = urllib.parse.urlparse(path)
257256
host_name = url.hostname
258257
port = url.port or 80
259258
newpath = url._replace(netloc='', scheme='').geturl()
260-
return host_name, port, f'{method} {newpath} {ver}\r\n{lines}\r\n\r\n'.encode()
259+
return host_name, port, b'', f'{method} {newpath} {ver}\r\n{lines}\r\n\r\n'.encode()
261260
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, myhost, **kw):
262261
writer_remote.write(f'CONNECT {host_name}:{port} HTTP/1.1\r\nHost: {myhost}'.encode() + (b'\r\nProxy-Authorization: Basic '+base64.b64encode(rauth) if rauth else b'') + b'\r\n\r\n')
263262
await reader_remote.read_until(b'\r\n\r\n')
@@ -324,7 +323,7 @@ async def parse(self, reader, auth, authtable, sock, **kw):
324323
raise Exception(f'Unauthorized {self.name}')
325324
authtable.set_authed()
326325
remote = self.query_remote(sock)
327-
return remote[0], remote[1], b''
326+
return remote[0], remote[1]
328327
def udp_parse(self, data, auth, sock, **kw):
329328
reader = io.BytesIO(data)
330329
if auth and reader.read(len(auth)) != auth:
@@ -445,12 +444,12 @@ async def parse(self, header, reader, writer, auth, authtable, sock, **kw):
445444
writer.write(f'{ver} 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {rseckey}\r\nSec-WebSocket-Protocol: chat\r\n\r\n'.encode())
446445
self.patch_ws_stream(reader, writer, False)
447446
if not self.param:
448-
return 'tunnel', 0, b''
447+
return 'tunnel', 0
449448
host, _, port = self.param.partition(':')
450449
dst = sock.getsockname()
451450
host = host or dst[0]
452451
port = int(port) if port else dst[1]
453-
return host, port, b''
452+
return host, port
454453
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, myhost, **kw):
455454
seckey = base64.b64encode(os.urandom(16)).decode()
456455
writer_remote.write(f'GET / HTTP/1.1\r\nHost: {myhost}\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: {seckey}\r\nSec-WebSocket-Protocol: chat\r\nSec-WebSocket-Version: 13'.encode() + (b'\r\nProxy-Authorization: Basic '+base64.b64encode(rauth) if rauth else b'') + b'\r\n\r\n')
@@ -552,6 +551,8 @@ async def parse(protos, reader, **kw):
552551
header = None
553552
if proto is not None:
554553
ret = await proto.parse(header=header, reader=reader, **kw)
554+
while len(ret) < 4:
555+
ret += (b'',)
555556
return (proto,) + ret
556557
raise Exception(f'Unsupported protocol {header}')
557558

pproxy/server.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async def stream_handler(reader, writer, unix, lbind, protos, rserver, cipher, a
6161
remote_text = f'{remote_ip}:{remote_port}'
6262
local_addr = None if server_ip in ('127.0.0.1', '::1', None) else (server_ip, 0)
6363
reader_cipher, _ = await prepare_ciphers(cipher, reader, writer, server_side=False)
64-
lproto, host_name, port, initbuf = await proto.parse(protos, reader=reader, writer=writer, authtable=AuthTable(remote_ip, authtime), reader_cipher=reader_cipher, sock=writer.get_extra_info('socket'), **kwargs)
64+
lproto, host_name, port, lbuf, rbuf = await proto.parse(protos, reader=reader, writer=writer, authtable=AuthTable(remote_ip, authtime), reader_cipher=reader_cipher, sock=writer.get_extra_info('socket'), **kwargs)
6565
if host_name == 'echo':
6666
asyncio.ensure_future(lproto.channel(reader, writer, DUMMY, DUMMY))
6767
elif host_name == 'empty':
@@ -77,12 +77,13 @@ async def stream_handler(reader, writer, unix, lbind, protos, rserver, cipher, a
7777
raise Exception(f'Connection timeout {roption.bind}')
7878
try:
7979
reader_remote, writer_remote = await roption.prepare_connection(reader_remote, writer_remote, host_name, port)
80-
writer_remote.write(initbuf)
80+
writer.write(lbuf)
81+
writer_remote.write(rbuf)
8182
except Exception:
8283
writer_remote.close()
8384
raise Exception('Unknown remote protocol')
8485
m = modstat(remote_ip, host_name)
85-
lchannel = lproto.http_channel if initbuf else lproto.channel
86+
lchannel = lproto.http_channel if rbuf else lproto.channel
8687
asyncio.ensure_future(lproto.channel(reader_remote, writer, m(2+roption.direct), m(4+roption.direct)))
8788
asyncio.ensure_future(lchannel(reader, writer_remote, m(roption.direct), roption.connection_change))
8889
except Exception as ex:

0 commit comments

Comments
 (0)