phpvpntraceroute

PHP Script to Traceroute?


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?


Solution

  • 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_addr\n";
    
    $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  %s\n", $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