Compare commits

..

5 Commits

Author SHA1 Message Date
Flowseal 222cabeee0 Clarify naming 2026-09-19 11:32:10 +03:00
Flowseal c2da669576 Bump metadata version 2026-09-19 11:27:50 +03:00
Flowseal 2c9a0b8a90 Bump version 2026-09-19 11:26:32 +03:00
Flowseal 87977962dc Disable SSL switch 2026-09-19 11:25:12 +03:00
Flowseal 5a61d8f782 Simplify passing None to --dc-ip 2026-09-18 17:30:35 +03:00
14 changed files with 88 additions and 44 deletions
+4 -3
View File
@@ -51,6 +51,7 @@ tg-ws-proxy [--port PORT] [--host HOST] [--dc-ip DC:IP ...] [-v]
| `--no-cfproxy` | `false` | Disable [Cloudflare proxying](./CfProxy.md) attempts | | `--no-cfproxy` | `false` | Disable [Cloudflare proxying](./CfProxy.md) attempts |
| `--cfproxy-domain` | | Specify your own domain for Cloudflare proxying [Learn more](./CfProxy.md). Can be specified multiple times. | | `--cfproxy-domain` | | Specify your own domain for Cloudflare proxying [Learn more](./CfProxy.md). Can be specified multiple times. |
| `--cfproxy-worker-domain` | | Cloudflare Worker domain [Learn more](./CfWorker.md). Can be specified multiple times. | | `--cfproxy-worker-domain` | | Cloudflare Worker domain [Learn more](./CfWorker.md). Can be specified multiple times. |
| `--no-secure` | `false` | Use 80 port for CF-proxy and CF-worker connections |
| `--fake-tls-domain` | | Enable Fake TLS masquerading (ee-secret) with specified SNI domain | | `--fake-tls-domain` | | Enable Fake TLS masquerading (ee-secret) with specified SNI domain |
| `--proxy-protocol` | disabled | Accept HAProxy PROXY protocol v1 (for use behind nginx/haproxy with `proxy_protocol on`) | | `--proxy-protocol` | disabled | Accept HAProxy PROXY protocol v1 (for use behind nginx/haproxy with `proxy_protocol on`) |
| `--buf-kb` | `256` | Buffer size in KB | | `--buf-kb` | `256` | Buffer size in KB |
@@ -64,13 +65,13 @@ tg-ws-proxy [--port PORT] [--host HOST] [--dc-ip DC:IP ...] [-v]
```bash ```bash
# Standard startup # Standard startup
tg-ws-proxy tg-ws-proxy --secret 00112233445566778899aabbccddeeff
# Different port and additional DCs # Different port and additional DCs
tg-ws-proxy --port 9050 --dc-ip 1:149.154.175.205 --dc-ip 2:149.154.167.220 tg-ws-proxy --port 9050 --dc-ip 1:149.154.175.205 --dc-ip 2:149.154.167.220
# With verbose logging # With verbose logging, without direct connections to DCs
tg-ws-proxy -v tg-ws-proxy -v --dc-ip
# Fake TLS masquerading (ee-secret) # Fake TLS masquerading (ee-secret)
tg-ws-proxy --fake-tls-domain example.com tg-ws-proxy --fake-tls-domain example.com
+4 -3
View File
@@ -51,6 +51,7 @@ tg-ws-proxy [--port PORT] [--host HOST] [--dc-ip DC:IP ...] [-v]
| `--no-cfproxy` | `false` | Отключить попытку [проксирования через Cloudflare](./CfProxy.md) | | `--no-cfproxy` | `false` | Отключить попытку [проксирования через Cloudflare](./CfProxy.md) |
| `--cfproxy-domain` | | Указать свой домен для проксирования через Cloudflare [Подробнее](./CfProxy.md). Можно указать несколько через повторение аргумента. | | `--cfproxy-domain` | | Указать свой домен для проксирования через Cloudflare [Подробнее](./CfProxy.md). Можно указать несколько через повторение аргумента. |
| `--cfproxy-worker-domain` | | Домен Cloudflare Worker [Подробнее](./CfWorker.md). Можно указать несколько через повторение аргумента. | | `--cfproxy-worker-domain` | | Домен Cloudflare Worker [Подробнее](./CfWorker.md). Можно указать несколько через повторение аргумента. |
| `--no-secure` | `false` | Принудительно использует 80 порт для CF-proxy и CF-worker |
| `--fake-tls-domain` | | Включить маскировку Fake TLS (ee-secret) с указанным SNI-доменом | | `--fake-tls-domain` | | Включить маскировку Fake TLS (ee-secret) с указанным SNI-доменом |
| `--proxy-protocol` | выкл. | Принимать HAProxy PROXY protocol v1 (для работы за nginx/haproxy с `proxy_protocol on`) | | `--proxy-protocol` | выкл. | Принимать HAProxy PROXY protocol v1 (для работы за nginx/haproxy с `proxy_protocol on`) |
| `--buf-kb` | `256` | Размер буфера в КБ | | `--buf-kb` | `256` | Размер буфера в КБ |
@@ -64,13 +65,13 @@ tg-ws-proxy [--port PORT] [--host HOST] [--dc-ip DC:IP ...] [-v]
```bash ```bash
# Стандартный запуск # Стандартный запуск
tg-ws-proxy tg-ws-proxy --secret 00112233445566778899aabbccddeeff
# Другой порт и дополнительные DC # Другой порт и дополнительные DC
tg-ws-proxy --port 9050 --dc-ip 1:149.154.175.205 --dc-ip 2:149.154.167.220 tg-ws-proxy --port 9050 --dc-ip 1:149.154.175.205 --dc-ip 2:149.154.167.220
# С подробным логированием # С подробным логированием, без прямого подключения к DC
tg-ws-proxy -v tg-ws-proxy -v --dc-ip
# Fake TLS маскировка (ee-secret) # Fake TLS маскировка (ee-secret)
tg-ws-proxy --fake-tls-domain example.com tg-ws-proxy --fake-tls-domain example.com
+4 -4
View File
@@ -4,8 +4,8 @@
# http://msdn.microsoft.com/en-us/library/ms646997.aspx # http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo( VSVersionInfo(
ffi=FixedFileInfo( ffi=FixedFileInfo(
filevers=(1, 10, 0, 0), filevers=(1, 10, 3, 0),
prodvers=(1, 10, 0, 0), prodvers=(1, 10, 3, 0),
mask=0x3f, mask=0x3f,
flags=0x0, flags=0x0,
OS=0x40004, OS=0x40004,
@@ -21,12 +21,12 @@ VSVersionInfo(
[ [
StringStruct(u'CompanyName', u'Flowseal'), StringStruct(u'CompanyName', u'Flowseal'),
StringStruct(u'FileDescription', u'Telegram Desktop WebSocket Bridge Proxy'), StringStruct(u'FileDescription', u'Telegram Desktop WebSocket Bridge Proxy'),
StringStruct(u'FileVersion', u'1.10.0.0'), StringStruct(u'FileVersion', u'1.10.3.0'),
StringStruct(u'InternalName', u'TgWsProxy'), StringStruct(u'InternalName', u'TgWsProxy'),
StringStruct(u'LegalCopyright', u'Copyright (c) Flowseal. MIT License.'), StringStruct(u'LegalCopyright', u'Copyright (c) Flowseal. MIT License.'),
StringStruct(u'OriginalFilename', u'TgWsProxy.exe'), StringStruct(u'OriginalFilename', u'TgWsProxy.exe'),
StringStruct(u'ProductName', u'TG WS Proxy'), StringStruct(u'ProductName', u'TG WS Proxy'),
StringStruct(u'ProductVersion', u'1.10.0.0'), StringStruct(u'ProductVersion', u'1.10.3.0'),
] ]
) )
] ]
+1 -1
View File
@@ -1,6 +1,6 @@
from .config import parse_dc_ip_list, proxy_config, coerce_domain_list from .config import parse_dc_ip_list, proxy_config, coerce_domain_list
from .utils import get_link_host, build_github_opener from .utils import get_link_host, build_github_opener
__version__ = "1.10.2" __version__ = "1.10.3"
__all__ = ["__version__", "get_link_host", "proxy_config", "parse_dc_ip_list", "build_github_opener", "coerce_domain_list"] __all__ = ["__version__", "get_link_host", "proxy_config", "parse_dc_ip_list", "build_github_opener", "coerce_domain_list"]
+4 -2
View File
@@ -201,7 +201,8 @@ async def _cfproxy_worker_fallback(reader, writer, relay_init, label,
try: try:
ws = await RawWebSocket.connect(worker_domain, worker_domain, ws = await RawWebSocket.connect(worker_domain, worker_domain,
timeout=10.0, path=path) timeout=10.0, path=path,
secure=not proxy_config.disable_secure)
break break
except Exception as exc: except Exception as exc:
cf_worker_pool.report_failure(worker_domain, exc) cf_worker_pool.report_failure(worker_domain, exc)
@@ -234,7 +235,8 @@ async def _cfproxy_fallback(reader, writer, relay_init, label,
for base_domain in balancer.get_domains_for_dc(dc): for base_domain in balancer.get_domains_for_dc(dc):
domain = f'kws{dc}.{base_domain}' domain = f'kws{dc}.{base_domain}'
try: try:
ws = await RawWebSocket.connect(domain, domain, timeout=10.0) ws = await RawWebSocket.connect(domain, domain, timeout=10.0,
secure=not proxy_config.disable_secure)
chosen_domain = base_domain chosen_domain = base_domain
break break
except Exception as exc: except Exception as exc:
+1
View File
@@ -70,6 +70,7 @@ class ProxyConfig:
fallback_cfproxy: bool = True fallback_cfproxy: bool = True
cfproxy_user_domains: List[str] = field(default_factory=list) cfproxy_user_domains: List[str] = field(default_factory=list)
cfproxy_worker_domains: List[str] = field(default_factory=list) cfproxy_worker_domains: List[str] = field(default_factory=list)
disable_secure: bool = False
fake_tls_domain: str = '' fake_tls_domain: str = ''
proxy_protocol: bool = False proxy_protocol: bool = False
force_test_dc: bool = False force_test_dc: bool = False
+2 -1
View File
@@ -289,7 +289,8 @@ class _CfWorkerPool:
for worker_domain in self.available_domains(worker_domains): for worker_domain in self.available_domains(worker_domains):
try: try:
ws = await RawWebSocket.connect( ws = await RawWebSocket.connect(
worker_domain, worker_domain, timeout=8, path=path) worker_domain, worker_domain, timeout=8, path=path,
secure=not proxy_config.disable_secure)
return ws, worker_domain return ws, worker_domain
except Exception as exc: except Exception as exc:
self.report_failure(worker_domain, exc) self.report_failure(worker_domain, exc)
+17 -7
View File
@@ -22,9 +22,8 @@ _st_H = struct.Struct('>H')
_st_Q = struct.Struct('>Q') _st_Q = struct.Struct('>Q')
_ssl_ctx = ssl.create_default_context() _ssl_ctx = ssl.create_default_context()
_ssl_ctx.check_hostname = False _ssl_ctx_fronting = ssl.create_default_context()
_ssl_ctx.verify_mode = ssl.CERT_NONE _ssl_ctx_fronting.check_hostname = False
class WsHandshakeError(Exception): class WsHandshakeError(Exception):
def __init__(self, status_code: int, status_line: str, def __init__(self, status_code: int, status_line: str,
@@ -87,14 +86,25 @@ class RawWebSocket:
@staticmethod @staticmethod
async def connect(host: str, domain: str, timeout: float = 10.0, async def connect(host: str, domain: str, timeout: float = 10.0,
path: str = '/apiws', *, path: str = '/apiws', *,
sni: Optional[str] = None) -> 'RawWebSocket': sni: Optional[str] = None, secure = True) -> 'RawWebSocket':
ssl = _ssl_ctx_fronting if sni else _ssl_ctx
print(f"Connecting to {host} with secure={secure}, sni={sni}, path={path}")
if sni is None: if sni is None:
sni = domain sni = domain
reader, writer = await asyncio.wait_for( reader, writer = await asyncio.wait_for(
asyncio.open_connection(host, 443, ssl=_ssl_ctx, (
server_hostname=sni), asyncio.open_connection(
timeout=min(timeout, 10)) host, 443,
ssl=ssl,
server_hostname=sni,
)
if secure
else asyncio.open_connection(host, 80)
),
timeout=min(timeout, 10),
)
set_sock_opts(writer.transport, proxy_config.buffer_size) set_sock_opts(writer.transport, proxy_config.buffer_size)
+13 -3
View File
@@ -531,6 +531,8 @@ async def _run(stop_event: Optional[asyncio.Event] = None):
if proxy_config.cfproxy_worker_domains: if proxy_config.cfproxy_worker_domains:
log.info(" CF worker: enabled (%s)", log.info(" CF worker: enabled (%s)",
", ".join(proxy_config.cfproxy_worker_domains)) ", ".join(proxy_config.cfproxy_worker_domains))
if proxy_config.disable_secure:
log.info(" No secure: enabled (port 80 for CF proxy/worker)")
log.info("=" * 60) log.info("=" * 60)
log.info(" Connect:") log.info(" Connect:")
if ftls: if ftls:
@@ -647,7 +649,7 @@ def main():
ap.add_argument('--secret', type=str, default=None, ap.add_argument('--secret', type=str, default=None,
help='MTProto proxy secret (32 hex chars). ' help='MTProto proxy secret (32 hex chars). '
'Auto-generated if not provided.') 'Auto-generated if not provided.')
ap.add_argument('--dc-ip', metavar='DC:IP', action='append', ap.add_argument('--dc-ip', metavar='DC:IP', nargs='?', action='append', const=None,
help='Target IP for a DC, e.g. --dc-ip 2:149.154.167.220') help='Target IP for a DC, e.g. --dc-ip 2:149.154.167.220')
ap.add_argument('-v', '--verbose', action='store_true', ap.add_argument('-v', '--verbose', action='store_true',
help='Debug logging') help='Debug logging')
@@ -673,6 +675,8 @@ def main():
'repeatable for multiple domains)') 'repeatable for multiple domains)')
ap.add_argument('--no-cfproxy', action='store_true', ap.add_argument('--no-cfproxy', action='store_true',
help='Disable Cloudflare proxy fallback') help='Disable Cloudflare proxy fallback')
ap.add_argument('--no-secure', action='store_true',
help='Use 80 port for CF-proxy and CF-worker connections')
ap.add_argument('--fake-tls-domain', type=str, default='', ap.add_argument('--fake-tls-domain', type=str, default='',
metavar='DOMAIN', metavar='DOMAIN',
help='Enable Fake TLS (ee-secret) masking with the given ' help='Enable Fake TLS (ee-secret) masking with the given '
@@ -687,8 +691,13 @@ def main():
'(for use behind nginx/haproxy with proxy_protocol on)') '(for use behind nginx/haproxy with proxy_protocol on)')
args = ap.parse_args() args = ap.parse_args()
if not args.dc_ip: if args.dc_ip is None:
args.dc_ip = ['2:149.154.167.220', '4:149.154.167.220'] args.dc_ip = [
'2:149.154.167.220',
'4:149.154.167.220',
]
elif None in args.dc_ip:
args.dc_ip = []
try: try:
dc_redirects = parse_dc_ip_list(args.dc_ip) dc_redirects = parse_dc_ip_list(args.dc_ip)
@@ -719,6 +728,7 @@ def main():
proxy_config.fallback_cfproxy = not args.no_cfproxy proxy_config.fallback_cfproxy = not args.no_cfproxy
proxy_config.cfproxy_user_domains = coerce_domain_list(args.cfproxy_domain) proxy_config.cfproxy_user_domains = coerce_domain_list(args.cfproxy_domain)
proxy_config.cfproxy_worker_domains = coerce_domain_list(args.cfproxy_worker_domain) proxy_config.cfproxy_worker_domains = coerce_domain_list(args.cfproxy_worker_domain)
proxy_config.disable_secure = args.no_secure
proxy_config.fake_tls_domain = args.fake_tls_domain.strip() proxy_config.fake_tls_domain = args.fake_tls_domain.strip()
proxy_config.proxy_protocol = args.proxy_protocol proxy_config.proxy_protocol = args.proxy_protocol
proxy_config.force_test_dc = args.force_test_dc proxy_config.force_test_dc = args.force_test_dc
+32 -20
View File
@@ -44,19 +44,21 @@ _CFWORKER_TEST_DST = {
} }
def _run_connectivity_test(cases: list) -> dict: def _run_connectivity_test(cases: list, *, secure: bool = True) -> dict:
import base64 import base64
from contextlib import nullcontext
import ssl import ssl
import socket as _socket import socket as _socket
ctx = ssl.create_default_context() ctx = ssl.create_default_context() if secure else None
ctx.check_hostname = False port = 443 if secure else 80
ctx.verify_mode = ssl.CERT_NONE
results = {} results = {}
for dc, connect_host, sni_host, req_host, path in cases: for dc, connect_host, sni_host, req_host, path in cases:
try: try:
with _socket.create_connection((connect_host, 443), timeout=5) as raw: with _socket.create_connection((connect_host, port), timeout=5) as raw:
with ctx.wrap_socket(raw, server_hostname=sni_host) as ssock: connection = (ctx.wrap_socket(raw, server_hostname=sni_host)
if secure else nullcontext(raw))
with connection as ssock:
ws_key = base64.b64encode(os.urandom(16)).decode() ws_key = base64.b64encode(os.urandom(16)).decode()
req = ( req = (
f"GET {path} HTTP/1.1\r\n" f"GET {path} HTTP/1.1\r\n"
@@ -91,36 +93,36 @@ def _run_connectivity_test(cases: list) -> dict:
return results return results
def _run_cfproxy_connectivity_test(domain: str) -> dict: def _run_cfproxy_connectivity_test(domain: str, *, secure: bool = True) -> dict:
cases = [] cases = []
for dc in _CFPROXY_TEST_DCS: for dc in _CFPROXY_TEST_DCS:
host = f"kws{dc}.{domain}" host = f"kws{dc}.{domain}"
cases.append((dc, host, host, host, "/apiws")) cases.append((dc, host, host, host, "/apiws"))
return _run_connectivity_test(cases) return _run_connectivity_test(cases, secure=secure)
def _run_cfworker_connectivity_test(domain: str) -> dict: def _run_cfworker_connectivity_test(domain: str, *, secure: bool = True) -> dict:
cases = [] cases = []
for dc in _CFPROXY_TEST_DCS: for dc in _CFPROXY_TEST_DCS:
dst = _CFWORKER_TEST_DST[dc] dst = _CFWORKER_TEST_DST[dc]
path = f"/apiws?dst={dst}&dc={dc}&media=0" path = f"/apiws?dst={dst}&dc={dc}&media=0"
cases.append((dc, domain, domain, domain, path)) cases.append((dc, domain, domain, domain, path))
return _run_connectivity_test(cases) return _run_connectivity_test(cases, secure=secure)
def _run_cfproxy_multi_test(domains: list) -> dict: def _run_cfproxy_multi_test(domains: list, *, secure: bool = True) -> dict:
return {domain: _run_cfproxy_connectivity_test(domain) for domain in domains} return {domain: _run_cfproxy_connectivity_test(domain, secure=secure) for domain in domains}
def _run_cfworker_multi_test(domains: list) -> dict: def _run_cfworker_multi_test(domains: list, *, secure: bool = True) -> dict:
return {domain: _run_cfworker_connectivity_test(domain) for domain in domains} return {domain: _run_cfworker_connectivity_test(domain, secure=secure) for domain in domains}
def _run_cfproxy_auto_test(domains: list) -> tuple: def _run_cfproxy_auto_test(domains: list, *, secure: bool = True) -> tuple:
merged: dict = {} merged: dict = {}
best_domain = None best_domain = None
for domain in reversed(domains): for domain in reversed(domains):
res = _run_cfproxy_connectivity_test(domain) res = _run_cfproxy_connectivity_test(domain, secure=secure)
if all(v is True for v in res.values()): if all(v is True for v in res.values()):
return domain, res return domain, res
for dc, v in res.items(): for dc, v in res.items():
@@ -350,6 +352,7 @@ class TrayConfigFormWidgets:
secret_var: Any secret_var: Any
dc_textbox: Any dc_textbox: Any
verbose_var: Any verbose_var: Any
no_secure_var: Any
adv_entries: List[Any] adv_entries: List[Any]
adv_keys: Tuple[str, ...] adv_keys: Tuple[str, ...]
autostart_var: Optional[Any] autostart_var: Optional[Any]
@@ -536,6 +539,7 @@ def install_tray_config_form(
_cf_test_btn = [None] _cf_test_btn = [None]
def _on_cf_test(): def _on_cf_test():
secure = not no_secure_var.get()
user_domains = ( user_domains = (
coerce_domain_list(cfproxy_user_domain_var.get()) coerce_domain_list(cfproxy_user_domain_var.get())
if cf_custom_cb_var.get() else [] if cf_custom_cb_var.get() else []
@@ -547,7 +551,7 @@ def install_tray_config_form(
if user_domains: if user_domains:
def _worker(): def _worker():
try: try:
per = _run_cfproxy_multi_test(user_domains) per = _run_cfproxy_multi_test(user_domains, secure=secure)
if btn: if btn:
btn.after( btn.after(
0, 0,
@@ -564,7 +568,7 @@ def install_tray_config_form(
else: else:
def _worker_auto(): def _worker_auto():
try: try:
ok_domain, res = _run_cfproxy_auto_test(balancer.domains) ok_domain, res = _run_cfproxy_auto_test(balancer.domains, secure=secure)
if btn: if btn:
btn.after( btn.after(
0, 0,
@@ -672,6 +676,7 @@ def install_tray_config_form(
btn.configure(state="normal" if enabled else "disabled") btn.configure(state="normal" if enabled else "disabled")
def _on_cfworker_test(): def _on_cfworker_test():
secure = not no_secure_var.get()
domains = coerce_domain_list(cfproxy_worker_domain_var.get()) domains = coerce_domain_list(cfproxy_worker_domain_var.get())
btn = _cfworker_test_btn[0] btn = _cfworker_test_btn[0]
if not cfproxy_worker_enabled_var.get() or not domains or btn is None: if not cfproxy_worker_enabled_var.get() or not domains or btn is None:
@@ -681,7 +686,7 @@ def install_tray_config_form(
def _worker(): def _worker():
try: try:
per = _run_cfworker_multi_test(domains) per = _run_cfworker_multi_test(domains, secure=secure)
btn.after( btn.after(
0, 0,
lambda: _show_multi_connectivity_results( lambda: _show_multi_connectivity_results(
@@ -730,6 +735,11 @@ def install_tray_config_form(
verbose_cb.pack(anchor="w", pady=(0, 6)) verbose_cb.pack(anchor="w", pady=(0, 6))
attach_ctk_tooltip(verbose_cb, t("tip.verbose")) attach_ctk_tooltip(verbose_cb, t("tip.verbose"))
no_secure_var = ctk.BooleanVar(value=cfg.get("no_secure", False))
no_secure_cb = _checkbox(ctk, log_inner, theme, t("label.no_secure"), no_secure_var)
no_secure_cb.pack(anchor="w", pady=(0, 6))
attach_ctk_tooltip(no_secure_cb, t("tip.no_secure"))
adv_frame = ctk.CTkFrame(log_inner, fg_color="transparent") adv_frame = ctk.CTkFrame(log_inner, fg_color="transparent")
adv_frame.pack(fill="x") adv_frame.pack(fill="x")
@@ -823,7 +833,7 @@ def install_tray_config_form(
return TrayConfigFormWidgets( return TrayConfigFormWidgets(
host_var=host_var, port_var=port_var, secret_var=secret_var, host_var=host_var, port_var=port_var, secret_var=secret_var,
dc_textbox=dc_textbox, verbose_var=verbose_var, dc_textbox=dc_textbox, verbose_var=verbose_var, no_secure_var=no_secure_var,
adv_entries=adv_entries, adv_keys=adv_keys, adv_entries=adv_entries, adv_keys=adv_keys,
autostart_var=autostart_var, check_updates_var=check_updates_var, autostart_var=autostart_var, check_updates_var=check_updates_var,
cfproxy_var=cfproxy_var, cfproxy_var=cfproxy_var,
@@ -935,6 +945,8 @@ def validate_config_form(
new_cfg["appearance"] = _appearance_to_cfg(widgets.appearance_var.get()) new_cfg["appearance"] = _appearance_to_cfg(widgets.appearance_var.get())
if widgets.language_var is not None: if widgets.language_var is not None:
new_cfg["language"] = language_from_label(widgets.language_var.get()).value new_cfg["language"] = language_from_label(widgets.language_var.get()).value
if widgets.no_secure_var is not None:
new_cfg["no_secure"] = bool(widgets.no_secure_var.get())
return new_cfg return new_cfg
+2
View File
@@ -32,6 +32,7 @@
"label.cf_custom_domain": "Custom domain", "label.cf_custom_domain": "Custom domain",
"label.cfworker_domains": "Cloudflare Worker domains (comma-separated)", "label.cfworker_domains": "Cloudflare Worker domains (comma-separated)",
"label.verbose": "Verbose logging", "label.verbose": "Verbose logging",
"label.no_secure": "Disable TLS for CF-proxy and CF-worker",
"label.buf_kb": "Buffer, KB (default 256)", "label.buf_kb": "Buffer, KB (default 256)",
"label.pool_size": "WebSocket session pool (default 4)", "label.pool_size": "WebSocket session pool (default 4)",
"label.log_max_mb": "Max log size, MB (default 5)", "label.log_max_mb": "Max log size, MB (default 5)",
@@ -44,6 +45,7 @@
"tip.secret": "Secret key for client authorization", "tip.secret": "Secret key for client authorization",
"tip.dc": "Mapping of Telegram data center (DC) number to web.telegram.org dc server IP.\nEach line: «number:IP», e.g. 4:149.154.167.220. The proxy routes traffic to Telegram servers using these rules\n\nIf connection fails then fallbacks are used", "tip.dc": "Mapping of Telegram data center (DC) number to web.telegram.org dc server IP.\nEach line: «number:IP», e.g. 4:149.154.167.220. The proxy routes traffic to Telegram servers using these rules\n\nIf connection fails then fallbacks are used",
"tip.verbose": "When enabled, more details are written to the log file — useful for troubleshooting", "tip.verbose": "When enabled, more details are written to the log file — useful for troubleshooting",
"tip.no_secure": "When enabled, the proxy will use port 80 for CF-proxy and CF-worker connections",
"tip.buf_kb": "Receive/send buffer size in kilobytes.\nA larger value allocates more memory per socket", "tip.buf_kb": "Receive/send buffer size in kilobytes.\nA larger value allocates more memory per socket",
"tip.pool": "How many parallel WebSocket sessions per data center can be kept open.\nIncreasing may help under high load", "tip.pool": "How many parallel WebSocket sessions per data center can be kept open.\nIncreasing may help under high load",
"tip.log_mb": "Maximum log file size; the file is overwritten when the limit is reached", "tip.log_mb": "Maximum log file size; the file is overwritten when the limit is reached",
+2
View File
@@ -32,6 +32,7 @@
"label.cf_custom_domain": "Свой домен", "label.cf_custom_domain": "Свой домен",
"label.cfworker_domains": "Cloudflare Worker домены (через запятую)", "label.cfworker_domains": "Cloudflare Worker домены (через запятую)",
"label.verbose": "Подробное логирование (verbose)", "label.verbose": "Подробное логирование (verbose)",
"label.no_secure": "Выключиь TLS для CF-прокси и CF-worker",
"label.buf_kb": "Буфер, КБ (по умолчанию 256)", "label.buf_kb": "Буфер, КБ (по умолчанию 256)",
"label.pool_size": "Пул WebSocket-сессий (по умолчанию 4)", "label.pool_size": "Пул WebSocket-сессий (по умолчанию 4)",
"label.log_max_mb": "Макс. размер лога, МБ (по умолчанию 5)", "label.log_max_mb": "Макс. размер лога, МБ (по умолчанию 5)",
@@ -44,6 +45,7 @@
"tip.secret": "Секретный ключ для авторизации клиентов", "tip.secret": "Секретный ключ для авторизации клиентов",
"tip.dc": "Соответствие номера датацентра Telegram (DC) и IP-адреса сервера.\nКаждая строка: «номер:IP», например 4:149.154.167.220. Прокси по этим правилам направляет трафик к нужным серверам Telegram\n\nЕсли у вас не работают медиа и работает CF-прокси, то попробуйте убрать строку 2:149.154.167.220", "tip.dc": "Соответствие номера датацентра Telegram (DC) и IP-адреса сервера.\nКаждая строка: «номер:IP», например 4:149.154.167.220. Прокси по этим правилам направляет трафик к нужным серверам Telegram\n\nЕсли у вас не работают медиа и работает CF-прокси, то попробуйте убрать строку 2:149.154.167.220",
"tip.verbose": "Если включено, в файл логов пишется больше подробностей — необходимо при поиске неполадок", "tip.verbose": "Если включено, в файл логов пишется больше подробностей — необходимо при поиске неполадок",
"tip.no_secure": "Если включено, прокси будет использовать 80 порт для CF-прокси и CF-worker подключений",
"tip.buf_kb": "Размер буфера приёма/передачи в килобайтах.\nБольше значение — больше выделение памяти на сокет", "tip.buf_kb": "Размер буфера приёма/передачи в килобайтах.\nБольше значение — больше выделение памяти на сокет",
"tip.pool": "Сколько параллельных WebSocket-сессий к одному датацентру можно держать.\nУвеличение может помочь при высокой нагрузке", "tip.pool": "Сколько параллельных WebSocket-сессий к одному датацентру можно держать.\nУвеличение может помочь при высокой нагрузке",
"tip.log_mb": "Максимальный размер файла лога; при достижении лимита файл перезаписывается", "tip.log_mb": "Максимальный размер файла лога; при достижении лимита файл перезаписывается",
+1
View File
@@ -25,6 +25,7 @@ _TRAY_DEFAULTS_COMMON: Dict[str, Any] = {
"cfproxy_worker_enabled": False, "cfproxy_worker_enabled": False,
"cfproxy_worker_domain": [], "cfproxy_worker_domain": [],
"force_test_dc": False, "force_test_dc": False,
"no_secure": False,
} }
+1
View File
@@ -374,6 +374,7 @@ def apply_proxy_config(cfg: dict) -> bool:
else [] else []
) )
pc.force_test_dc = cfg.get("force_test_dc", DEFAULT_CONFIG["force_test_dc"]) pc.force_test_dc = cfg.get("force_test_dc", DEFAULT_CONFIG["force_test_dc"])
pc.disable_secure = cfg.get("no_secure", DEFAULT_CONFIG["no_secure"])
return True return True