Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
await reader_remote.read_until(b'\x00\x05\x00\x00')
header = (await reader_remote.read_n(1))[0]
await reader_remote.read_n(6 if header == 1 else (18 if header == 4 else (await reader_remote.read_n(1))[0]+2))
def udp_parse(self, data, **kw):
reader = io.BytesIO(data)
if reader.read(3) != b'\x00\x00\x00':
return
n = reader.read(1)[0]
if n not in (1, 3, 4):
return
host_name, port = socks_address(reader, n)
return host_name, port, reader.read()
def udp_connect(self, rauth, host_name, port, data, **kw):
return b'\x00\x00\x00\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big') + data
class HTTP(BaseProtocol):
def correct_header(self, header, **kw):
return header and header.isalpha()
async def parse(self, header, reader, writer, auth, authtable, httpget=None, **kw):
lines = header + await reader.read_until(b'\r\n\r\n')
headers = lines[:-4].decode().split('\r\n')
method, path, ver = HTTP_LINE.match(headers.pop(0)).groups()
lines = '\r\n'.join(i for i in headers if not i.startswith('Proxy-'))
headers = dict(i.split(': ', 1) for i in headers if ': ' in i)
url = urllib.parse.urlparse(path)
if method == 'GET' and not url.hostname and httpget:
for path, text in httpget.items():
if url.path == path:
authtable.set_authed()
if type(text) is str:
text = (text % dict(host=headers["Host"])).encode()
writer.write(f'{ver} 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\nCache-Control: max-age=900\r\nContent-Length: {len(text)}\r\n\r\n'.encode() + text)
host, _, port = self.param.partition(':')
dst = sock.getsockname()
host = host or dst[0]
port = int(port) if port else dst[1]
return host, port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, myhost, **kw):
seckey = base64.b64encode(os.urandom(16)).decode()
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')
await reader_remote.read_until(b'\r\n\r\n')
self.patch_ws_stream(reader_remote, writer_remote, True)
class Echo(Transparent):
def query_remote(self, sock):
return 'echo', 0
class Pack(BaseProtocol):
def reuse(self):
return True
def get_handler(self, reader, writer, verbose, tcp_handler=None, udp_handler=None):
class Handler:
def __init__(self):
self.sessions = {}
self.udpmap = {}
self.closed = False
self.ready = False
asyncio.ensure_future(self.reader_handler())
def __bool__(self):
return not self.closed
async def reader_handler(self):
try:
while True:
try:
if not data: return
if header:
return o(data)
buffer.extend(data)
pos = buffer.find(10)
if pos != -1 or len(buffer) > 4096:
header = HTTP_LINE.match(buffer[:pos].decode().rstrip())
if not header:
writer_remote.close()
raise Exception('Unknown HTTP header for protocol HTTPOnly')
method, path, ver = header.groups()
data = f'{method} http://{host_name}{":"+str(port) if port!=80 else ""}{path} {ver}'.encode() + (b'\r\nProxy-Authorization: Basic '+base64.b64encode(rauth) if rauth else b'') + b'\r\n' + buffer[pos+1:]
return o(data)
writer_remote.write = write
class SSH(BaseProtocol):
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, myhost, **kw):
pass
class Transparent(BaseProtocol):
def correct_header(self, header, auth, sock, **kw):
remote = self.query_remote(sock)
if remote is None or sock.getsockname() == remote:
return False
return auth and header == auth[:1] or not auth
async def parse(self, reader, auth, authtable, sock, **kw):
if auth:
if (await reader.read_n(len(auth)-1)) != auth[1:]:
raise Exception(f'Unauthorized {self.name}')
authtable.set_authed()
remote = self.query_remote(sock)
return remote[0], remote[1]
pos = buffer.find(10)
if pos != -1 or len(buffer) > 4096:
header = HTTP_LINE.match(buffer[:pos].decode().rstrip())
if not header:
writer_remote.close()
raise Exception('Unknown HTTP header for protocol HTTPOnly')
method, path, ver = header.groups()
data = f'{method} http://{host_name}{":"+str(port) if port!=80 else ""}{path} {ver}'.encode() + (b'\r\nProxy-Authorization: Basic '+base64.b64encode(rauth) if rauth else b'') + b'\r\n' + buffer[pos+1:]
return o(data)
writer_remote.write = write
class SSH(BaseProtocol):
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, myhost, **kw):
pass
class Transparent(BaseProtocol):
def correct_header(self, header, auth, sock, **kw):
remote = self.query_remote(sock)
if remote is None or sock.getsockname() == remote:
return False
return auth and header == auth[:1] or not auth
async def parse(self, reader, auth, authtable, sock, **kw):
if auth:
if (await reader.read_n(len(auth)-1)) != auth[1:]:
raise Exception(f'Unauthorized {self.name}')
authtable.set_authed()
remote = self.query_remote(sock)
return remote[0], remote[1]
def udp_parse(self, data, auth, sock, **kw):
reader = io.BytesIO(data)
if auth and reader.read(len(auth)) != auth:
return
while True:
data = await reader.read_()
if not data:
break
if stat_bytes is None:
continue
stat_bytes(len(data))
writer.write(data)
await writer.drain()
except Exception:
pass
finally:
stat_conn(-1)
writer.close()
class Direct(BaseProtocol):
pass
class SSR(BaseProtocol):
def correct_header(self, header, auth, **kw):
return auth and header == auth[:1] or not auth and header and header[0] in (1, 3, 4)
async def parse(self, header, reader, auth, authtable, **kw):
if auth:
if (await reader.read_n(len(auth)-1)) != auth[1:]:
raise Exception('Unauthorized SSR')
authtable.set_authed()
header = await reader.read_n(1)
host_name, port, data = await socks_address_stream(reader, header[0])
return host_name, port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
writer_remote.write(rauth + b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
return host_name, port, reader.read()
def udp_client(self, data):
reader = io.BytesIO(data)
n = reader.read(1)[0]
host_name, port = socks_address(reader, n)
return reader.read()
def udp_client2(self, host_name, port, data):
try:
return b'\x01' + socket.inet_aton(host_name) + port.to_bytes(2, 'big') + data
except Exception:
pass
return b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big') + data
def udp_connect(self, rauth, host_name, port, data, **kw):
return rauth + b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big') + data
class Socks4(BaseProtocol):
def correct_header(self, header, **kw):
return header == b'\x04'
async def parse(self, reader, writer, auth, authtable, **kw):
assert await reader.read_n(1) == b'\x01'
port = int.from_bytes(await reader.read_n(2), 'big')
ip = await reader.read_n(4)
userid = (await reader.read_until(b'\x00'))[:-1]
if auth:
if auth != userid and not authtable.authed():
raise Exception(f'Unauthorized SOCKS {auth}')
authtable.set_authed()
writer.write(b'\x00\x5a' + port.to_bytes(2, 'big') + ip)
return socket.inet_ntoa(ip), port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
ip = socket.inet_aton((await asyncio.get_event_loop().getaddrinfo(host_name, port, family=socket.AF_INET))[0][4][0])
writer_remote.write(b'\x04\x01' + port.to_bytes(2, 'big') + ip + rauth + b'\x00')
class SSR(BaseProtocol):
def correct_header(self, header, auth, **kw):
return auth and header == auth[:1] or not auth and header and header[0] in (1, 3, 4)
async def parse(self, header, reader, auth, authtable, **kw):
if auth:
if (await reader.read_n(len(auth)-1)) != auth[1:]:
raise Exception('Unauthorized SSR')
authtable.set_authed()
header = await reader.read_n(1)
host_name, port, data = await socks_address_stream(reader, header[0])
return host_name, port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
writer_remote.write(rauth + b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
class SS(BaseProtocol):
def correct_header(self, header, auth, **kw):
return auth and header == auth[:1] or not auth and header and header[0] in (1, 3, 4, 17, 19, 20)
def patch_ota_reader(self, cipher, reader):
chunk_id, data_len, _buffer = 0, None, bytearray()
def decrypt(s):
nonlocal chunk_id, data_len
_buffer.extend(s)
ret = bytearray()
while 1:
if data_len is None:
if len(_buffer) < 2:
break
data_len = int.from_bytes(_buffer[:2], 'big')
del _buffer[:2]
else:
if len(_buffer) < 10+data_len:
class Tunnel(Transparent):
def query_remote(self, sock):
if not self.param:
return 'tunnel', 0
host, _, port = self.param.partition(':')
dst = sock.getsockname()
host = host or dst[0]
port = int(port) if port else dst[1]
return host, port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
writer_remote.write(rauth)
def udp_connect(self, rauth, host_name, port, data, **kw):
return rauth + data
class WS(BaseProtocol):
def correct_header(self, header, **kw):
return header and header.isalpha()
def patch_ws_stream(self, reader, writer, masked=False):
data_len, mask_key, _buffer = None, None, bytearray()
def feed_data(s, o=reader.feed_data):
nonlocal data_len, mask_key
_buffer.extend(s)
while 1:
if data_len is None:
if len(_buffer) < 2:
break
required = 2 + (4 if _buffer[1]&128 else 0)
p = _buffer[1] & 127
required += 2 if p == 126 else 4 if p == 127 else 0
if len(_buffer) < required:
break
break
if stat_bytes is None:
continue
stat_bytes(len(data))
writer.write(data)
await writer.drain()
except Exception:
pass
finally:
stat_conn(-1)
writer.close()
class Direct(BaseProtocol):
pass
class SSR(BaseProtocol):
def correct_header(self, header, auth, **kw):
return auth and header == auth[:1] or not auth and header and header[0] in (1, 3, 4)
async def parse(self, header, reader, auth, authtable, **kw):
if auth:
if (await reader.read_n(len(auth)-1)) != auth[1:]:
raise Exception('Unauthorized SSR')
authtable.set_authed()
header = await reader.read_n(1)
host_name, port, data = await socks_address_stream(reader, header[0])
return host_name, port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
writer_remote.write(rauth + b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
class SS(BaseProtocol):
def correct_header(self, header, auth, **kw):
return auth and header == auth[:1] or not auth and header and header[0] in (1, 3, 4, 17, 19, 20)
port = int.from_bytes(await reader.read_n(2), 'big')
ip = await reader.read_n(4)
userid = (await reader.read_until(b'\x00'))[:-1]
if auth:
if auth != userid and not authtable.authed():
raise Exception(f'Unauthorized SOCKS {auth}')
authtable.set_authed()
writer.write(b'\x00\x5a' + port.to_bytes(2, 'big') + ip)
return socket.inet_ntoa(ip), port
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
ip = socket.inet_aton((await asyncio.get_event_loop().getaddrinfo(host_name, port, family=socket.AF_INET))[0][4][0])
writer_remote.write(b'\x04\x01' + port.to_bytes(2, 'big') + ip + rauth + b'\x00')
assert await reader_remote.read_n(2) == b'\x00\x5a'
await reader_remote.read_n(6)
class Socks5(BaseProtocol):
def correct_header(self, header, **kw):
return header == b'\x05'
async def parse(self, reader, writer, auth, authtable, **kw):
methods = await reader.read_n((await reader.read_n(1))[0])
if auth and (b'\x00' not in methods or not authtable.authed()):
writer.write(b'\x05\x02')
assert (await reader.read_n(1))[0] == 1, 'Unknown SOCKS auth'
u = await reader.read_n((await reader.read_n(1))[0])
p = await reader.read_n((await reader.read_n(1))[0])
if u+b':'+p != auth:
raise Exception(f'Unauthorized SOCKS {u}:{p}')
writer.write(b'\x01\x00')
else:
writer.write(b'\x05\x00')
if auth:
authtable.set_authed()