mirror of
https://github.com/R0GGER/public-iperf3-servers.git
synced 2026-11-11 01:00:07 +01:00
* Updated Server List URL * Adapted to New JSON Format * Improved Closest Server Logic * Enhanced Port Handling
This commit is contained in:
1 parent
9a433ee8a0
commit
923a613e6b
1 file changed
+174
-99
+174
-99
@@ -12,7 +12,6 @@ NC='\033[0m' # No Color
|
||||
install_packages() {
|
||||
echo "Installing required packages..."
|
||||
if [ -f /etc/debian_version ]; then
|
||||
# Force non-interactive mode for apt
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y iperf3 jq curl bc sudo || {
|
||||
@@ -31,7 +30,6 @@ install_packages() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify installations
|
||||
for cmd in iperf3 jq curl bc; do
|
||||
if ! command -v $cmd &>/dev/null; then
|
||||
echo -e "${RED}Failed to install $cmd. Please install it manually.${NC}"
|
||||
@@ -63,6 +61,67 @@ haversine() {
|
||||
echo $distance
|
||||
}
|
||||
|
||||
construct_iperf_command() {
|
||||
local host=$1
|
||||
local port=$2
|
||||
local command="iperf3 -c $host"
|
||||
if [ -n "$port" ]; then
|
||||
command="$command -p $port"
|
||||
fi
|
||||
echo "$command"
|
||||
}
|
||||
|
||||
run_iperf_test() {
|
||||
local host=$1
|
||||
local port_spec=$2
|
||||
local output
|
||||
|
||||
# Default command if no port spec
|
||||
if [ -z "$port_spec" ]; then
|
||||
iperf3 -c "$host"
|
||||
return
|
||||
fi
|
||||
|
||||
local ports_to_try=()
|
||||
if [[ "$port_spec" =~ ([0-9]+)-([0-9]+) ]]; then
|
||||
local start_port=${BASH_REMATCH[1]}
|
||||
local end_port=${BASH_REMATCH[2]}
|
||||
# Add first port as preferred
|
||||
ports_to_try+=($start_port)
|
||||
# Add a random port from the rest of the range if available
|
||||
if [ "$start_port" -lt "$end_port" ]; then
|
||||
if command -v shuf &> /dev/null; then
|
||||
ports_to_try+=($(shuf -i $((start_port + 1))-$end_port -n 1))
|
||||
else
|
||||
# Fallback for systems without shuf
|
||||
ports_to_try+=($((RANDOM % (end_port - start_port) + start_port + 1)))
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Single port
|
||||
ports_to_try+=($port_spec)
|
||||
fi
|
||||
|
||||
for port in "${ports_to_try[@]}"; do
|
||||
echo "Testing $host on port $port..."
|
||||
output=$(iperf3 -c "$host" -p "$port" 2>&1)
|
||||
echo "$output"
|
||||
|
||||
# If it's NOT busy, we're done.
|
||||
if ! echo "$output" | grep -q "the server is busy"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If it was busy and there are more ports to try...
|
||||
if [ ${#ports_to_try[@]} -gt 1 ] && [ "$port" == "${ports_to_try[0]}" ]; then
|
||||
echo -e "${YELLOW}Server is busy. Trying another port...${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "${RED}All attempted ports were busy.${NC}"
|
||||
return 1
|
||||
}
|
||||
|
||||
show_top_3_servers() {
|
||||
local current_server=$1
|
||||
local current_distance=$2
|
||||
@@ -73,31 +132,30 @@ show_top_3_servers() {
|
||||
echo "$current_server $current_distance" > "$temp_file"
|
||||
|
||||
while read -r server_info; do
|
||||
local ip_host=$(echo "$server_info" | jq -r '.IP_HOST')
|
||||
if [[ $ip_host =~ iperf3[[:space:]]+-c[[:space:]]+([^[:space:]]+) ]]; then
|
||||
local ip="${BASH_REMATCH[1]}"
|
||||
local site=$(echo "$server_info" | jq -r '.SITE')
|
||||
local country=$(echo "$server_info" | jq -r '.COUNTRY')
|
||||
local ip_host=$(echo "$server_info" | jq -r '.["IP/HOST"]')
|
||||
local port=$(echo "$server_info" | jq -r '.PORT')
|
||||
local site=$(echo "$server_info" | jq -r '.SITE')
|
||||
local country=$(echo "$server_info" | jq -r '.COUNTRY')
|
||||
local ip_host_cmd=$(construct_iperf_command "$ip_host" "$port")
|
||||
|
||||
[ "$ip" = "$current_server" ] && continue
|
||||
[ "$ip_host" = "$current_server" ] && continue
|
||||
|
||||
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
SERVER_INFO=$(curl -s "https://ipinfo.io/$ip/json")
|
||||
if [[ $ip_host =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
SERVER_INFO=$(curl -s "https://ipinfo.io/$ip_host/json")
|
||||
SERVER_LOC=$(echo "$SERVER_INFO" | jq -r '.loc')
|
||||
else
|
||||
resolved_ip=$(dig +short "$ip_host" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
|
||||
if [ -n "$resolved_ip" ]; then
|
||||
SERVER_INFO=$(curl -s "https://ipinfo.io/$resolved_ip/json")
|
||||
SERVER_LOC=$(echo "$SERVER_INFO" | jq -r '.loc')
|
||||
else
|
||||
resolved_ip=$(dig +short "$ip" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
|
||||
if [ -n "$resolved_ip" ]; then
|
||||
SERVER_INFO=$(curl -s "https://ipinfo.io/$resolved_ip/json")
|
||||
SERVER_LOC=$(echo "$SERVER_INFO" | jq -r '.loc')
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$SERVER_LOC" ]; then
|
||||
SERVER_LAT=$(echo "$SERVER_LOC" | cut -d',' -f1)
|
||||
SERVER_LON=$(echo "$SERVER_LOC" | cut -d',' -f2)
|
||||
distance=$(haversine $MY_LAT $MY_LON $SERVER_LAT $SERVER_LON)
|
||||
printf "%s\t%s\t%s\t%.2f\n" "$ip_host" "$site" "$country" "$distance" >> "$temp_file"
|
||||
fi
|
||||
if [ -n "$SERVER_LOC" ]; then
|
||||
SERVER_LAT=$(echo "$SERVER_LOC" | cut -d',' -f1)
|
||||
SERVER_LON=$(echo "$SERVER_LOC" | cut -d',' -f2)
|
||||
distance=$(haversine $MY_LAT $MY_LON $SERVER_LAT $SERVER_LON)
|
||||
printf "%s\t%s\t%s\t%.2f\n" "$ip_host_cmd" "$site" "$country" "$distance" >> "$temp_file"
|
||||
fi
|
||||
done < <(jq -c '.[]' "$SERVER_JSON")
|
||||
|
||||
@@ -118,7 +176,7 @@ for cmd in iperf3 jq curl bc; do
|
||||
if ! command -v $cmd &>/dev/null; then
|
||||
echo -e "${YELLOW}$cmd not found. Installing required packages...${NC}"
|
||||
install_packages
|
||||
break # Only need to run install_packages once
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -146,8 +204,8 @@ MY_LON=$(echo "$MY_LOC" | cut -d',' -f2)
|
||||
|
||||
echo -e "${YELLOW}My location: $MY_CITY, $MY_COUNTRY ($MY_LAT, $MY_LON)${NC}\n"
|
||||
|
||||
SERVER_JSON="all_servers-export.json"
|
||||
curl -s "https://export.iperf3serverlist.net/json/all_servers-export.json" -o "$SERVER_JSON"
|
||||
SERVER_JSON="listed_iperf3_servers.json"
|
||||
curl -s "https://export.iperf3serverlist.net/listed_iperf3_servers.json" -o "$SERVER_JSON"
|
||||
if [ ! -f "$SERVER_JSON" ]; then
|
||||
echo -e "${RED}Error: Unable to download server list.${NC}"
|
||||
exit 1
|
||||
@@ -155,24 +213,26 @@ fi
|
||||
|
||||
echo -e "${ORANGE}Finding closest servers by city name...${NC}"
|
||||
|
||||
NEAREST_SERVER=$(jq -r \
|
||||
NEAREST_SERVER_OBJ=$(jq \
|
||||
--arg MY_CITY "$MY_CITY" \
|
||||
--arg MY_COUNTRY "$MY_COUNTRY" \
|
||||
'.[] | select(.SITE==$MY_CITY and .COUNTRY==$MY_COUNTRY) | .IP_HOST' "$SERVER_JSON")
|
||||
'.[] | select(.SITE==$MY_CITY and .COUNTRY==$MY_COUNTRY)' "$SERVER_JSON" | jq -s '.[0]')
|
||||
|
||||
if [ -z "$NEAREST_SERVER" ]; then
|
||||
if [ -z "$NEAREST_SERVER_OBJ" ] || [ "$NEAREST_SERVER_OBJ" == "null" ]; then
|
||||
echo -e "${ORANGE}No exact match found for $MY_CITY, $MY_COUNTRY. Searching for servers in $MY_COUNTRY...${NC}"
|
||||
NEAREST_SERVER=$(jq -r \
|
||||
NEAREST_SERVER_OBJ=$(jq \
|
||||
--arg MY_COUNTRY "$MY_COUNTRY" \
|
||||
'.[] | select(.COUNTRY==$MY_COUNTRY) | .IP_HOST' "$SERVER_JSON" | head -n 1)
|
||||
'.[] | select(.COUNTRY==$MY_COUNTRY)' "$SERVER_JSON" | jq -s '.[0]')
|
||||
|
||||
if [ -z "$NEAREST_SERVER" ]; then
|
||||
if [ -z "$NEAREST_SERVER_OBJ" ] || [ "$NEAREST_SERVER_OBJ" == "null" ]; then
|
||||
echo -e "${ORANGE}No servers found in $MY_COUNTRY. Finding closest city...${NC}"
|
||||
|
||||
TEMP_FILE=$(mktemp)
|
||||
|
||||
jq -r --arg CITY "$MY_CITY" '.[] | "\(.SITE)\t\(.COUNTRY)\t\(.IP_HOST)"' "$SERVER_JSON" | \
|
||||
while IFS=$'\t' read -r site country ip_host; do
|
||||
SIMILARITY_FILE=$(mktemp)
|
||||
jq -r '.[] | "\(.SITE)\t\(.COUNTRY)\t\(.["IP/HOST"])\t\(.PORT)"' "$SERVER_JSON" | \
|
||||
while IFS=$'\t' read -r site country ip_host port; do
|
||||
if [ -z "$site" ] || [ "$site" == "null" ]; then
|
||||
continue
|
||||
fi
|
||||
similarity=$(echo "$MY_CITY $site" | tr '[:upper:]' '[:lower:]' | \
|
||||
awk '{
|
||||
a=$1; b=$2;
|
||||
@@ -189,79 +249,94 @@ if [ -z "$NEAREST_SERVER" ]; then
|
||||
}
|
||||
print int((matches/length(b))*100);
|
||||
}')
|
||||
echo -e "$similarity\t$site\t$country\t$ip_host" >> "$TEMP_FILE"
|
||||
echo -e "$similarity\t$site\t$country\t$ip_host\t$port" >> "$SIMILARITY_FILE"
|
||||
done
|
||||
|
||||
closest_match=$(sort -nr "$TEMP_FILE" | head -n 1)
|
||||
if [ -n "$closest_match" ]; then
|
||||
similarity=$(echo "$closest_match" | cut -f1)
|
||||
site=$(echo "$closest_match" | cut -f2)
|
||||
country=$(echo "$closest_match" | cut -f3)
|
||||
ip_host=$(echo "$closest_match" | cut -f4)
|
||||
CANDIDATES_FILE=$(mktemp)
|
||||
sort -nr "$SIMILARITY_FILE" | head -n 20 > "$CANDIDATES_FILE"
|
||||
rm -f "$SIMILARITY_FILE"
|
||||
|
||||
echo -e "\n${GREEN}Found closest city: $site, $country $distance${NC}\n"
|
||||
DISTANCE_FILE=$(mktemp)
|
||||
while IFS=$'\t' read -r sim site country ip_host port; do
|
||||
distance="999999"
|
||||
server_loc=""
|
||||
if [[ $ip_host =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
server_info_json=$(curl -s "https://ipinfo.io/$ip_host/json")
|
||||
server_loc=$(echo "$server_info_json" | jq -r '.loc')
|
||||
else
|
||||
resolved_ip=$(dig +short "$ip_host" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
|
||||
if [ -n "$resolved_ip" ]; then
|
||||
server_info_json=$(curl -s "https://ipinfo.io/$resolved_ip/json")
|
||||
server_loc=$(echo "$server_info_json" | jq -r '.loc')
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$server_loc" ] && [ "$server_loc" != "null" ]; then
|
||||
server_lat=$(echo "$server_loc" | cut -d',' -f1)
|
||||
server_lon=$(echo "$server_loc" | cut -d',' -f2)
|
||||
distance=$(haversine "$MY_LAT" "$MY_LON" "$server_lat" "$server_lon")
|
||||
fi
|
||||
echo -e "$distance\t$sim\t$site\t$country\t$ip_host\t$port" >> "$DISTANCE_FILE"
|
||||
done < "$CANDIDATES_FILE"
|
||||
rm -f "$CANDIDATES_FILE"
|
||||
|
||||
closest_match=$(sort -n "$DISTANCE_FILE" | head -n 1)
|
||||
|
||||
if [ -n "$closest_match" ]; then
|
||||
distance=$(echo "$closest_match" | cut -f1)
|
||||
similarity=$(echo "$closest_match" | cut -f2)
|
||||
site=$(echo "$closest_match" | cut -f3)
|
||||
country=$(echo "$closest_match" | cut -f4)
|
||||
ip_host=$(echo "$closest_match" | cut -f5)
|
||||
port=$(echo "$closest_match" | cut -f6)
|
||||
ip_host_cmd=$(construct_iperf_command "$ip_host" "$port")
|
||||
|
||||
echo -e "\n${GREEN}Found closest city: $site, $country${NC}\n"
|
||||
echo -e "Starting iPerf3 test with server from $site...\n"
|
||||
|
||||
if [[ $ip_host =~ iperf3[[:space:]]+-c[[:space:]]+([^[:space:]]+) ]]; then
|
||||
server="${BASH_REMATCH[1]}"
|
||||
iperf3 -c "$server"
|
||||
run_iperf_test "$ip_host" "$port"
|
||||
|
||||
echo -e "\n${YELLOW}Top 3 closest iperf3-servers by name match:${NC}"
|
||||
echo -e "${YELLOW}-------------------------------------------${NC}"
|
||||
sort -nr "$TEMP_FILE" | head -n 3 | while IFS=$'\t' read -r sim site country cmd; do
|
||||
echo -e "\nCity: $site, $country"
|
||||
|
||||
if [[ $cmd =~ iperf3[[:space:]]+-c[[:space:]]+([^[:space:]]+) ]]; then
|
||||
server="${BASH_REMATCH[1]}"
|
||||
if [[ $server =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
SERVER_INFO=$(curl -s "https://ipinfo.io/$server/json")
|
||||
else
|
||||
resolved_ip=$(dig +short "$server" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
|
||||
if [ -n "$resolved_ip" ]; then
|
||||
SERVER_INFO=$(curl -s "https://ipinfo.io/$resolved_ip/json")
|
||||
fi
|
||||
fi
|
||||
|
||||
SERVER_LOC=$(echo "$SERVER_INFO" | jq -r '.loc')
|
||||
if [ -n "$SERVER_LOC" ]; then
|
||||
SERVER_LAT=$(echo "$SERVER_LOC" | cut -d',' -f1)
|
||||
SERVER_LON=$(echo "$SERVER_LOC" | cut -d',' -f2)
|
||||
distance=$(haversine $MY_LAT $MY_LON $SERVER_LAT $SERVER_LON)
|
||||
printf "Distance: %.2f km (Match score: %d%%)\n" "$distance" "$sim"
|
||||
else
|
||||
echo "Distance: unavailable (Match score: ${sim}%)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Command: $cmd"
|
||||
if [ "$cmd" = "$ip_host" ]; then
|
||||
echo -e "${GREEN}Status: Just tested${NC}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# Display top 3 based on original similarity sort, but with calculated distances
|
||||
echo -e "\n${YELLOW}Top 3 closest iperf3-servers by geographical distance:${NC}"
|
||||
echo -e "${YELLOW}----------------------------------------------------${NC}"
|
||||
sort -n "$DISTANCE_FILE" | head -n 3 | while IFS=$'\t' read -r dist sim site country server port; do
|
||||
cmd=$(construct_iperf_command "$server" "$port")
|
||||
echo -e "\nCity: $site, $country"
|
||||
printf "Distance: %.2f km (Match score: %d%%)\n" "$dist" "$sim"
|
||||
echo "Command: $cmd"
|
||||
if [ "$cmd" = "$ip_host_cmd" ]; then
|
||||
echo -e "${GREEN}Status: Just tested${NC}"
|
||||
fi
|
||||
done
|
||||
rm -f "$DISTANCE_FILE"
|
||||
else
|
||||
rm -f "$DISTANCE_FILE"
|
||||
fi
|
||||
|
||||
rm -f "$TEMP_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$NEAREST_SERVER" ]; then
|
||||
if [[ $NEAREST_SERVER =~ iperf3[[:space:]]+-c[[:space:]]+([^[:space:]]+) ]]; then
|
||||
server="${BASH_REMATCH[1]}"
|
||||
echo -e "\n${GREEN}Nearest iperf3-server: $server${NC}\n"
|
||||
echo -e "Starting iPerf3 test with server $server...\n"
|
||||
iperf3 -c "$server"
|
||||
if [ -n "$NEAREST_SERVER_OBJ" ] && [ "$NEAREST_SERVER_OBJ" != "null" ]; then
|
||||
server=$(echo "$NEAREST_SERVER_OBJ" | jq -r '.["IP/HOST"]')
|
||||
port=$(echo "$NEAREST_SERVER_OBJ" | jq -r '.PORT')
|
||||
NEAREST_SERVER_CMD=$(construct_iperf_command "$server" "$port")
|
||||
echo -e "\n${GREEN}Nearest iperf3-server: $server${NC}\n"
|
||||
echo -e "Starting iPerf3 test with server $server...\n"
|
||||
run_iperf_test "$server" "$port"
|
||||
|
||||
echo -e "\n${YELLOW}Top 3 closest iperf3-servers:${NC}"
|
||||
echo -e "${YELLOW}-----------------------------${NC}"
|
||||
jq -r --arg COUNTRY "$MY_COUNTRY" \
|
||||
'.[] | select(.COUNTRY==$COUNTRY) | "\(.SITE)\t\(.COUNTRY)\t\(.IP_HOST)"' "$SERVER_JSON" | \
|
||||
head -n 3 | while IFS=$'\t' read -r site country cmd; do
|
||||
echo -e "\nCity: $site, $country"
|
||||
echo "Command: $cmd"
|
||||
if [ "$cmd" = "$NEAREST_SERVER" ]; then
|
||||
echo -e "${GREEN}Status: Just tested${NC}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo -e "\n${YELLOW}Top 3 closest iperf3-servers:${NC}"
|
||||
echo -e "${YELLOW}-----------------------------${NC}"
|
||||
jq -c --arg COUNTRY "$MY_COUNTRY" \
|
||||
'.[] | select(.COUNTRY==$COUNTRY)' "$SERVER_JSON" | \
|
||||
head -n 3 | while read -r server_info; do
|
||||
site=$(echo "$server_info" | jq -r '.SITE')
|
||||
country=$(echo "$server_info" | jq -r '.COUNTRY')
|
||||
host=$(echo "$server_info" | jq -r '.["IP/HOST"]')
|
||||
port=$(echo "$server_info" | jq -r '.PORT')
|
||||
cmd=$(construct_iperf_command "$host" "$port")
|
||||
echo -e "\nCity: $site, $country"
|
||||
echo "Command: $cmd"
|
||||
if [ "$cmd" = "$NEAREST_SERVER_CMD" ]; then
|
||||
echo -e "${GREEN}Status: Just tested${NC}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
Reference in new issue
Block a user