9router 0.3.54 → 0.3.56
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.
- package/app/.next/BUILD_ID +1 -1
- package/app/.next/app-path-routes-manifest.json +34 -34
- package/app/.next/build-manifest.json +5 -5
- package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/mitm/page.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/page.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error.html +2 -2
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_not-found.html +1 -1
- package/app/.next/server/app/_not-found.rsc +4 -4
- package/app/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/claude-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/codex-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/copilot-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/droid-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/openclaw-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cli-tools/opencode-settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/auth/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/credentials/update/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/model/resolve/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/cloud/models/alias/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/combos/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/combos/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/keys/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/keys/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/locale/route.js +1 -1
- package/app/.next/server/app/api/locale/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/models/alias/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/models/route.js +1 -1
- package/app/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/models/test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/[provider]/[action]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/cursor/auto-import/route.js +1 -1
- package/app/.next/server/app/api/oauth/cursor/auto-import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/cursor/import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/iflow/cookie/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/auto-import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/import/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/social-authorize/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/social-exchange/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/provider-nodes/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/provider-nodes/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/provider-nodes/validate/route.js +1 -1
- package/app/.next/server/app/api/provider-nodes/validate/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/models/route.js +1 -1
- package/app/.next/server/app/api/providers/[id]/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/[id]/test-models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/client/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/route.js +1 -1
- package/app/.next/server/app/api/providers/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/test-batch/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/providers/validate/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/proxy-pools/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/database/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/proxy-test/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/require-login/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tags/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/stream/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/load/route.js.nft.json +1 -1
- package/app/.next/server/app/api/translator/load/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/save/route.js.nft.json +1 -1
- package/app/.next/server/app/api/translator/save/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/send/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/translator/translate/route.js +1 -1
- package/app/.next/server/app/api/translator/translate/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tunnel/disable/route.js +1 -1
- package/app/.next/server/app/api/tunnel/disable/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tunnel/enable/route.js +1 -1
- package/app/.next/server/app/api/tunnel/enable/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/tunnel/status/route.js +1 -1
- package/app/.next/server/app/api/tunnel/status/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/[connectionId]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/chart/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/history/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/providers/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/request-details/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/request-logs/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/stats/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/usage/stream/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/api/chat/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/chat/completions/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/embeddings/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/messages/count_tokens/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/messages/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/responses/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1beta/models/[...path]/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/v1beta/models/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/api/version/route.js +1 -1
- package/app/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/callback.html +1 -1
- package/app/.next/server/app/callback.rsc +4 -4
- package/app/.next/server/app/callback.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/callback.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.html +1 -1
- package/app/.next/server/app/dashboard/cli-tools.rsc +6 -6
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/combos.html +1 -1
- package/app/.next/server/app/dashboard/combos.rsc +6 -6
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/combos.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/combos.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/endpoint.html +1 -1
- package/app/.next/server/app/dashboard/endpoint.rsc +6 -6
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/mitm.html +1 -1
- package/app/.next/server/app/dashboard/mitm.rsc +6 -6
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/profile.html +1 -1
- package/app/.next/server/app/dashboard/profile.rsc +6 -6
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/profile.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/profile.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers/new.html +1 -1
- package/app/.next/server/app/dashboard/providers/new.rsc +6 -6
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers.html +1 -1
- package/app/.next/server/app/dashboard/providers.rsc +6 -6
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/providers.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/providers.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/proxy-pools.html +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.rsc +6 -6
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/quota.html +2 -2
- package/app/.next/server/app/dashboard/quota.rsc +7 -7
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/quota.segments/_full.segment.rsc +7 -7
- package/app/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/quota.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/settings/pricing/page.js +1 -1
- package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.rsc +5 -5
- package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.html +1 -1
- package/app/.next/server/app/dashboard/translator.rsc +6 -6
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/translator.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/translator.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/usage.html +1 -1
- package/app/.next/server/app/dashboard/usage.rsc +6 -6
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/usage.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/usage.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard.html +1 -1
- package/app/.next/server/app/dashboard.rsc +6 -6
- package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
- package/app/.next/server/app/dashboard.segments/_full.segment.rsc +6 -6
- package/app/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/index.html +1 -1
- package/app/.next/server/app/index.rsc +4 -4
- package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/landing.html +1 -1
- package/app/.next/server/app/landing.rsc +5 -5
- package/app/.next/server/app/landing.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/landing.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/landing.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
- package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/login.html +1 -1
- package/app/.next/server/app/login.rsc +5 -5
- package/app/.next/server/app/login.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/login.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/app/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
- package/app/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app-paths-manifest.json +34 -34
- package/app/.next/server/chunks/1114.js +1 -1
- package/app/.next/server/chunks/1424.js +1 -1
- package/app/.next/server/chunks/318.js +1 -1
- package/app/.next/server/chunks/3832.js +1 -1
- package/app/.next/server/chunks/412.js +1 -1
- package/app/.next/server/chunks/6182.js +4 -17
- package/app/.next/server/chunks/649.js +2 -2
- package/app/.next/server/chunks/7341.js +1 -1
- package/app/.next/server/chunks/8590.js +1 -1
- package/app/.next/server/chunks/9201.js +1 -1
- package/app/.next/server/chunks/9718.js +1 -1
- package/app/.next/server/middleware-build-manifest.js +1 -1
- package/app/.next/server/pages/404.html +1 -1
- package/app/.next/server/pages/500.html +2 -2
- package/app/.next/server/server-reference-manifest.js +1 -1
- package/app/.next/server/server-reference-manifest.json +1 -1
- package/app/.next/static/chunks/2652-51aca5cd32bd186f.js +1 -0
- package/app/.next/static/chunks/3794-23858078d298f399.js +2 -0
- package/app/.next/static/chunks/{4bd1b696-e5d7c65570c947b7.js → 4bd1b696-84e33c69f320f6a0.js} +1 -1
- package/app/.next/static/chunks/{5497-4115bafa029568f2.js → 5497-c5403d4340dfbeb0.js} +3 -3
- package/app/.next/static/chunks/{619-c4c101a6a78feeb4.js → 619-bfe7e89fff6eb942.js} +1 -1
- package/app/.next/static/chunks/{9242-c9d752975b449b44.js → 9242-a85bb5812b359227.js} +3 -3
- package/app/.next/static/chunks/app/(dashboard)/dashboard/cli-tools/{page-d973cbda9e65d6ae.js → page-15fc16f73981b9be.js} +1 -1
- package/app/.next/static/chunks/app/(dashboard)/dashboard/mitm/page-fb6736d76c7a3b6a.js +1 -0
- package/app/.next/static/chunks/app/(dashboard)/dashboard/providers/[id]/{page-4ebc425afc0a221a.js → page-5e7e72628fe63cec.js} +1 -1
- package/app/.next/static/chunks/app/(dashboard)/dashboard/providers/page-bf901cec2b7f0ea0.js +1 -0
- package/app/.next/static/chunks/app/dashboard/settings/pricing/{page-4b7305b3e5d6e57b.js → page-e097c892258ad1fd.js} +1 -1
- package/app/.next/static/chunks/app/landing/{page-106f74afc6f71a31.js → page-cb9f1320605eaafc.js} +1 -1
- package/app/.next/static/chunks/app/{layout-2cf69a29bcc7722e.js → layout-a3634d564d5e7993.js} +1 -1
- package/app/.next/static/chunks/{framework-9f63a52f5ba18ac8.js → framework-6854168261815bb6.js} +1 -1
- package/app/.next/static/chunks/{main-aab9e1b069a77e0f.js → main-5b78d3de83609121.js} +2 -2
- package/app/.next/static/chunks/webpack-9bef9bba7ebc0551.js +1 -0
- package/app/.next/static/css/9dff3edaebe94c91.css +3 -0
- package/app/package.json +4 -1
- package/app/public/i18n/literals/ar.json +196 -0
- package/app/public/i18n/literals/bn.json +196 -0
- package/app/public/i18n/literals/cs.json +196 -0
- package/app/public/i18n/literals/da.json +196 -0
- package/app/public/i18n/literals/de.json +196 -0
- package/app/public/i18n/literals/el.json +196 -0
- package/app/public/i18n/literals/es.json +196 -0
- package/app/public/i18n/literals/fi.json +196 -0
- package/app/public/i18n/literals/fr.json +196 -0
- package/app/public/i18n/literals/he.json +196 -0
- package/app/public/i18n/literals/hi.json +196 -0
- package/app/public/i18n/literals/hu.json +196 -0
- package/app/public/i18n/literals/id.json +196 -0
- package/app/public/i18n/literals/it.json +196 -0
- package/app/public/i18n/literals/ja.json +196 -0
- package/app/public/i18n/literals/ko.json +196 -0
- package/app/public/i18n/literals/nl.json +196 -0
- package/app/public/i18n/literals/no.json +196 -0
- package/app/public/i18n/literals/pl.json +196 -0
- package/app/public/i18n/literals/pt-BR.json +196 -0
- package/app/public/i18n/literals/pt-PT.json +196 -0
- package/app/public/i18n/literals/ro.json +196 -0
- package/app/public/i18n/literals/ru.json +196 -0
- package/app/public/i18n/literals/sv.json +196 -0
- package/app/public/i18n/literals/th.json +196 -0
- package/app/public/i18n/literals/tl.json +196 -0
- package/app/public/i18n/literals/tr.json +196 -0
- package/app/public/i18n/literals/uk.json +196 -0
- package/app/public/i18n/literals/ur.json +196 -0
- package/app/public/i18n/literals/zh-TW.json +196 -0
- package/app/src/mitm/server.js +1 -297
- package/cli.js +6 -8
- package/package.json +1 -1
- package/app/.next/static/chunks/2652-378fd4fa14847021.js +0 -1
- package/app/.next/static/chunks/3794-c67589461d449d62.js +0 -2
- package/app/.next/static/chunks/app/(dashboard)/dashboard/mitm/page-bf88929b2cc595ab.js +0 -1
- package/app/.next/static/chunks/app/(dashboard)/dashboard/providers/page-3143d3dbb2dc3422.js +0 -1
- package/app/.next/static/chunks/webpack-25c43999146c934e.js +0 -1
- package/app/.next/static/css/4016074f63f34af9.css +0 -3
- package/app/src/mitm/cert/generate.js +0 -32
- package/app/src/mitm/cert/install.js +0 -177
- package/app/src/mitm/cert/rootCA.js +0 -153
- package/app/src/mitm/dns/dnsConfig.js +0 -270
- package/app/src/mitm/logger.js +0 -8
- package/app/src/mitm/manager.js +0 -611
- package/app/src/mitm/paths.js +0 -16
- package/app/src/mitm/server2.js +0 -1099
- /package/app/.next/static/{lQALtClEnCtM3rGs1b9Jb → gStrggE8HSBGxSIt_oloe}/_buildManifest.js +0 -0
- /package/app/.next/static/{lQALtClEnCtM3rGs1b9Jb → gStrggE8HSBGxSIt_oloe}/_ssgManifest.js +0 -0
package/app/src/mitm/manager.js
DELETED
|
@@ -1,611 +0,0 @@
|
|
|
1
|
-
const { exec, spawn, execSync } = require("child_process");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const os = require("os");
|
|
5
|
-
const net = require("net");
|
|
6
|
-
const https = require("https");
|
|
7
|
-
const crypto = require("crypto");
|
|
8
|
-
const { addDNSEntry, removeDNSEntry, removeAllDNSEntries, checkAllDNSStatus, executeElevatedPowerShell, TOOL_HOSTS } = require("./dns/dnsConfig");
|
|
9
|
-
|
|
10
|
-
const IS_WIN = process.platform === "win32";
|
|
11
|
-
const { generateCert } = require("./cert/generate");
|
|
12
|
-
const { installCert } = require("./cert/install");
|
|
13
|
-
const { MITM_DIR } = require("./paths");
|
|
14
|
-
const { log, err } = require("./logger");
|
|
15
|
-
|
|
16
|
-
const MITM_PORT = 443;
|
|
17
|
-
const MITM_WIN_NODE_PORT = 8443;
|
|
18
|
-
const PID_FILE = path.join(MITM_DIR, ".mitm.pid");
|
|
19
|
-
|
|
20
|
-
const MITM_MAX_RESTARTS = 5;
|
|
21
|
-
const MITM_RESTART_DELAYS_MS = [5000, 10000, 20000, 30000, 60000];
|
|
22
|
-
const MITM_RESTART_RESET_MS = 60000;
|
|
23
|
-
|
|
24
|
-
let mitmRestartCount = 0;
|
|
25
|
-
let mitmLastStartTime = 0;
|
|
26
|
-
let mitmIsRestarting = false;
|
|
27
|
-
|
|
28
|
-
function resolveServerPath() {
|
|
29
|
-
if (process.env.MITM_SERVER_PATH) return process.env.MITM_SERVER_PATH;
|
|
30
|
-
const sibling = path.join(__dirname, "server.js");
|
|
31
|
-
if (fs.existsSync(sibling)) return sibling;
|
|
32
|
-
const fromCwd = path.join(process.cwd(), "src", "mitm", "server.js");
|
|
33
|
-
if (fs.existsSync(fromCwd)) return fromCwd;
|
|
34
|
-
const fromNext = path.join(process.cwd(), "..", "src", "mitm", "server.js");
|
|
35
|
-
if (fs.existsSync(fromNext)) return fromNext;
|
|
36
|
-
return fromCwd;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const SERVER_PATH = resolveServerPath();
|
|
40
|
-
const ENCRYPT_ALGO = "aes-256-gcm";
|
|
41
|
-
const ENCRYPT_SALT = "9router-mitm-pwd";
|
|
42
|
-
|
|
43
|
-
function getProcessUsingPort443() {
|
|
44
|
-
try {
|
|
45
|
-
if (IS_WIN) {
|
|
46
|
-
const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command ` +
|
|
47
|
-
`"$c = Get-NetTCPConnection -LocalPort 443 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1; if ($c) { $c.OwningProcess } else { 0 }"`;
|
|
48
|
-
const pidStr = execSync(psCmd, { encoding: "utf8", windowsHide: true }).trim();
|
|
49
|
-
const pid = parseInt(pidStr, 10);
|
|
50
|
-
if (pid && pid > 4) {
|
|
51
|
-
const tasklistResult = execSync(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { encoding: "utf8", windowsHide: true });
|
|
52
|
-
const processMatch = tasklistResult.match(/"([^"]+)"/);
|
|
53
|
-
if (processMatch) return processMatch[1].replace(".exe", "");
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
const result = execSync("lsof -i :443", { encoding: "utf8" });
|
|
57
|
-
const lines = result.trim().split("\n");
|
|
58
|
-
if (lines.length > 1) return lines[1].split(/\s+/)[0];
|
|
59
|
-
}
|
|
60
|
-
} catch {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let serverProcess = null;
|
|
67
|
-
let serverPid = null;
|
|
68
|
-
|
|
69
|
-
function getCachedPassword() { return globalThis.__mitmSudoPassword || null; }
|
|
70
|
-
function setCachedPassword(pwd) { globalThis.__mitmSudoPassword = pwd; }
|
|
71
|
-
|
|
72
|
-
function isProcessAlive(pid) {
|
|
73
|
-
try {
|
|
74
|
-
process.kill(pid, 0);
|
|
75
|
-
return true;
|
|
76
|
-
} catch (err) {
|
|
77
|
-
return err.code === "EACCES";
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function killProcess(pid, force = false, sudoPassword = null) {
|
|
82
|
-
if (IS_WIN) {
|
|
83
|
-
const flag = force ? "/F " : "";
|
|
84
|
-
exec(`taskkill ${flag}/PID ${pid}`, () => { });
|
|
85
|
-
} else {
|
|
86
|
-
const sig = force ? "SIGKILL" : "SIGTERM";
|
|
87
|
-
const cmd = `pkill -${sig} -P ${pid} 2>/dev/null; kill -${sig} ${pid} 2>/dev/null`;
|
|
88
|
-
if (sudoPassword) {
|
|
89
|
-
const { execWithPassword } = require("./dns/dnsConfig");
|
|
90
|
-
execWithPassword(cmd, sudoPassword).catch(() => exec(cmd, () => { }));
|
|
91
|
-
} else {
|
|
92
|
-
exec(cmd, () => { });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function deriveKey() {
|
|
98
|
-
try {
|
|
99
|
-
const { machineIdSync } = require("node-machine-id");
|
|
100
|
-
const raw = machineIdSync();
|
|
101
|
-
return crypto.createHash("sha256").update(raw + ENCRYPT_SALT).digest();
|
|
102
|
-
} catch {
|
|
103
|
-
return crypto.createHash("sha256").update(ENCRYPT_SALT).digest();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function encryptPassword(plaintext) {
|
|
108
|
-
const key = deriveKey();
|
|
109
|
-
const iv = crypto.randomBytes(12);
|
|
110
|
-
const cipher = crypto.createCipheriv(ENCRYPT_ALGO, key, iv);
|
|
111
|
-
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
112
|
-
const tag = cipher.getAuthTag();
|
|
113
|
-
return `${iv.toString("hex")}:${tag.toString("hex")}:${encrypted.toString("hex")}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function decryptPassword(stored) {
|
|
117
|
-
try {
|
|
118
|
-
const [ivHex, tagHex, dataHex] = stored.split(":");
|
|
119
|
-
if (!ivHex || !tagHex || !dataHex) return null;
|
|
120
|
-
const key = deriveKey();
|
|
121
|
-
const decipher = crypto.createDecipheriv(ENCRYPT_ALGO, key, Buffer.from(ivHex, "hex"));
|
|
122
|
-
decipher.setAuthTag(Buffer.from(tagHex, "hex"));
|
|
123
|
-
return decipher.update(Buffer.from(dataHex, "hex")) + decipher.final("utf8");
|
|
124
|
-
} catch {
|
|
125
|
-
return null;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
let _getSettings = null;
|
|
130
|
-
let _updateSettings = null;
|
|
131
|
-
|
|
132
|
-
function initDbHooks(getSettingsFn, updateSettingsFn) {
|
|
133
|
-
_getSettings = getSettingsFn;
|
|
134
|
-
_updateSettings = updateSettingsFn;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function saveMitmSettings(enabled, password) {
|
|
138
|
-
if (!_updateSettings) return;
|
|
139
|
-
try {
|
|
140
|
-
const updates = { mitmEnabled: enabled };
|
|
141
|
-
if (password) updates.mitmSudoEncrypted = encryptPassword(password);
|
|
142
|
-
await _updateSettings(updates);
|
|
143
|
-
} catch (e) {
|
|
144
|
-
err(`Failed to save settings: ${e.message}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async function loadEncryptedPassword() {
|
|
149
|
-
if (!_getSettings) return null;
|
|
150
|
-
try {
|
|
151
|
-
const settings = await _getSettings();
|
|
152
|
-
if (!settings.mitmSudoEncrypted) return null;
|
|
153
|
-
return decryptPassword(settings.mitmSudoEncrypted);
|
|
154
|
-
} catch {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function checkPort443Free() {
|
|
160
|
-
return new Promise((resolve) => {
|
|
161
|
-
const tester = net.createServer();
|
|
162
|
-
tester.once("error", (err) => {
|
|
163
|
-
if (err.code === "EADDRINUSE") resolve("in-use");
|
|
164
|
-
else resolve("no-permission");
|
|
165
|
-
});
|
|
166
|
-
tester.once("listening", () => { tester.close(() => resolve("free")); });
|
|
167
|
-
tester.listen(MITM_PORT, "127.0.0.1");
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function getPort443Owner(sudoPassword) {
|
|
172
|
-
return new Promise((resolve) => {
|
|
173
|
-
if (IS_WIN) {
|
|
174
|
-
const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "` +
|
|
175
|
-
`$c = Get-NetTCPConnection -LocalPort 443 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1; ` +
|
|
176
|
-
`if ($c) { $c.OwningProcess } else { 0 }"`;
|
|
177
|
-
exec(psCmd, { windowsHide: true }, (err, stdout) => {
|
|
178
|
-
if (err) return resolve(null);
|
|
179
|
-
const pid = parseInt(stdout.trim(), 10);
|
|
180
|
-
if (!pid || pid <= 4) return resolve(null);
|
|
181
|
-
exec(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`, { windowsHide: true }, (e2, out2) => {
|
|
182
|
-
const m = out2?.match(/"([^"]+)"/);
|
|
183
|
-
resolve({ pid, name: m ? m[1] : "unknown" });
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
} else {
|
|
187
|
-
exec(`ps aux | grep "[s]erver.js"`, (err, stdout) => {
|
|
188
|
-
if (!stdout?.trim()) return resolve(null);
|
|
189
|
-
for (const line of stdout.split("\n")) {
|
|
190
|
-
const parts = line.trim().split(/\s+/);
|
|
191
|
-
const pid = parseInt(parts[1], 10);
|
|
192
|
-
if (!isNaN(pid)) return resolve({ pid, name: "node" });
|
|
193
|
-
}
|
|
194
|
-
resolve(null);
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async function killLeftoverMitm(sudoPassword) {
|
|
201
|
-
if (serverProcess && !serverProcess.killed) {
|
|
202
|
-
try { serverProcess.kill("SIGKILL"); } catch { /* ignore */ }
|
|
203
|
-
serverProcess = null;
|
|
204
|
-
serverPid = null;
|
|
205
|
-
}
|
|
206
|
-
try {
|
|
207
|
-
if (fs.existsSync(PID_FILE)) {
|
|
208
|
-
const savedPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
209
|
-
if (savedPid && isProcessAlive(savedPid)) {
|
|
210
|
-
killProcess(savedPid, true, sudoPassword);
|
|
211
|
-
await new Promise(r => setTimeout(r, 500));
|
|
212
|
-
}
|
|
213
|
-
fs.unlinkSync(PID_FILE);
|
|
214
|
-
}
|
|
215
|
-
} catch { /* ignore */ }
|
|
216
|
-
if (!IS_WIN && SERVER_PATH) {
|
|
217
|
-
try {
|
|
218
|
-
const escaped = SERVER_PATH.replace(/'/g, "'\\''");
|
|
219
|
-
if (sudoPassword) {
|
|
220
|
-
const { execWithPassword } = require("./dns/dnsConfig");
|
|
221
|
-
await execWithPassword(`pkill -SIGKILL -f "${escaped}" 2>/dev/null || true`, sudoPassword).catch(() => { });
|
|
222
|
-
} else {
|
|
223
|
-
exec(`pkill -SIGKILL -f "${escaped}" 2>/dev/null || true`, () => { });
|
|
224
|
-
}
|
|
225
|
-
await new Promise(r => setTimeout(r, 500));
|
|
226
|
-
} catch { /* ignore */ }
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function pollMitmHealth(timeoutMs, port = MITM_PORT) {
|
|
231
|
-
return new Promise((resolve) => {
|
|
232
|
-
const deadline = Date.now() + timeoutMs;
|
|
233
|
-
const check = () => {
|
|
234
|
-
const req = https.request(
|
|
235
|
-
{ hostname: "127.0.0.1", port, path: "/_mitm_health", method: "GET", rejectUnauthorized: false },
|
|
236
|
-
(res) => {
|
|
237
|
-
let body = "";
|
|
238
|
-
res.on("data", (d) => { body += d; });
|
|
239
|
-
res.on("end", () => {
|
|
240
|
-
try {
|
|
241
|
-
const json = JSON.parse(body);
|
|
242
|
-
resolve(json.ok === true ? { ok: true, pid: json.pid || null } : null);
|
|
243
|
-
} catch { resolve(null); }
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
);
|
|
247
|
-
req.on("error", () => {
|
|
248
|
-
if (Date.now() < deadline) setTimeout(check, 500);
|
|
249
|
-
else resolve(null);
|
|
250
|
-
});
|
|
251
|
-
req.end();
|
|
252
|
-
};
|
|
253
|
-
check();
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Get full MITM status including per-tool DNS status
|
|
259
|
-
*/
|
|
260
|
-
async function getMitmStatus() {
|
|
261
|
-
let running = serverProcess !== null && !serverProcess.killed;
|
|
262
|
-
let pid = serverPid;
|
|
263
|
-
|
|
264
|
-
if (!running) {
|
|
265
|
-
try {
|
|
266
|
-
if (fs.existsSync(PID_FILE)) {
|
|
267
|
-
const savedPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
268
|
-
if (savedPid && isProcessAlive(savedPid)) {
|
|
269
|
-
running = true;
|
|
270
|
-
pid = savedPid;
|
|
271
|
-
} else {
|
|
272
|
-
fs.unlinkSync(PID_FILE);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
} catch { /* ignore */ }
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const dnsStatus = checkAllDNSStatus();
|
|
279
|
-
const rootCACertPath = path.join(MITM_DIR, "rootCA.crt");
|
|
280
|
-
const certExists = fs.existsSync(rootCACertPath);
|
|
281
|
-
const { checkCertInstalled } = require("./cert/install");
|
|
282
|
-
const certTrusted = certExists ? await checkCertInstalled(rootCACertPath) : false;
|
|
283
|
-
|
|
284
|
-
return { running, pid, certExists, certTrusted, dnsStatus };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async function scheduleMitmRestart(apiKey) {
|
|
288
|
-
if (mitmIsRestarting) return;
|
|
289
|
-
|
|
290
|
-
const aliveMs = Date.now() - mitmLastStartTime;
|
|
291
|
-
if (aliveMs >= MITM_RESTART_RESET_MS) mitmRestartCount = 0;
|
|
292
|
-
|
|
293
|
-
if (mitmRestartCount >= MITM_MAX_RESTARTS) {
|
|
294
|
-
err("Max restart attempts reached. Giving up.");
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const attempt = mitmRestartCount;
|
|
299
|
-
const delay = MITM_RESTART_DELAYS_MS[Math.min(attempt, MITM_RESTART_DELAYS_MS.length - 1)];
|
|
300
|
-
mitmRestartCount++;
|
|
301
|
-
mitmIsRestarting = true;
|
|
302
|
-
|
|
303
|
-
log(`Restarting in ${delay / 1000}s... (${mitmRestartCount}/${MITM_MAX_RESTARTS})`);
|
|
304
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
const settings = _getSettings ? await _getSettings() : null;
|
|
308
|
-
if (settings && !settings.mitmEnabled) {
|
|
309
|
-
log("MITM disabled, skipping restart");
|
|
310
|
-
mitmIsRestarting = false;
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const password = getCachedPassword() || await loadEncryptedPassword();
|
|
314
|
-
if (!password && !IS_WIN) {
|
|
315
|
-
err("No cached password, cannot auto-restart");
|
|
316
|
-
mitmIsRestarting = false;
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
await startServer(apiKey, password);
|
|
320
|
-
log("🔄 Restarted successfully");
|
|
321
|
-
mitmRestartCount = 0;
|
|
322
|
-
mitmIsRestarting = false;
|
|
323
|
-
} catch (e) {
|
|
324
|
-
err(`Restart attempt ${mitmRestartCount}/${MITM_MAX_RESTARTS} failed: ${e.message}`);
|
|
325
|
-
mitmIsRestarting = false;
|
|
326
|
-
// Schedule next retry
|
|
327
|
-
scheduleMitmRestart(apiKey);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Start MITM server only (cert + server, no DNS)
|
|
333
|
-
*/
|
|
334
|
-
async function startServer(apiKey, sudoPassword) {
|
|
335
|
-
if (!serverProcess || serverProcess.killed) {
|
|
336
|
-
try {
|
|
337
|
-
if (fs.existsSync(PID_FILE)) {
|
|
338
|
-
const savedPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
339
|
-
if (savedPid && isProcessAlive(savedPid)) {
|
|
340
|
-
serverPid = savedPid;
|
|
341
|
-
log(`♻️ Reusing existing process (PID: ${savedPid})`);
|
|
342
|
-
await saveMitmSettings(true, sudoPassword);
|
|
343
|
-
if (sudoPassword) setCachedPassword(sudoPassword);
|
|
344
|
-
return { running: true, pid: savedPid };
|
|
345
|
-
} else {
|
|
346
|
-
fs.unlinkSync(PID_FILE);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
} catch { /* ignore */ }
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
if (serverProcess && !serverProcess.killed) {
|
|
353
|
-
throw new Error("MITM server is already running");
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
await killLeftoverMitm(sudoPassword);
|
|
357
|
-
|
|
358
|
-
if (!IS_WIN) {
|
|
359
|
-
const portStatus = await checkPort443Free();
|
|
360
|
-
if (portStatus === "in-use" || portStatus === "no-permission") {
|
|
361
|
-
const owner = await getPort443Owner(sudoPassword);
|
|
362
|
-
if (owner && owner.name === "node") {
|
|
363
|
-
log(`Killing orphan node process on port 443 (PID ${owner.pid})...`);
|
|
364
|
-
try {
|
|
365
|
-
const { execWithPassword } = require("./dns/dnsConfig");
|
|
366
|
-
await execWithPassword(`kill -9 ${owner.pid}`, sudoPassword);
|
|
367
|
-
await new Promise(r => setTimeout(r, 800));
|
|
368
|
-
} catch { /* best effort */ }
|
|
369
|
-
} else if (owner) {
|
|
370
|
-
const shortName = owner.name.includes("/")
|
|
371
|
-
? owner.name.split("/").filter(Boolean).pop()
|
|
372
|
-
: owner.name;
|
|
373
|
-
throw new Error(`Port 443 is already in use by "${shortName}" (PID ${owner.pid}). Stop that process first.`);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Step 1: Auto-migration - Generate Root CA if not exists
|
|
379
|
-
const rootCACertPath = path.join(MITM_DIR, "rootCA.crt");
|
|
380
|
-
const rootCAKeyPath = path.join(MITM_DIR, "rootCA.key");
|
|
381
|
-
|
|
382
|
-
if (!fs.existsSync(rootCACertPath) || !fs.existsSync(rootCAKeyPath)) {
|
|
383
|
-
log("🔐 Generating Root CA (first time)...");
|
|
384
|
-
await generateCert();
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Step 1.5: Auto-install Root CA if not trusted yet
|
|
388
|
-
const { checkCertInstalled } = require("./cert/install");
|
|
389
|
-
const rootCATrusted = await checkCertInstalled(rootCACertPath);
|
|
390
|
-
if (!rootCATrusted) {
|
|
391
|
-
log("🔐 Cert: not trusted → installing...");
|
|
392
|
-
// Use provided password or cached/stored password
|
|
393
|
-
const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
|
|
394
|
-
if (!password && !IS_WIN) {
|
|
395
|
-
throw new Error("Sudo password required to install Root CA certificate");
|
|
396
|
-
}
|
|
397
|
-
await installCert(password, rootCACertPath);
|
|
398
|
-
log("🔐 Cert: ✅ trusted");
|
|
399
|
-
} else {
|
|
400
|
-
log("🔐 Cert: already trusted ✅");
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Step 2: Spawn server (Root CA already installed in Step 1.5)
|
|
404
|
-
log("🚀 Starting server...");
|
|
405
|
-
if (IS_WIN) {
|
|
406
|
-
const psSQ = (s) => s.replace(/'/g, "''");
|
|
407
|
-
const nodePs = psSQ(process.execPath);
|
|
408
|
-
const serverPs = psSQ(SERVER_PATH);
|
|
409
|
-
|
|
410
|
-
const psScript = [
|
|
411
|
-
`$ErrorActionPreference = 'Stop'`,
|
|
412
|
-
`$conn = Get-NetTCPConnection -LocalPort 443 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1`,
|
|
413
|
-
`if ($conn -and $conn.OwningProcess -gt 4) { Stop-Process -Id $conn.OwningProcess -Force -ErrorAction SilentlyContinue }`,
|
|
414
|
-
`Start-Sleep -Milliseconds 500`,
|
|
415
|
-
`$nodeCmd = 'set ROUTER_API_KEY=${psSQ(apiKey)}&& set NODE_ENV=production&& "${nodePs}" "${serverPs}"'`,
|
|
416
|
-
`Start-Process cmd -ArgumentList '/c',$nodeCmd -WindowStyle Hidden`,
|
|
417
|
-
`Start-Sleep -Milliseconds 500`,
|
|
418
|
-
].join("\n");
|
|
419
|
-
|
|
420
|
-
const tmpPs1 = path.join(os.tmpdir(), `mitm_start_${Date.now()}.ps1`);
|
|
421
|
-
fs.writeFileSync(tmpPs1, psScript, "utf8");
|
|
422
|
-
await executeElevatedPowerShell(tmpPs1, 90000);
|
|
423
|
-
|
|
424
|
-
if (_updateSettings) await _updateSettings({ mitmCertInstalled: true }).catch(() => { });
|
|
425
|
-
} else {
|
|
426
|
-
// Non-Windows: Root CA already installed in Step 1.5, just spawn server
|
|
427
|
-
const inlineCmd = `ROUTER_API_KEY='${apiKey}' NODE_ENV='production' '${process.execPath}' '${SERVER_PATH}'`;
|
|
428
|
-
serverProcess = spawn(
|
|
429
|
-
"sudo", ["-S", "-E", "sh", "-c", inlineCmd],
|
|
430
|
-
{ detached: false, stdio: ["pipe", "pipe", "pipe"] }
|
|
431
|
-
);
|
|
432
|
-
serverProcess.stdin.write(`${sudoPassword}\n`);
|
|
433
|
-
serverProcess.stdin.end();
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (!IS_WIN && serverProcess) {
|
|
437
|
-
serverPid = serverProcess.pid;
|
|
438
|
-
fs.writeFileSync(PID_FILE, String(serverPid));
|
|
439
|
-
mitmLastStartTime = Date.now();
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
let startError = null;
|
|
443
|
-
if (!IS_WIN) {
|
|
444
|
-
serverProcess.stdout.on("data", (data) => {
|
|
445
|
-
// server.js already formats its own logs — print as-is
|
|
446
|
-
process.stdout.write(data);
|
|
447
|
-
});
|
|
448
|
-
serverProcess.stderr.on("data", (data) => {
|
|
449
|
-
const msg = data.toString().trim();
|
|
450
|
-
if (msg && !msg.includes("Password:") && !msg.includes("password for")) {
|
|
451
|
-
err(msg);
|
|
452
|
-
startError = msg;
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
serverProcess.on("exit", (code) => {
|
|
456
|
-
log(`Server exited (code: ${code})`);
|
|
457
|
-
serverProcess = null;
|
|
458
|
-
serverPid = null;
|
|
459
|
-
try { fs.unlinkSync(PID_FILE); } catch { /* ignore */ }
|
|
460
|
-
// Auto-restart on unexpected exit
|
|
461
|
-
if (code !== 0 && !mitmIsRestarting) scheduleMitmRestart(apiKey);
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const health = await pollMitmHealth(IS_WIN ? 15000 : 8000, MITM_PORT);
|
|
466
|
-
if (!health) {
|
|
467
|
-
if (IS_WIN) serverProcess = null;
|
|
468
|
-
const processUsing443 = getProcessUsingPort443();
|
|
469
|
-
const portInfo = processUsing443 ? ` Port 443 already in use by ${processUsing443}.` : "";
|
|
470
|
-
const reason = startError || `Check sudo password or port 443 access.${portInfo}`;
|
|
471
|
-
throw new Error(`MITM server failed to start. ${reason}`);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (IS_WIN && _updateSettings) await _updateSettings({ mitmCertInstalled: true }).catch(() => { });
|
|
475
|
-
if (IS_WIN && health.pid) {
|
|
476
|
-
serverPid = health.pid;
|
|
477
|
-
fs.writeFileSync(PID_FILE, String(serverPid));
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
log(`✅ Server healthy (PID: ${serverPid || health.pid})`);
|
|
481
|
-
|
|
482
|
-
// Log DNS status per tool
|
|
483
|
-
const dnsStatus = checkAllDNSStatus();
|
|
484
|
-
for (const [tool, active] of Object.entries(dnsStatus)) {
|
|
485
|
-
log(`🌐 DNS ${tool}: ${active ? "✅ active" : "❌ inactive"}`);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
await saveMitmSettings(true, sudoPassword);
|
|
489
|
-
if (sudoPassword) setCachedPassword(sudoPassword);
|
|
490
|
-
|
|
491
|
-
return { running: true, pid: serverPid };
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Stop MITM server — removes ALL tool DNS entries first, then kills server
|
|
496
|
-
*/
|
|
497
|
-
async function stopServer(sudoPassword) {
|
|
498
|
-
// Prevent auto-restart from triggering on intentional stop
|
|
499
|
-
mitmIsRestarting = true;
|
|
500
|
-
mitmRestartCount = 0;
|
|
501
|
-
log("⏹ Stopping server...");
|
|
502
|
-
|
|
503
|
-
// Kill server process
|
|
504
|
-
const proc = serverProcess;
|
|
505
|
-
const pidToKill = proc && !proc.killed
|
|
506
|
-
? proc.pid
|
|
507
|
-
: (() => { try { return parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10); } catch { return null; } })();
|
|
508
|
-
|
|
509
|
-
if (pidToKill && isProcessAlive(pidToKill)) {
|
|
510
|
-
log(`Killing server (PID: ${pidToKill})...`);
|
|
511
|
-
killProcess(pidToKill, false, sudoPassword);
|
|
512
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
513
|
-
if (isProcessAlive(pidToKill)) killProcess(pidToKill, true, sudoPassword);
|
|
514
|
-
}
|
|
515
|
-
serverProcess = null;
|
|
516
|
-
serverPid = null;
|
|
517
|
-
|
|
518
|
-
if (IS_WIN) {
|
|
519
|
-
// Single elevated script: clean DNS + flush — 1 UAC prompt only
|
|
520
|
-
const hostsFile = path.join(process.env.SystemRoot || "C:\\Windows", "System32", "drivers", "etc", "hosts");
|
|
521
|
-
const psSQ = (s) => s.replace(/'/g, "''");
|
|
522
|
-
const allHosts = Object.values(TOOL_HOSTS).flat();
|
|
523
|
-
|
|
524
|
-
let hostsContent = "";
|
|
525
|
-
try { hostsContent = fs.readFileSync(hostsFile, "utf8"); } catch { /* ignore */ }
|
|
526
|
-
const filtered = hostsContent.split(/\r?\n/)
|
|
527
|
-
.filter(l => !allHosts.some(h => l.includes(h)))
|
|
528
|
-
.join("\r\n");
|
|
529
|
-
const tmpHosts = path.join(os.tmpdir(), `mitm_hosts_clean_${Date.now()}.tmp`);
|
|
530
|
-
fs.writeFileSync(tmpHosts, filtered, "utf8");
|
|
531
|
-
|
|
532
|
-
const psScript = [
|
|
533
|
-
`$ErrorActionPreference = 'Stop'`,
|
|
534
|
-
`try {`,
|
|
535
|
-
` Copy-Item -Path '${psSQ(tmpHosts)}' -Destination '${psSQ(hostsFile)}' -Force -ErrorAction Stop`,
|
|
536
|
-
` ipconfig /flushdns | Out-Null`,
|
|
537
|
-
` Remove-Item '${psSQ(tmpHosts)}' -ErrorAction SilentlyContinue`,
|
|
538
|
-
`} catch {`,
|
|
539
|
-
` Remove-Item '${psSQ(tmpHosts)}' -ErrorAction SilentlyContinue`,
|
|
540
|
-
`}`,
|
|
541
|
-
].join("\n");
|
|
542
|
-
|
|
543
|
-
const tmpPs1 = path.join(os.tmpdir(), `mitm_stop_${Date.now()}.ps1`);
|
|
544
|
-
fs.writeFileSync(tmpPs1, psScript, "utf8");
|
|
545
|
-
await executeElevatedPowerShell(tmpPs1, 30000);
|
|
546
|
-
} else {
|
|
547
|
-
await removeAllDNSEntries(sudoPassword);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
try { fs.unlinkSync(PID_FILE); } catch { /* ignore */ }
|
|
551
|
-
await saveMitmSettings(false, null);
|
|
552
|
-
mitmIsRestarting = false;
|
|
553
|
-
|
|
554
|
-
return { running: false, pid: null };
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Enable DNS for a specific tool (requires server running)
|
|
559
|
-
*/
|
|
560
|
-
async function enableToolDNS(tool, sudoPassword) {
|
|
561
|
-
const status = await getMitmStatus();
|
|
562
|
-
if (!status.running) throw new Error("MITM server is not running. Start the server first.");
|
|
563
|
-
|
|
564
|
-
// Use cached password if not provided
|
|
565
|
-
const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
|
|
566
|
-
await addDNSEntry(tool, password);
|
|
567
|
-
return { success: true };
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* Disable DNS for a specific tool
|
|
572
|
-
*/
|
|
573
|
-
async function disableToolDNS(tool, sudoPassword) {
|
|
574
|
-
// Use cached password if not provided
|
|
575
|
-
const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
|
|
576
|
-
await removeDNSEntry(tool, password);
|
|
577
|
-
return { success: true };
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* Install Root CA to system trust store (standalone, no server start)
|
|
582
|
-
*/
|
|
583
|
-
async function trustCert(sudoPassword) {
|
|
584
|
-
const rootCACertPath = path.join(MITM_DIR, "rootCA.crt");
|
|
585
|
-
if (!fs.existsSync(rootCACertPath)) throw new Error("Root CA not found. Start server first to generate it.");
|
|
586
|
-
const { installCert } = require("./cert/install");
|
|
587
|
-
const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
|
|
588
|
-
if (!password && !IS_WIN) throw new Error("Sudo password required to trust certificate");
|
|
589
|
-
await installCert(password, rootCACertPath);
|
|
590
|
-
if (password) setCachedPassword(password);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// Legacy aliases for backward compatibility
|
|
594
|
-
const startMitm = startServer;
|
|
595
|
-
const stopMitm = stopServer;
|
|
596
|
-
|
|
597
|
-
module.exports = {
|
|
598
|
-
getMitmStatus,
|
|
599
|
-
startServer,
|
|
600
|
-
stopServer,
|
|
601
|
-
enableToolDNS,
|
|
602
|
-
disableToolDNS,
|
|
603
|
-
trustCert,
|
|
604
|
-
// Legacy
|
|
605
|
-
startMitm,
|
|
606
|
-
stopMitm,
|
|
607
|
-
getCachedPassword,
|
|
608
|
-
setCachedPassword,
|
|
609
|
-
loadEncryptedPassword,
|
|
610
|
-
initDbHooks,
|
|
611
|
-
};
|
package/app/src/mitm/paths.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const path = require("path");
|
|
2
|
-
const os = require("os");
|
|
3
|
-
|
|
4
|
-
// Single source of truth for data directory — matches localDb.js logic
|
|
5
|
-
function getDataDir() {
|
|
6
|
-
if (process.env.DATA_DIR) return process.env.DATA_DIR;
|
|
7
|
-
if (process.platform === "win32") {
|
|
8
|
-
return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), "9router");
|
|
9
|
-
}
|
|
10
|
-
return path.join(os.homedir(), ".9router");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const DATA_DIR = getDataDir();
|
|
14
|
-
const MITM_DIR = path.join(DATA_DIR, "mitm");
|
|
15
|
-
|
|
16
|
-
module.exports = { DATA_DIR, MITM_DIR };
|