Skip to content

Commit 0289ad3

Browse files
committed
feat: add ability to test multiple domains in autosearch_preconfig
1 parent 076ccd0 commit 0289ad3

File tree

2 files changed

+188
-47
lines changed

2 files changed

+188
-47
lines changed

cmd/preconfig_tester/preconfig_tester.go

+184-47
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"fmt"
77
"os"
88
"os/exec"
9+
"os/signal"
910
"path/filepath"
1011
"strconv"
1112
"strings"
13+
"syscall"
1214
"time"
1315
)
1416

@@ -40,6 +42,7 @@ var domainList = []struct {
4042
{"4", "speedtest.net"},
4143
{"5", "steampowered.com"},
4244
{"6", "custom"},
45+
{"7", "custom_multiple"},
4346
{"0", "exit"},
4447
}
4548

@@ -99,13 +102,21 @@ func requestElevation() error {
99102
return fmt.Errorf("failed to get executable path: %v", err)
100103
}
101104

102-
cmd := exec.Command("powershell", "Start-Process", executable, "-Verb", "RunAs", "-ArgumentList", "--elevated")
105+
cmd := exec.Command("powershell", "-Command", fmt.Sprintf(`
106+
$proc = Start-Process -FilePath "%s" -Verb RunAs -PassThru -WindowStyle Normal
107+
if ($proc.ExitCode -ne 0) {
108+
exit $proc.ExitCode
109+
}
110+
`, executable))
111+
cmd.Stdout = os.Stdout
112+
cmd.Stderr = os.Stderr
113+
103114
return cmd.Run()
104115
}
105116

106117
func ensureProcessTerminated(processName string) {
107118
cmd := exec.Command("taskkill", "/F", "/IM", processName)
108-
cmd.Run() // Игнорируем ошибки, так как процесс может не существовать
119+
cmd.Run() // Ignore errors as the process may not exist
109120
}
110121

111122
func waitForProcess(processName string, timeout time.Duration) bool {
@@ -138,14 +149,17 @@ func testConnection(domain string, timeout time.Duration) bool {
138149
return err == nil
139150
}
140151

141-
func getDomainChoice() (string, error) {
152+
func getDomainChoice() ([]string, error) {
142153
fmt.Println("\nSelect domain for checking:")
143154
for _, item := range domainList {
144-
if item.domain == "exit" {
155+
switch item.domain {
156+
case "exit":
145157
fmt.Printf("%s. Exit\n", item.number)
146-
} else if item.domain == "custom" {
158+
case "custom":
147159
fmt.Printf("%s. Enter your own domain\n", item.number)
148-
} else {
160+
case "custom_multiple":
161+
fmt.Printf("%s. Enter multiple domains (space-separated)\n", item.number)
162+
default:
149163
fmt.Printf("%s. %s\n", item.number, item.domain)
150164
}
151165
}
@@ -155,7 +169,7 @@ func getDomainChoice() (string, error) {
155169
fmt.Print("\nEnter number of variant: ")
156170
choice, err := reader.ReadString('\n')
157171
if err != nil {
158-
return "", fmt.Errorf("error reading input: %v", err)
172+
return nil, fmt.Errorf("error reading input: %v", err)
159173
}
160174
choice = strings.TrimSpace(choice)
161175

@@ -168,19 +182,41 @@ func getDomainChoice() (string, error) {
168182
}
169183
if item.domain == "custom" {
170184
fmt.Print("Enter domain (for example, example.com): ")
171-
172185
domain, err := reader.ReadString('\n')
173186
if err != nil {
174-
return "", err
187+
return nil, err
175188
}
176189
domain = strings.TrimSpace(domain)
177190
if isValidDomain(domain) {
178-
return formatDomainWithPort(domain), nil
191+
return []string{formatDomainWithPort(domain)}, nil
179192
}
180193
fmt.Println("Invalid domain format. Use format domain.com")
181194
continue
182195
}
183-
return formatDomainWithPort(item.domain), nil
196+
if item.domain == "custom_multiple" {
197+
fmt.Print("Enter domains separated by spaces: ")
198+
domains, err := reader.ReadString('\n')
199+
if err != nil {
200+
return nil, err
201+
}
202+
203+
domainList := strings.Fields(domains)
204+
var formattedDomains []string
205+
206+
for _, domain := range domainList {
207+
if !isValidDomain(domain) {
208+
fmt.Printf("Invalid domain format for '%s'. Use format domain.com\n", domain)
209+
continue
210+
}
211+
formattedDomains = append(formattedDomains, formatDomainWithPort(domain))
212+
}
213+
214+
if len(formattedDomains) > 0 {
215+
return formattedDomains, nil
216+
}
217+
continue
218+
}
219+
return []string{formatDomainWithPort(item.domain)}, nil
184220
}
185221
}
186222
fmt.Printf("Invalid selection. Please select number from 0 to %d\n", len(domainList)-1)
@@ -219,54 +255,102 @@ func formatDomainWithPort(domain string) string {
219255

220256
func checkDPIFingerprint(domain string) (DPITestResult, error) {
221257
cmd := exec.Command("powershell", "-Command", fmt.Sprintf(`
258+
# Save console settings
259+
$originalForeground = $host.UI.RawUI.ForegroundColor
260+
$originalBackground = $host.UI.RawUI.BackgroundColor
261+
262+
# Force TLS 1.2
263+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
264+
222265
try {
223-
$webRequest = [System.Net.WebRequest]::Create("https://%s")
266+
$url = "https://%s"
267+
Write-Information "Trying to connect to $url"
268+
269+
$webRequest = [System.Net.WebRequest]::Create($url)
224270
$webRequest.Timeout = 5000
225-
$response = $webRequest.GetResponse()
226-
$response.Close()
227-
return 0 # NoDPI
228-
} catch [System.Net.WebException] {
229-
if ($_.Exception.Message -like "*actively refused*") {
230-
return 1 # HasDPI
271+
$webRequest.AllowAutoRedirect = $false
272+
273+
try {
274+
$response = $webRequest.GetResponse()
275+
$response.Close()
276+
Write-Output "0" # NoDPI
277+
} catch [System.Net.WebException] {
278+
$exception = $_.Exception
279+
Write-Information "Exception details: $($exception.Message)"
280+
Write-Information "Status: $($exception.Status)"
281+
282+
if ($exception.Message -like "*actively refused*" -or
283+
$exception.Message -like "*connection was forcibly closed*" -or
284+
$exception.Status -eq [System.Net.WebExceptionStatus]::SecureChannelFailure -or
285+
$exception.Status -eq [System.Net.WebExceptionStatus]::TrustFailure -or
286+
$exception.Status -eq [System.Net.WebExceptionStatus]::ProtocolError) {
287+
Write-Output "1" # HasDPI
288+
} elseif ($exception.Status -eq [System.Net.WebExceptionStatus]::NameResolutionFailure) {
289+
Write-Output "2" # DNS resolution failed
290+
Write-Information "DNS resolution failed"
291+
} elseif ($exception.Status -eq [System.Net.WebExceptionStatus]::Timeout) {
292+
Write-Output "1" # Treat timeout as potential DPI
293+
Write-Information "Connection timed out - possible DPI"
294+
} else {
295+
Write-Output "2" # NoConnection
296+
Write-Information "Unknown connection error"
297+
}
231298
}
232-
return 2 # NoConnection
299+
} catch {
300+
Write-Output "2" # NoConnection
301+
Write-Information "Unexpected error: $_"
302+
} finally {
303+
# Restore console settings
304+
$host.UI.RawUI.ForegroundColor = $originalForeground
305+
$host.UI.RawUI.BackgroundColor = $originalBackground
233306
}
307+
exit 0
234308
`, domain))
235309

310+
cmd.Stderr = os.Stderr // Show diagnostic output
236311
output, err := cmd.Output()
237312
if err != nil {
238-
return NoConnection, err
313+
if len(output) == 0 {
314+
return NoConnection, fmt.Errorf("no output from DPI check: %v", err)
315+
}
239316
}
240317

241-
result, err := strconv.Atoi(strings.TrimSpace(string(output)))
318+
// Берем только последнюю строку вывода, которая содержит результат
319+
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
320+
result, err := strconv.Atoi(lines[len(lines)-1])
242321
if err != nil {
243-
return NoConnection, err
322+
return NoConnection, fmt.Errorf("invalid output from DPI check: %v", err)
244323
}
245324

246325
return DPITestResult(result), nil
247326
}
248327

249328
func runBypassCheck(config Config) error {
250-
domainWithoutPort := strings.Split(config.targetDomain, ":")[0]
329+
domains := strings.Split(config.targetDomain, " ")
251330

252-
fmt.Printf("\nStarting testing domain: %s\n", config.targetDomain)
331+
fmt.Printf("\nStarting testing domains: %s\n", config.targetDomain)
253332
fmt.Println("------------------------------------------------")
254333

255-
fmt.Println("Checking DPI blocks...")
256-
result, err := checkDPIFingerprint(domainWithoutPort)
257-
if err != nil {
258-
fmt.Printf("Error occurred while checking: %v\n", err)
259-
} else {
260-
fmt.Printf("Checking result: %s\n", result)
334+
// Check DPI for each domain
335+
for _, domain := range domains {
336+
// Remove port before DPI check but keep it for display
337+
domainForCheck := strings.Split(domain, ":")[0]
338+
fmt.Printf("\nChecking DPI blocks for %s...\n", domainForCheck)
339+
result, err := checkDPIFingerprint(domainForCheck)
340+
if err != nil {
341+
fmt.Printf("Checking result for %s: %s (with error: %v)\n", domainForCheck, result, err)
342+
} else {
343+
fmt.Printf("Checking result for %s: %s\n", domainForCheck, result)
344+
}
261345

262346
if result == NoDPI {
263-
fmt.Println("Using DPI spoofer not required.")
264-
return nil
347+
fmt.Printf("Using DPI spoofer not required for %s.\n", domainForCheck)
348+
continue
265349
}
266350

267351
if result == NoConnection {
268-
fmt.Println("Check internet connection and if domain is correct.")
269-
return nil
352+
fmt.Printf("Check internet connection and if domain %s is correct.\n", domainForCheck)
353+
continue
270354
}
271355
}
272356

@@ -282,10 +366,44 @@ func runBypassCheck(config Config) error {
282366
for _, batFile := range batFiles {
283367
fmt.Printf("\n%sRunning pre-config: %s%s\n", colorMagenta, batFile, colorReset)
284368

285-
// Ensure no previous process is running
286369
ensureProcessTerminated(config.processName)
287370

288-
cmd := exec.Command("cmd", "/c", batFile)
371+
cmd := exec.Command("powershell", "-Command", fmt.Sprintf(`
372+
# Save console settings
373+
$originalForeground = $host.UI.RawUI.ForegroundColor
374+
$originalBackground = $host.UI.RawUI.BackgroundColor
375+
$originalBufferSize = $host.UI.RawUI.BufferSize
376+
$originalWindowSize = $host.UI.RawUI.WindowSize
377+
378+
# Save font settings
379+
$key = 'HKCU:\Console'
380+
$originalFontSize = Get-ItemProperty -Path $key -Name 'FontSize' -ErrorAction SilentlyContinue
381+
$originalFaceName = Get-ItemProperty -Path $key -Name 'FaceName' -ErrorAction SilentlyContinue
382+
$originalFontFamily = Get-ItemProperty -Path $key -Name 'FontFamily' -ErrorAction SilentlyContinue
383+
384+
try {
385+
# Execute BAT file
386+
cmd /c "%s"
387+
} finally {
388+
# Restore console settings
389+
$host.UI.RawUI.ForegroundColor = $originalForeground
390+
$host.UI.RawUI.BackgroundColor = $originalBackground
391+
$host.UI.RawUI.BufferSize = $originalBufferSize
392+
$host.UI.RawUI.WindowSize = $originalWindowSize
393+
394+
# Restore font settings
395+
if ($originalFontSize) {
396+
Set-ItemProperty -Path $key -Name 'FontSize' -Value $originalFontSize.FontSize
397+
}
398+
if ($originalFaceName) {
399+
Set-ItemProperty -Path $key -Name 'FaceName' -Value $originalFaceName.FaceName
400+
}
401+
if ($originalFontFamily) {
402+
Set-ItemProperty -Path $key -Name 'FontFamily' -Value $originalFontFamily.FontFamily
403+
}
404+
}
405+
`, batFile))
406+
289407
cmd.Stdout = os.Stdout
290408
cmd.Stderr = os.Stderr
291409

@@ -300,35 +418,52 @@ func runBypassCheck(config Config) error {
300418
continue
301419
}
302420

303-
if testConnection(config.targetDomain, config.connectionTimeout) {
421+
// Check all domains
422+
allDomainsWork := true
423+
for _, domain := range domains {
424+
if !testConnection(domain, config.connectionTimeout) {
425+
fmt.Printf("%s[FAIL] Failed to establish connection to %s using pre-config: %s%s\n",
426+
colorRed, domain, batFile, colorReset)
427+
allDomainsWork = false
428+
break
429+
}
430+
}
431+
432+
if allDomainsWork {
304433
filename := filepath.Base(batFile)
305-
fmt.Printf("\n%s!!!!!!!!!!!!!\n[SUCCESS] It seems, this pre-config is suitable for you - %s\n!!!!!!!!!!!!!\n%s\n",
434+
fmt.Printf("\n%s!!!!!!!!!!!!!\n[SUCCESS] It seems, this pre-config is suitable for all specified domains - %s\n!!!!!!!!!!!!!\n%s\n",
306435
colorGreen, filename, colorReset)
307436
cmd.Process.Kill()
308437
success = true
309438
break
310-
} else {
311-
fmt.Printf("%s[FAIL] Failed to establish connection using pre-config: %s%s\n",
312-
colorRed, batFile, colorReset)
313-
cmd.Process.Kill()
314439
}
440+
441+
cmd.Process.Kill()
315442
}
316443

317-
// Final cleanup
318444
ensureProcessTerminated(config.processName)
319445
time.Sleep(500 * time.Millisecond)
320446
ensureProcessTerminated(config.processName)
321447

322448
if !success {
323449
fmt.Println("\n------------------------------------------------")
324-
fmt.Println("Unfortunately, not found pre-config we can establish connection with :(")
450+
fmt.Println("Unfortunately, not found pre-config we can establish connection with for all specified domains :(")
325451
fmt.Println("Try to run BLOCKCHECK, to find necessary parameters for BAT file.")
326452
}
327453

328454
return nil
329455
}
330456

331457
func main() {
458+
// Add signal handling at the start of main
459+
c := make(chan os.Signal, 1)
460+
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
461+
go func() {
462+
<-c
463+
fmt.Print(showCursor + exitAltScreen)
464+
os.Exit(1)
465+
}()
466+
332467
var buf bytes.Buffer
333468
buf.Grow(bufferSize)
334469

@@ -354,26 +489,28 @@ func main() {
354489
return
355490
}
356491
fmt.Print(showCursor + exitAltScreen)
492+
// Wait a bit to ensure new process starts
493+
time.Sleep(1 * time.Second)
357494
os.Exit(0)
358495
}
359496

360-
targetDomain, err := getDomainChoice()
497+
targetDomains, err := getDomainChoice()
361498
if err != nil {
362499
fmt.Printf("Error: %v\n", err)
363500
return
364501
}
365502

366503
config := Config{
367504
batchDir: "pre-configs",
368-
targetDomain: targetDomain,
505+
targetDomain: strings.Join(targetDomains, " "),
369506
processName: "winws.exe",
370507
processWaitTime: 10 * time.Second,
371508
connectionTimeout: 5 * time.Second,
372509
}
373510

374511
// Use buffered output for all writes
375512
buf.Reset()
376-
buf.WriteString(fmt.Sprintf("\nStarting testing domain: %s\n", config.targetDomain))
513+
buf.WriteString(fmt.Sprintf("\nStarting testing domains: %s\n", config.targetDomain))
377514
output.Write(buf.Bytes())
378515
output.Flush()
379516

cmd/run_preconfig/run_preconfig.go

+4
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ func runMainLoop(buf *bytes.Buffer, options []string, startRow, termHeight int)
171171
buf.WriteString(fmt.Sprintf("%s↑ more items above%s\n", colorGrey, colorReset))
172172
}
173173

174+
if currentSelection >= len(options) {
175+
currentSelection = len(options) - 1
176+
}
177+
174178
endIdx := min(scrollOffset+maxVisibleOptions, len(options))
175179

176180
if currentSelection >= scrollOffset+maxVisibleOptions-1 {

0 commit comments

Comments
 (0)