Skip to content

Instantly share code, notes, and snippets.

@andrew-wilkes
Created March 20, 2021 11:18
Show Gist options
  • Save andrew-wilkes/0af8d23fcd74f0d1ab7732145923733b to your computer and use it in GitHub Desktop.
Save andrew-wilkes/0af8d23fcd74f0d1ab7732145923733b to your computer and use it in GitHub Desktop.
PHP Script to Start and Stop a Reverse SSH Tunnel from a Remote Server
<?php
/*
This script is placed on a server or computer that remains powered up and is run via a
crontab job at regular intervals to ensure that the reverse SSH tunnel that it creates
remains active or gets killed according to the text value contained in a file on a remote
server that tells it whether to start or kill the process.
That file contains "on" or "off" text that is accessible via a URL.
On that server, the user should be able to SSH to it and change the command value in the file.
Then, they wait for it to be acted upon according to the schedule set in the CRONTAB and then
they try to connect to the exposed local port that leads to the tunnel with a command:
ssh localhost -p TUNNEL_PORT
If the connection is refused, then the tunnel is not available or the SSH is not set up
such as for known hosts and public keys.
The process ID is not stored, but is detected based on a signature using the selected TUNNEL_PORT
that is used for the tunnel.
*/
define("TUNNEL_PORT", 12345); // An unused port number on localhost of the server that you connect to directly
$pid = get_pid();
$turn_on = turn_on();
if ($pid > 0 && !$turn_on) {
// Turn off
exec("kill $pid");
log_msg("stopped");
}
if ($pid < 1 && $turn_on) {
// Turn on
// Replace user@ip_address with the value for your server account where you are recognized for SSH access
exec('nohup ssh -f -N -R TUNNEL_PORT:localhost:22 user@server_ip_address > /dev/null 2>&1 & echo $!', $op);
log_msg("started");
}
function turn_on() {
// Get the on/off string from your server end point file called tunnel
$ch = curl_init("http://server_ip_address/path/tunnel");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$on = trim((string)curl_exec($ch)) == "on";
if(curl_error($ch)) {
$on = false;
log_msg("Error: " . curl_error($ch));
}
curl_close($ch);
return $on;
}
function get_pid() {
$pid = 0;
// Filter the running processes on your computer that is providing the tunnel to it over port 12345 for example
exec('ps aux | grep -v grep | grep TUNNEL_PORT', $op);
if (count($op) > 0) {
$pid = (int)preg_split("/\s+/", $op[0])[1]; // Extract the PID number
}
return $pid;
}
// Log start and stop activity
function log_msg($txt) {
file_put_contents(__DIR__ . "/log", date("Y-m-d H:i:s") . "\t" . $txt . "\n", FILE_APPEND);
}
@andrew-wilkes
Copy link
Author

Please edit TUNNEL_PORT and the code where it gets inserted and server_ip_address/path to get it working for your needs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment