hiddifypanel 10.11.1__py3-none-any.whl → 10.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +2 -2
- hiddifypanel/auth.py +15 -5
- hiddifypanel/hutils/encode.py +0 -1
- hiddifypanel/hutils/proxy/__init__.py +1 -0
- hiddifypanel/hutils/proxy/shared.py +18 -10
- hiddifypanel/hutils/proxy/singbox.py +22 -21
- hiddifypanel/hutils/proxy/xray.py +26 -352
- hiddifypanel/hutils/proxy/xrayjson.py +391 -0
- hiddifypanel/hutils/random.py +4 -0
- hiddifypanel/models/config.py +7 -2
- hiddifypanel/models/config_enum.py +9 -5
- hiddifypanel/panel/admin/DomainAdmin.py +3 -2
- hiddifypanel/panel/admin/templates/model/user_list.html +44 -20
- hiddifypanel/panel/commercial/restapi/v1/tgmsg.py +14 -10
- hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +17 -23
- hiddifypanel/panel/common_bp/login.py +2 -2
- hiddifypanel/panel/user/templates/base_xray_config.json.j2 +2 -2
- hiddifypanel/panel/user/user.py +1 -1
- hiddifypanel/static/images/hiddify.png +0 -0
- hiddifypanel/static/images/hiddify1.png +0 -0
- hiddifypanel/static/new/assets/hiddify-logo-7617d937.png +0 -0
- hiddifypanel/static/new/assets/hiddify-logo-7617d937_old.png +0 -0
- hiddifypanel/templates/admin-layout.html +22 -11
- hiddifypanel/templates/master.html +48 -25
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +25 -16
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +12 -5
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +8 -5
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +108 -47
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +108 -55
- hiddifypanel/translations.i18n/en.json +15 -13
- hiddifypanel/translations.i18n/fa.json +4 -2
- hiddifypanel/translations.i18n/pt.json +3 -1
- hiddifypanel/translations.i18n/ru.json +50 -48
- hiddifypanel/translations.i18n/zh.json +58 -56
- {hiddifypanel-10.11.1.dist-info → hiddifypanel-10.12.0.dist-info}/METADATA +1 -1
- {hiddifypanel-10.11.1.dist-info → hiddifypanel-10.12.0.dist-info}/RECORD +46 -43
- {hiddifypanel-10.11.1.dist-info → hiddifypanel-10.12.0.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-10.11.1.dist-info → hiddifypanel-10.12.0.dist-info}/WHEEL +0 -0
- {hiddifypanel-10.11.1.dist-info → hiddifypanel-10.12.0.dist-info}/entry_points.txt +0 -0
- {hiddifypanel-10.11.1.dist-info → hiddifypanel-10.12.0.dist-info}/top_level.txt +0 -0
hiddifypanel/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
10.
|
1
|
+
10.12.0
|
hiddifypanel/VERSION.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
__version__='10.
|
1
|
+
__version__='10.12.0'
|
2
2
|
from datetime import datetime
|
3
|
-
__release_date__= datetime.strptime('2024-03-
|
3
|
+
__release_date__= datetime.strptime('2024-03-19','%Y-%m-%d')
|
hiddifypanel/auth.py
CHANGED
@@ -143,9 +143,11 @@ def auth_before_request():
|
|
143
143
|
# print(account)
|
144
144
|
if not account:
|
145
145
|
return logout_redirect()
|
146
|
-
|
147
|
-
|
148
|
-
|
146
|
+
if is_admin_path:
|
147
|
+
next_url = request.url
|
148
|
+
next_url = next_url.replace(f'/{g.uuid}/', '/admin/')
|
149
|
+
next_url = next_url.replace("/admin/admin/", '/admin/')
|
150
|
+
next_url = next_url.replace("http://", "https://")
|
149
151
|
|
150
152
|
elif apikey := request.headers.get("Hiddify-API-Key"):
|
151
153
|
account = get_account_by_api_key(apikey, is_admin_path)
|
@@ -180,8 +182,16 @@ def auth_before_request():
|
|
180
182
|
g.is_admin = hutils.flask.is_admin_role(account.role) # type: ignore
|
181
183
|
login_user(account, force=True)
|
182
184
|
# print("loggining in")
|
183
|
-
if
|
184
|
-
return
|
185
|
+
if not g.is_admin:
|
186
|
+
return
|
187
|
+
if next_url is None:
|
188
|
+
return
|
189
|
+
if not g.user_agent['is_browser']:
|
190
|
+
return
|
191
|
+
if ".webmanifest" in request.path:
|
192
|
+
return
|
193
|
+
|
194
|
+
return redirect(next_url)
|
185
195
|
|
186
196
|
|
187
197
|
def logout_redirect():
|
hiddifypanel/hutils/encode.py
CHANGED
@@ -259,6 +259,11 @@ def make_proxy(hconfigs: dict, proxy: Proxy, domain_db: Domain, phttp=80, ptls=4
|
|
259
259
|
}
|
260
260
|
if proxy.proto in ['tuic', 'hysteria2']:
|
261
261
|
base['alpn'] = "h3"
|
262
|
+
if proxy.proto == 'hysteria2':
|
263
|
+
base['hysteria_up_mbps'] = hconfigs.get(ConfigEnum.hysteria_up_mbps)
|
264
|
+
base['hysteria_down_mbps'] = hconfigs.get(ConfigEnum.hysteria_down_mbps)
|
265
|
+
base['hysteria_obfs_enable'] = hconfigs.get(ConfigEnum.hysteria_obfs_enable)
|
266
|
+
base['hysteria_obfs_password'] = hconfigs.get(ConfigEnum.proxy_path) # TODO: it should not be correct
|
262
267
|
return base
|
263
268
|
if proxy.proto in ['wireguard']:
|
264
269
|
base['wg_pub'] = g.account.wg_pub
|
@@ -343,20 +348,18 @@ def make_proxy(hconfigs: dict, proxy: Proxy, domain_db: Domain, phttp=80, ptls=4
|
|
343
348
|
|
344
349
|
if proxy.proto in {'vless', 'trojan', 'vmess'} and hconfigs.get(ConfigEnum.mux_enable):
|
345
350
|
if hconfigs[ConfigEnum.mux_enable]:
|
346
|
-
base['mux_enable'] =
|
347
|
-
base['mux_protocol'] = hconfigs[ConfigEnum.mux_protocol]
|
348
|
-
base['mux_max_connections'] = hconfigs[ConfigEnum.mux_max_connections]
|
349
|
-
base['mux_min_streams'] = hconfigs[ConfigEnum.mux_min_streams]
|
350
|
-
base['mux_max_streams'] = hconfigs[ConfigEnum.mux_max_streams]
|
351
|
-
base['mux_padding_enable'] = hconfigs[ConfigEnum.mux_padding_enable]
|
351
|
+
base['mux_enable'] = hconfigs[ConfigEnum.core_type]
|
352
352
|
|
353
|
-
|
354
|
-
base['
|
353
|
+
base['mux_protocol'] = hconfigs.get(ConfigEnum.mux_protocol, "h2mux")
|
354
|
+
base['mux_max_connections'] = hconfigs.get(ConfigEnum.mux_max_connections, 0)
|
355
|
+
base['mux_min_streams'] = hconfigs.get(ConfigEnum.mux_min_streams, 0)
|
356
|
+
base['mux_max_streams'] = hconfigs.get(ConfigEnum.mux_max_streams, 0)
|
357
|
+
base['mux_padding_enable'] = hconfigs.get(ConfigEnum.mux_padding_enable)
|
355
358
|
|
356
359
|
if hconfigs[ConfigEnum.mux_brutal_enable]:
|
357
360
|
base['mux_brutal_enable'] = True
|
358
|
-
base['mux_brutal_up_mbps'] = hconfigs
|
359
|
-
base['mux_brutal_down_mbps'] = hconfigs
|
361
|
+
base['mux_brutal_up_mbps'] = hconfigs.get(ConfigEnum.mux_brutal_up_mbps, 10)
|
362
|
+
base['mux_brutal_down_mbps'] = hconfigs.get(ConfigEnum.mux_brutal_down_mbps, 10)
|
360
363
|
|
361
364
|
if is_cdn and proxy.proto in {'vless', 'trojan', "vmess"}:
|
362
365
|
if hconfigs[ConfigEnum.tls_fragment_enable]:
|
@@ -366,6 +369,11 @@ def make_proxy(hconfigs: dict, proxy: Proxy, domain_db: Domain, phttp=80, ptls=4
|
|
366
369
|
|
367
370
|
if hconfigs[ConfigEnum.tls_mixed_case]:
|
368
371
|
base["tls_mixed_case"] = hconfigs[ConfigEnum.tls_mixed_case]
|
372
|
+
base['host'] = hutils.random.random_case(base['host'])
|
373
|
+
base['sni'] = hutils.random.random_case(base['sni'])
|
374
|
+
base['server'] = hutils.random.random_case(base['server'])
|
375
|
+
if base.get('fakedomain'):
|
376
|
+
base['fakedomain'] = hutils.random.random_case(base['fakedomain'])
|
369
377
|
|
370
378
|
if hconfigs[ConfigEnum.tls_padding_enable]:
|
371
379
|
base["tls_padding_enable"] = hconfigs[ConfigEnum.tls_padding_enable]
|
@@ -2,7 +2,7 @@ from flask import render_template, request, g
|
|
2
2
|
import json
|
3
3
|
|
4
4
|
from hiddifypanel import hutils
|
5
|
-
from hiddifypanel.models import ProxyProto, ProxyTransport, Domain, ConfigEnum
|
5
|
+
from hiddifypanel.models import ProxyProto, ProxyTransport, Domain, ConfigEnum
|
6
6
|
from hiddifypanel.panel.hiddify import is_hiddify_next_version
|
7
7
|
|
8
8
|
|
@@ -80,7 +80,7 @@ def to_singbox(proxy: dict) -> list[dict] | dict:
|
|
80
80
|
base["uuid"] = proxy["uuid"]
|
81
81
|
|
82
82
|
if proxy['proto'] in ['vmess', 'vless', 'trojan']:
|
83
|
-
add_multiplex(base)
|
83
|
+
add_multiplex(base, proxy)
|
84
84
|
|
85
85
|
add_tls(base, proxy)
|
86
86
|
|
@@ -109,32 +109,33 @@ def to_singbox(proxy: dict) -> list[dict] | dict:
|
|
109
109
|
return all_base
|
110
110
|
|
111
111
|
|
112
|
-
def add_multiplex(base: dict):
|
113
|
-
if
|
112
|
+
def add_multiplex(base: dict, proxy: dict):
|
113
|
+
if proxy.get('mux_enable') != "singbox":
|
114
114
|
return
|
115
115
|
base['multiplex'] = {
|
116
116
|
"enabled": True,
|
117
|
-
"protocol":
|
118
|
-
"padding":
|
117
|
+
"protocol": proxy['mux_protocol'],
|
118
|
+
"padding": proxy['mux_padding_enable']
|
119
119
|
}
|
120
120
|
# Conflicts: max_streams with max_connections and min_streams
|
121
|
-
mux_max_streams =
|
121
|
+
mux_max_streams = proxy.get('mux_max_streams', 0)
|
122
122
|
if mux_max_streams and mux_max_streams != 0:
|
123
123
|
base['multiplex']['max_streams'] = mux_max_streams
|
124
124
|
else:
|
125
|
-
base['multiplex']['max_connections'] =
|
126
|
-
base['multiplex']['min_streams'] =
|
125
|
+
base['multiplex']['max_connections'] = proxy.get('mux_max_connections', 0)
|
126
|
+
base['multiplex']['min_streams'] = proxy.get('mux_min_streams', 0)
|
127
127
|
|
128
|
-
add_tcp_brutal(base)
|
128
|
+
add_tcp_brutal(base,proxy)
|
129
129
|
|
130
130
|
|
131
|
-
def add_tcp_brutal(base: dict):
|
131
|
+
def add_tcp_brutal(base: dict, proxy: dict):
|
132
132
|
if 'multiplex' in base:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
if proxy.get('mux_brutal_enable'):
|
134
|
+
base['multiplex']['brutal'] = {
|
135
|
+
"enabled": proxy.get('mux_brutal_enable', False),
|
136
|
+
"up_mbps": proxy.get('mux_brutal_up_mbps', 10),
|
137
|
+
"down_mbps": proxy.get('mux_brutal_down_mbps', 10)
|
138
|
+
}
|
138
139
|
|
139
140
|
|
140
141
|
def add_udp_over_tcp(base: dict):
|
@@ -261,7 +262,7 @@ def add_shadowsocks_base(all_base: list[dict], proxy: dict):
|
|
261
262
|
base["method"] = proxy["cipher"]
|
262
263
|
base["password"] = proxy["password"]
|
263
264
|
add_udp_over_tcp(base)
|
264
|
-
add_multiplex(base)
|
265
|
+
add_multiplex(base, proxy)
|
265
266
|
if proxy["transport"] == "faketls":
|
266
267
|
base["plugin"] = "obfs-local"
|
267
268
|
base["plugin_opts"] = f'obfs=tls;obfs-host={proxy["fakedomain"]}'
|
@@ -327,12 +328,12 @@ def add_tuic(base: dict, proxy: dict):
|
|
327
328
|
|
328
329
|
|
329
330
|
def add_hysteria(base: dict, proxy: dict):
|
330
|
-
base['up_mbps'] =
|
331
|
-
base['down_mbps'] =
|
331
|
+
base['up_mbps'] = proxy.get(ConfigEnum.hysteria_up_mbps)
|
332
|
+
base['down_mbps'] = proxy.get(ConfigEnum.hysteria_down_mbps)
|
332
333
|
# TODO: check the obfs should be empty or not exists at all
|
333
|
-
if
|
334
|
+
if proxy.get('hysteria_obfs_enable'):
|
334
335
|
base['obfs'] = {
|
335
336
|
"type": "salamander",
|
336
|
-
"password":
|
337
|
+
"password": proxy.get('hysteria_obfs_password')
|
337
338
|
}
|
338
339
|
base['password'] = proxy['uuid']
|
@@ -3,12 +3,22 @@ import json
|
|
3
3
|
import copy
|
4
4
|
from flask import render_template, request, g
|
5
5
|
from hiddifypanel import hutils
|
6
|
-
from hiddifypanel.models import Proxy, ProxyTransport, ProxyL3, ProxyCDN, ProxyProto, Domain,
|
6
|
+
from hiddifypanel.models import Proxy, ProxyTransport, ProxyL3, ProxyCDN, ProxyProto, Domain, ConfigEnum, DomainType, hconfig
|
7
7
|
from flask_babel import gettext as _
|
8
8
|
|
9
9
|
OUTBOUND_LEVEL = 8
|
10
10
|
|
11
11
|
|
12
|
+
def is_muxable_agent(proxy: dict) -> bool:
|
13
|
+
if not proxy.get('mux_enable'):
|
14
|
+
return False
|
15
|
+
if proxy.get('mux_enable') == "xray" and g.user_agent.get('is_singbox'):
|
16
|
+
return False
|
17
|
+
if proxy.get('mux_enable') == "singbox" and not g.user_agent.get('is_singbox'):
|
18
|
+
return False
|
19
|
+
return True
|
20
|
+
|
21
|
+
|
12
22
|
def to_link(proxy: dict) -> str | dict:
|
13
23
|
if 'error' in proxy:
|
14
24
|
return proxy
|
@@ -38,6 +48,7 @@ def to_link(proxy: dict) -> str | dict:
|
|
38
48
|
"sni": proxy["sni"],
|
39
49
|
"fp": proxy["fingerprint"]
|
40
50
|
}
|
51
|
+
|
41
52
|
if 'reality' in proxy["l3"]:
|
42
53
|
vmess_data['tls'] = "reality"
|
43
54
|
vmess_data['pbk'] = proxy['reality_pbk']
|
@@ -77,7 +88,7 @@ def to_link(proxy: dict) -> str | dict:
|
|
77
88
|
baseurl += "&allow_insecure=1"
|
78
89
|
return f"{baseurl}#{name_link}"
|
79
90
|
if proxy['proto'] == 'hysteria2':
|
80
|
-
baseurl = f'hysteria2://{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}?hiddify=1&obfs=salamander&obfs-password={
|
91
|
+
baseurl = f'hysteria2://{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}?hiddify=1&obfs=salamander&obfs-password={proxy["hysteria_obfs_password"]}&sni={proxy["sni"]}'
|
81
92
|
if proxy['mode'] == 'Fake' or proxy['allow_insecure']:
|
82
93
|
baseurl += "&insecure=1"
|
83
94
|
return f"{baseurl}#{name_link}"
|
@@ -183,345 +194,6 @@ def make_v2ray_configs(user, user_activate, domains: list[Domain], expire_days,
|
|
183
194
|
return "\n".join(res)
|
184
195
|
|
185
196
|
|
186
|
-
def configs_as_json(domains: list[Domain], remarks: str) -> str:
|
187
|
-
'''Returns xray configs as json'''
|
188
|
-
outbounds = []
|
189
|
-
for proxy in hutils.proxy.get_valid_proxies(domains):
|
190
|
-
outbound = to_xray(proxy)
|
191
|
-
if 'msg' not in outbound:
|
192
|
-
outbounds.append(outbound)
|
193
|
-
|
194
|
-
outbounds_len = len(outbounds)
|
195
|
-
# reutrn no outbound
|
196
|
-
if outbounds_len < 1:
|
197
|
-
return ''
|
198
|
-
|
199
|
-
all_configs = []
|
200
|
-
base_config = json.loads(render_template('base_xray_config.json.j2', remarks=remarks))
|
201
|
-
# multiple outbounds needs multiple whole base config not just one with multiple outbounds (at least for v2rayng)
|
202
|
-
# https://github.com/2dust/v2rayNG/pull/2827#issue-2127534078
|
203
|
-
if outbounds_len > 1:
|
204
|
-
for out in outbounds:
|
205
|
-
base_config['remarks'] = out['tag']
|
206
|
-
base_config['outbounds'].insert(0, out)
|
207
|
-
all_configs.append(copy.deepcopy(base_config))
|
208
|
-
del base_config['outbounds'][0]
|
209
|
-
else: # single outbound
|
210
|
-
base_config['outbounds'].insert(0, outbounds[0])
|
211
|
-
all_configs = base_config
|
212
|
-
|
213
|
-
json_configs = json.dumps(all_configs, indent=2, cls=hutils.proxy.ProxyJsonEncoder)
|
214
|
-
return json_configs
|
215
|
-
|
216
|
-
|
217
|
-
def to_xray(proxy: dict) -> dict:
|
218
|
-
outbound = {
|
219
|
-
'tag': f'{proxy["extra_info"]} {proxy["name"]} § {proxy["port"]} {proxy["dbdomain"].id}',
|
220
|
-
'protocol': str(proxy['proto']),
|
221
|
-
'settings': {},
|
222
|
-
'streamSettings': {},
|
223
|
-
'mux': { # default value
|
224
|
-
'enabled': False,
|
225
|
-
'concurrency': -1
|
226
|
-
}
|
227
|
-
}
|
228
|
-
# add multiplex to outbound
|
229
|
-
add_multiplex(outbound)
|
230
|
-
|
231
|
-
# add stream setting to outbound
|
232
|
-
add_stream_settings(outbound, proxy)
|
233
|
-
|
234
|
-
# add protocol settings to outbound
|
235
|
-
add_proto_settings(outbound, proxy)
|
236
|
-
|
237
|
-
return outbound
|
238
|
-
|
239
|
-
# region proto settings
|
240
|
-
|
241
|
-
|
242
|
-
def add_proto_settings(base: dict, proxy: dict):
|
243
|
-
if proxy['proto'] == ProxyProto.wireguard:
|
244
|
-
add_wireguard_settings(base, proxy)
|
245
|
-
elif proxy['proto'] == ProxyProto.ss:
|
246
|
-
add_shadowsocks_settings(base, proxy)
|
247
|
-
elif proxy['proto'] == ProxyProto.vless:
|
248
|
-
add_vless_settings(base, proxy)
|
249
|
-
elif proxy['proto'] == ProxyProto.vmess:
|
250
|
-
add_vmess_settings(base, proxy)
|
251
|
-
elif proxy['proto'] == ProxyProto.trojan:
|
252
|
-
proxy['password'] = proxy['uuid']
|
253
|
-
add_trojan_settings(base, proxy)
|
254
|
-
|
255
|
-
|
256
|
-
def add_wireguard_settings(base: dict, proxy: dict):
|
257
|
-
|
258
|
-
base['settings']['secretKey'] = proxy['wg_pk']
|
259
|
-
base['settings']['reversed'] = [0, 0, 0]
|
260
|
-
base['settings']['mtu'] = 1380 # optional
|
261
|
-
base['settings']['peers'] = [{
|
262
|
-
'endpoint': f'{proxy["server"]}:{int(proxy["port"])}',
|
263
|
-
'publicKey': proxy["wg_server_pub"]
|
264
|
-
# 'allowedIPs':'', 'preSharedKey':'', 'keepAlive':'' # optionals
|
265
|
-
}]
|
266
|
-
|
267
|
-
# optionals
|
268
|
-
# base['settings']['address'] = [f'{proxy["wg_ipv4"]}/32',f'{proxy["wg_ipv6"]}/128']
|
269
|
-
# base['settings']['workers'] = 4
|
270
|
-
# base['settings']['domainStrategy'] = 'ForceIP' # default
|
271
|
-
|
272
|
-
|
273
|
-
def add_vless_settings(base: dict, proxy: dict):
|
274
|
-
base['settings']['vnext'] = [
|
275
|
-
{
|
276
|
-
'address': proxy['server'],
|
277
|
-
'port': proxy['port'],
|
278
|
-
"users": [
|
279
|
-
{
|
280
|
-
'id': proxy['uuid'],
|
281
|
-
'encryption': 'none',
|
282
|
-
# 'security': 'auto',
|
283
|
-
'flow': 'xtls-rprx-vision' if (proxy['transport'] == ProxyTransport.XTLS or base['streamSettings']['security'] == 'reality') else '',
|
284
|
-
'level': OUTBOUND_LEVEL
|
285
|
-
}
|
286
|
-
]
|
287
|
-
}
|
288
|
-
]
|
289
|
-
|
290
|
-
|
291
|
-
def add_vmess_settings(base: dict, proxy: dict):
|
292
|
-
base['settings']['vnext'] = [
|
293
|
-
{
|
294
|
-
"address": proxy['server'],
|
295
|
-
"port": proxy['port'],
|
296
|
-
"users": [
|
297
|
-
{
|
298
|
-
"id": proxy['uuid'],
|
299
|
-
"security": proxy['cipher'],
|
300
|
-
"level": OUTBOUND_LEVEL
|
301
|
-
}
|
302
|
-
]
|
303
|
-
}
|
304
|
-
]
|
305
|
-
|
306
|
-
|
307
|
-
def add_trojan_settings(base: dict, proxy: dict):
|
308
|
-
base['settings']['servers'] = [
|
309
|
-
{
|
310
|
-
# 'email': proxy['uuid'], optional
|
311
|
-
'address': proxy['server'],
|
312
|
-
'port': proxy['port'],
|
313
|
-
'password': proxy['password'],
|
314
|
-
'level': OUTBOUND_LEVEL
|
315
|
-
}
|
316
|
-
]
|
317
|
-
|
318
|
-
|
319
|
-
def add_shadowsocks_settings(base: dict, proxy: dict):
|
320
|
-
base['settings']['servers'] = [
|
321
|
-
{
|
322
|
-
'address': proxy['server'],
|
323
|
-
'port': proxy['port'],
|
324
|
-
'method': proxy['cipher'],
|
325
|
-
'password': proxy['password'],
|
326
|
-
'uot': True,
|
327
|
-
'level': OUTBOUND_LEVEL
|
328
|
-
# 'email': '', optional
|
329
|
-
}
|
330
|
-
]
|
331
|
-
|
332
|
-
# endregion
|
333
|
-
|
334
|
-
|
335
|
-
# region stream settings
|
336
|
-
|
337
|
-
def add_stream_settings(base: dict, proxy: dict):
|
338
|
-
ss = base['streamSettings']
|
339
|
-
ss['security'] = 'none' # default
|
340
|
-
|
341
|
-
# security
|
342
|
-
if proxy['l3'] == ProxyL3.reality:
|
343
|
-
ss['security'] = 'reality'
|
344
|
-
elif proxy['l3'] in [ProxyL3.tls, ProxyL3.tls_h2, ProxyL3.tls_h2_h1]:
|
345
|
-
ss['security'] = 'tls'
|
346
|
-
|
347
|
-
# network and transport settings
|
348
|
-
if ss['security'] == 'tls' or 'xtls':
|
349
|
-
ss['tlsSettings'] = {
|
350
|
-
'serverName': proxy['sni'],
|
351
|
-
'allowInsecure': proxy['allow_insecure'],
|
352
|
-
'fingerprint': proxy['fingerprint'],
|
353
|
-
'alpn': [proxy['alpn']],
|
354
|
-
# 'minVersion': '1.2',
|
355
|
-
# 'disableSystemRoot': '',
|
356
|
-
# 'enableSessionResumption': '',
|
357
|
-
# 'pinnedPeerCertificateChainSha256': '',
|
358
|
-
# 'certificates': '',
|
359
|
-
# 'maxVersion': '1.3', # Go lang sets
|
360
|
-
# 'cipherSuites': '', # Go lang sets
|
361
|
-
# 'rejectUnknownSni': '', # default is false
|
362
|
-
}
|
363
|
-
if ss['security'] == 'reality':
|
364
|
-
ss['network'] = proxy['transport']
|
365
|
-
add_reality_stream(ss, proxy)
|
366
|
-
if proxy['l3'] == ProxyL3.kcp:
|
367
|
-
ss['network'] = 'kcp'
|
368
|
-
add_kcp_stream(ss, proxy)
|
369
|
-
|
370
|
-
if proxy['l3'] == ProxyL3.h3_quic:
|
371
|
-
add_quic_stream(ss, proxy)
|
372
|
-
|
373
|
-
if proxy['transport'] == 'tcp' or ss['security'] == 'reality' or (ss['security'] == 'none' and proxy['transport'] not in [ProxyTransport.httpupgrade, ProxyTransport.WS]):
|
374
|
-
ss['network'] = proxy['transport']
|
375
|
-
add_tcp_stream(ss, proxy)
|
376
|
-
if proxy['transport'] == ProxyTransport.h2 and ss['security'] == 'none' and ss['security'] != 'reality':
|
377
|
-
ss['network'] = proxy['transport']
|
378
|
-
add_http_stream(ss, proxy)
|
379
|
-
if proxy['transport'] == ProxyTransport.grpc:
|
380
|
-
ss['network'] = proxy['transport']
|
381
|
-
add_grpc_stream(ss, proxy)
|
382
|
-
if proxy['transport'] == ProxyTransport.httpupgrade:
|
383
|
-
ss['network'] = proxy['transport']
|
384
|
-
add_httpupgrade_stream(ss, proxy)
|
385
|
-
if proxy['transport'] == 'ws':
|
386
|
-
ss['network'] = proxy['transport']
|
387
|
-
add_ws_stream(ss, proxy)
|
388
|
-
|
389
|
-
# tls fragmentaion
|
390
|
-
add_tls_fragmentation_stream_settings(base)
|
391
|
-
|
392
|
-
|
393
|
-
def add_tcp_stream(ss: dict, proxy: dict):
|
394
|
-
if proxy['l3'] == ProxyL3.http:
|
395
|
-
ss['tcpSettings'] = {
|
396
|
-
'header': {
|
397
|
-
'type': 'http',
|
398
|
-
'request': {
|
399
|
-
'path': [proxy['path']]
|
400
|
-
}
|
401
|
-
}
|
402
|
-
# 'acceptProxyProtocol': False
|
403
|
-
}
|
404
|
-
else:
|
405
|
-
ss['tcpSettings'] = {
|
406
|
-
'header': {
|
407
|
-
'type': 'none'
|
408
|
-
}
|
409
|
-
# 'acceptProxyProtocol': False
|
410
|
-
}
|
411
|
-
|
412
|
-
|
413
|
-
def add_http_stream(ss: dict, proxy: dict):
|
414
|
-
ss['httpSettings'] = {
|
415
|
-
'host': proxy['host'],
|
416
|
-
'path': proxy['path'],
|
417
|
-
# 'read_idle_timeout': 10, # default disabled
|
418
|
-
# 'health_check_timeout': 15, # default is 15
|
419
|
-
# 'method': 'PUT', # default is 15
|
420
|
-
# 'headers': {
|
421
|
-
|
422
|
-
# }
|
423
|
-
}
|
424
|
-
|
425
|
-
|
426
|
-
def add_ws_stream(ss: dict, proxy: dict):
|
427
|
-
ss['wsSettings'] = {
|
428
|
-
'path': proxy['path'],
|
429
|
-
'headers': {
|
430
|
-
"Host": proxy['host']
|
431
|
-
}
|
432
|
-
# 'acceptProxyProtocol': False,
|
433
|
-
}
|
434
|
-
|
435
|
-
|
436
|
-
def add_grpc_stream(ss: dict, proxy: dict):
|
437
|
-
ss['grpcSettings'] = {
|
438
|
-
'serviceName': proxy['path'], # proxy['path'] is equal toproxy['grpc_service_name']
|
439
|
-
'idle_timeout': 115, # by default, the health check is not enabled. may solve some "connection drop" issues
|
440
|
-
'health_check_timeout': 20, # default is 20
|
441
|
-
# 'initial_windows_size': 0, # 0 means disabled. greater than 65535 means Dynamic Window mechanism will be disabled
|
442
|
-
# 'permit_without_stream': False, # health check performed when there are no sub-connections
|
443
|
-
# 'multiMode': false, # experimental
|
444
|
-
}
|
445
|
-
|
446
|
-
|
447
|
-
def add_httpupgrade_stream(ss: dict, proxy: dict):
|
448
|
-
ss['httpupgradeSettings'] = {
|
449
|
-
'path': proxy['path'],
|
450
|
-
'host': proxy['host'],
|
451
|
-
# 'acceptProxyProtocol': '', for inbounds only
|
452
|
-
}
|
453
|
-
|
454
|
-
|
455
|
-
def add_kcp_stream(ss: dict, proxy: dict):
|
456
|
-
# TODO: fix server side configs first
|
457
|
-
ss['kcpSettings'] = {}
|
458
|
-
return
|
459
|
-
ss['kcpSettings'] = {
|
460
|
-
'seed': proxy['path'],
|
461
|
-
# 'mtu': 1350, # optional, default value is written
|
462
|
-
# 'tti': 50, # optional, default value is written
|
463
|
-
# 'uplinkCapacity': 5, # optional, default value is written
|
464
|
-
# 'downlinkCapacity': 20, # optional, default value is written
|
465
|
-
# 'congestion':False, # optional, default value is written
|
466
|
-
# 'readBufferSize': 2,# optional, default value is written
|
467
|
-
# 'writeBufferSize':2 # optional, default value is written
|
468
|
-
# 'header': { # must be same as server (hiddify doesn't use yet)
|
469
|
-
# 'type': 'none' # choices: none(default), srtp, utp, wechat-video, dtls, wireguards
|
470
|
-
# }
|
471
|
-
}
|
472
|
-
|
473
|
-
|
474
|
-
def add_quic_stream(ss: dict, proxy: dict):
|
475
|
-
# TODO: fix server side configs first
|
476
|
-
ss['quicSettings'] = {}
|
477
|
-
return
|
478
|
-
ss['quicSettings'] = {
|
479
|
-
'security': 'chacha20-poly1305',
|
480
|
-
'key': proxy['path'],
|
481
|
-
'header': {
|
482
|
-
'type': 'none'
|
483
|
-
}
|
484
|
-
}
|
485
|
-
|
486
|
-
|
487
|
-
def add_reality_stream(ss: dict, proxy: dict):
|
488
|
-
ss['realitySettings'] = {
|
489
|
-
'serverName': proxy['sni'],
|
490
|
-
'fingerprint': proxy['fingerprint'],
|
491
|
-
'shortId': proxy['reality_short_id'],
|
492
|
-
'publicKey': proxy['reality_pbk'],
|
493
|
-
'show': False,
|
494
|
-
}
|
495
|
-
|
496
|
-
|
497
|
-
def add_tls_fragmentation_stream_settings(base: dict):
|
498
|
-
'''Adds tls fragment in the outbounds if tls fragmentation is enabled'''
|
499
|
-
if base['streamSettings']['security'] in ['tls', 'reality']:
|
500
|
-
if hconfig(ConfigEnum.tls_fragment_enable):
|
501
|
-
base['streamSettings']['sockopt'] = {
|
502
|
-
'dialerProxy': 'fragment',
|
503
|
-
'tcpKeepAliveIdle': 100,
|
504
|
-
'tcpNoDelay': True, # recommended to be enabled with "tcpMptcp": true.
|
505
|
-
"mark": 255
|
506
|
-
# 'tcpFastOpen': True, # the system default setting be used.
|
507
|
-
# 'tcpKeepAliveInterval': 0, # 0 means default GO lang settings, -1 means not enable
|
508
|
-
# 'tcpcongestion': bbr, # Not configuring means using the system default value
|
509
|
-
# 'tcpMptcp': True, # need to be enabled in both server and client configuration (not supported by panel yet)
|
510
|
-
}
|
511
|
-
|
512
|
-
# endregion
|
513
|
-
|
514
|
-
|
515
|
-
def add_multiplex(base: dict):
|
516
|
-
if hconfig(ConfigEnum.mux_enable):
|
517
|
-
concurrency = hutils.convert.to_int(hconfig(ConfigEnum.mux_max_connections))
|
518
|
-
if concurrency and concurrency > 0:
|
519
|
-
base['mux']['enabled'] = True
|
520
|
-
base['mux']['concurrency'] = concurrency
|
521
|
-
base['mux']['xudpConcurrency'] = concurrency
|
522
|
-
base['mux']['xudpProxyUDP443'] = 'reject'
|
523
|
-
|
524
|
-
|
525
197
|
def add_tls_tricks_to_dict(d: dict, proxy: dict):
|
526
198
|
if proxy.get('tls_fragment_enable'):
|
527
199
|
if g.user_agent.get('is_shadowrocket'):
|
@@ -536,17 +208,19 @@ def add_tls_tricks_to_dict(d: dict, proxy: dict):
|
|
536
208
|
|
537
209
|
|
538
210
|
def add_mux_to_dict(d: dict, proxy):
|
539
|
-
if proxy
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
211
|
+
if not is_muxable_agent(proxy):
|
212
|
+
return
|
213
|
+
|
214
|
+
# according to github.com/hiddify/ray2sing/
|
215
|
+
d['muxtype'] = proxy["mux_protocol"]
|
216
|
+
d['muxmaxc'] = proxy["mux_max_connections"]
|
217
|
+
d['mux'] = proxy['mux_min_streams']
|
218
|
+
d['muxsmax'] = proxy["mux_max_streams"]
|
219
|
+
d['muxpad'] = proxy["mux_padding_enable"]
|
220
|
+
|
221
|
+
if proxy.get('mux_brutal_enable'):
|
222
|
+
d['muxup'] = proxy["mux_brutal_up_mbps"]
|
223
|
+
d['muxdown'] = proxy["mux_brutal_down_mbps"]
|
550
224
|
|
551
225
|
|
552
226
|
def add_tls_tricks_to_link(proxy: dict) -> str:
|