hiddifypanel 10.10.20__py3-none-any.whl → 10.11.1__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.
Files changed (68) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +2 -2
  3. hiddifypanel/hutils/__init__.py +3 -0
  4. hiddifypanel/hutils/crypto.py +29 -0
  5. hiddifypanel/hutils/encode.py +4 -0
  6. hiddifypanel/hutils/flask.py +4 -0
  7. hiddifypanel/hutils/github_issue.py +1 -1
  8. hiddifypanel/{models/utils.py → hutils/model.py} +14 -4
  9. hiddifypanel/hutils/network/net.py +46 -2
  10. hiddifypanel/hutils/proxy/__init__.py +4 -0
  11. hiddifypanel/hutils/proxy/clash.py +161 -0
  12. hiddifypanel/hutils/proxy/shared.py +414 -0
  13. hiddifypanel/hutils/proxy/singbox.py +338 -0
  14. hiddifypanel/hutils/proxy/xray.py +561 -0
  15. hiddifypanel/models/admin.py +16 -14
  16. hiddifypanel/models/base_account.py +4 -4
  17. hiddifypanel/models/config.py +1 -1
  18. hiddifypanel/models/proxy.py +17 -17
  19. hiddifypanel/models/user.py +15 -13
  20. hiddifypanel/panel/admin/AdminstratorAdmin.py +1 -1
  21. hiddifypanel/panel/admin/DomainAdmin.py +13 -27
  22. hiddifypanel/panel/admin/ProxyAdmin.py +3 -3
  23. hiddifypanel/panel/admin/SettingAdmin.py +22 -11
  24. hiddifypanel/panel/admin/UserAdmin.py +9 -7
  25. hiddifypanel/panel/cf_api.py +1 -2
  26. hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +5 -6
  27. hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +1 -1
  28. hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +4 -7
  29. hiddifypanel/panel/common.py +5 -3
  30. hiddifypanel/panel/hiddify.py +0 -90
  31. hiddifypanel/panel/init_db.py +14 -9
  32. hiddifypanel/panel/user/__init__.py +0 -1
  33. hiddifypanel/panel/user/templates/all_configs copy.txt +2 -2
  34. hiddifypanel/panel/user/templates/all_configs.txt +2 -2
  35. hiddifypanel/panel/user/templates/base_singbox_config.json.j2 +2 -1
  36. hiddifypanel/panel/user/templates/base_xray_config.json.j2 +125 -0
  37. hiddifypanel/panel/user/templates/clash_config copy.yml +1 -1
  38. hiddifypanel/panel/user/templates/clash_config.yml +4 -4
  39. hiddifypanel/panel/user/templates/clash_proxies.yml +1 -1
  40. hiddifypanel/panel/user/templates/home/all-configs.html +2 -2
  41. hiddifypanel/panel/user/templates/home/all-configs_old.html +1 -1
  42. hiddifypanel/panel/user/templates/home/ios copy.html +2 -2
  43. hiddifypanel/panel/user/user.py +50 -44
  44. hiddifypanel/templates/admin-layout.html +16 -24
  45. hiddifypanel/templates/fake.html +0 -276
  46. hiddifypanel/templates/flaskadmin-layout.html +2 -1
  47. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  48. hiddifypanel/translations/en/LC_MESSAGES/messages.po +16 -9
  49. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  50. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +12 -6
  51. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  52. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +9 -4
  53. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  54. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +12 -7
  55. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  56. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +9 -4
  57. hiddifypanel/translations.i18n/en.json +8 -7
  58. hiddifypanel/translations.i18n/fa.json +5 -4
  59. hiddifypanel/translations.i18n/pt.json +3 -2
  60. hiddifypanel/translations.i18n/ru.json +6 -5
  61. hiddifypanel/translations.i18n/zh.json +3 -2
  62. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/METADATA +1 -1
  63. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/RECORD +67 -61
  64. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/WHEEL +1 -1
  65. hiddifypanel/panel/user/link_maker.py +0 -1089
  66. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/LICENSE.md +0 -0
  67. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/entry_points.txt +0 -0
  68. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/top_level.txt +0 -0
@@ -1,1089 +0,0 @@
1
- from flask import g, request, render_template
2
- from ipaddress import IPv4Address, IPv6Address
3
- from hiddifypanel import hutils
4
- from hiddifypanel.models import *
5
- import yaml
6
- import json
7
- from hiddifypanel.panel import hiddify
8
- import random
9
- import re
10
- import datetime
11
- from flask_babel import gettext as _
12
-
13
-
14
- def all_proxies(child_id=0):
15
- all_proxies = hiddify.get_available_proxies(child_id)
16
- all_proxies = [p for p in all_proxies if p.enable]
17
-
18
- # all_proxies = [p for p in all_proxies if p.proto == ProxyProto.ss]
19
- # all_cfg=Proxy.query.filter(Proxy.enable==True).all()
20
- # if not hconfig(ConfigEnum.domain_fronting_domain):
21
- # all_cfg=[c for c in all_cfg if 'Fake' not in c.cdn]
22
- # if not g.is_cdn:
23
- # all_cfg=[c for c in all_cfg if 'CDN' not in c.cdn]
24
- # if not hconfig(ConfigEnum.ssfaketls_enable):
25
- # all_cfg=[c for c in all_cfg if 'faketls' not in c.transport and 'v2ray' not in c.proto]
26
- # if not hconfig(ConfigEnum.vmess_enable):
27
- # all_cfg=[c for c in all_cfg if 'vmess' not in c.proto]
28
-
29
- return all_proxies
30
-
31
-
32
- def proxy_info(name, mode="tls"):
33
- return "error"
34
-
35
-
36
- def check_proxy_incorrect(proxy, domain_db, port):
37
- name = proxy.name
38
- l3 = proxy.l3
39
- if not port:
40
- return {'name': name, 'msg': "port not defined", 'type': 'error', 'proto': proxy.proto}
41
- if "reality" not in l3 and domain_db.mode == DomainType.reality:
42
- return {'name': name, 'msg': "reality proxy not in reality domain", 'type': 'debug', 'proto': proxy.proto}
43
-
44
- if "reality" in l3 and domain_db.mode != DomainType.reality:
45
- return {'name': name, 'msg': "reality proxy not in reality domain", 'type': 'debug', 'proto': proxy.proto}
46
-
47
- if "reality" in l3 and domain_db.grpc and ProxyTransport.grpc != proxy.transport:
48
- return {'name': name, 'msg': "reality proxy not in reality domain", 'type': 'debug', 'proto': proxy.proto}
49
-
50
- if "reality" in l3 and (not domain_db.grpc) and ProxyTransport.grpc == proxy.transport:
51
- return {'name': name, 'msg': "reality proxy not in reality domain", 'type': 'debug', 'proto': proxy.proto}
52
-
53
- is_cdn = ProxyCDN.CDN == proxy.cdn or ProxyCDN.Fake == proxy.cdn
54
- if is_cdn and domain_db.mode not in [DomainType.cdn, DomainType.auto_cdn_ip, DomainType.worker]:
55
- # print("cdn proxy not in cdn domain", domain, name)
56
- return {'name': name, 'msg': "cdn proxy not in cdn domain", 'type': 'debug', 'proto': proxy.proto}
57
-
58
- if not is_cdn and domain_db.mode in [DomainType.cdn, DomainType.auto_cdn_ip, DomainType.worker]:
59
- # print("not cdn proxy in cdn domain", domain, name, proxy.cdn)
60
- return {'name': name, 'msg': "not cdn proxy in cdn domain", 'type': 'debug', 'proto': proxy.proto}
61
-
62
- if proxy.cdn == ProxyCDN.relay and domain_db.mode not in [DomainType.relay]:
63
- return {'name': name, 'msg': "relay proxy not in relay domain", 'type': 'debug', 'proto': proxy.proto}
64
-
65
- if proxy.cdn != ProxyCDN.relay and domain_db.mode in [DomainType.relay]:
66
- return {'name': name, 'msg': "relay proxy not in relay domain", 'type': 'debug', 'proto': proxy.proto}
67
-
68
- if domain_db.mode == DomainType.worker and proxy.transport == ProxyTransport.grpc:
69
- return {'name': name, 'msg': "worker does not support grpc", 'type': 'debug', 'proto': proxy.proto}
70
-
71
- if domain_db.mode != DomainType.old_xtls_direct and "tls" in proxy.l3 and proxy.cdn == ProxyCDN.direct and proxy.transport in [ProxyTransport.tcp, ProxyTransport.XTLS]:
72
- return {'name': name, 'msg': "only old_xtls_direct support this", 'type': 'debug', 'proto': proxy.proto}
73
-
74
- if proxy.proto == "trojan" and not is_tls(l3):
75
- return {'name': name, 'msg': "trojan but not tls", 'type': 'warning', 'proto': proxy.proto}
76
-
77
- if l3 == "http" and ProxyTransport.XTLS in proxy.transport:
78
- return {'name': name, 'msg': "http and xtls???", 'type': 'warning', 'proto': proxy.proto}
79
-
80
- if l3 == "http" and proxy.proto in [ProxyProto.ss, ProxyProto.ssr]:
81
- return {'name': name, 'msg': "http and ss or ssr???", 'type': 'warning', 'proto': proxy.proto}
82
-
83
-
84
- def is_tls(l3):
85
- return 'tls' in l3 or "reality" in l3
86
-
87
-
88
- def get_port(proxy, hconfigs, domain_db, ptls, phttp, pport):
89
- l3 = proxy.l3
90
- port = None
91
- if isinstance(phttp, str):
92
- phttp = int(phttp) if phttp != "None" else None
93
- if isinstance(ptls, str):
94
- ptls = int(ptls) if ptls != "None" else None
95
- if l3 == "kcp":
96
- port = hconfigs[ConfigEnum.kcp_ports].split(",")[0]
97
- elif proxy.proto == ProxyProto.wireguard:
98
- port = hconfigs[ConfigEnum.wireguard_port]
99
- elif proxy.proto == "tuic":
100
- port = domain_db.internal_port_tuic
101
- elif proxy.proto == "hysteria2":
102
- port = domain_db.internal_port_hysteria2
103
- elif l3 == 'ssh':
104
- port = hconfigs[ConfigEnum.ssh_server_port]
105
- elif is_tls(l3):
106
- port = ptls
107
- elif l3 == "http":
108
- port = phttp
109
- else:
110
- port = int(pport)
111
- return port
112
-
113
-
114
- def make_proxy(hconfigs, proxy: Proxy, domain_db: Domain, phttp=80, ptls=443, pport=None) -> dict:
115
- l3 = proxy.l3
116
- domain = domain_db.domain
117
- child_id = domain_db.child_id
118
- name = proxy.name
119
- port = get_port(proxy, hconfigs, domain_db, ptls, phttp, pport)
120
- # if not port:
121
- # return {'name': name, 'msg': "port not defined", 'type': 'error', 'proto': proxy.proto}
122
- # print("=========",proxy)
123
- if val_res := check_proxy_incorrect(proxy, domain_db, port):
124
- # print(val_res)
125
- return val_res
126
-
127
- if 'reality' in proxy.l3:
128
- alpn = "h2" if proxy.transport in ['h2', "grpc"] else 'http/1.1'
129
- else:
130
- alpn = "h2" if proxy.l3 in ['tls_h2'] or proxy.transport in ["grpc", 'h2'] else 'h2,http/1.1' if proxy.l3 == 'tls_h2_h1' else "http/1.1"
131
- cdn_forced_host = domain_db.cdn_ip or (domain_db.domain if domain_db.mode != DomainType.reality else hutils.network.get_direct_host_or_ip(4))
132
- is_cdn = ProxyCDN.CDN == proxy.cdn or ProxyCDN.Fake == proxy.cdn
133
- base = {
134
- 'name': name,
135
- 'cdn': is_cdn,
136
- 'mode': "CDN" if is_cdn else "direct",
137
- 'l3': l3,
138
- 'host': domain,
139
- 'port': port,
140
- 'server': cdn_forced_host,
141
- 'sni': domain_db.servernames if is_cdn and domain_db.servernames else domain,
142
- 'uuid': str(g.account.uuid),
143
- 'proto': proxy.proto,
144
- 'transport': proxy.transport,
145
- 'proxy_path': hconfigs[ConfigEnum.proxy_path],
146
- 'alpn': alpn,
147
- 'extra_info': f'{domain_db.alias or domain}',
148
- 'fingerprint': hconfigs[ConfigEnum.utls],
149
- 'allow_insecure': domain_db.mode == DomainType.fake or "Fake" in proxy.cdn,
150
- 'dbe': proxy,
151
- 'dbdomain': domain_db
152
- }
153
- if proxy.proto in ['tuic', 'hysteria2']:
154
- base['alpn'] = "h3"
155
- return base
156
- if proxy.proto in ['wireguard']:
157
- base['wg_pub'] = g.account.wg_pub
158
- base['wg_pk'] = g.account.wg_pk
159
- base['wg_psk'] = g.account.wg_psk
160
- base['wg_ipv4'] = hutils.network.add_number_to_ipv4(hconfigs[ConfigEnum.wireguard_ipv4], g.account.id)
161
- base['wg_ipv6'] = hutils.network.add_number_to_ipv6(hconfigs[ConfigEnum.wireguard_ipv6], g.account.id)
162
- base['wg_server_pub'] = hconfigs[ConfigEnum.wireguard_public_key]
163
- base['wg_noise_trick'] = hconfigs[ConfigEnum.wireguard_noise_trick]
164
- return base
165
-
166
- if proxy.proto in [ProxyProto.vmess]:
167
- base['cipher'] = "chacha20-poly1305"
168
-
169
- if l3 in ['reality']:
170
- base['reality_short_id'] = random.sample(hconfigs[ConfigEnum.reality_short_ids].split(','), 1)[0]
171
- # base['flow']="xtls-rprx-vision"
172
- base['reality_pbk'] = hconfigs[ConfigEnum.reality_public_key]
173
- if (domain_db.servernames):
174
- all_servernames = re.split('[ \t\r\n;,]+', domain_db.servernames)
175
- base['sni'] = random.sample(all_servernames, 1)[0]
176
- if hconfigs[ConfigEnum.core_type] == "singbox":
177
- base['sni'] = all_servernames[0]
178
- else:
179
- base['sni'] = domain_db.domain
180
-
181
- del base['host']
182
- if base.get('fingerprint', 'none') != 'none':
183
- base['fingerprint'] = hconfigs[ConfigEnum.utls]
184
- # if not domain_db.cdn_ip:
185
- # base['server']=hiddify.get_domain_ip(base['server'])
186
-
187
- if "Fake" in proxy.cdn:
188
- if not hconfigs[ConfigEnum.domain_fronting_domain]:
189
- return {'name': name, 'msg': "no domain_fronting_domain", 'type': 'debug', 'proto': proxy.proto}
190
- if l3 == "http" and not hconfigs[ConfigEnum.domain_fronting_http_enable]:
191
- return {'name': name, 'msg': "no http in domain_fronting_domain", 'type': 'debug', 'proto': proxy.proto}
192
- if l3 == "tls" and not hconfigs[ConfigEnum.domain_fronting_tls_enable]:
193
- return {'name': name, 'msg': "no tls in domain_fronting_domain", 'type': 'debug', 'proto': proxy.proto}
194
- base['server'] = hconfigs[ConfigEnum.domain_fronting_domain]
195
- base['sni'] = hconfigs[ConfigEnum.domain_fronting_domain]
196
- # base["host"]=domain
197
- base['mode'] = 'Fake'
198
-
199
- elif l3 == "http" and not hconfigs[ConfigEnum.http_proxy_enable]:
200
- return {'name': name, 'msg': "http but http is disabled ", 'type': 'debug', 'proto': proxy.proto}
201
-
202
- path = {
203
- 'vless': f'{hconfigs[ConfigEnum.path_vless]}',
204
- 'trojan': f'{hconfigs[ConfigEnum.path_trojan]}',
205
- 'vmess': f'{hconfigs[ConfigEnum.path_vmess]}',
206
- 'ss': f'{hconfigs[ConfigEnum.path_ss]}',
207
- 'v2ray': f'{hconfigs[ConfigEnum.path_ss]}'
208
- }
209
-
210
- if base["proto"] in ['v2ray', 'ss', 'ssr']:
211
- base['cipher'] = hconfigs[ConfigEnum.shadowsocks2022_method]
212
- base['password'] = f'{hutils.encode.do_base_64(hconfigs[ConfigEnum.shared_secret].replace("-",""))}:{hutils.encode.do_base_64(g.account.uuid.replace("-",""))}'
213
-
214
- if base["proto"] == "ssr":
215
- base["ssr-obfs"] = "tls1.2_ticket_auth"
216
- base["ssr-protocol"] = "auth_sha1_v4"
217
- base["fakedomain"] = hconfigs[ConfigEnum.ssr_fakedomain]
218
- base["mode"] = "FakeTLS"
219
- return base
220
- elif "faketls" in proxy.transport:
221
- base['fakedomain'] = hconfigs[ConfigEnum.ssfaketls_fakedomain]
222
- base['mode'] = 'FakeTLS'
223
- return base
224
- elif "shadowtls" in proxy.transport:
225
-
226
- base['fakedomain'] = hconfigs[ConfigEnum.shadowtls_fakedomain]
227
- # base['sni'] = hconfigs[ConfigEnum.shadowtls_fakedomain]
228
- base['shared_secret'] = hconfigs[ConfigEnum.shared_secret]
229
- base['mode'] = 'ShadowTLS'
230
- return base
231
- elif "shadowsocks" in proxy.transport:
232
- return base
233
- if ProxyTransport.XTLS in proxy.transport:
234
- base['flow'] = 'xtls-rprx-vision'
235
- return {**base, 'transport': 'tcp'}
236
-
237
- if proxy.proto in {'vless', 'trojan', 'vmess'} and hconfigs.get(ConfigEnum.mux_enable):
238
- if hconfigs[ConfigEnum.mux_enable]:
239
- base['mux_enable'] = True
240
- base['mux_protocol'] = hconfigs[ConfigEnum.mux_protocol]
241
- base['mux_max_connections'] = hconfigs[ConfigEnum.mux_max_connections]
242
- base['mux_min_streams'] = hconfigs[ConfigEnum.mux_min_streams]
243
- base['mux_max_streams'] = hconfigs[ConfigEnum.mux_max_streams]
244
- base['mux_padding_enable'] = hconfigs[ConfigEnum.mux_padding_enable]
245
-
246
- # the hiddify next client doesn't support mux max streams
247
- base['mux_max_streams'] = hconfigs[ConfigEnum.mux_max_streams]
248
-
249
- if hconfigs[ConfigEnum.mux_brutal_enable]:
250
- base['mux_brutal_up_mbps'] = hconfigs[ConfigEnum.mux_brutal_up_mbps]
251
- base['mux_brutal_down_mbps'] = hconfigs[ConfigEnum.mux_brutal_down_mbps]
252
-
253
- if is_cdn and proxy.proto in {'vless', 'trojan', "vmess"}:
254
- if hconfigs[ConfigEnum.tls_fragment_enable]:
255
- base["tls_fragment_enable"] = True
256
- base["tls_fragment_size"] = hconfigs[ConfigEnum.tls_fragment_size]
257
- base["tls_fragment_sleep"] = hconfigs[ConfigEnum.tls_fragment_sleep]
258
-
259
- if hconfigs[ConfigEnum.tls_mixed_case]:
260
- base["tls_mixed_case"] = hconfigs[ConfigEnum.tls_mixed_case]
261
-
262
- if hconfigs[ConfigEnum.tls_padding_enable]:
263
- base["tls_padding_enable"] = hconfigs[ConfigEnum.tls_padding_enable]
264
- base["tls_padding_length"] = hconfigs[ConfigEnum.tls_padding_length]
265
-
266
- if "tcp" in proxy.transport:
267
- base['transport'] = 'tcp'
268
- base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_tcp]}'
269
- return base
270
- if proxy.transport in ["ws", "WS"]:
271
- base['transport'] = 'ws'
272
- base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_ws]}'
273
- base["host"] = domain
274
- return base
275
-
276
- if proxy.transport in [ProxyTransport.httpupgrade]:
277
- base['transport'] = 'httpupgrade'
278
- base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_httpupgrade]}'
279
- base["host"] = domain
280
- return base
281
-
282
- if proxy.transport == "grpc":
283
- base['transport'] = 'grpc'
284
- # base['grpc_mode'] = "multi" if hconfigs[ConfigEnum.core_type]=='xray' else 'gun'
285
- base['grpc_mode'] = 'gun'
286
- base['grpc_service_name'] = f'{path[base["proto"]]}{hconfigs[ConfigEnum.path_grpc]}'
287
- base['path'] = base['grpc_service_name']
288
- return base
289
-
290
- if "h1" in proxy.transport:
291
- base['transport'] = 'tcp'
292
- base['alpn'] = 'http/1.1'
293
- return base
294
- if ProxyProto.ssh == proxy.proto:
295
- base['private_key'] = g.account.ed25519_private_key
296
- base['host_key'] = hiddify.get_hostkeys(False)
297
- # base['ssh_port'] = hconfig(ConfigEnum.ssh_server_port)
298
- return base
299
- return {'name': name, 'msg': 'not valid', 'type': 'error', 'proto': proxy.proto}
300
-
301
-
302
- def to_link(proxy):
303
- if 'error' in proxy:
304
- return proxy
305
- # ignore httpupgrade for Streisand
306
- if g.user_agent.get('is_streisand') and proxy.get('transport') == 'httpupgrade':
307
- return {'msg': 'ignore httpupgrade for streisand'}
308
-
309
- orig_name_link = (proxy['extra_info'] + " " + proxy["name"]).strip()
310
- name_link = hutils.encode.url_encode(orig_name_link)
311
- if proxy['proto'] == 'vmess':
312
- # print(proxy)
313
- vmess_type = None
314
- if proxy["transport"] == 'tcp':
315
- vmess_type = 'http'
316
- if 'grpc_mode' in proxy:
317
- vmess_type = proxy['grpc_mode']
318
- vmess_data = {"v": "2",
319
- "ps": orig_name_link,
320
- "add": proxy['server'],
321
- "port": proxy['port'],
322
- "id": proxy["uuid"],
323
- "aid": 0,
324
- "scy": proxy['cipher'],
325
- "net": proxy["transport"],
326
- "type": vmess_type or "none",
327
- "host": proxy.get("host", ""),
328
- "alpn": proxy.get("alpn", "h2,http/1.1"),
329
- "path": proxy["path"] if "path" in proxy else "",
330
- "tls": "tls" if "tls" in proxy["l3"] else "",
331
- "sni": proxy["sni"],
332
- "fp": proxy["fingerprint"]
333
- }
334
- if 'reality' in proxy["l3"]:
335
- vmess_data['tls'] = "reality"
336
- vmess_data['pbk'] = proxy['reality_pbk']
337
- vmess_data['sid'] = proxy['reality_short_id']
338
-
339
- add_tls_tricks_to_dict(vmess_data, proxy)
340
- add_mux_to_dict(vmess_data, proxy)
341
-
342
- return "vmess://" + hutils.encode.do_base_64(f'{json.dumps(vmess_data,cls=CustomEncoder)}')
343
- if proxy['proto'] == 'ssh':
344
- baseurl = 'ssh://'
345
- if g.user_agent.get('is_streisand'):
346
- streisand_ssh = hutils.encode.do_base_64(f'{proxy["uuid"]}:0:{proxy["private_key"]}::@{proxy["server"]}:{proxy["port"]}')
347
- baseurl += f'{streisand_ssh}#{name_link}'
348
- else:
349
- hk = ",".join(proxy["host_key"])
350
- pk = proxy["private_key"].replace('\n', '')
351
- baseurl += f'{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}/?file=ssh&pk={pk}&pp={pk}&hk={hk}#{name_link}'
352
-
353
- return baseurl
354
- if proxy['proto'] == "ssr":
355
- baseurl = f'ssr://{proxy["cipher"]}:{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}'
356
- return baseurl
357
- if proxy['proto'] in ['ss', 'v2ray']:
358
- baseurl = f'ss://{proxy["cipher"]}:{proxy["password"]}@{proxy["server"]}:{proxy["port"]}'
359
- if proxy['mode'] == 'faketls':
360
- return f'{baseurl}?plugin=obfs-local%3Bobfs%3Dtls%3Bobfs-host%3D{proxy["fakedomain"]}%3Budp-over-tcp=true#{name_link}'
361
- # if proxy['mode'] == 'shadowtls':
362
- # return f'{baseurl}?plugin=shadow-tls%3Bpassword%3D{proxy["proxy_path"]}%3Bhost%3D{proxy["fakedomain"]}%3Budp-over-tcp=true#{name_link}'
363
- if proxy['proto'] == 'v2ray':
364
- return f'{baseurl}?plugin=v2ray-plugin%3Bmode%3Dwebsocket%3Bpath%3D{proxy["path"]}%3Bhost%3D{proxy["host"]}%3Btls%3Budp-over-tcp=true#{name_link}'
365
- if proxy['transport'] == 'shadowsocks':
366
- return baseurl
367
- if proxy['proto'] == 'tuic':
368
- baseurl = f'tuic://{proxy["uuid"]}:{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}?congestion_control=cubic&udp_relay_mode=native&sni={proxy["sni"]}&alpn=h3'
369
- if proxy['mode'] == 'Fake' or proxy['allow_insecure']:
370
- baseurl += "&allow_insecure=1"
371
- return f"{baseurl}#{name_link}"
372
- if proxy['proto'] == 'hysteria2':
373
- baseurl = f'hysteria2://{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}?hiddify=1&obfs=salamander&obfs-password={hconfig(ConfigEnum.proxy_path)}&sni={proxy["sni"]}'
374
- if proxy['mode'] == 'Fake' or proxy['allow_insecure']:
375
- baseurl += "&insecure=1"
376
- return f"{baseurl}#{name_link}"
377
- if proxy['proto'] == ProxyProto.wireguard:
378
- if g.user_agent.get('is_streisand'):
379
- return f'wireguard://{proxy["server"]}:{proxy["port"]}?private_key={proxy["wg_pk"]}&peer_public_key={proxy["wg_server_pub"]}&pre_shared_key={proxy["wg_psk"]}&reserved=0,0,0#{name_link}'
380
- else:
381
- # hiddify_format =
382
- # f'wg://{proxy["server"]}:{proxy["port"]}/?pk={proxy["wg_pk"]}&local_address={proxy["wg_ipv4"]}/32&peer_pk={proxy["wg_server_pub"]}&pre_shared_key={proxy["wg_psk"]}&workers=4&mtu=1380&reserved=0,0,0&ifp={proxy["wg_noise_trick"]}#{name_link}'
383
- return f'wg://{proxy["server"]}:{proxy["port"]}?publicKey={proxy["wg_pub"]}&privateKey={proxy["wg_pk"]}=&presharedKey={proxy["wg_psk"]}&ip=10.0.0.1&mtu=1380&keepalive=30&udp=1&reserved=0,0,0&ifp={proxy["wg_noise_trick"]}#{name_link}'
384
-
385
- baseurl = f'{proxy["proto"]}://{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}?hiddify=1'
386
- baseurl += f'&sni={proxy["sni"]}&type={proxy["transport"]}'
387
- baseurl += f"&alpn={proxy['alpn']}"
388
-
389
- # the ray2sing supports vless, vmess and trojan tls tricks and mux
390
- # the vmess handled already
391
-
392
- baseurl += add_mux_to_link(proxy)
393
- baseurl += add_tls_tricks_to_link(proxy)
394
-
395
- # infos+=f'&alpn={proxy["alpn"]}'
396
- baseurl += f'&path={proxy["path"]}' if "path" in proxy else ""
397
- baseurl += f'&host={proxy["host"]}' if "host" in proxy else ""
398
- if "grpc" == proxy["transport"]:
399
- baseurl += f'&serviceName={proxy["grpc_service_name"]}&mode={proxy["grpc_mode"]}'
400
- # print(proxy['cdn'],proxy["transport"])
401
- if request.args.get("fragment"):
402
- baseurl += f'&fragment=' + request.args.get("fragment") # type: ignore
403
- if "ws" == proxy["transport"] and proxy['cdn'] and request.args.get("fragment_v1"):
404
- baseurl += f'&fragment_v1=' + request.args.get("fragment_v1") # type: ignore
405
- if 'vless' == proxy['proto']:
406
- baseurl += "&encryption=none"
407
- if proxy.get('fingerprint', 'none') != 'none':
408
- baseurl += "&fp=" + proxy['fingerprint']
409
- if proxy['l3'] != 'quic':
410
- if proxy.get('transport') == ProxyTransport.tcp and proxy['proto'] in [ProxyProto.vless, ProxyProto.vmess] and proxy.get('l3') != ProxyL3.reality:
411
- baseurl += '&headerType=http'
412
- else:
413
- baseurl += '&headerType=None'
414
- if proxy['mode'] == 'Fake' or proxy['allow_insecure']:
415
- baseurl += "&allowInsecure=true"
416
- if proxy.get('flow'):
417
- baseurl += f'&flow={proxy["flow"]}'
418
-
419
- infos = f'#{name_link}'
420
-
421
- if 'reality' in proxy["l3"]:
422
- return f"{baseurl}&security=reality&pbk={proxy['reality_pbk']}&sid={proxy['reality_short_id']}{infos}"
423
- if 'tls' in proxy['l3']:
424
- return f'{baseurl}&security=tls{infos}'
425
- if proxy['l3'] == 'http':
426
- return f'{baseurl}&security=none{infos}'
427
- return proxy
428
-
429
- # region tls tricks & mux
430
- # notice: combining the functions into two function would make code less readable and difficult to maintain
431
-
432
-
433
- def add_tls_tricks_to_link(proxy) -> str:
434
- out = {}
435
- add_tls_tricks_to_dict(out, proxy)
436
- return convert_dict_to_url(out)
437
-
438
-
439
- def add_tls_tricks_to_dict(d: dict, proxy):
440
- if proxy.get('tls_fragment_enable'):
441
- if g.user_agent.get('is_shadowrocket'):
442
- d['fragment'] = f'1,{proxy["tls_fragment_size"]},{proxy["tls_fragment_sleep"]}'
443
- else:
444
- d['fragment'] = f'{proxy["tls_fragment_size"]},{proxy["tls_fragment_sleep"]},tlshello'
445
-
446
- if proxy.get("tls_mixed_case"):
447
- d['mc'] = 1
448
- if proxy.get("tls_padding_enable"):
449
- d['padsize'] = proxy["tls_padding_length"]
450
-
451
-
452
- def convert_dict_to_url(dict):
453
- return '&' + '&'.join([f'{k}={v}' for k, v in dict.items()]) if len(dict) else ''
454
-
455
-
456
- def add_mux_to_link(proxy) -> str:
457
- out = {}
458
- add_mux_to_dict(out, proxy)
459
- return convert_dict_to_url(out)
460
-
461
-
462
- def add_mux_to_dict(d: dict, proxy):
463
- if proxy.get('mux_enable'):
464
- # d['mux'] = proxy["mux_protocol"]
465
- # mux is equals to concurrency in clients
466
- d['mux'] = proxy["mux_max_streams"]
467
- d['mux_max'] = proxy["mux_max_connections"]
468
- d['mux_pad'] = proxy["mux_padding_enable"]
469
- # doesn't exist
470
- # d['mux_min'] = proxy["mux_min_connections"]
471
-
472
- if proxy.get('mux_brutal_enable'):
473
- d['mux_up'] = proxy["mux_brutal_up_mbps"]
474
- d['mux_down'] = proxy["mux_brutal_down_mbps"]
475
-
476
- # endregion
477
-
478
-
479
- # def to_clash_yml(proxy):
480
- # return yaml.dump(to_clash(proxy,'normal'))
481
-
482
-
483
- def to_clash(proxy, meta_or_normal):
484
-
485
- name = proxy['name']
486
- if proxy['l3'] == "kcp":
487
- return {'name': name, 'msg': "clash does not support kcp", 'type': 'debug'}
488
- if proxy['proto'] == "ssh":
489
- return {'name': name, 'msg': "clash does not support ssh", 'type': 'debug'}
490
- if meta_or_normal == "normal":
491
- if proxy['proto'] in ["vless", 'tuic', 'hysteria2']:
492
- return {'name': name, 'msg': f"{proxy['proto']} not supported in clash", 'type': 'debug'}
493
- if proxy.get('flow'):
494
- return {'name': name, 'msg': "xtls not supported in clash", 'type': 'debug'}
495
- if proxy['transport'] == "shadowtls":
496
- return {'name': name, 'msg': "shadowtls not supported in clash", 'type': 'debug'}
497
- if proxy['l3'] == ProxyL3.tls_h2 and proxy['proto'] in [ProxyProto.vmess, ProxyProto.vless] and proxy['dbe'].cdn == ProxyCDN.direct:
498
- return {'name': name, 'msg': "bug tls_h2 vmess and vless in clash meta", 'type': 'warning'}
499
- base = {}
500
- # vmess ws
501
- base["name"] = f"""{proxy['extra_info']} {proxy["name"]} § {proxy['port']} {proxy["dbdomain"].id}"""
502
- base["type"] = str(proxy["proto"])
503
- base["server"] = proxy["server"]
504
- base["port"] = proxy["port"]
505
- base['alpn'] = proxy['alpn'].split(',')
506
- if proxy["proto"] == "ssr":
507
- base["cipher"] = proxy["cipher"]
508
- base["password"] = proxy["uuid"]
509
- base["udp"] = True
510
- base["obfs"] = proxy["ssr-obfs"]
511
- base["protocol"] = proxy["ssr-protocol"]
512
- base["obfs-param"] = proxy["fakedomain"]
513
- return base
514
- elif proxy["proto"] == "tuic":
515
- base["uuid"] = proxy["uuid"]
516
- base["password"] = proxy["uuid"]
517
- base["disable-sni"] = proxy['allow_insecure']
518
- base["reduce-rtt"] = True
519
- base["request-timeout"] = 8000
520
- base["udp-relay-mode"] = 'native'
521
- base["congestion-controller"] = 'cubic'
522
- base['sni'] = proxy['sni']
523
- return base
524
- elif proxy["proto"] in ["ss", "v2ray"]:
525
- base["cipher"] = proxy["cipher"]
526
- base["password"] = proxy["password"]
527
- base["udp_over_tcp"] = True
528
- if proxy["transport"] == "faketls":
529
- base["plugin"] = "obfs"
530
- base["plugin-opts"] = {
531
- "mode": 'tls',
532
- "host": proxy["fakedomain"]
533
- }
534
- elif proxy["transport"] == "shadowtls":
535
- base["plugin"] = "shadow-tls"
536
- base["plugin-opts"] = {
537
- "host": proxy["fakedomain"],
538
- "password": proxy["proxy_path"],
539
- "version": 3 # support 1/2/3
540
-
541
- }
542
-
543
- elif proxy["proto"] == "v2ray":
544
- base["plugin"] = "v2ray-plugin"
545
- base["type"] = "ss"
546
- base["plugin-opts"] = {
547
- "mode": "websocket",
548
- "tls": "tls" in proxy["l3"],
549
- "skip-cert-verify": proxy["mode"] == "Fake" or proxy['allow_insecure'],
550
- "host": proxy['sni'],
551
- "path": proxy["path"]
552
- }
553
- return base
554
- elif proxy["proto"] == "trojan":
555
- base["password"] = proxy["uuid"]
556
- base["sni"] = proxy["sni"]
557
-
558
- else:
559
- base["uuid"] = proxy["uuid"]
560
- base["servername"] = proxy["sni"]
561
- base["tls"] = "tls" in proxy["l3"] or "reality" in proxy["l3"]
562
- if meta_or_normal == "meta":
563
- base['client-fingerprint'] = proxy['fingerprint']
564
- if proxy.get('flow'):
565
- base["flow"] = proxy['flow']
566
- # base["flow-show"] = True
567
-
568
- if proxy["proto"] == "vmess":
569
- base["alterId"] = 0
570
- base["cipher"] = proxy["cipher"]
571
- base["udp"] = True
572
-
573
- base["skip-cert-verify"] = proxy["mode"] == "Fake"
574
-
575
- base["network"] = proxy["transport"]
576
-
577
- if base["network"] == "ws":
578
- base["ws-opts"] = {
579
- "path": proxy["path"]
580
- }
581
- if "host" in proxy:
582
- base["ws-opts"]["headers"] = {"Host": proxy["host"]}
583
-
584
- if base["network"] == "tcp" and proxy['alpn'] != 'h2':
585
- if proxy['transport'] != ProxyTransport.XTLS:
586
- base["network"] = "http"
587
-
588
- if "path" in proxy:
589
- base["http-opts"] = {
590
- "path": [proxy["path"]]
591
- }
592
- if 'host' in proxy:
593
- base["http-opts"]["host"] = [proxy["host"]]
594
- if base["network"] == "tcp" and proxy['alpn'] == 'h2':
595
- base["network"] = "h2"
596
-
597
- if "path" in proxy:
598
- base["h2-opts"] = {
599
- "path": proxy["path"]
600
- }
601
- if 'host' in proxy:
602
- base["h2-opts"]["host"] = [proxy["host"]]
603
- if base["network"] == "grpc":
604
- base["grpc-opts"] = {
605
- "grpc-service-name": proxy["grpc_service_name"]
606
- }
607
- if proxy['l3'] == ProxyL3.reality:
608
- base["reality-opts"] = {
609
- "public-key": proxy['reality_pbk'],
610
- "short-id": proxy['reality_short_id'],
611
- }
612
- if proxy["transport"] != 'grpc':
613
- base["network"] = 'tcp'
614
-
615
- return base
616
-
617
-
618
- def get_clash_config_names(meta_or_normal, domains):
619
- allp = []
620
- for pinfo in get_all_validated_proxies(domains):
621
- clash = to_clash(pinfo, meta_or_normal)
622
- if 'msg' not in clash:
623
- allp.append(clash['name'])
624
-
625
- return yaml.dump(allp, sort_keys=False)
626
-
627
-
628
- def get_all_clash_configs(meta_or_normal, domains):
629
- allp = []
630
- for pinfo in get_all_validated_proxies(domains):
631
- clash = to_clash(pinfo, meta_or_normal)
632
- if 'msg' not in clash:
633
- allp.append(clash)
634
-
635
- return yaml.dump({"proxies": allp}, sort_keys=False)
636
-
637
-
638
- def to_singbox(proxy):
639
- name = proxy['name']
640
-
641
- all_base = []
642
- if proxy['l3'] == "kcp":
643
- return {'name': name, 'msg': "clash does not support kcp", 'type': 'debug'}
644
-
645
- base = {}
646
- all_base.append(base)
647
- # vmess ws
648
- base["tag"] = f"""{proxy['extra_info']} {proxy["name"]} § {proxy['port']} {proxy["dbdomain"].id}"""
649
- base["type"] = str(proxy["proto"])
650
- base["server"] = proxy["server"]
651
- base["server_port"] = int(proxy["port"])
652
- # base['alpn'] = proxy['alpn'].split(',')
653
- if proxy["proto"] == "ssr":
654
- add_singbox_ssr(base, proxy)
655
- return all_base
656
- if proxy["proto"] == ProxyProto.wireguard:
657
- add_singbox_wireguard(base, proxy)
658
- return all_base
659
-
660
- if proxy["proto"] in ["ss", "v2ray"]:
661
- add_singbox_shadowsocks_base(all_base, proxy)
662
- return all_base
663
- if proxy["proto"] == "ssh":
664
- add_singbox_ssh(all_base, proxy)
665
- return all_base
666
-
667
- if proxy["proto"] == "trojan":
668
- base["password"] = proxy["uuid"]
669
-
670
- if proxy['proto'] in ['vmess', 'vless']:
671
- base["uuid"] = proxy["uuid"]
672
-
673
- if proxy['proto'] in ['vmess', 'vless', 'trojan']:
674
- add_singbox_multiplex(base)
675
-
676
- add_singbox_tls(base, proxy)
677
-
678
- if g.user_agent.get('is_hiddify'):
679
- add_singbox_tls_tricks(base, proxy)
680
-
681
- if proxy.get('flow'):
682
- base["flow"] = proxy['flow']
683
- # base["flow-show"] = True
684
-
685
- if proxy["proto"] == "vmess":
686
- base["alter_id"] = 0
687
- base["security"] = proxy["cipher"]
688
-
689
- # base["udp"] = True
690
- if proxy["proto"] in ["vmess", "vless"]:
691
- base["packet_encoding"] = "xudp" # udp packet encoding
692
-
693
- if proxy["proto"] == "tuic":
694
- add_tuic(base, proxy)
695
- elif proxy["proto"] == "hysteria2":
696
- add_hysteria(base, proxy)
697
- else:
698
- add_singbox_transport(base, proxy)
699
-
700
- return all_base
701
-
702
-
703
- def add_tuic(base, proxy):
704
- base['congestion_control'] = "cubic"
705
- base['udp_relay_mode'] = 'native'
706
- base['zero_rtt_handshake'] = True
707
- base['heartbeat'] = "10s"
708
- base['password'] = proxy['uuid']
709
- base['uuid'] = proxy['uuid']
710
-
711
-
712
- def add_hysteria(base, proxy):
713
- base['up_mbps'] = int(hconfig(ConfigEnum.hysteria_up_mbps))
714
- base['down_mbps'] = int(hconfig(ConfigEnum.hysteria_down_mbps))
715
- # TODO: check the obfs should be empty or not exists at all
716
- if hconfig(ConfigEnum.hysteria_obfs_enable):
717
- base['obfs'] = {
718
- "type": "salamander",
719
- "password": hconfig(ConfigEnum.proxy_path)
720
- }
721
- base['password'] = proxy['uuid']
722
-
723
-
724
- def add_singbox_multiplex(base):
725
- if not hconfig(ConfigEnum.mux_enable):
726
- return
727
- base['multiplex'] = {
728
- "enabled": True,
729
- "protocol": hconfig(ConfigEnum.mux_protocol),
730
- "padding": hconfig(ConfigEnum.mux_padding_enable)
731
- }
732
- # Conflicts: max_streams with max_connections and min_streams
733
- mux_max_streams = int(hconfig(ConfigEnum.mux_max_streams))
734
- if mux_max_streams and mux_max_streams != 0:
735
- base['multiplex']['max_streams'] = mux_max_streams
736
- else:
737
- base['multiplex']['max_connections'] = int(hconfig(ConfigEnum.mux_max_connections))
738
- base['multiplex']['min_streams'] = int(hconfig(ConfigEnum.mux_min_streams))
739
-
740
- add_singbox_tcp_brutal(base)
741
-
742
-
743
- def add_singbox_tcp_brutal(base):
744
- if 'multiplex' in base:
745
- base['multiplex']['brutal'] = {
746
- "enabled": hconfig(ConfigEnum.mux_brutal_enable),
747
- "up_mbps": int(hconfig(ConfigEnum.mux_brutal_up_mbps)),
748
- "down_mbps": int(hconfig(ConfigEnum.mux_brutal_down_mbps))
749
- }
750
-
751
-
752
- def add_singbox_udp_over_tcp(base):
753
- base['udp_over_tcp'] = {
754
- "enabled": True,
755
- "version": 2
756
- }
757
-
758
-
759
- def add_singbox_tls(base, proxy):
760
- if not ("tls" in proxy["l3"] or "reality" in proxy["l3"]):
761
- return
762
- base["tls"] = {
763
- "enabled": True,
764
- "server_name": proxy["sni"]
765
- }
766
- if proxy['proto'] not in ["tuic", "hysteria2"]:
767
- base["tls"]["utls"] = {
768
- "enabled": True,
769
- "fingerprint": proxy.get('fingerprint', 'none')
770
- }
771
-
772
- if "reality" in proxy["l3"]:
773
- base["tls"]["reality"] = {
774
- "enabled": True,
775
- "public_key": proxy['reality_pbk'],
776
- "short_id": proxy['reality_short_id']
777
- }
778
- base["tls"]['insecure'] = proxy['allow_insecure'] or (proxy["mode"] == "Fake")
779
- base["tls"]["alpn"] = proxy['alpn'].split(',')
780
- # base['ech'] = {
781
- # "enabled": True,
782
- # }
783
-
784
-
785
- def add_singbox_tls_tricks(base, proxy):
786
- if proxy.get('tls_fragment_enable'):
787
- base['tls_fragment'] = {
788
- 'enabled': True,
789
- 'size': proxy["tls_fragment_size"],
790
- 'sleep': proxy["tls_fragment_sleep"]
791
- }
792
-
793
- if 'tls' in base:
794
- if proxy.get("tls_padding_enable") or proxy.get("tls_mixed_case"):
795
- base['tls']['tls_tricks'] = {}
796
- if proxy.get("tls_padding_enable"):
797
- base['tls']['tls_tricks']['padding_size'] = proxy["tls_padding_length"]
798
-
799
- if proxy.get("tls_mixed_case"):
800
- base['tls']['tls_tricks']['mixedcase_sni'] = True
801
-
802
-
803
- def add_singbox_transport(base, proxy):
804
- if proxy['l3'] == 'reality' and proxy['transport'] not in ["grpc"]:
805
- return
806
- base["transport"] = {}
807
- if proxy['transport'] in ["ws", "WS"]:
808
- base["transport"] = {
809
- "type": "ws",
810
- "path": proxy["path"],
811
- "early_data_header_name": "Sec-WebSocket-Protocol"
812
- }
813
- if "host" in proxy:
814
- base["transport"]["headers"] = {"Host": proxy["host"]}
815
-
816
- if proxy['transport'] in [ProxyTransport.httpupgrade]:
817
- base["transport"] = {
818
- "type": "httpupgrade",
819
- "path": proxy["path"]
820
- }
821
- if "host" in proxy:
822
- base["transport"]["headers"] = {"Host": proxy["host"]}
823
-
824
- if proxy["transport"] in ["tcp", "h2"]:
825
- base["transport"] = {
826
- "type": "http",
827
- "path": proxy.get("path", ""),
828
- # "method": "",
829
- # "headers": {},
830
- "idle_timeout": "15s",
831
- "ping_timeout": "15s"
832
- }
833
-
834
- if 'host' in proxy:
835
- base["transport"]["host"] = [proxy["host"]]
836
-
837
- if proxy["transport"] == "grpc":
838
- base["transport"] = {
839
- "type": "grpc",
840
- "service_name": proxy["grpc_service_name"],
841
- "idle_timeout": "115s",
842
- "ping_timeout": "15s",
843
- # "permit_without_stream": false
844
- }
845
-
846
-
847
- def add_singbox_ssr(base, proxy):
848
-
849
- base["method"] = proxy["cipher"]
850
- base["password"] = proxy["uuid"]
851
- # base["udp"] = True
852
- base["obfs"] = proxy["ssr-obfs"]
853
- base["protocol"] = proxy["ssr-protocol"]
854
- base["protocol-param"] = proxy["fakedomain"]
855
-
856
-
857
- def add_singbox_wireguard(base, proxy):
858
-
859
- base["local_address"] = f'{proxy["wg_ipv4"]}/32'
860
- base["private_key"] = proxy["wg_pk"]
861
- base["peer_public_key"] = proxy["wg_server_pub"]
862
-
863
- base["pre_shared_key"] = proxy["wg_psk"]
864
-
865
- base["mtu"] = 1380
866
- if g.user_agent.get('is_hiddify') and hiddify.is_hiddify_next_version(0, 15, 0):
867
- base["fake_packets"] = proxy["wg_noise_trick"]
868
-
869
-
870
- def add_singbox_shadowsocks_base(all_base, proxy):
871
- base = all_base[0]
872
- base["type"] = "shadowsocks"
873
- base["method"] = proxy["cipher"]
874
- base["password"] = proxy["password"]
875
- add_singbox_udp_over_tcp(base)
876
- add_singbox_multiplex(base)
877
- if proxy["transport"] == "faketls":
878
- base["plugin"] = "obfs-local"
879
- base["plugin_opts"] = f'obfs=tls;obfs-host={proxy["fakedomain"]}'
880
- if proxy['proto'] == 'v2ray':
881
- base["plugin"] = "v2ray-plugin"
882
- # "skip-cert-verify": proxy["mode"] == "Fake" or proxy['allow_insecure'],
883
- base["plugin_opts"] = f'mode=websocket;path={proxy["path"]};host={proxy["host"]};tls'
884
-
885
- if proxy["transport"] == "shadowtls":
886
- base['detour'] = base['tag'] + "_shadowtls-out §hide§"
887
-
888
- shadowtls_base = {
889
- "type": "shadowtls",
890
- "tag": base['detour'],
891
- "server": base['server'],
892
- "server_port": base['server_port'],
893
- "version": 3,
894
- "password": proxy["shared_secret"],
895
- "tls": {
896
- "enabled": True,
897
- "server_name": proxy["fakedomain"],
898
- "utls": {
899
- "enabled": True,
900
- "fingerprint": proxy.get('fingerprint', 'none')
901
- },
902
- # "alpn": proxy['alpn'].split(',')
903
- }
904
- }
905
- # add_singbox_utls(shadowtls_base)
906
- del base['server']
907
- del base['server_port']
908
- all_base.append(shadowtls_base)
909
-
910
-
911
- def add_singbox_ssh(all_base, proxy):
912
- base = all_base[0]
913
- # base["client_version"]= "{{ssh_client_version}}"
914
- base["user"] = proxy['uuid']
915
- base["private_key"] = proxy['private_key'] # .replace('\n', '\\n')
916
-
917
- base["host_key"] = proxy.get('host_key', [])
918
-
919
- socks_front = {
920
- "type": "socks",
921
- "tag": base['tag'] + "+UDP",
922
- "server": "127.0.0.1",
923
- "server_port": 2000,
924
- "version": "5",
925
- "udp_over_tcp": True,
926
- "network": "tcp",
927
- "detour": base['tag']
928
- }
929
- all_base.append(socks_front)
930
-
931
-
932
- def make_full_singbox_config(domains, **kwargs):
933
- ua = hutils.flask.get_user_agent()
934
- base_config = json.loads(render_template('base_singbox_config.json.j2'))
935
- allphttp = [p for p in request.args.get("phttp", "").split(',') if p]
936
- allptls = [p for p in request.args.get("ptls", "").split(',') if p]
937
-
938
- allp = []
939
- for d in domains:
940
- base_config['dns']['rules'][0]['domain'].append(d.domain)
941
- for pinfo in get_all_validated_proxies(domains):
942
- sing = to_singbox(pinfo)
943
- if 'msg' not in sing:
944
- allp += sing
945
- base_config['outbounds'] += allp
946
-
947
- select = {
948
- "type": "selector",
949
- "tag": "Select",
950
- "outbounds": [p['tag'] for p in allp if 'shadowtls-out' not in p['tag']],
951
- "default": "Auto"
952
- }
953
- select['outbounds'].insert(0, "Auto")
954
- base_config['outbounds'].insert(0, select)
955
- smart = {
956
- "type": "urltest",
957
- "tag": "Auto",
958
- "outbounds": [p['tag'] for p in allp if 'shadowtls-out' not in p],
959
- "url": "https://www.gstatic.com/generate_204",
960
- "interval": "10m",
961
- "tolerance": 200
962
- }
963
- base_config['outbounds'].insert(1, smart)
964
- res = json.dumps(base_config, indent=4, cls=CustomEncoder)
965
- # if ua['is_hiddify']:
966
- # res = res[:-1]+',"experimental": {}}'
967
- return res
968
-
969
-
970
- def make_v2ray_configs(user, user_activate, domains, expire_days, ip_debug, db_domain, has_auto_cdn, asn, profile_title, **kwargs):
971
- res = []
972
-
973
- ua = hutils.flask.get_user_agent()
974
- if hconfig(ConfigEnum.show_usage_in_sublink):
975
-
976
- if not ua['is_hiddify']:
977
-
978
- fake_ip_for_sub_link = datetime.datetime.now().strftime(f"%H.%M--%Y.%m.%d.time:%H%M")
979
- # if ua['app'] == "Fair1":
980
- # res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{round(user.current_usage_GB,3)}/{user.usage_limit_GB}GB_Remain:{expire_days}days')
981
- # else:
982
-
983
- # res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{hutils.encode.url_encode(profile_title)}')
984
-
985
- name = '⏳' if user_activate else '✖'
986
- if user.usage_limit_GB < 1000:
987
- name += f'{round(user.current_usage_GB,3)}/{str(user.usage_limit_GB).replace(".0","")}GB'
988
- elif user.usage_limit_GB < 100000:
989
- name += f'{round(user.current_usage_GB/1000,3)}/{str(round(user.usage_limit_GB/1000,1)).replace(".0","")}TB'
990
- else:
991
- res.append("#No Usage Limit")
992
- if expire_days < 1000:
993
- name += " " + _(f'📅%(expire_days)s days', expire_days=expire_days)
994
- else:
995
- res.append("#No Time Limit")
996
-
997
- name = name.strip()
998
- if len(name) > 3:
999
- res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{hutils.encode.url_encode(name)}')
1000
-
1001
- if ua['is_browser']:
1002
- res.append(f'#Hiddify auto ip: {ip_debug}')
1003
-
1004
- if not user_activate:
1005
-
1006
- if hconfig(ConfigEnum.lang) == 'fa':
1007
- res.append('trojan://1@1.1.1.1#' + hutils.encode.url_encode('✖بسته شما به پایان رسید'))
1008
- else:
1009
- res.append('trojan://1@1.1.1.1#' + hutils.encode.url_encode('✖Package_Ended'))
1010
- return "\n".join(res)
1011
-
1012
- for pinfo in get_all_validated_proxies(domains):
1013
- link = to_link(pinfo)
1014
- if 'msg' not in link:
1015
- res.append(link)
1016
- return "\n".join(res)
1017
-
1018
-
1019
- def get_all_validated_proxies(domains):
1020
- allp = []
1021
- allphttp = [p for p in request.args.get("phttp", "").split(',') if p]
1022
- allptls = [p for p in request.args.get("ptls", "").split(',') if p]
1023
- added_ip = {}
1024
- configsmap = {}
1025
- proxeismap = {}
1026
- for d in domains:
1027
- if d.child_id not in configsmap:
1028
- configsmap[d.child_id] = get_hconfigs(d.child_id)
1029
- proxeismap[d.child_id] = all_proxies(d.child_id)
1030
- hconfigs = configsmap[d.child_id]
1031
-
1032
- ip = hutils.network.get_domain_ip(d.domain, version=4)
1033
- ip6 = hutils.network.get_domain_ip(d.domain, version=6)
1034
- ips = [x for x in [ip, ip6] if x is not None]
1035
- for type in proxeismap[d.child_id]:
1036
- noDomainProxies = False
1037
- if type.proto in [ProxyProto.ssh, ProxyProto.wireguard]:
1038
- noDomainProxies = True
1039
- if type.proto in [ProxyProto.ss] and type.transport not in [ProxyTransport.grpc, ProxyTransport.h2, ProxyTransport.WS, ProxyTransport.httpupgrade]:
1040
- noDomainProxies = True
1041
- options = []
1042
- key = f'{type.proto}{type.transport}{type.cdn}{type.l3}'
1043
- if key not in added_ip:
1044
- added_ip[key] = {}
1045
- if type.proto in [ProxyProto.ssh, ProxyProto.tuic, ProxyProto.hysteria2, ProxyProto.wireguard, ProxyProto.ss]:
1046
- if noDomainProxies and all([x in added_ip[key] for x in ips]):
1047
- continue
1048
-
1049
- for x in ips:
1050
- added_ip[key][x] = 1
1051
-
1052
- if type.proto in [ProxyProto.ssh, ProxyProto.wireguard, ProxyProto.ss]:
1053
- if d.mode == 'fake':
1054
- continue
1055
- if type.proto in [ProxyProto.ssh]:
1056
- options = [{'pport': hconfigs[ConfigEnum.ssh_server_port]}]
1057
- elif type.proto in [ProxyProto.wireguard]:
1058
- options = [{'pport': hconfigs[ConfigEnum.wireguard_port]}]
1059
- elif type.transport in [ProxyTransport.shadowsocks]:
1060
- options = [{'pport': hconfigs[ConfigEnum.shadowsocks2022_port]}]
1061
- elif type.proto in [ProxyProto.ss]:
1062
- options = [{'pport': 443}]
1063
- elif type.proto == ProxyProto.tuic:
1064
- options = [{'pport': hconfigs[ConfigEnum.tuic_port]}]
1065
- elif type.proto == ProxyProto.hysteria2:
1066
- options = [{'pport': hconfigs[ConfigEnum.hysteria_port]}]
1067
- else:
1068
- for t in (['http', 'tls'] if hconfigs[ConfigEnum.http_proxy_enable] else ['tls']):
1069
- for port in hconfigs[ConfigEnum.http_ports if t == 'http' else ConfigEnum.tls_ports].split(','):
1070
- phttp = port if t == 'http' else None
1071
- ptls = port if t == 'tls' else None
1072
- if phttp and len(allphttp) and phttp not in allphttp:
1073
- continue
1074
- if ptls and len(allptls) and ptls not in allptls:
1075
- continue
1076
- options.append({'phttp': phttp, 'ptls': ptls})
1077
-
1078
- for opt in options:
1079
- pinfo = make_proxy(hconfigs, type, d, **opt)
1080
- if 'msg' not in pinfo:
1081
- allp.append(pinfo)
1082
- return allp
1083
-
1084
-
1085
- class CustomEncoder(json.JSONEncoder):
1086
- def default(self, obj):
1087
- if isinstance(obj, IPv4Address) or isinstance(obj, IPv6Address):
1088
- return str(obj)
1089
- return super().default(obj)