Browse Source

feat: url decode of shadowsocksr

master
Dnomd343 3 years ago
parent
commit
db27f754e1
  1. 22
      ProxyDecoder/Shadowsocks.py
  2. 71
      ProxyDecoder/ShadowsocksR.py
  3. 3
      ProxyDecoder/decoder.py
  4. 4
      decode.py

22
ProxyDecoder/Shadowsocks.py

@ -99,7 +99,7 @@ def __sip002Decode(url: str):
for field in content.group(1).split('&'): # /?plugin=...&other1=...&other2=... for field in content.group(1).split('&'): # /?plugin=...&other1=...&other2=...
if field.find('=') == -1: # 缺失xxx=... if field.find('=') == -1: # 缺失xxx=...
continue continue
field = re.search(r'^([\S]*)=([\S]*)$', field) # xxx=... field = re.search(r'^([\S]*?)=([\S]*)$', field) # xxx=...
if field.group(1) == 'plugin': if field.group(1) == 'plugin':
plugin = baseFunc.urlDecode(field.group(2)) # plugin参数 plugin = baseFunc.urlDecode(field.group(2)) # plugin参数
break break
@ -119,18 +119,28 @@ def __sip002Decode(url: str):
return None return None
def ssDecode(url: str): def ssDecode(url: str):
'''
Shadowsocks 分享链接解码
链接合法:
return {...}
链接不合法:
return None
'''
try: try:
if url[0:5] != 'ss://': if url[0:5] != 'ss://':
return None return None
result = __ssCommonDecode(url) # try shadowsocks common decode result = __ssCommonDecode(url) # try shadowsocks common decode
if result != None: if result == None:
return result
result = __sip002Decode(url) # try shadowsocks sip002 decode result = __sip002Decode(url) # try shadowsocks sip002 decode
if result != None: if result == None:
return result
result = __ssPlainDecode(url) # try shadowsocks plain decode result = __ssPlainDecode(url) # try shadowsocks plain decode
if result != None: if result != None: # 解析成功
result['type'] = 'ss'
return result return result
else: # 解析失败
return None
except: except:
pass pass
return None return None

71
ProxyDecoder/ShadowsocksR.py

@ -0,0 +1,71 @@
#!/usr/bin/python
# -*- coding:utf-8 -*-
import re
from ProxyDecoder import baseFunc
def __ssrCommonDecode(url: str):
'''
ShadowsocksR经典分享链接解码
FORMAT: ssr://BASE64-ENCODED-STRING-WITHOUT-PADDING
EXAMPLE:
ssr://{base64}
-> server:port:protocol:method:obfs:base64(passwd)/?...
-> obfsparam=...&protoparam=...&remarks=...&group=...
'''
try:
content = re.search(r'^ssr://([\S]+)$', url).group(1) # ssr://{base64}
content = re.search(
r'^([a-zA-Z0-9.:_-]*):([0-9]*):' # server:p/r
r'([0-9a-zA-Z_.-]*):([0-9a-zA-Z_.-]*):([0-9a-zA-Z_.-]*):' # protocol:method:obfs:
r'([0-9a-zA-Z_=+\\-]*)(/\?)?([\S]*)?$' # base(passwd)/?...
, baseFunc.base64Decode(content)
)
info = {
'server': content.group(1),
'port': int(content.group(2)),
'password': baseFunc.base64Decode(content.group(6)),
'method': content.group(4),
'protocol': content.group(3),
'obfs': content.group(5),
}
for field in content.group(8).split('&'): # /?obfsparam=...&protoparam=...&remarks=...&group=...
if field.find('=') == -1: # 缺失xxx=...
continue
field = re.search(r'^([\S]*?)=([\S]*)$', field) # xxx=...
if field.group(1) == 'protoparam':
info['protocolParam'] = baseFunc.base64Decode(field.group(2))
elif field.group(1) == 'obfsparam':
info['obfsParam'] = baseFunc.base64Decode(field.group(2))
elif field.group(1) == 'remarks':
info['remark'] = baseFunc.base64Decode(field.group(2))
elif field.group(1) == 'group':
info['group'] = baseFunc.base64Decode(field.group(2))
return info
except:
return None
def ssrDecode(url: str):
'''
ShadowsocksR 分享链接解码
链接合法:
return {...}
链接不合法:
return None
'''
try:
if url[0:6] != 'ssr://':
return None
result = __ssrCommonDecode(url) # try common decode
if result != None: # 解析成功
result['type'] = 'ssr'
return result
else: # 解析失败
return None
except:
pass
return None

3
ProxyDecoder/decoder.py

@ -3,6 +3,7 @@
import re import re
from ProxyDecoder import Shadowsocks from ProxyDecoder import Shadowsocks
from ProxyDecoder import ShadowsocksR
def decode(url): def decode(url):
''' '''
@ -23,6 +24,8 @@ def decode(url):
scheme = re.search(r'^([\S]+?)://([\s\S]+)$', url).group(1) scheme = re.search(r'^([\S]+?)://([\s\S]+)$', url).group(1)
if scheme == 'ss': if scheme == 'ss':
return Shadowsocks.ssDecode(url) return Shadowsocks.ssDecode(url)
elif scheme == 'ssr':
return ShadowsocksR.ssrDecode(url)
except: except:
pass pass
return None return None

4
decode.py

@ -7,4 +7,6 @@ ssPlainUrl = 'ss://bf-cfb:test@192.168.100.1:8888'
ssCommonUrl = 'ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server' ssCommonUrl = 'ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server'
ssSip002Url = 'ss://cmM0LW1kNTpwYXNzd2Q@192.168.100.1:8888/?plugin=obfs-local%3Bobfs%3Dhttp#Example' ssSip002Url = 'ss://cmM0LW1kNTpwYXNzd2Q@192.168.100.1:8888/?plugin=obfs-local%3Bobfs%3Dhttp#Example'
print(Decoder.decode(ssPlainUrl)) ssrCommonUrl = 'ssr://ZmU4MDo6MTo2MDA0OmF1dGhfYWVzMTI4X21kNTphZXMtMjU2LWNmYjp0bHMxLjJfdGlja2V0X2F1dGg6Y0dGemMzZGsvP29iZnNwYXJhbT1ZMlUzTUdVeE5EY3dOekF1ZFhCa1lYUmxMbTFwWTNKdmMyOW1kQzVqYjIwJnByb3RvcGFyYW09TVRRM01EY3dPa0pGTTIxck9RJnJlbWFya3M9UlZoQlRWQk1SUSZncm91cD1kR1Z6ZEE'
print(Decoder.decode(ssrCommonUrl))

Loading…
Cancel
Save