Skip to content

Commit f281a05

Browse files
committed
Initial Checkin
0 parents  commit f281a05

File tree

6 files changed

+233
-0
lines changed

6 files changed

+233
-0
lines changed

README.md

Whitespace-only changes.

composer.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "stechstudio/laravel-ssh-tunnel",
3+
"description": "Easy creation & maintenance of an SSH Tunnel for Laravel/Lumen",
4+
"type": "library",
5+
"authors": [
6+
{
7+
"name": "Bubba Hines",
8+
"email": "[email protected]"
9+
}
10+
],
11+
"minimum-stability": "dev",
12+
"require": {}
13+
}

src/Console/TunnelerCommand.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php namespace stechstudio\Tunneler\Console;
2+
3+
use Illuminate\Console\Command;
4+
use stechstudio\Tunneler\Jobs\CreateTunnel;
5+
6+
class TunnelerCommand extends Command {
7+
/**
8+
* The console command name.
9+
*
10+
* @var string
11+
*/
12+
protected $name = 'tunneler:activate';
13+
/**
14+
* The console command description.
15+
*
16+
* @var string
17+
*/
18+
protected $description = 'Creates and Maintains an SSH Tunnel';
19+
20+
public function handle(){
21+
try {
22+
$result = dispatch(new CreateTunnel());
23+
}catch (\ErrorException $e){
24+
$this->error($e->getMessage());
25+
return 1;
26+
}
27+
28+
if ($result === 1 ){
29+
$this->info('The Tunnel is already Activated.');
30+
return 0;
31+
}
32+
33+
if ($result === 2 ){
34+
$this->info('The Tunnel has been Activated.');
35+
return 0;
36+
}
37+
38+
$this->warn('I have no idea how this happened. Let me know if you figure it out.');
39+
return 1;
40+
}
41+
}

src/Jobs/CreateTunnel.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php namespace stechstudio\Tunneler\Jobs;
2+
3+
class CreateTunnel
4+
{
5+
6+
/**
7+
* The Command for checking if the tunnel is open
8+
* @var string
9+
*/
10+
protected $ncCommand;
11+
12+
/**
13+
* The command for creating the tunnel
14+
* @var string
15+
*/
16+
protected $sshCommand;
17+
18+
/**
19+
* Simple place to keep all output.
20+
* @var array
21+
*/
22+
protected $output = [];
23+
24+
public function __construct()
25+
{
26+
$this->ncCommand = sprintf('%s -z %s %d > /dev/null 2>&1',
27+
config('tunneler.nc_path'),
28+
config('tunneler.local_address'),
29+
config('tunneler.local_port')
30+
);
31+
32+
$this->sshCommand = sprintf('%s -N -i %s -L %d:%s:%d -p %d %s@%s',
33+
config('tunneler.ssh_path'),
34+
config('tunneler.identity_file'),
35+
config('tunneler.local_port'),
36+
config('tunneler.bind_address'),
37+
config('tunneler.bind_port'),
38+
config('tunneler.port'),
39+
config('tunneler.user'),
40+
config('tunneler.hostname')
41+
);
42+
}
43+
44+
45+
public function handle(): int
46+
{
47+
if ($this->verifyTunnel()){
48+
return 1;
49+
}
50+
51+
$this->createTunnel();
52+
53+
if ($this->verifyTunnel()){
54+
return 2;
55+
}
56+
57+
throw new \ErrorException(sprintf("Could Not Create SSH Tunnel with command:\n\t%s\nCheck your configuration.",
58+
$this->sshCommand));
59+
}
60+
61+
62+
/**
63+
* Creates the SSH Tunnel for us.
64+
*/
65+
protected function createTunnel()
66+
{
67+
$this->runCommand(sprintf('%s %s > /dev/null &', config('tunneler.nohup_path'), $this->sshCommand));
68+
// Ensure we wait long enough for it to actually connect.
69+
usleep(config('tunneler.wait'));
70+
}
71+
72+
/**
73+
* Verifies whether the tunnel is active or not.
74+
* @return bool
75+
*/
76+
protected function verifyTunnel(): bool
77+
{
78+
return $this->runCommand($this->ncCommand);
79+
}
80+
81+
/**
82+
* Runs a command and converts the exit code to a boolean
83+
* @param $command
84+
* @return bool
85+
*/
86+
protected function runCommand($command): bool
87+
{
88+
$return_var = 1;
89+
exec($command, $this->output, $return_var);
90+
return (bool)($return_var === 0);
91+
}
92+
93+
94+
}

src/TunnelerServiceProvider.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php namespace stechstudio\Tunneler;
2+
3+
use Illuminate\Support\ServiceProvider;
4+
use stechstudio\Tunneler\Console\TunnelerCommand;
5+
use stechstudio\Tunneler\Jobs\CreateTunnel;
6+
7+
8+
class TunnelerServiceProvider extends ServiceProvider{
9+
/**
10+
* Indicates if loading of the provider is deferred.
11+
*
12+
* @var bool
13+
*/
14+
protected $defer = false;
15+
16+
/**
17+
* Default path to configuration
18+
* @var string
19+
*/
20+
protected $configPath = __DIR__ . '/config/tunneler.php';
21+
22+
23+
public function boot()
24+
{
25+
// helps deal with Lumen vs Laravel differences
26+
if (function_exists('config_path')) {
27+
$publishPath = config_path('tunneler.php');
28+
} else {
29+
$publishPath = base_path('config/tunneler.php');
30+
}
31+
32+
$this->publishes([$this->configPath => $publishPath], 'config');
33+
34+
if (config('tunneler.on_boot')){
35+
dispatch(new CreateTunnel());
36+
}
37+
}
38+
39+
public function register()
40+
{
41+
if ( is_a($this->app,'Laravel\Lumen\Application')){
42+
$this->app->configure('tunneler');
43+
}
44+
$this->mergeConfigFrom($this->configPath, 'tunneler');
45+
46+
$this->app['command.tunneler.activate'] = $this->app->share(
47+
function ($app) {
48+
return new TunnelerCommand();
49+
}
50+
);
51+
52+
$this->commands('command.tunneler.activate');
53+
}
54+
55+
/**
56+
* Get the services provided by the provider.
57+
*
58+
* @return array
59+
*/
60+
public function provides()
61+
{
62+
return array('command.tunneler.activate');
63+
}
64+
65+
}

src/config/tunneler.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
return [
3+
'nc_path' => env('TUNNELER_NC_PATH', 'nc'),
4+
'ssh_path' => env('TUNNELER_SSH_PATH', 'ssh'),
5+
'nohup_path' => env('TUNNELER_NOHUP_PATH', 'nohup'),
6+
7+
'local_address' => env('TUNNELER_LOCAL_ADDRESS', '127.0.0.1'),
8+
'local_port' => env('TUNNELER_LOCAL_PORT'),
9+
'identity_file' => env('TUNNELER_IDENTITY_FILE'),
10+
11+
'bind_address' => env('TUNNELER_BIND_ADDRESS', '127.0.0.1'),
12+
'bind_port' => env('TUNNELER_BIND_PORT'),
13+
14+
'user' => env('TUNNELER_USER'),
15+
'hostname' => env('TUNNELER_HOSTNAME'),
16+
'port' => env('TUNNELER_PORT'),
17+
'wait' => env('TUNNELER_CONN_WAIT', '500000'),
18+
19+
'on_boot' => filter_var(env('TUNNELER_ON_BOOT', false), FILTER_VALIDATE_BOOLEAN)
20+
];

0 commit comments

Comments
 (0)