function openRemote($http_user, $http_pass) { global $copts, $dad, $dpo, $bad, $bpo, $CASCADING, $CAS_SERVER, $CAS_PORT, $CAS_AUTH_PASSTHROUGH, $CAS_AUTH_USER, $CAS_AUTH_PASS, $usock, $rmsock, $ident; if ($CASCADING == 4 && $copts & 4) { return "UDP connections cannot be cascaded over SOCKS4"; } $s = $CASCADING ? $CAS_SERVER : $dad; $p = $CASCADING ? $CAS_PORT : $dpo; if ($copts & 4) { // udp socket $usock = stream_socket_server("udp://0.0.0.0:0", $errno, $errstr, STREAM_SERVER_BIND); if (!$usock) { return "UDP stream_socket_server() failed: reason: {$errstr}"; } $bad = "0.0.0.0"; $bpo = 0; } if (!$CASCADING && $copts & 8) { // bind and no cascading $bad = getmyip(true); $rmsock = stream_socket_server("tcp://0.0.0.0:0", $errno, $errstr); if (!$rmsock) { return "BIND stream_socket_server() failed: reason: {$errstr}"; } $bpo = preg_replace('/^.*?:/', '', stream_socket_get_name($rmsock, false)); logline(4, "{$ident}: opened BIND server on {$bad}:{$bpo}"); } if ($CASCADING || !($copts & 12)) { // tcp socket $rmsock = stream_socket_client("tcp://{$s}:{$p}", $errno, $errstr); if (!$rmsock) { return "TCP stream_socket_client(tcp://{$s}:{$p}) failed: reason: {$errstr}"; } $bad = preg_replace('/:.*$/', '', stream_socket_get_name($rmsock, false)); $bpo = preg_replace('/^.*?:/', '', stream_socket_get_name($rmsock, false)); stream_set_blocking($rmsock, 1); } $user = $CAS_AUTH_PASSTHROUGH ? $http_user : $CAS_AUTH_USER; $pass = $CAS_AUTH_PASSTHROUGH ? $http_pass : $CAS_AUTH_PASS; if ($CASCADING == 4) { # SOCKS4 connect $iaddr = ip2long(gethostbyname($dad)); # try to resolve target ip if ($iaddr) { myfwrite($rmsock, pack("CCCCN", 0x4, $copts & 8 ? 0x2 : 0x1, floor($dpo / 256), $dpo % 256, $iaddr) . $user . chr(0)); } else { myfwrite($rmsock, pack("C*", 0x4, $copts & 8 ? 0x2 : 0x1, floor($dpo / 256), $dpo % 256, 0, 0, 0, 1) . $user . chr(0) . $server . chr(0)); } $a = get_socks4_reply($rmsock); if ($a[0]) { return $a[0]; } $bad = $a[1]; $bpo = $a[2]; } elseif ($CASCADING == 5) { # SOCKS5 connect if ($copts & 4) { # UDP connection cascading $dpo = preg_replace('/^.*?:/', '', stream_socket_get_name($usock, false)); $dad = preg_replace('/:.*$/', '', stream_socket_get_name($rmsock, false)); } # send greeting myfwrite($rmsock, pack("C*", 0x5, 0x2, 0x0, 0x2)); $buf = fread($rmsock, 2); if (empty($buf)) { return $msg; } $a = unpack("C*", $buf); if ($a[2] == 2) { # authenticate myfwrite($rmsock, chr(1) . chr(strlen($user)) . $user . chr(strlen($pass)) . $pass); $buf = fread($rmsock, 2); if (empty($buf)) { return $msg; } $a = unpack("C*", $buf); if ($a[2] != 0) { return "SOCKS5 authentication failed"; } } $iaddr = ip2long(gethostbyname($dad)); if ($iaddr) { $buf = pack("CCCCNCC", 0x5, $copts & 4 ? 0x3 : ($copts & 8 ? 0x2 : 0x1), 0x0, 0x1, $iaddr, floor($dpo / 256), $dpo % 256); } else { $buf = pack("C*", 0x5, $copts & 4 ? 0x3 : ($copts & 8 ? 0x2 : 0x1), 0x0, 0x3, strlen($dad)) . $dad . chr(floor($dpo / 256)) . chr($dpo % 256); } myfwrite($rmsock, $buf); $a = get_socks5_reply($rmsock); if ($a[0]) { return $a[0]; } $bad = $a[1]; $bpo = $a[2]; } return ""; }
} } } } elseif ($rmsock && $rin[0] == $rmsock || $usock && $rin[0] == $usock) { // we got data coming in from the remote port, lets dump it to the client if (($copts & 24) == 8) { # BIND should accept the connection logline(4, "{$ident}: client trying to connect to bound socket"); if ($CASCADING == 4) { $a = get_socks4_reply($rmsock); if ($a[0]) { echo "c:disconnect {$a['0']}\n"; exit; } } elseif ($CASCADING == 5) { $a = get_socks5_reply($rmsock); if ($a[0]) { echo "c:disconnect {$a['0']}\n"; exit; } } else { if (($rmsock1 = stream_socket_accept($rmsock)) === false) { echo "c:disconnect BIND accept failed\n"; exit; } fclose($rmsock); $rmsock = $rmsock1; $a[1] = preg_replace('/:.*$/', '', stream_socket_get_name($rmsock, true)); $a[2] = preg_replace('/^.*?:/', '', stream_socket_get_name($rmsock, true)); } logline(4, "{$ident}: {$a['1']} connecting to bound socket");