X Tutup
Skip to content

Commit 5b4efca

Browse files
authored
v1.6.2
1 parent 5f42481 commit 5b4efca

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

pproxy/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pproxy import proto
33

44
__title__ = 'pproxy'
5-
__version__ = "1.6"
5+
__version__ = "1.6.2"
66
__description__ = "Proxy server that can tunnel among remote servers by regex rules."
77
__author__ = "Qian Wenjie"
88
__license__ = "MIT License"
@@ -213,15 +213,15 @@ def main():
213213
parser.add_argument('-r', dest='rserver', default=[], action='append', type=ProxyURI.compile_relay, help='remote server setting uri (default: direct)')
214214
parser.add_argument('-b', dest='block', type=pattern_compile, help='block regex rules')
215215
parser.add_argument('-a', dest='alived', default=0, type=int, help='interval to check remote alive (default: no check)')
216-
parser.add_argument('-v', dest='v', action='store_true', help='print verbose output')
216+
parser.add_argument('-v', dest='v', action='count', help='print verbose output')
217217
parser.add_argument('--ssl', dest='sslfile', help='certfile[,keyfile] if server listen in ssl mode')
218-
parser.add_argument('--pac', dest='pac', help='http PAC path')
218+
parser.add_argument('--pac', help='http PAC path')
219219
parser.add_argument('--get', dest='gets', default=[], action='append', help='http custom {path,file}')
220-
parser.add_argument('--test', dest='testurl', help='test this url for all remote proxies and exit')
220+
parser.add_argument('--test', help='test this url for all remote proxies and exit')
221221
parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}')
222222
args = parser.parse_args()
223-
if args.testurl:
224-
asyncio.run(test_url(args.testurl, args.rserver))
223+
if args.test:
224+
asyncio.run(test_url(args.test, args.rserver))
225225
return
226226
if not args.listen:
227227
args.listen.append(ProxyURI.compile_relay('http+socks://:8080/'))
@@ -251,7 +251,7 @@ def main():
251251
loop = asyncio.get_event_loop()
252252
if args.v:
253253
from pproxy import verbose
254-
verbose.setup(loop, args)
254+
verbose.setup(loop, args, args.v)
255255
servers = []
256256
for option in args.listen:
257257
print('Serving on', option.bind, 'by', ",".join(i.name for i in option.protos) + ('(SSL)' if option.sslclient else ''), '({}{})'.format(option.cipher.name, ' '+','.join(i.name() for i in option.cipher.plugins) if option.cipher and option.cipher.plugins else '') if option.cipher else '')

pproxy/proto.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,28 @@ async def connect(self, reader_remote, writer_remote, rauth, host_name, port, wr
116116
else:
117117
writer_remote.write(b'\x03' + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
118118

119-
class Socks(BaseProtocol):
119+
class Socks4(BaseProtocol):
120+
name = 'socks4'
121+
def correct_header(self, header, **kw):
122+
return header == b'\x04'
123+
async def parse(self, reader, writer, auth, authtable, **kw):
124+
assert await reader.read_n(1) == b'\x01'
125+
port = int.from_bytes(await reader.read_n(2), 'big')
126+
ip = await reader.read_n(4)
127+
userid = (await reader.read_until(b'\x00'))[:-1]
128+
if auth:
129+
if auth != userid and not authtable.authed():
130+
raise Exception('Unauthorized SOCKS')
131+
authtable.set_authed()
132+
writer.write(b'\x00\x5a' + port.to_bytes(2, 'big') + ip)
133+
return socket.inet_ntoa(ip), port, b''
134+
async def connect(self, reader_remote, writer_remote, rauth, host_name, port, **kw):
135+
ip = socket.inet_aton((await asyncio.get_event_loop().getaddrinfo(host_name, port, family=socket.AF_INET))[0][4][0])
136+
writer_remote.write(b'\x04\x01' + port.to_bytes(2, 'big') + ip + rauth + b'\x00')
137+
assert await reader_remote.read_n(2) == b'\x00\x5a'
138+
await reader_remote.read_n(6)
139+
140+
class Socks5(BaseProtocol):
120141
name = 'socks'
121142
def correct_header(self, header, **kw):
122143
return header == b'\x05'
@@ -246,7 +267,8 @@ async def parse(protos, reader, **kw):
246267
return (proto,) + ret
247268
raise Exception(f'Unsupported protocol {header}')
248269

249-
MAPPINGS = dict(direct=Direct(), http=HTTP(), socks=Socks(), ss=Shadowsocks(), ssr=ShadowsocksR(), redir=Redirect(), ssl='', secure='')
270+
MAPPINGS = dict(direct=Direct(), http=HTTP(), socks5=Socks5(), socks4=Socks4(), ss=Shadowsocks(), ssr=ShadowsocksR(), redir=Redirect(), ssl='', secure='')
271+
MAPPINGS['socks'] = MAPPINGS['socks5']
250272

251273
def get_protos(rawprotos):
252274
protos = []

pproxy/verbose.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def all_stat(stats):
1616
for i in range(6):
1717
h[i] += v2[i]
1818
stat = [b2s(i) for i in stat[:4]] + stat[4:]
19-
print(remote_ip, '\tDIRECT: {4} ({0},{2}) PROXY: {5} ({1},{3})'.format(*stat))
19+
print(remote_ip, '\tDIRECT: {5} ({1},{3}) PROXY: {4} ({0},{2})'.format(*stat))
2020
print(' '*3+'-'*64)
2121
hstat = sorted(hstat.items(), key=lambda x: sum(x[1]), reverse=True)[:15]
2222
hlen = max(map(lambda x: len(x[0]), hstat)) if hstat else 0
@@ -32,20 +32,21 @@ async def realtime_stat(stats):
3232
history.append((stats[:4], time.time()))
3333
i0, t0, i1, t1 = history[0][0], history[0][1], history[-1][0], history[-1][1]
3434
stat = [b2s((i1[i]-i0[i])/(t1-t0))+'/s' for i in range(4)] + stats[4:]
35-
sys.stdout.write('DIRECT: {4} ({0},{2}) PROXY: {5} ({1},{3})\x1b[0K\r'.format(*stat))
35+
sys.stdout.write('DIRECT: {5} ({1},{3}) PROXY: {4} ({0},{2})\x1b[0K\r'.format(*stat))
3636
sys.stdout.flush()
3737
if len(history) >= 10:
3838
del history[:1]
3939

40-
def setup(loop, args):
40+
def setup(loop, args, v):
4141
args.verbose = lambda s: sys.stdout.write(s+'\x1b[0K\n') and sys.stdout.flush()
4242
args.stats = {0: [0]*6}
4343
def modstat(remote_ip, host_name, stats=args.stats):
4444
host_name_2 = '.'.join(host_name.split('.')[-3 if host_name.endswith('.com.cn') else -2:]) if host_name.split('.')[-1].isalpha() else host_name
4545
tostat = (stats[0], stats.setdefault(remote_ip, {}).setdefault(host_name_2, [0]*6))
4646
return lambda i: lambda s: [st.__setitem__(i, st[i] + s) for st in tostat]
4747
args.modstat = modstat
48-
asyncio.ensure_future(realtime_stat(args.stats[0]))
49-
loop.add_reader(sys.stdin, functools.partial(all_stat, args.stats))
48+
if v >= 2:
49+
asyncio.ensure_future(realtime_stat(args.stats[0]))
50+
loop.add_reader(sys.stdin, functools.partial(all_stat, args.stats))
5051

5152

0 commit comments

Comments
 (0)
X Tutup