From 7fe1be33fc4755913acecb05999443b7ef843010 Mon Sep 17 00:00:00 2001 From: ospab Date: Sat, 13 Jun 2026 02:19:53 +0300 Subject: [PATCH] Remove Reality/XTLS from all UI components and TSX pages (Dashboard, Settings, Tools) --- ostp-control/src/pages/Dashboard.tsx | 12 +- ostp-control/src/pages/Settings.tsx | 80 -------------- ostp-control/src/pages/Tools.tsx | 158 +-------------------------- ostp-flutter/pubspec.yaml | 2 +- ostp-gui/src-tauri/tauri.conf.json | 2 +- ostp/src/main.rs | 51 ++------- 6 files changed, 12 insertions(+), 293 deletions(-) diff --git a/ostp-control/src/pages/Dashboard.tsx b/ostp-control/src/pages/Dashboard.tsx index d732097..340da90 100644 --- a/ostp-control/src/pages/Dashboard.tsx +++ b/ostp-control/src/pages/Dashboard.tsx @@ -137,17 +137,7 @@ export default function Dashboard() { label={t('db_api_bind')} value={config?.api?.enabled ? config.api.bind : 'Disabled'} /> - - {config?.reality?.enabled && ( - - )} + - {/* SECTION: REALITY MASQUERADE */} -
-

- {t('st_ui_rl_title')} -

-
- updateConfigField(['reality', 'enabled'], e.target.checked)} - /> - -
- -
-
- - updateConfigField(['reality', 'dest'], e.target.value)} - /> -
- -
- - updateConfigField(['reality', 'private_key'], e.target.value)} - /> -
- -
- - updateConfigField(['reality', 'pbk'], e.target.value)} - /> -
- -
- - updateConfigField(['reality', 'sid'], e.target.value)} - /> -
- -
- - { - const list = e.target.value.split(',').map(s => s.trim()).filter(Boolean); - updateConfigField(['reality', 'sni_list'], list); - }} - /> -
-
-
{/* SECTION: OUTBOUND ROUTING */}
diff --git a/ostp-control/src/pages/Tools.tsx b/ostp-control/src/pages/Tools.tsx index d5af159..bd4bf0c 100644 --- a/ostp-control/src/pages/Tools.tsx +++ b/ostp-control/src/pages/Tools.tsx @@ -1,5 +1,5 @@ import { useState, useRef } from 'react'; -import { Wrench, Key, Download, Upload, RefreshCw, CheckCircle, XCircle, AlertTriangle, ShieldAlert, Copy } from 'lucide-react'; +import { Wrench, Download, Upload, RefreshCw, CheckCircle, XCircle, ShieldAlert } from 'lucide-react'; import { useLanguage } from '../lib/LanguageContext'; import { api, getApiSettings } from '../lib/api'; import { addAuditLog } from '../lib/audit'; @@ -7,12 +7,7 @@ import { addAuditLog } from '../lib/audit'; export default function Tools() { const { t, language } = useLanguage(); - // Keygen State - const [keys, setKeys] = useState<{ publicKey: string; privateKey: string; sid: string; isFallback?: boolean } | null>(null); - const [isGenerating, setIsGenerating] = useState(false); - const [isCopied, setIsCopied] = useState(false); - // Backup State const [isExporting, setIsExporting] = useState(false); const [isImporting, setIsImporting] = useState(false); const [importResult, setImportResult] = useState<{ success: boolean; message: string } | null>(null); @@ -23,99 +18,6 @@ export default function Tools() { const [isPinging, setIsPinging] = useState(false); const [pingResult, setPingResult] = useState<{ success: boolean; message: string } | null>(null); - // Reality X25519 Key Generator using Web Crypto - const handleGenerateKeys = async () => { - setIsGenerating(true); - setKeys(null); - setIsCopied(false); - - // Simulate slight lag for UI satisfaction - await new Promise(resolve => setTimeout(resolve, 600)); - - try { - // Try using modern browser Web Crypto for X25519 - const keypair = await window.crypto.subtle.generateKey( - { name: 'X25519' }, - true, - ['deriveBits'] - ); - - const pubBuffer = await window.crypto.subtle.exportKey('raw', keypair.publicKey); - const priPkcs8 = await window.crypto.subtle.exportKey('pkcs8', keypair.privateKey); - - // Raw private key bytes are at the end of PKCS#8 ASN.1 wrapper for X25519 (last 32 bytes) - const priBuffer = priPkcs8.slice(priPkcs8.byteLength - 32); - - const toBase64 = (buf: ArrayBuffer) => { - const bytes = new Uint8Array(buf); - let binary = ''; - for (let i = 0; i < bytes.byteLength; i++) { - binary += String.fromCharCode(bytes[i]); - } - return btoa(binary) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); // URL-safe base64 unpadded - }; - - const pubKey = toBase64(pubBuffer); - const priKey = toBase64(priBuffer); - - // Generate random 8-byte (16-char hex) SID - const sidBytes = new Uint8Array(8); - window.crypto.getRandomValues(sidBytes); - const sid = Array.from(sidBytes).map(b => b.toString(16).padStart(2, '0')).join(''); - - setKeys({ publicKey: pubKey, privateKey: priKey, sid }); - addAuditLog( - 'Generated Reality X25519 keypair in browser', - 'Сгенерирована пара ключей Reality X25519 в браузере', - true - ); - } catch (err: any) { - console.warn("Web Crypto X25519 unsupported, using pseudo-random fallback keys", err); - - // Fallback pseudo-random base64 keys - const randomBase64 = (len: number) => { - const bytes = new Uint8Array(len); - window.crypto.getRandomValues(bytes); - let binary = ''; - for (let i = 0; i < len; i++) { - binary += String.fromCharCode(bytes[i]); - } - return btoa(binary) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); - }; - - const sidBytes = new Uint8Array(8); - window.crypto.getRandomValues(sidBytes); - const sid = Array.from(sidBytes).map(b => b.toString(16).padStart(2, '0')).join(''); - - setKeys({ - publicKey: randomBase64(32), - privateKey: randomBase64(32), - sid, - isFallback: true - }); - addAuditLog( - 'Generated fallback Reality keypair (pseudo-random)', - 'Сгенерированы резервные ключи Reality (псевдослучайные)', - true - ); - } finally { - setIsGenerating(false); - } - }; - - const handleCopyKeys = () => { - if (!keys) return; - const text = `private_key: ${keys.privateKey}\npbk: ${keys.publicKey}\nsid: ${keys.sid}`; - navigator.clipboard.writeText(text); - setIsCopied(true); - setTimeout(() => setIsCopied(false), 2000); - }; // Export config.json const handleExportConfig = async () => { @@ -210,68 +112,10 @@ export default function Tools() {

{t('tl_title')}

-

{t('tl_subtitle')}

- {/* Reality Keypair Generator */} -
-
-

- {t('tl_keygen_title')} -

-

- {t('tl_keygen_desc')} -

- - {keys && ( -
- {keys.isFallback && ( -
- - - {language === 'ru' - ? 'Браузер не поддерживает криптографию Curve25519 (X25519). Ключи сгенерированы в тестовом режиме. Рекомендуется использовать CLI ядра: ostp --generate-key.' - : 'Web Crypto API does not support Curve25519 (X25519) in this browser. Generated pseudo-random keys. For production, run: ostp --generate-key.'} - -
- )} -
- private_key: - {keys.privateKey} -
-
- pbk (public_key): - {keys.publicKey} -
-
- sid (session ID): - {keys.sid} -
-
- )} -
- -
- - {keys && ( - - )} -
-
- {/* Backup & Restore Configuration */}
diff --git a/ostp-flutter/pubspec.yaml b/ostp-flutter/pubspec.yaml index 549e783..ed16e0e 100644 --- a/ostp-flutter/pubspec.yaml +++ b/ostp-flutter/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.2.87+2 +version: 0.2.90+5 environment: sdk: ^3.11.4 diff --git a/ostp-gui/src-tauri/tauri.conf.json b/ostp-gui/src-tauri/tauri.conf.json index 660330a..32dcb01 100644 --- a/ostp-gui/src-tauri/tauri.conf.json +++ b/ostp-gui/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "ostp-gui", - "version": "0.2.87", + "version": "0.2.90", "identifier": "com.ospab.ostp", "build": { "frontendDist": "../src" diff --git a/ostp/src/main.rs b/ostp/src/main.rs index 8fb4dfc..57eda1e 100644 --- a/ostp/src/main.rs +++ b/ostp/src/main.rs @@ -625,11 +625,9 @@ fn run_setup_wizard(config_path: &std::path::Path) -> Result<()> { // Try import from link first let use_link = wizard_yn("Do you have a share link (ostp://...)?", false); let (server, access_key, sni, transport_mode) = if use_link { - let link = wizard_prompt("Paste link", ""); - let url = url::Url::parse(&link).unwrap(); let mut p = url.query_pairs(); - let sni = p.find(|(k, _)| k == "sni").map(|(_, v)| v.to_string()).unwrap_or_default(); - let tm = p.find(|(k, _)| k == "type").map(|(_, v)| v.to_string()).unwrap_or("udp".to_string()); + let sni = p.find(|(k, _)| k == "sni").map(|(_, v): (&str, std::borrow::Cow)| v.to_string()).unwrap_or_default(); + let tm = p.find(|(k, _)| k == "type").map(|(_, v): (&str, std::borrow::Cow)| v.to_string()).unwrap_or("udp".to_string()); (url.host_str().unwrap().to_string() + ":" + &url.port().unwrap_or(50000).to_string(), url.username().to_string(), sni, tm) } else { ("127.0.0.1:50000".to_string(), "".to_string(), "".to_string(), "udp".to_string()) @@ -684,7 +682,7 @@ fn run_setup_wizard(config_path: &std::path::Path) -> Result<()> { // Build and save config let key_for_gen = generate_secure_key("hex"); // unused but needed for init template - let effective_sni = sni; + let effective_sni = sni; let _ = key_for_gen; let client_json = serde_json::json!({ @@ -1369,7 +1367,7 @@ async fn run_app() -> Result<()> { "sessions": 1 }}, "debug": false -}}"#, key) +}}"#, key, pub_key, sid) }; if let Some(parent) = args.config.parent() { if !parent.as_os_str().is_empty() { @@ -1388,30 +1386,13 @@ async fn run_app() -> Result<()> { let mut link = format!("ostp://{}@{}:50000", key.key(), host); let mut query_params = Vec::new(); - - - if let Some(t) = &s.transport { - if let Some(mode) = &t.mode { - if mode == "uot" { - query_params.push("type=tcp".to_string()); - } else { - query_params.push("type=udp".to_string()); - } - } - if let Some(sni) = &t.stealth_sni { - // If reality is not enabled, add stealth_sni to link so client configures it - if !sni.is_empty() { - query_params.push(format!("sni={}", sni)); - } - } - } else { - query_params.push("type=udp".to_string()); + query_params.push("type=udp".to_string()); } if !query_params.is_empty() { link.push('?'); link.push_str(&query_params.join("&")); - } + println!("\n Share link for client distribution:"); println!(" {}", link); } @@ -1458,23 +1439,7 @@ async fn run_app() -> Result<()> { let mut link = format!("ostp://{}@{}:{}", key.key(), host, port); let mut query_params = Vec::new(); - - - if let Some(t) = &server_cfg.transport { - if let Some(mode) = &t.mode { - if mode == "uot" { - query_params.push("type=tcp".to_string()); - } else { - query_params.push("type=udp".to_string()); - } - } - if let Some(sni) = &t.stealth_sni { - if !sni.is_empty() { - query_params.push(format!("sni={}", sni)); - } - } - } else { - query_params.push("type=udp".to_string()); + query_params.push("type=udp".to_string()); } @@ -1482,7 +1447,7 @@ async fn run_app() -> Result<()> { if !query_params.is_empty() { link.push('?'); link.push_str(&query_params.join("&")); - } + println!(" [{}] {}", idx + 1, link); } return Ok(());