From 796c15e323c825ed0f8517ef6a3e38f05f94d763 Mon Sep 17 00:00:00 2001 From: Seyed Mahdi <39972836+SeyedHashtag@users.noreply.github.com> Date: Mon, 26 May 2025 18:53:17 +0330 Subject: [PATCH 01/12] Update singbox.json fix: Changed DNS-over-HTTPS (DoH) implementation to standard UDP DNS resolution to prevent potential service disruptions in regions where HTTPS DNS domains may be blocked or restricted. --- core/scripts/normalsub/singbox.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/scripts/normalsub/singbox.json b/core/scripts/normalsub/singbox.json index 84fb19d..a9851ba 100644 --- a/core/scripts/normalsub/singbox.json +++ b/core/scripts/normalsub/singbox.json @@ -12,7 +12,7 @@ }, { "tag": "localDns", - "address": "https://223.5.5.5/dns-query", + "address": "udp://8.8.8.8", "detour": "direct" } ], From 699069adb61500717ef74b3062ee3cee89277533 Mon Sep 17 00:00:00 2001 From: Seyed Mahdi <39972836+SeyedHashtag@users.noreply.github.com> Date: Mon, 26 May 2025 22:43:02 +0330 Subject: [PATCH 02/12] fix: update DNS configuration and logging level in singbox.json --- core/scripts/normalsub/singbox.json | 34 ++++++++++------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/core/scripts/normalsub/singbox.json b/core/scripts/normalsub/singbox.json index a9851ba..8a3e050 100644 --- a/core/scripts/normalsub/singbox.json +++ b/core/scripts/normalsub/singbox.json @@ -1,29 +1,25 @@ { "log": { - "level": "info", + "level": "warn", "timestamp": true }, "dns": { "servers": [ { "tag": "proxyDns", - "address": "tls://8.8.8.8", + "address": "https://1.1.1.1/dns-query", "detour": "Proxy" }, { "tag": "localDns", - "address": "udp://8.8.8.8", + "address": "local", "detour": "direct" } ], "rules": [ - { - "outbound": "any", - "server": "localDns" - }, { "rule_set": "geosite-ir", - "server": "proxyDns" + "server": "localDns" }, { "clash_mode": "direct", @@ -34,19 +30,20 @@ "server": "proxyDns" } ], - "final": "localDns", - "strategy": "ipv4_only" + "final": "proxyDns", + "strategy": "prefer_ipv4" }, "inbounds": [ { "tag": "tun-in", "type": "tun", "address": [ - "172.19.0.0/30" + "172.19.0.0/30", + "fdfe:dcba:9876::1/126" ], "mtu": 9000, "auto_route": true, - "strict_route": true, + "strict_route": false, "stack": "system", "platform": { "http_proxy": { @@ -110,16 +107,7 @@ "action": "sniff" }, { - "type": "logical", - "mode": "or", - "rules": [ - { - "port": 53 - }, - { - "protocol": "dns" - } - ], + "protocol": "dns", "action": "hijack-dns" }, { @@ -169,4 +157,4 @@ } ] } -} +} \ No newline at end of file From a532f7969fb1f49105facec60bba469d78771d47 Mon Sep 17 00:00:00 2001 From: Seyed Mahdi <39972836+SeyedHashtag@users.noreply.github.com> Date: Tue, 27 May 2025 15:00:14 +0330 Subject: [PATCH 03/12] refactor: reorganize DNS configuration and enhance routing rules in singbox.json --- core/scripts/normalsub/singbox.json | 203 ++++++++++++++-------------- 1 file changed, 101 insertions(+), 102 deletions(-) diff --git a/core/scripts/normalsub/singbox.json b/core/scripts/normalsub/singbox.json index 8a3e050..2bb7ea3 100644 --- a/core/scripts/normalsub/singbox.json +++ b/core/scripts/normalsub/singbox.json @@ -1,159 +1,158 @@ { - "log": { - "level": "warn", - "timestamp": true - }, "dns": { - "servers": [ - { - "tag": "proxyDns", - "address": "https://1.1.1.1/dns-query", - "detour": "Proxy" - }, - { - "tag": "localDns", - "address": "local", - "detour": "direct" - } - ], + "final": "local-dns", "rules": [ { - "rule_set": "geosite-ir", - "server": "localDns" + "action": "route", + "clash_mode": "Global", + "server": "proxy-dns", + "source_ip_cidr": [ + "172.19.0.0/30", + "fdfe:dcba:9876::1/126" + ] }, { - "clash_mode": "direct", - "server": "localDns" - }, - { - "clash_mode": "global", - "server": "proxyDns" + "action": "route", + "server": "proxy-dns", + "source_ip_cidr": [ + "172.19.0.0/30", + "fdfe:dcba:9876::1/126" + ] + } + ], + "servers": [ + { + "address": "https://1.1.1.1/dns-query", + "address_resolver": "local-dns", + "detour": "proxy", + "tag": "proxy-dns" + }, + { + "address": "local", + "detour": "direct", + "tag": "local-dns" } ], - "final": "proxyDns", "strategy": "prefer_ipv4" }, "inbounds": [ { - "tag": "tun-in", - "type": "tun", "address": [ - "172.19.0.0/30", + "172.19.0.1/30", "fdfe:dcba:9876::1/126" ], - "mtu": 9000, "auto_route": true, - "strict_route": false, - "stack": "system", + "endpoint_independent_nat": false, + "mtu": 9000, "platform": { "http_proxy": { "enabled": true, "server": "127.0.0.1", "server_port": 2080 } - } + }, + "stack": "system", + "strict_route": false, + "type": "tun" }, { - "tag": "mixed-in", - "type": "mixed", "listen": "127.0.0.1", - "listen_port": 2080 + "listen_port": 2080, + "type": "mixed", + "users": [] } ], + "log": { + "level": "warn", + "timestamp": true + }, "outbounds": [ { - "tag": "Proxy", - "type": "selector", "outbounds": [ "auto", "direct" - ] - }, - { - "tag": "Global", - "type": "selector", - "outbounds": [ - "direct" - ] - }, - { - "tag": "auto", - "type": "urltest", - "outbounds": [ - "Proxy" ], - "url": "http://www.gstatic.com/generate_204", + "tag": "proxy", + "type": "selector" + }, + { "interval": "10m", - "tolerance": 50 + "outbounds": [], + "tag": "auto", + "tolerance": 50, + "type": "urltest", + "url": "http://www.gstatic.com/generate_204" }, { - "type": "direct", - "tag": "direct" - }, - { - "type": "direct", - "tag": "local" + "tag": "direct", + "type": "direct" } ], "route": { "auto_detect_interface": true, - "final": "Proxy", + "final": "proxy", + "rule_set": [ + { + "download_detour": "direct", + "format": "binary", + "tag": "geosite-ads", + "type": "remote", + "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/category-ads-all.srs" + }, + { + "download_detour": "direct", + "format": "binary", + "tag": "geosite-private", + "type": "remote", + "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/private.srs" + }, + { + "download_detour": "direct", + "format": "binary", + "tag": "geosite-ir", + "type": "remote", + "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/category-ir.srs" + }, + { + "download_detour": "direct", + "format": "binary", + "tag": "geoip-ir", + "type": "remote", + "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geoip/ir.srs" + } + ], "rules": [ { - "inbound": [ - "tun-in", - "mixed-in" - ], "action": "sniff" }, { - "protocol": "dns", - "action": "hijack-dns" - }, - { - "rule_set": "geosite-category-ads-all", - "action": "reject" - }, - { - "rule_set": "geosite-category-ads-all", - "outbound": "Proxy" - }, - { - "ip_is_private": true, + "action": "route", + "clash_mode": "Direct", "outbound": "direct" }, { "action": "route", - "rule_set": "geosite-ir", - "outbound": "direct" + "clash_mode": "Global", + "outbound": "proxy" + }, + { + "action": "hijack-dns", + "protocol": "dns" }, { "action": "route", - "rule_set": "geoip-ir", - "outbound": "direct" - } - ], - "rule_set": [ - { - "tag": "geosite-category-ads-all", - "type": "remote", - "format": "binary", - "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-category-ads-all.srs", - "download_detour": "direct" + "outbound": "direct", + "rule_set": [ + "geosite-ir", + "geoip-ir", + "geosite-private" + ] }, { - "type": "remote", - "tag": "geoip-ir", - "format": "binary", - "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geoip-ir.srs", - "update_interval": "120h0m0s" - }, - { - "type": "remote", - "tag": "geosite-ir", - "format": "binary", - "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-ir.srs", - "update_interval": "120h0m0s" + "action": "reject", + "rule_set": [ + "geosite-ads" + ] } ] } From 8b30b26e0c2ef2be961ed7683b265ccdfa57e317 Mon Sep 17 00:00:00 2001 From: Seyed Mahdi <39972836+SeyedHashtag@users.noreply.github.com> Date: Wed, 28 May 2025 23:09:36 +0330 Subject: [PATCH 04/12] fix: correct server configuration in singbox.json --- core/scripts/normalsub/singbox.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/scripts/normalsub/singbox.json b/core/scripts/normalsub/singbox.json index 2bb7ea3..d1f8fbc 100644 --- a/core/scripts/normalsub/singbox.json +++ b/core/scripts/normalsub/singbox.json @@ -22,7 +22,8 @@ ], "servers": [ { - "address": "https://1.1.1.1/dns-query", + "type": "https", + "server": "1.1.1.1", "address_resolver": "local-dns", "detour": "proxy", "tag": "proxy-dns" From 5d2b8b2bf88b6bd57eb560ba6d00721711f46e7a Mon Sep 17 00:00:00 2001 From: Seyed Mahdi <39972836+SeyedHashtag@users.noreply.github.com> Date: Fri, 30 May 2025 23:34:26 +0330 Subject: [PATCH 05/12] fix: update geosite URLs and tags in singbox.json for consistency --- core/scripts/normalsub/singbox.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/scripts/normalsub/singbox.json b/core/scripts/normalsub/singbox.json index d1f8fbc..c22f140 100644 --- a/core/scripts/normalsub/singbox.json +++ b/core/scripts/normalsub/singbox.json @@ -98,28 +98,28 @@ "format": "binary", "tag": "geosite-ads", "type": "remote", - "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/category-ads-all.srs" + "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-category-ads-all.srs" }, { "download_detour": "direct", "format": "binary", - "tag": "geosite-private", + "tag": "geoip-private", "type": "remote", - "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/private.srs" + "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geoip-private.srs" }, { "download_detour": "direct", "format": "binary", "tag": "geosite-ir", "type": "remote", - "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/category-ir.srs" + "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-ir.srs" }, { "download_detour": "direct", "format": "binary", "tag": "geoip-ir", "type": "remote", - "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geoip/ir.srs" + "url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geoip-ir.srs" } ], "rules": [ @@ -152,7 +152,7 @@ { "action": "reject", "rule_set": [ - "geosite-ads" + "geoip-ads" ] } ] From 3ddb98107788b308ec312d1edd14c593cf36248f Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Mon, 2 Jun 2025 00:14:55 +0330 Subject: [PATCH 06/12] feat: Add OBFS status check functionality Adds a new `--check` or `-c` option to `manage_obfs.py` to determine if OBFS is currently configured in `config.json`. --- core/scripts/hysteria2/manage_obfs.py | 45 ++++++++++++++++++--------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/core/scripts/hysteria2/manage_obfs.py b/core/scripts/hysteria2/manage_obfs.py index 3368649..3a11f52 100644 --- a/core/scripts/hysteria2/manage_obfs.py +++ b/core/scripts/hysteria2/manage_obfs.py @@ -9,16 +9,14 @@ from init_paths import * from paths import * def restart_hysteria(): - """Restart the Hysteria2 service using the CLI script.""" try: subprocess.run(["python3", CLI_PATH, "restart-hysteria2"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except Exception as e: - print(f"⚠️ Failed to restart Hysteria2: {e}") + print(f"Failed to restart Hysteria2: {e}") def remove_obfs(): - """Remove the 'obfs' section from the config.""" try: with open(CONFIG_FILE, 'r') as f: config = json.load(f) @@ -27,9 +25,9 @@ def remove_obfs(): del config['obfs'] with open(CONFIG_FILE, 'w') as f: json.dump(config, f, indent=2) - print("✅ Successfully removed 'obfs' from config.json.") + print("Successfully removed 'obfs' from config.json.") else: - print("ℹ️ 'obfs' section not found in config.json.") + print("'obfs' section not found in config.json.") restart_hysteria() @@ -39,13 +37,12 @@ def remove_obfs(): print(f"❌ Error removing 'obfs': {e}") def generate_obfs(): - """Generate and add an 'obfs' section with a random password.""" try: with open(CONFIG_FILE, 'r') as f: config = json.load(f) if 'obfs' in config: - print("ℹ️ 'obfs' section already exists. Replacing it.") + print("'obfs' section already exists. Replacing it.") del config['obfs'] password = ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(32)) @@ -60,30 +57,48 @@ def generate_obfs(): with open(CONFIG_FILE, 'w') as f: json.dump(config, f, indent=2) - print(f"✅ Successfully added 'obfs' to config.json with password: {password}") + print(f"Successfully added 'obfs' to config.json with password: {password}") restart_hysteria() except FileNotFoundError: - print(f"❌ Config file not found: {CONFIG_FILE}") + print(f"Config file not found: {CONFIG_FILE}") except Exception as e: - print(f"❌ Error generating 'obfs': {e}") + print(f"Error generating 'obfs': {e}") + +def check_obfs(): + try: + with open(CONFIG_FILE, 'r') as f: + config = json.load(f) + + if 'obfs' in config: + print("OBFS is active.") + else: + print("OBFS is not active.") + + except FileNotFoundError: + print(f"Config file not found: {CONFIG_FILE}") + except Exception as e: + print(f"Error checking 'obfs' status: {e}") def main(): if len(sys.argv) != 2: - print("Usage: python3 obfs_manager.py --remove|-r | --generate|-g") + print("Usage: python3 obfs_manager.py --remove|-r | --generate|-g | --check|-c") sys.exit(1) option = sys.argv[1] if option in ("--remove", "-r"): - print("Removing 'obfs' from config.json...") + # print("Removing 'obfs' from config.json...") remove_obfs() elif option in ("--generate", "-g"): - print("Generating 'obfs' in config.json...") + # print("Generating 'obfs' in config.json...") generate_obfs() + elif option in ("--check", "-c"): + # print("Checking 'obfs' status in config.json...") + check_obfs() else: - print("Invalid option. Use --remove|-r or --generate|-g") + print("Invalid option. Use --remove|-r, --generate|-g, or --check|-c") sys.exit(1) if __name__ == "__main__": - main() + main() \ No newline at end of file From 228e01f6e98c1c4c4b9e96726b1e5e9c3d66edfb Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Mon, 2 Jun 2025 00:16:41 +0330 Subject: [PATCH 07/12] feat: Add --check flag to manage_obfs CLI command Integrates the OBFS status check functionality into the main CLI. Users can now use `cli.py manage_obfs --check` to see if OBFS is active. --- core/cli.py | 20 +++++++++++++------- core/cli_api.py | 4 ++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/core/cli.py b/core/cli.py index ab0c9f7..32873f1 100644 --- a/core/cli.py +++ b/core/cli.py @@ -250,19 +250,25 @@ def server_info(): @cli.command('manage_obfs') @click.option('--remove', '-r', is_flag=True, help="Remove 'obfs' from config.json.") @click.option('--generate', '-g', is_flag=True, help="Generate new 'obfs' in config.json.") -def manage_obfs(remove: bool, generate: bool): +@click.option('--check', '-c', is_flag=True, help="Check 'obfs' status in config.json.") +def manage_obfs(remove: bool, generate: bool, check: bool): try: - if not remove and not generate: - raise click.UsageError('Error: You must use either --remove or --generate') - if remove and generate: - raise click.UsageError('Error: You cannot use both --remove and --generate at the same time') + options_selected = sum([remove, generate, check]) + if options_selected == 0: + raise click.UsageError('Error: You must use either --remove, --generate, or --check.') + if options_selected > 1: + raise click.UsageError('Error: You can only use one of --remove, --generate, or --check at a time.') if generate: cli_api.enable_hysteria2_obfs() - click.echo('Obfs enabled successfully.') + click.echo('OBFS enabled successfully.') elif remove: cli_api.disable_hysteria2_obfs() - click.echo('Obfs disabled successfully.') + click.echo('OBFS disabled successfully.') + elif check: + status_output = cli_api.check_hysteria2_obfs() + click.echo(status_output) + except Exception as e: click.echo(f'{e}', err=True) diff --git a/core/cli_api.py b/core/cli_api.py index 834da6c..c131c53 100644 --- a/core/cli_api.py +++ b/core/cli_api.py @@ -218,6 +218,10 @@ def disable_hysteria2_obfs(): '''Removes 'obfs' from Hysteria2 configuration.''' run_cmd(['python3', Command.MANAGE_OBFS.value, '--remove']) +def check_hysteria2_obfs(): + '''Removes 'obfs' from Hysteria2 configuration.''' + result = subprocess.run(["python3", Command.MANAGE_OBFS.value, "--check"], check=True, capture_output=True, text=True) + return result.stdout.strip() def enable_hysteria2_masquerade(domain: str): '''Enables masquerade for Hysteria2.''' From 97ade9e4eb2f112ac0eef57d9a13c468f384a3df Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Mon, 2 Jun 2025 00:19:25 +0330 Subject: [PATCH 08/12] feat: Add OBFS status API endpoint --- .../routers/api/v1/config/hysteria.py | 19 ++++++++++++++++++- .../routers/api/v1/schema/config/hysteria.py | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/core/scripts/webpanel/routers/api/v1/config/hysteria.py b/core/scripts/webpanel/routers/api/v1/config/hysteria.py index 2f08f59..7c676df 100644 --- a/core/scripts/webpanel/routers/api/v1/config/hysteria.py +++ b/core/scripts/webpanel/routers/api/v1/config/hysteria.py @@ -1,5 +1,5 @@ from fastapi import APIRouter, BackgroundTasks, HTTPException, UploadFile, File -from ..schema.config.hysteria import ConfigFile, GetPortResponse, GetSniResponse +from ..schema.config.hysteria import ConfigFile, GetPortResponse, GetSniResponse, GetObfsResponse from ..schema.response import DetailResponse, IPLimitConfig, SetupDecoyRequest, DecoyStatusResponse, IPLimitConfigResponse from fastapi.responses import FileResponse import shutil @@ -223,6 +223,23 @@ async def disable_obfs(): raise HTTPException(status_code=400, detail=f'Error: {str(e)}') +@router.get('/check-obfs', response_model=GetObfsResponse, summary='Check Hysteria2 OBFS Status') +async def check_obfs(): + """ + Checks the current status of Hysteria2 OBFS. + + Returns: + A GetObfsResponse containing the Hysteria2 OBFS status message (e.g., 'OBFS is active.'). + + Raises: + HTTPException: if an error occurs while checking the Hysteria2 OBFS status. + """ + try: + obfs_status_message = cli_api.check_hysteria2_obfs() + return GetObfsResponse(obfs=obfs_status_message) + except Exception as e: + raise HTTPException(status_code=400, detail=f'Error checking OBFS status: {str(e)}') + @router.get('/enable-masquerade/{domain}', response_model=DetailResponse, summary='Enable Hysteria2 masquerade') async def enable_masquerade(domain: str): """ diff --git a/core/scripts/webpanel/routers/api/v1/schema/config/hysteria.py b/core/scripts/webpanel/routers/api/v1/schema/config/hysteria.py index 82e51a4..444db27 100644 --- a/core/scripts/webpanel/routers/api/v1/schema/config/hysteria.py +++ b/core/scripts/webpanel/routers/api/v1/schema/config/hysteria.py @@ -18,3 +18,6 @@ class GetPortResponse(BaseModel): class GetSniResponse(BaseModel): sni: str + +class GetObfsResponse(BaseModel): + obfs: str \ No newline at end of file From 5e61afe15c6fa6154fc67f59365b13f8bb62ac05 Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Mon, 2 Jun 2025 00:38:53 +0330 Subject: [PATCH 09/12] feat: Add OBFS management tab to settings page - Added a new "OBFS" tab in `settings.html`. - The tab displays the current OBFS status (active/inactive). --- core/scripts/webpanel/templates/settings.html | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/core/scripts/webpanel/templates/settings.html b/core/scripts/webpanel/templates/settings.html index c4c5c58..49bc10a 100644 --- a/core/scripts/webpanel/templates/settings.html +++ b/core/scripts/webpanel/templates/settings.html @@ -40,6 +40,11 @@ Change SNI + +