-
Notifications
You must be signed in to change notification settings - Fork 15
/
batch-fragment-test.ps1
274 lines (218 loc) · 10.3 KB
/
batch-fragment-test.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# Check if running on Windows 10 or Windows 11
$osVersion = [System.Environment]::OSVersion.Version
if ($osVersion.Major -eq 10) {
# For Windows 10, set execution policy to Bypass
Set-ExecutionPolicy Bypass -Scope Process
} elseif ($osVersion.Major -eq 11) {
# For Windows 11, set execution policy to RemoteSigned
Set-ExecutionPolicy RemoteSigned -Scope Process
} else {
Write-Host "Unsupported version of Windows. Exiting script."
exit
}
# Path to the xray executable and config file in the same folder as the script
$XRAY_PATH = Join-Path -Path $PSScriptRoot -ChildPath "xray.exe"
$CONFIG_PATH = Join-Path -Path $PSScriptRoot -ChildPath "config.json"
$LOG_FILE = Join-Path -Path $PSScriptRoot -ChildPath "pings.txt"
$XRAY_LOG_FILE = Join-Path -Path $PSScriptRoot -ChildPath "xraylogs.txt"
# Enclose paths with spaces in double quotes
$XRAY_PATH = "$XRAY_PATH"
$CONFIG_PATH = "$CONFIG_PATH"
$LOG_FILE = "$LOG_FILE"
$XRAY_LOG_FILE = "$XRAY_LOG_FILE"
# Check if xray.exe exists
if (-Not (Test-Path -Path $XRAY_PATH)) {
Write-Host "Error: xray.exe not found"
exit
}
# Create pings.txt and xraylogs.txt if they do not exist
if (-Not (Test-Path -Path $LOG_FILE)) {
New-Item -Path $LOG_FILE -ItemType File
}
if (-Not (Test-Path -Path $XRAY_LOG_FILE)) {
New-Item -Path $XRAY_LOG_FILE -ItemType File
}
# Clear the content of the log files before running the tests
Clear-Content -Path $LOG_FILE
Clear-Content -Path $XRAY_LOG_FILE
# Prompt user for input values with defaults
$InstancesInput = Read-Host -Prompt "Enter the number of instances (default is 10)"
$TimeoutSecInput = Read-Host -Prompt "Enter the timeout for each ping test in seconds (default is 10)"
$HTTP_PROXY_PORTInput = Read-Host -Prompt "Enter the HTTP Listening port (default is 10809)"
$PingCountInput = Read-Host -Prompt "Enter the number of requests per instance (default is 3)"
# Set default values if inputs are empty
$Instances = if ($InstancesInput) { [int]$InstancesInput } else { 10 }
$TimeoutSec = if ($TimeoutSecInput) { [int]$TimeoutSecInput } else { 10 }
$HTTP_PROXY_PORT = if ($HTTP_PROXY_PORTInput) { [int]$HTTP_PROXY_PORTInput } else { 10809 }
$PingCount = if ($PingCountInput) { [int]$PingCountInput + 1 } else { 4 } # Add 1 to the user input to account for the extra request
# HTTP Proxy server address
$HTTP_PROXY_SERVER = "127.0.0.1"
# Arrays of possible values for packets, length, and interval
$packetsOptions = @("1-1", "1-2", "1-3", "1-5")
$lengthOptions = @("1-1", "1-2", "1-3", "2-5", "1-5", "1-10", "3-5", "5-10", "3-10", "10-15", "10-30", "10-20", "20-50", "50-100", "100-150")
$intervalOptions = @("1-1", "1-2", "3-5", "1-5", "5-10", "10-15", "10-20", "20-30", "20-50", "40-50", "50-100", "50-80", "100-150", "150-200", "100-200")
# Calculate the maximum possible instances
$maxPossibleInstances = $packetsOptions.Count * $lengthOptions.Count * $intervalOptions.Count
# Validate user input for instances against the maximum possible instances
while ($Instances -gt $maxPossibleInstances) {
Write-Host "Error: Number of instances cannot be greater than the maximum possible instances ($maxPossibleInstances)"
$InstancesInput = Read-Host -Prompt "Enter the number of instances (default is 10)"
$Instances = if ($InstancesInput) { [int]$InstancesInput } else { 10 }
}
# Array to store top three lowest average response times
$topThree = @()
# Function to randomly select a value from an array
function Get-RandomValue {
param (
[array]$options
)
$randomIndex = Get-Random -Minimum 0 -Maximum $options.Length
return $options[$randomIndex]
}
# Function to generate a unique combination of packets, length, and interval values
function Get-UniqueCombination {
$combination = $null
$usedCombinations = New-Object System.Collections.ArrayList
do {
$packets = Get-RandomValue -options $packetsOptions
$length = Get-RandomValue -options $lengthOptions
$interval = Get-RandomValue -options $intervalOptions
$combination = "$packets,$length,$interval"
} while ($usedCombinations -contains $combination)
[void]$usedCombinations.Add($combination)
return $packets, $length, $interval
}
# Function to modify config.json with random parameters
function Modify-Config {
param (
[string]$packets,
[string]$length,
[string]$interval
)
$config = Get-Content -Path $CONFIG_PATH | Out-String | ConvertFrom-Json
# Find the outbound with tag 'fragment' and modify its fragment settings
$fragmentOutbound = $config.outbounds | Where-Object { $_.tag -eq 'fragment' }
if ($fragmentOutbound -ne $null) {
$fragmentOutbound.settings.fragment.packets = $packets
$fragmentOutbound.settings.fragment.length = $length
$fragmentOutbound.settings.fragment.interval = $interval
} else {
Write-Host "No 'fragment' outbound found in config.json"
return
}
$config | ConvertTo-Json -Depth 100 | Set-Content -Path $CONFIG_PATH
}
# Function to stop the Xray process
function Stop-XrayProcess {
try {
Stop-Process -Name "xray" -Force -ErrorAction Stop
} catch {
# Do not display "Xray process not found" message
}
}
# Function to perform HTTP requests with proxy and measure response time
function Send-HTTPRequest {
param (
[int]$pingCount,
[int]$timeout = $TimeoutSec * 1000 # Convert seconds to milliseconds
)
# Set the target URL
$url = "http://cp.cloudflare.com"
# Initialize variables to store total time and count of pings
$totalTime = 0
$individualTimes = @()
# Ping the specified number of times and measure the time for each ping
for ($i = 1; $i -le $pingCount; $i++) {
# Create a WebRequest object
$request = [System.Net.HttpWebRequest]::Create($url)
# Set the timeout for the request
$request.Timeout = $timeout
# Set the proxy settings
$proxy = New-Object System.Net.WebProxy($HTTP_PROXY_SERVER, $HTTP_PROXY_PORT)
$request.Proxy = $proxy
try {
$elapsedTime = Measure-Command {
# Send the HTTP request and get the response
$response = $request.GetResponse()
}
# Accumulate total time
$totalTime += $elapsedTime.TotalMilliseconds
$individualTimes += $elapsedTime.TotalMilliseconds
} catch {
$individualTimes += -1 # Mark failed requests with -1
}
# Add a 1-second delay between each ping
Start-Sleep -Seconds 1
}
# Skip the first ping result
$individualTimes = $individualTimes[1..($individualTimes.Count - 1)]
# Calculate average ping time, considering -1 as timeout
$validPings = $individualTimes | Where-Object { $_ -ne -1 }
if ($validPings.Count -gt 0) {
$totalValidTime = $validPings | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$averagePing = ($totalValidTime + ($individualTimes.Count - $validPings.Count) * $timeout) / ($pingCount - 1)
} else {
$averagePing = 0
}
# Log individual ping times to pings.txt
Add-Content -Path $LOG_FILE -Value "Individual Ping Times:"
Add-Content -Path $LOG_FILE -Value ($individualTimes -join ",")
return $averagePing
}
# Main script
# Clear the content of the log files before running the tests
Clear-Content -Path $LOG_FILE
Clear-Content -Path $XRAY_LOG_FILE
# Create a table header
$tableHeader = @"
+--------------+-----------------+---------------+-----------------+---------------+
| Instance | Packets | Length | Interval | Average Ping |
+--------------+-----------------+---------------+-----------------+---------------+
"@
# Write the table header to the console
Write-Host $tableHeader
for ($i = 0; $i -lt $Instances; $i++) {
$packets, $length, $interval = Get-UniqueCombination
Modify-Config -packets $packets -length $length -interval $interval
# Stop Xray process if running
Stop-XrayProcess
# Start Xray process and redirect output to xraylogs.txt
Start-Process -NoNewWindow -FilePath "$XRAY_PATH" -ArgumentList "-c `"$CONFIG_PATH`"" -RedirectStandardOutput "$XRAY_LOG_FILE" -RedirectStandardError "$XRAY_LOG_FILE.Error"
Start-Sleep -Seconds 3
Add-Content -Path $LOG_FILE -Value "Testing with packets=$packets, length=$length, interval=$interval..."
$averagePing = Send-HTTPRequest -pingCount $PingCount
Add-Content -Path $LOG_FILE -Value "Average Ping Time: $averagePing ms`n"
# Add the average ping time along with fragment values to the top three list
$topThree += [PSCustomObject]@{
Instance = $i + 1
Packets = $packets
Length = $length
Interval = $interval
AverageResponseTime = $averagePing
}
# Display the results in table format
$averagePingRounded = "{0:N2}" -f $averagePing
$tableRow = @"
| {0,-9} | {1,-15} | {2,-13} | {3,-15} | {4,-13} |
"@ -f ($i + 1), $packets, $length, $interval, $averagePingRounded
Write-Host $tableRow
# Add a one-second delay between each test instance
Start-Sleep -Seconds 1
}
# Create a table footer
$tableFooter = @"
+--------------+-----------------+---------------+-----------------+---------------+
"@
# Write the table footer to the console
Write-Host $tableFooter
# Filter out entries with an average response time of 0 ms
$validResults = $topThree | Where-Object { $_.AverageResponseTime -gt 0 }
# Sort the top three list by average response time in ascending order
$sortedTopThree = $validResults | Sort-Object -Property AverageResponseTime | Select-Object -First 3
# Display the top three lowest average response times along with their corresponding fragment values
Write-Host "Top three lowest average response times:"
$sortedTopThree | Format-Table -Property Instance, Packets, Length, Interval, @{Name='AverageResponseTime (ms)';Expression={[math]::Round($_.AverageResponseTime, 2)}}
# Stop Xray process if running
Stop-XrayProcess
# Prevent the PowerShell window from closing immediately
Read-Host -Prompt "Press Enter to exit the script..."