I have a website running PHP on a GoDaddy shared linux server. I need to determine if users are connected to the companies VPN. If I simply do $_SERVER[‘REMOTE_ADDR’] it gives me the clients IP address. However if I can dig deeper with a tracert, the 2nd hop would show up as the companies IP address.
Is it possible to do a traceroute from the webpage using PHP to determine if users are connected to the company’s split tunnel VPN?
Advertisement
Answer
Creating a traceroute program in PHP
http://www.adayinthelifeof.nl/2010/07/30/creating-a-traceroute-program-in-php/
In case the site goes down here’s the jist:
<?php define ("SOL_IP", 0); define ("IP_TTL", 2); // On OSX, use '4' instead of '2'. $dest_url = "www.google.com"; // Fill in your own URL here, or use $argv[1] to fetch from commandline. $maximum_hops = 30; $port = 33434; // Standard port that traceroute programs use. Could be anything actually. // Get IP from URL $dest_addr = gethostbyname ($dest_url); print "Tracerouting to destination: $dest_addrn"; $ttl = 1; while ($ttl < $maximum_hops) { // Create ICMP and UDP sockets $recv_socket = socket_create (AF_INET, SOCK_RAW, getprotobyname ('icmp')); $send_socket = socket_create (AF_INET, SOCK_DGRAM, getprotobyname ('udp')); // Set TTL to current lifetime socket_set_option ($send_socket, SOL_IP, IP_TTL, $ttl); // Bind receiving ICMP socket to default IP (no port needed since it's ICMP) socket_bind ($recv_socket, 0, 0); // Save the current time for roundtrip calculation $t1 = microtime (true); // Send a zero sized UDP packet towards the destination socket_sendto ($send_socket, "", 0, 0, $dest_addr, $port); // Wait for an event to occur on the socket or timeout after 5 seconds. This will take care of the // hanging when no data is received (packet is dropped silently for example) $r = array ($recv_socket); $w = $e = array (); socket_select ($r, $w, $e, 5, 0); // Nothing to read, which means a timeout has occurred. if (count ($r)) { // Receive data from socket (and fetch destination address from where this data was found) socket_recvfrom ($recv_socket, $buf, 512, 0, $recv_addr, $recv_port); // Calculate the roundtrip time $roundtrip_time = (microtime(true) - $t1) * 1000; // No decent address found, display a * instead if (empty ($recv_addr)) { $recv_addr = "*"; $recv_name = "*"; } else { // Otherwise, fetch the hostname for the address found $recv_name = gethostbyaddr ($recv_addr); } // Print statistics printf ("%3d %-15s %.3f ms %sn", $ttl, $recv_addr, $roundtrip_time, $recv_name); } else { // A timeout has occurred, display a timeout printf ("%3d (timeout)n", $ttl); } // Close sockets socket_close ($recv_socket); socket_close ($send_socket); // Increase TTL so we can fetch the next hop $ttl++; // When we have hit our destination, stop the traceroute if ($recv_addr == $dest_addr) break; } ?>
You need to be root. This means it probably is not going to work when running it from a web-server, you have to run it from the command line:
jthijssen@tarabas:~/traceroute$ sudo php traceroute.php Tracerouting to destination: 199.6.1.164 1 192.168.1.1 0.004 ms 192.168.1.1 2 * 0.005 ms static.kpn.net 3 (timeout) 4 139.156.113.141 0.005 ms nl-asd-dc2-ias-csg01-ge-3-2-0-kpn.net 5 195.190.227.221 0.005 ms asd2-rou-1022.nl.euroringen.net 6 134.222.229.105 0.005 ms asd2-rou-1001.NL.eurorings.net 7 134.222.97.186 0.007 ms kpn-1402.xe-0-0-0.jun1.galilei.network.bit.nl 8 213.154.236.75 0.012 ms 213.154.236.75 9 199.6.1.164 0.012 ms pub3.kernel.org
This is a traceroute to www.kernel.org. I’ve removed the second hop (because that’s the IP at my place). The 3rd hop returned a timeout. Probably the station there did not return a ICMP packet back to use.
The above code can be found on github: https://github.com/jaytaph/traceroute