PHP Script to Test SOCKS5 Proxy UDP Support
Standard browser-based IP tests or SOCKS5 connections only evaluate TCP traffic. A provider claiming SOCKS5 support does not guarantee that UDP packets are properly forwarded — a feature critical for VoIP (Telegram, Discord), video streaming, and online gaming.
This CLI PHP script verifies both the initial UDP ASSOCIATE handshake and actual UDP packet delivery: it connects to the proxy, authenticates, retrieves the assigned UDP relay address, and sends a real DNS query to 1.1.1.1:53 through the relay.
Running the script via CLI:
- Download the script and open it to configure your credentials:
wget https://dieg.net/scripts/socks5-udp-check.php
nano socks5-udp-check.php- Set your proxy host, port, username, and password in $proxy, $port, $user, and $pass.
- Execute the check:
php socks5-udp-check.phpIf UDP transfer is fully functional, you will get: [OK] UDP is working: DNS response received through SOCKS5.
Source Code:
socks5-udp-check.php
[ Raw / Download ]
php <<'PHP'
<?php
$proxy = "accel.ipflygates.com";
$port = 5001;
$user = "USERNAME";
$pass = "PASSWORD";
function readExact($s, $n) {
$data = "";
while (strlen($data) < $n) {
$part = fread($s, $n - strlen($data));
if ($part === false || $part === "") {
throw new Exception("Incomplete TCP response or timeout");
}
$data .= $part;
}
return $data;
}
function readAddress($s, $type) {
switch ($type) {
case 1: return inet_ntop(readExact($s, 4));
case 3: return readExact($s, ord(readExact($s, 1)));
case 4: return inet_ntop(readExact($s, 16));
default: throw new Exception("Unknown address type");
}
}
try {
$tcp = @stream_socket_client("tcp://$proxy:$port", $errno, $errstr, 5);
if (!$tcp) throw new Exception("TCP: $errstr");
stream_set_timeout($tcp, 5);
fwrite($tcp, "\x05\x01\x02");
if (readExact($tcp, 2) !== "\x05\x02") {
throw new Exception("Server did not select username/password authentication");
}
fwrite($tcp, "\x01".chr(strlen($user)).$user.chr(strlen($pass)).$pass);
if (readExact($tcp, 2) !== "\x01\x00") {
throw new Exception("Authentication failed");
}
fwrite($tcp, "\x05\x03\x00\x01".str_repeat("\x00", 6));
$h = readExact($tcp, 4);
if ($h[0] !== "\x05" || $h[2] !== "\x00") {
throw new Exception("Invalid SOCKS5 response");
}
if (ord($h[1]) !== 0) {
throw new Exception("UDP ASSOCIATE: reply code ".ord($h[1]));
}
$relay = readAddress($tcp, ord($h[3]));
$relayPort = unpack("n", readExact($tcp, 2))[1];
if ($relay === "0.0.0.0" || $relay === "::") {
$peer = stream_socket_get_name($tcp, true);
$relay = trim(substr($peer, 0, strrpos($peer, ":")), "[]");
}
if (!$relayPort) throw new Exception("Server returned UDP port zero");
$host = strpos($relay, ":") !== false ? "[$relay]" : $relay;
$udp = @stream_socket_client("udp://$host:$relayPort", $errno, $errstr, 5);
if (!$udp) throw new Exception("UDP: $errstr");
stream_set_timeout($udp, 5);
// DNS A query for example.com sent through the UDP relay to 1.1.1.1:53.
$id = random_bytes(2);
$dns = $id.pack("nnnnn", 0x0100, 1, 0, 0, 0)
. "\x07example\x03com\x00".pack("nn", 1, 1);
$packet = "\x00\x00\x00\x01".inet_pton("1.1.1.1").pack("n", 53).$dns;
fwrite($udp, $packet);
$reply = fread($udp, 4096);
if ($reply === false || strlen($reply) < 4) {
throw new Exception("No UDP response: UDP data transfer not confirmed");
}
if (substr($reply, 0, 3) !== "\x00\x00\x00") {
throw new Exception("Invalid SOCKS5 UDP header or fragmented datagram");
}
$type = ord($reply[3]);
switch ($type) {
case 1: $offset = 10; break;
case 4: $offset = 22; break;
case 3:
if (strlen($reply) < 5) throw new Exception("Response too short");
$offset = 7 + ord($reply[4]);
break;
default: throw new Exception("Unknown UDP address type");
}
$answer = substr($reply, $offset);
if (strlen($answer) < 12 || substr($answer, 0, 2) !== $id
|| !(ord($answer[2]) & 0x80)) {
throw new Exception("No matching DNS response received");
}
echo "[OK] UDP is working: DNS response received through SOCKS5.\n";
} catch (Throwable $e) {
echo "[FAIL] ".$e->getMessage()."\n";
exit(1);
}
PHP